-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgoconfiguration.go
More file actions
156 lines (137 loc) · 3.58 KB
/
goconfiguration.go
File metadata and controls
156 lines (137 loc) · 3.58 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
package configuration
import (
"errors"
"strings"
)
// Create a new config reader instance
// files - list of files to read configuration from
func NewConfigReader(files ...string) *configReader {
config := &configReader{
sources: []configSource{},
options: ConfigOptions{
RewriteValues: true,
Parsers: make(map[string]Parser),
},
data: configData{
currentLine: 0,
currentPos: 0,
currentFile: "",
initErrors: []string{},
},
}
for _, file := range files {
config.AddFile(file)
}
return config
}
// Add configuration file
// file - relative or absolute path to the file
// supported file types: json, ini, env
func (cr *configReader) AddFile(file string) *configReader {
fileType := cr.getFileType(file)
if fileType == ftUnknown {
cr.data.initErrors = append(cr.data.initErrors, unsupportedFileTypeError(file))
return cr
}
source := configSource{
value: file,
ft: fileType,
fromFile: true,
}
cr.sources = append(cr.sources, source)
return cr
}
// Use environment variables as a configuration source
func (cr *configReader) AddEnvironment() *configReader {
source := configSource{
value: "",
ft: ftEnvironment,
fromFile: false,
}
cr.sources = append(cr.sources, source)
return cr
}
// Add configuration as a string
// values - configuration string
// formatType - format of the configuration string
func (cr *configReader) AddString(values string, formatType formatType, name string) *configReader {
source := configSource{
name: name,
value: values,
ft: formatType,
fromFile: false,
}
cr.sources = append(cr.sources, source)
return cr
}
// Set configuration reader options
// options - configuration reader options
func (cr *configReader) WithOptions(options ConfigOptions) *configReader {
if options.Parsers == nil {
options.Parsers = make(map[string]Parser)
}
cr.options = options
return cr
}
// Set whether to rewrite values (not for slice values)
// rewrite - rewrite values or not
func (cr *configReader) RewriteValues(rewrite bool) *configReader {
cr.options.RewriteValues = rewrite
return cr
}
// Add custom parser for user types
// fieldName - field name
// parser - custom parser for user type
func (cr *configReader) WithParser(envName string, parser Parser) *configReader {
if cr.options.Parsers == nil {
cr.options.Parsers = make(map[string]Parser)
}
cr.options.Parsers[envName] = parser
return cr
}
// Ensure that there are no errors during configuration reading
// panic if there are errors
func (cr *configReader) EnsureHasNoErrors() *configReader {
if len(cr.data.initErrors) > 0 {
panic(strings.Join(cr.data.initErrors, "\n"))
}
return cr
}
// Get errors that occurred during preparation of the configuration reader
func (cr *configReader) GetErrors() []error {
if len(cr.data.initErrors) > 0 {
errs := make([]error, len(cr.data.initErrors))
for i, e := range cr.data.initErrors {
errs[i] = errors.New(e)
}
return errs
}
return nil
}
// Read configuration into the user config struct
// userConfig - pointer to the user config struct
func (cr *configReader) ReadConfig(userConfig interface{}) error {
si, err := cr.getStructInfo(userConfig, "", "")
if err != nil {
return err
}
it := intermediateTree{}
for i, source := range cr.sources {
var err error = nil
if source.ft == ftEnvironment {
cr.readEnvironment(it, si, i)
} else if source.fromFile {
err = cr.readConfigFile(source, it, si, i)
} else {
err = cr.readConfigString(source, it, si, i)
}
if err != nil {
return err
}
}
err = cr.setValues(it, si)
if err != nil {
return err
}
return nil
}