-
Notifications
You must be signed in to change notification settings - Fork 60
/
archaius.go
executable file
·313 lines (276 loc) · 8.04 KB
/
archaius.go
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
// Package archaius provides you APIs which helps to manage files,
// remote config center configurations
package archaius
import (
"errors"
"fmt"
"io"
filesource "github.com/go-chassis/go-archaius/source/file"
"os"
"strings"
"github.com/go-chassis/go-archaius/event"
"github.com/go-chassis/go-archaius/pkg/cast"
"github.com/go-chassis/go-archaius/source"
"github.com/go-chassis/go-archaius/source/cli"
"github.com/go-chassis/go-archaius/source/env"
"github.com/go-chassis/go-archaius/source/mem"
"github.com/go-chassis/openlog"
)
var (
manager *source.Manager
fs filesource.FileSource
running = false
configServerRunning = false
)
func initFileSource(o *Options) (source.ConfigSource, error) {
files := make([]string, 0)
// created file source object
fs = filesource.NewFileSource()
// adding all files with file source
for _, v := range o.RequiredFiles {
if err := fs.AddFile(v, filesource.DefaultFilePriority, o.FileHandler); err != nil {
openlog.Error(fmt.Sprintf("add file source error [%s].", err.Error()))
return nil, err
}
files = append(files, v)
}
for _, v := range o.OptionalFiles {
_, err := os.Stat(v)
if os.IsNotExist(err) {
openlog.Info(fmt.Sprintf("[%s] not exist", v))
continue
}
if err := fs.AddFile(v, filesource.DefaultFilePriority, o.FileHandler); err != nil {
openlog.Info(err.Error())
return nil, err
}
files = append(files, v)
}
openlog.Info(fmt.Sprintf("Configuration files: %s", strings.Join(files, ", ")))
return fs, nil
}
// Init create a Archaius config singleton
func Init(opts ...Option) error {
if running {
openlog.Warn("can not init archaius again, call Clean first")
return nil
}
var err error
o := &Options{}
for _, opt := range opts {
opt(o)
}
manager = source.NewManager()
fs, err := initFileSource(o)
if err != nil {
return err
}
err = manager.AddSource(fs)
if err != nil {
return err
}
if o.RemoteSource != "" {
if err = EnableRemoteSource(o.RemoteSource, o.RemoteInfo); err != nil {
return err
}
}
// build-in config sources
if o.UseMemSource {
ms := mem.NewMemoryConfigurationSource()
if err = manager.AddSource(ms); err != nil {
return err
}
}
if o.UseCLISource {
cmdSource := cli.NewCommandlineConfigSource()
if err = manager.AddSource(cmdSource); err != nil {
return err
}
}
if o.UseENVSource {
envSource := env.NewEnvConfigurationSource()
if err = manager.AddSource(envSource); err != nil {
return err
}
}
openlog.Info("archaius init success")
running = true
return nil
}
//CustomInit accept a list of config source, add it into archaius runtime.
//it almost like Init(), but you can fully control config sources you inject to archaius
func CustomInit(sources ...source.ConfigSource) error {
if running {
openlog.Warn("can not init archaius again, call Clean first")
return nil
}
var err error
manager = source.NewManager()
for _, s := range sources {
err = manager.AddSource(s)
if err != nil {
return err
}
}
running = true
return err
}
//EnableRemoteSource create a remote source singleton
//A config center source pull remote config server key values into local memory
//so that you can use GetXXX to get value easily
func EnableRemoteSource(remoteSource string, ci *RemoteInfo) error {
if ci == nil {
return errors.New("RemoteInfo can not be empty")
}
if configServerRunning {
openlog.Warn("can not init config server again, call Clean first")
return nil
}
f, ok := newFuncMap[remoteSource]
if !ok {
return errors.New("don not support remote source: " + remoteSource)
}
s, err := f(ci)
if err != nil {
return err
}
err = manager.AddSource(s)
if err != nil {
return err
}
configServerRunning = true
return nil
}
// Get is for to get the value of configuration key
func Get(key string) interface{} {
return manager.GetConfig(key)
}
//GetValue return interface
func GetValue(key string) cast.Value {
var confValue cast.Value
val := manager.GetConfig(key)
if val == nil {
confValue = cast.NewValue(nil, source.ErrKeyNotExist)
} else {
confValue = cast.NewValue(val, nil)
}
return confValue
}
// Exist check the configuration key existence
func Exist(key string) bool {
return manager.IsKeyExist(key)
}
// UnmarshalConfig unmarshal the config of receiving object
func UnmarshalConfig(obj interface{}) error {
return manager.Unmarshal(obj)
}
// WriteTo write the config to writer by yaml
func WriteTo(w io.Writer) error {
return manager.Marshal(w)
}
// GetBool is gives the key value in the form of bool
func GetBool(key string, defaultValue bool) bool {
b, err := GetValue(key).ToBool()
if err != nil {
return defaultValue
}
return b
}
// GetFloat64 gives the key value in the form of float64
func GetFloat64(key string, defaultValue float64) float64 {
result, err := GetValue(key).ToFloat64()
if err != nil {
return defaultValue
}
return result
}
// GetInt gives the key value in the form of GetInt
func GetInt(key string, defaultValue int) int {
result, err := GetValue(key).ToInt()
if err != nil {
return defaultValue
}
return result
}
// GetInt64 gives the key value in the form of int64
func GetInt64(key string, defaultValue int64) int64 {
result, err := GetValue(key).ToInt64()
if err != nil {
return defaultValue
}
return result
}
// GetString gives the key value in the form of GetString
func GetString(key string, defaultValue string) string {
result, err := GetValue(key).ToString()
if err != nil {
return defaultValue
}
return result
}
// GetConfigs gives the information about all configurations
func GetConfigs() map[string]interface{} {
return manager.Configs()
}
// GetConfigsWithSourceNames gives the information about all configurations
// each config key, along with its source will be returned
// the returned map will be like:
// map[string]interface{}{
// key string: map[string]interface{"value": value, "sourceName": sourceName}
// }
func GetConfigsWithSourceNames() map[string]interface{} {
return manager.ConfigsWithSourceNames()
}
// AddDimensionInfo adds a NewDimensionInfo of which configurations needs to be taken
func AddDimensionInfo(labels map[string]string) (map[string]string, error) {
config, err := manager.AddDimensionInfo(labels)
return config, err
}
//RegisterListener to Register all listener for different key changes, each key could be a regular expression
func RegisterListener(listenerObj event.Listener, key ...string) error {
return manager.RegisterListener(listenerObj, key...)
}
// UnRegisterListener is to remove the listener
func UnRegisterListener(listenerObj event.Listener, key ...string) error {
return manager.UnRegisterListener(listenerObj, key...)
}
//RegisterModuleListener to Register all moduleListener for different key(prefix) changes
func RegisterModuleListener(listenerObj event.ModuleListener, prefix ...string) error {
return manager.RegisterModuleListener(listenerObj, prefix...)
}
// UnRegisterModuleListener is to remove the moduleListener
func UnRegisterModuleListener(listenerObj event.ModuleListener, prefix ...string) error {
return manager.UnRegisterModuleListener(listenerObj, prefix...)
}
// AddFile is for to add the configuration files at runtime
func AddFile(file string, opts ...FileOption) error {
o := &FileOptions{}
for _, f := range opts {
f(o)
}
if err := fs.AddFile(file, filesource.DefaultFilePriority, o.Handler); err != nil {
return err
}
return manager.Refresh(fs.GetSourceName())
}
//Set add the configuration key, value pairs into memory source at runtime
//it is just affect the local configs
func Set(key string, value interface{}) error {
return manager.Set(key, value)
}
// Delete delete the configuration key, value pairs in memory source
func Delete(key string) error {
return manager.Delete(key)
}
//AddSource add source implementation
func AddSource(source source.ConfigSource) error {
return manager.AddSource(source)
}
//Clean will call config manager CleanUp Method,
//it deletes all sources which means all of key value is deleted.
//after you call Clean, you can init archaius again
func Clean() error {
manager.Cleanup()
running = false
return nil
}