@@ -46,151 +46,230 @@ func New(pp ...Param) *Seeder {
46
46
return & Seeder {getters : gg }
47
47
}
48
48
49
+ type fieldMap map [* config.Field ]bool
50
+
51
+ type flagInfo struct {
52
+ key string
53
+ field * config.Field
54
+ value * string
55
+ }
56
+
49
57
// Seed the provided config with values for their sources.
50
58
func (s * Seeder ) Seed (cfg * config.Config ) error {
51
- seedMap := make (map [ * config. Field ] bool , len (cfg .Fields ))
59
+ seeded := make (fieldMap , len (cfg .Fields ))
52
60
flagSet := flag .NewFlagSet ("Harvester flags" , flag .ContinueOnError )
53
- type flagInfo struct {
54
- key string
55
- field * config.Field
56
- value * string
57
- }
61
+
58
62
var flagInfos []* flagInfo
59
63
for _ , f := range cfg .Fields {
60
- seedMap [f ] = false
61
- ss := f .Sources ()
62
- val , ok := ss [config .SourceSeed ]
63
- if ok {
64
- err := f .Set (val , 0 )
65
- if err != nil {
66
- return err
67
- }
68
- slog .Debug ("seed applied" , "value" , f , "name" , f .Name ())
69
- seedMap [f ] = true
64
+ seeded [f ] = false
65
+
66
+ err := processSeedField (f , seeded )
67
+ if err != nil {
68
+ return err
70
69
}
71
- key , ok := ss [config .SourceEnv ]
72
- if ok { //nolint:nestif
73
- val , ok := os .LookupEnv (key )
74
- if ok {
75
- err := f .Set (val , 0 )
76
- if err != nil {
77
- return err
78
- }
79
- slog .Debug ("env var applied" , "value" , f , "name" , f .Name ())
80
- seedMap [f ] = true
81
- } else {
82
- if seedMap [f ] {
83
- slog .Debug ("env var did not exist" , "key" , key , "name" , f .Name ())
84
- } else {
85
- slog .Debug ("env var did not exist and no seed value provided" , "key" , key , "name" , f .Name ())
86
- }
87
- }
70
+
71
+ err = processEnvField (f , seeded )
72
+ if err != nil {
73
+ return err
88
74
}
89
- key , ok = ss [config .SourceFlag ]
75
+
76
+ fi , ok := processFlagField (f , flagSet )
90
77
if ok {
91
- var val string
92
- flagSet .StringVar (& val , key , "" , "" )
93
- flagInfos = append (flagInfos , & flagInfo {key , f , & val })
78
+ flagInfos = append (flagInfos , fi )
94
79
}
95
- key , ok = ss [config .SourceFile ]
96
- if ok {
97
- body , err := os .ReadFile (key )
98
- if err != nil {
99
- slog .Error ("failed to read file" , "file" , key , "name" , f .Name (), "err" , err )
100
- } else {
101
- err := f .Set (string (body ), 0 )
102
- if err != nil {
103
- return err
104
- }
105
-
106
- slog .Debug ("file based var applied" , "value" , f , "field" , f .Name ())
107
- seedMap [f ] = true
108
- }
80
+
81
+ err = processFileField (f , seeded )
82
+ if err != nil {
83
+ return err
109
84
}
110
- key , ok = ss [config .SourceConsul ]
111
- if ok {
112
- gtr , ok := s .getters [config .SourceConsul ]
113
- if ! ok {
114
- return errors .New ("consul getter required" )
115
- }
116
- value , version , err := gtr .Get (key )
117
- if err != nil {
118
- slog .Error ("failed to get consul" , "key" , key , "field" , f .Name (), "err" , err )
119
- continue
120
- }
121
- if value == nil {
122
- slog .Error ("consul key does not exist" , "key" , key , "field" , f .Name ())
123
- continue
124
- }
125
- err = f .Set (* value , version )
126
- if err != nil {
127
- return err
128
- }
129
- slog .Debug ("consul value applied" , "value" , f , "field" , f .Name ())
130
- seedMap [f ] = true
85
+
86
+ err = s .processConsulField (f , seeded )
87
+ if err != nil {
88
+ return err
131
89
}
132
90
133
- key , ok = ss [config .SourceRedis ]
134
- if ok {
135
- gtr , ok := s .getters [config .SourceRedis ]
136
- if ! ok {
137
- return errors .New ("redis getter required" )
138
- }
139
- value , version , err := gtr .Get (key )
140
- if err != nil {
141
- slog .Error ("failed to get redis" , "key" , key , "field" , f .Name (), "err" , err )
142
- continue
143
- }
144
- if value == nil {
145
- slog .Error ("redis key does not exist" , "key" , key , "field" , f .Name ())
146
- continue
147
- }
148
- err = f .Set (* value , version )
149
- if err != nil {
150
- return err
151
- }
152
- slog .Debug ("redis value applied" , "value" , f , "field" , f .Name ())
153
- seedMap [f ] = true
91
+ err = s .processRedisField (f , seeded )
92
+ if err != nil {
93
+ return err
154
94
}
155
95
}
156
96
157
- if len (flagInfos ) > 0 { //nolint:nestif
158
- if ! flagSet .Parsed () {
159
- // Set the flagSet output to something that will not be displayed, otherwise in case of an error
160
- // it will display the usage, which we don't want.
161
- flagSet .SetOutput (io .Discard )
162
-
163
- // Try to parse each flag independently so that if we encounter any unexpected flag (maybe used elsewhere),
164
- // the parsing won't stop, and we make sure we try to parse every flag passed when running the command.
165
- for _ , arg := range os .Args [1 :] {
166
- if err := flagSet .Parse ([]string {arg }); err != nil {
167
- // Simply log errors that can happen, such as parsing unexpected flags. We want this to be silent,
168
- // and we won't want to stop the execution.
169
- slog .Error ("could not parse flagSet" , "err" , err )
170
- }
97
+ err := processFlags (flagInfos , flagSet , seeded )
98
+ if err != nil {
99
+ return err
100
+ }
101
+
102
+ return evaluateSeedMap (seeded )
103
+ }
104
+
105
+ func processSeedField (f * config.Field , seedMap fieldMap ) error {
106
+ val , ok := f .Sources ()[config .SourceSeed ]
107
+ if ! ok {
108
+ return nil
109
+ }
110
+ err := f .Set (val , 0 )
111
+ if err != nil {
112
+ return err
113
+ }
114
+ slog .Debug ("seed applied" , "value" , f , "name" , f .Name ())
115
+ seedMap [f ] = true
116
+ return nil
117
+ }
118
+
119
+ func processEnvField (f * config.Field , seedMap fieldMap ) error {
120
+ key , ok := f .Sources ()[config .SourceEnv ]
121
+ if ! ok {
122
+ return nil
123
+ }
124
+ val , ok := os .LookupEnv (key )
125
+ if ! ok {
126
+ if seedMap [f ] {
127
+ slog .Debug ("env var did not exist" , "key" , key , "name" , f .Name ())
128
+ } else {
129
+ slog .Debug ("env var did not exist and no seed value provided" , "key" , key , "name" , f .Name ())
130
+ }
131
+ return nil
132
+ }
133
+
134
+ err := f .Set (val , 0 )
135
+ if err != nil {
136
+ return err
137
+ }
138
+ slog .Debug ("env var applied" , "value" , f , "name" , f .Name ())
139
+ seedMap [f ] = true
140
+ return nil
141
+ }
142
+
143
+ func processFileField (f * config.Field , seedMap fieldMap ) error {
144
+ key , ok := f .Sources ()[config .SourceFile ]
145
+ if ! ok {
146
+ return nil
147
+ }
148
+
149
+ body , err := os .ReadFile (key )
150
+ if err != nil {
151
+ slog .Error ("failed to read file" , "file" , key , "name" , f .Name (), "err" , err )
152
+ return nil
153
+ }
154
+
155
+ err = f .Set (string (body ), 0 )
156
+ if err != nil {
157
+ return err
158
+ }
159
+
160
+ slog .Debug ("file based var applied" , "value" , f , "field" , f .Name ())
161
+ seedMap [f ] = true
162
+ return nil
163
+ }
164
+
165
+ func (s * Seeder ) processConsulField (f * config.Field , seedMap fieldMap ) error {
166
+ key , ok := f .Sources ()[config .SourceConsul ]
167
+ if ! ok {
168
+ return nil
169
+ }
170
+ gtr , ok := s .getters [config .SourceConsul ]
171
+ if ! ok {
172
+ return errors .New ("consul getter required" )
173
+ }
174
+ value , version , err := gtr .Get (key )
175
+ if err != nil {
176
+ slog .Error ("failed to get consul" , "key" , key , "field" , f .Name (), "err" , err )
177
+ return nil
178
+ }
179
+ if value == nil {
180
+ slog .Error ("consul key does not exist" , "key" , key , "field" , f .Name ())
181
+ return nil
182
+ }
183
+ err = f .Set (* value , version )
184
+ if err != nil {
185
+ return err
186
+ }
187
+ slog .Debug ("consul value applied" , "value" , f , "field" , f .Name ())
188
+ seedMap [f ] = true
189
+ return nil
190
+ }
191
+
192
+ func (s * Seeder ) processRedisField (f * config.Field , seedMap fieldMap ) error {
193
+ key , ok := f .Sources ()[config .SourceRedis ]
194
+ if ! ok {
195
+ return nil
196
+ }
197
+ gtr , ok := s .getters [config .SourceRedis ]
198
+ if ! ok {
199
+ return errors .New ("redis getter required" )
200
+ }
201
+ value , version , err := gtr .Get (key )
202
+ if err != nil {
203
+ slog .Error ("failed to get redis" , "key" , key , "field" , f .Name (), "err" , err )
204
+ return nil
205
+ }
206
+ if value == nil {
207
+ slog .Error ("redis key does not exist" , "key" , key , "field" , f .Name ())
208
+ return nil
209
+ }
210
+ err = f .Set (* value , version )
211
+ if err != nil {
212
+ return err
213
+ }
214
+ slog .Debug ("redis value applied" , "value" , f , "field" , f .Name ())
215
+ seedMap [f ] = true
216
+ return nil
217
+ }
218
+
219
+ func processFlagField (f * config.Field , flagSet * flag.FlagSet ) (* flagInfo , bool ) {
220
+ key , ok := f .Sources ()[config .SourceFlag ]
221
+ if ! ok {
222
+ return nil , false
223
+ }
224
+ var val string
225
+ flagSet .StringVar (& val , key , "" , "" )
226
+ return & flagInfo {key , f , & val }, true
227
+ }
228
+
229
+ func processFlags (infos []* flagInfo , flagSet * flag.FlagSet , seedMap fieldMap ) error {
230
+ if len (infos ) == 0 {
231
+ return nil
232
+ }
233
+
234
+ if ! flagSet .Parsed () {
235
+ // Set the flagSet output to something that will not be displayed, otherwise in case of an error
236
+ // it will display the usage, which we don't want.
237
+ flagSet .SetOutput (io .Discard )
238
+
239
+ // Try to parse each flag independently so that if we encounter any unexpected flag (maybe used elsewhere),
240
+ // the parsing won't stop, and we make sure we try to parse every flag passed when running the command.
241
+ for _ , arg := range os .Args [1 :] {
242
+ if err := flagSet .Parse ([]string {arg }); err != nil {
243
+ // Simply log errors that can happen, such as parsing unexpected flags. We want this to be silent,
244
+ // and we won't want to stop the execution.
245
+ slog .Error ("could not parse flagSet" , "err" , err )
171
246
}
172
247
}
173
- for _ , flagInfo := range flagInfos {
174
- hasFlag := false
175
- flagSet .Visit (func (f * flag.Flag ) {
176
- if f .Name == flagInfo .key {
177
- hasFlag = true
178
- return
179
- }
180
- })
181
- if hasFlag && flagInfo .value != nil {
182
- err := flagInfo .field .Set (* flagInfo .value , 0 )
183
- if err != nil {
184
- return err
185
- }
186
- slog .Debug ("flag value applied" , "value" , flagInfo .field , "field" , flagInfo .field .Name ())
187
- seedMap [flagInfo .field ] = true
188
- } else {
189
- slog .Debug ("flag var did not exist" , "key" , flagInfo .key , "field" , flagInfo .field .Name ())
248
+ }
249
+
250
+ for _ , info := range infos {
251
+ hasFlag := false
252
+ flagSet .Visit (func (f * flag.Flag ) {
253
+ if f .Name == info .key {
254
+ hasFlag = true
255
+ return
190
256
}
257
+ })
258
+ if hasFlag && info .value != nil {
259
+ err := info .field .Set (* info .value , 0 )
260
+ if err != nil {
261
+ return err
262
+ }
263
+ slog .Debug ("flag value applied" , "value" , info .field , "field" , info .field .Name ())
264
+ seedMap [info .field ] = true
265
+ } else {
266
+ slog .Debug ("flag var did not exist" , "key" , info .key , "field" , info .field .Name ())
191
267
}
192
268
}
269
+ return nil
270
+ }
193
271
272
+ func evaluateSeedMap (seedMap fieldMap ) error {
194
273
sb := strings.Builder {}
195
274
for f , seeded := range seedMap {
196
275
if ! seeded {
0 commit comments