@@ -244,8 +244,9 @@ func GetKnownKeys() []string {
244
244
245
245
// configSection is the main config structure passed to plugins, and used for root to wrap viper
246
246
type configSection struct {
247
- prefix string
248
- parent sectionParent
247
+ prefix string
248
+ parent sectionParent
249
+ arrayEntry bool
249
250
}
250
251
251
252
// configArray is a point in the config that supports an array
@@ -301,12 +302,21 @@ func (c *configArray) SubSection(name string) Section {
301
302
return cp
302
303
}
303
304
304
- func findArrayParent (c * configSection ) * configArray {
305
- switch p := c .parent .(type ) {
305
+ // If any parent is an array entry, retrieve fully-qualified defaults via its array parent
306
+ func getArrayEntryDefaults (p sectionParent ) map [string ][]interface {} {
307
+ switch c := p .(type ) {
306
308
case * configArray :
307
- return p
309
+ return getArrayEntryDefaults ( c . parent )
308
310
case * configSection :
309
- return findArrayParent (p )
311
+ if ! c .arrayEntry {
312
+ return getArrayEntryDefaults (c .parent )
313
+ }
314
+ arrayParent := c .parent .(* configArray )
315
+ defaults := make (map [string ][]interface {})
316
+ for k , v := range arrayParent .defaults {
317
+ defaults [c .prefix + "." + k ] = v
318
+ }
319
+ return defaults
310
320
default :
311
321
return nil
312
322
}
@@ -318,14 +328,12 @@ func (c *configSection) SubArray(name string) ArraySection {
318
328
parent : c ,
319
329
defaults : make (map [string ][]interface {}),
320
330
}
321
- // If a parent array already has defaults for this subtree, copy them here (for later use in ArrayEntry)
322
- parentArray := findArrayParent (c )
323
- if parentArray != nil {
324
- prefix := a .base + "[]."
325
- for key , val := range parentArray .defaults {
326
- if strings .HasPrefix (key , prefix ) {
327
- a .defaults [strings .TrimPrefix (key , prefix )] = val
328
- }
331
+ // Get defaults from any enclosing array entry, and copy over any applicable to this subtree
332
+ // This is necessary to propagate known keys for arrays within arrays
333
+ prefix := a .base + "[]."
334
+ for key , val := range getArrayEntryDefaults (c ) {
335
+ if strings .HasPrefix (key , prefix ) {
336
+ a .defaults [strings .TrimPrefix (key , prefix )] = val
329
337
}
330
338
}
331
339
return a
@@ -343,8 +351,9 @@ func (c *configArray) ArraySize() int {
343
351
// ArrayEntry must only be called after the config has been loaded
344
352
func (c * configArray ) ArrayEntry (i int ) Section {
345
353
cp := & configSection {
346
- prefix : keyName (c .base , fmt .Sprintf ("%d" , i )),
347
- parent : c ,
354
+ prefix : keyName (c .base , fmt .Sprintf ("%d" , i )),
355
+ parent : c ,
356
+ arrayEntry : true ,
348
357
}
349
358
for knownKey , defValue := range c .defaults {
350
359
cp .AddKnownKey (knownKey , defValue ... )
@@ -391,7 +400,9 @@ func (c *configSection) AddKnownKey(k string, defValue ...interface{}) {
391
400
func (c * configArray ) AddChild (k string , defValue ... interface {}) {
392
401
// When a child is added anywhere below this array, add it to the defaults map
393
402
prefix := c .base + "[]."
394
- c .defaults [strings .TrimPrefix (k , prefix )] = defValue
403
+ if strings .HasPrefix (k , prefix ) {
404
+ c .defaults [strings .TrimPrefix (k , prefix )] = defValue
405
+ }
395
406
396
407
// Also bubble it upwards
397
408
if c .parent != nil {
0 commit comments