-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathconfig.go
More file actions
176 lines (155 loc) · 5.89 KB
/
Copy pathconfig.go
File metadata and controls
176 lines (155 loc) · 5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package config
import (
"encoding/json"
"fmt"
"os"
"regexp"
"github.com/outbrain/golib/log"
)
var (
envVariableRegexp = regexp.MustCompile("[$][{](.*?)[}]")
)
var instance = newConfiguration()
// Instance returns the global instance of Configuration
func Instance() *Configuration {
return instance
}
// Settings returns the settings of the global instance of Configuration
func Settings() *ConfigurationSettings {
return Instance().settings
}
// Reset sets the initial state of the configuration instance
func Reset() {
instance = newConfiguration()
}
// Configuration struct stores the readFileNames and points to the settings
// which are the configuration parameters used in the application.
// see ConfigurationSettings for the available settings.
// Read file names are also stored to allow configuration reloading.
type Configuration struct {
readFileNames []string
settings *ConfigurationSettings
}
func newConfiguration() *Configuration {
return &Configuration{
settings: newConfigurationSettings(),
}
}
// Read reads configuration from all given files, in order of input.
// Each file can override the properties of the previous files
// Initially, the settings are the defult ones defined by newConfigurationSettings
func (config *Configuration) Read(fileNames ...string) error {
settings := newConfigurationSettings()
for _, fileName := range fileNames {
if _, err := os.Stat(fileName); err == nil {
file, err := os.Open(fileName)
if err != nil {
return log.Errorf("Cannot read config file %s, error was: %s", fileName, err)
}
defer file.Close()
decoder := json.NewDecoder(file)
err = decoder.Decode(settings)
if err == nil {
log.Infof("Config read from %s", fileName)
} else {
return fmt.Errorf("Cannot read config file %s, error was: %s", fileName, err)
}
}
}
if err := settings.postReadAdjustments(); err != nil {
return log.Errore(err)
}
config.readFileNames = fileNames
config.settings = settings
return nil
}
// Reload re-reads configuration from last used files
func (config *Configuration) Reload() error {
return config.Read(config.readFileNames...)
}
// ConfigurationSettings models a set of configurable values, that can be
// provided by the user via one or several JSON formatted files.
//
// Some of the settinges have reasonable default values, and some other
// (like database credentials) are strictly expected from user.
type ConfigurationSettings struct {
ListenPort int
DataCenter string
Environment string
Domain string
ShareDomain string
RaftBind string
RaftDataDir string
DefaultRaftPort int // if a RaftNodes entry does not specify port, use this one
RaftNodes []string // Raft nodes to make initial connection with
BackendMySQLHost string
BackendMySQLPort int
BackendMySQLSchema string
BackendMySQLUser string
BackendMySQLPassword string
BackendMySQLCollation string // if specified, use this collation instead of charset when connecting to MySQL backend
MemcacheServers []string // if given, freno will report to aggregated values to given memcache
MemcachePath string // use as prefix to metric path in memcache key, e.g. if `MemcachePath` is "myprefix" the key would be "myprefix/mysql/maincluster". Default: "freno"
PrometheusNamespace string
PrometheusSubsystem string
EnableProfiling bool // enable pprof profiling http api
Stores StoresSettings
}
func newConfigurationSettings() *ConfigurationSettings {
return &ConfigurationSettings{
ListenPort: 8087,
RaftBind: "127.0.0.1:10008",
RaftDataDir: "",
DefaultRaftPort: 0,
RaftNodes: []string{},
BackendMySQLHost: "",
BackendMySQLSchema: "",
BackendMySQLPort: 3306,
MemcacheServers: []string{},
MemcachePath: "freno",
PrometheusNamespace: "freno",
//Debug: false,
//ListenSocket: "",
//AnExampleListOfStrings: []string{"*"},
//AnExampleMapOfStringsToStrings: make(map[string]string),
}
}
// Hook to implement adjustments after reading each configuration file.
func (settings *ConfigurationSettings) postReadAdjustments() error {
if submatch := envVariableRegexp.FindStringSubmatch(settings.BackendMySQLHost); len(submatch) > 1 {
settings.BackendMySQLHost = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.BackendMySQLSchema); len(submatch) > 1 {
settings.BackendMySQLSchema = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.BackendMySQLUser); len(submatch) > 1 {
settings.BackendMySQLUser = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.BackendMySQLPassword); len(submatch) > 1 {
settings.BackendMySQLPassword = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.DataCenter); len(submatch) > 1 {
settings.DataCenter = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.Environment); len(submatch) > 1 {
settings.Environment = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.Domain); len(submatch) > 1 {
settings.Domain = os.Getenv(submatch[1])
}
if submatch := envVariableRegexp.FindStringSubmatch(settings.ShareDomain); len(submatch) > 1 {
settings.ShareDomain = os.Getenv(submatch[1])
}
if settings.RaftDataDir == "" && settings.BackendMySQLHost == "" {
return fmt.Errorf("Either RaftDataDir or BackendMySQLHost must be set")
}
if settings.BackendMySQLHost != "" {
if settings.BackendMySQLSchema == "" {
return fmt.Errorf("BackendMySQLSchema must be set when BackendMySQLHost is specified")
}
}
if err := settings.Stores.postReadAdjustments(); err != nil {
return err
}
return nil
}