88 "strings"
99
1010 "github.com/docker/app/internal/yaml"
11+ yml "gopkg.in/yaml.v2"
1112)
1213
1314const (
@@ -295,7 +296,7 @@ func recurseList(input []interface{}, settings map[string]interface{}, flattened
295296 var res []interface {}
296297 for _ , v := range input {
297298 switch vv := v .(type ) {
298- case map [ interface {}] interface {} :
299+ case yml. MapSlice :
299300 newv , err := recurse (vv , settings , flattened , o )
300301 if err != nil {
301302 return nil , err
@@ -337,15 +338,17 @@ func recurseList(input []interface{}, settings map[string]interface{}, flattened
337338
338339// FIXME complexity on this is 47… get it lower than 16
339340// nolint: gocyclo
340- func recurse (input map [interface {}]interface {}, settings map [string ]interface {}, flattened map [string ]interface {}, o options ) (map [interface {}]interface {}, error ) {
341- res := make (map [interface {}]interface {})
342- for k , v := range input {
341+ func recurse (input yml.MapSlice , settings map [string ]interface {}, flattened map [string ]interface {}, o options ) (yml.MapSlice , error ) {
342+ res := yml.MapSlice {}
343+ for _ , kvp := range input {
344+ k := kvp .Key
345+ v := kvp .Value
343346 rk := k
344347 kstr , isks := k .(string )
345348 if isks {
346349 trimed := strings .TrimLeft (kstr , " " )
347350 if strings .HasPrefix (trimed , "@switch " ) {
348- mii , ok := v .(map [ interface {}] interface {} )
351+ mii , ok := v .(yml. MapSlice )
349352 if ! ok {
350353 return nil , fmt .Errorf ("@switch value must be a mapping" )
351354 }
@@ -355,7 +358,9 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
355358 }
356359 var defaultValue interface {}
357360 hit := false
358- for sk , sv := range mii {
361+ for _ , sval := range mii {
362+ sk := sval .Key
363+ sv := sval .Value
359364 ssk , ok := sk .(string )
360365 if ! ok {
361366 return nil , fmt .Errorf ("@switch entry key must be a string" )
@@ -365,28 +370,28 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
365370 }
366371 if ssk == key {
367372 hit = true
368- svv , ok := sv .(map [ interface {}] interface {} )
373+ svv , ok := sv .(yml. MapSlice )
369374 if ! ok {
370375 return nil , fmt .Errorf ("@switch entry must be a mapping" )
371376 }
372- for valk , valv := range svv {
373- res [ valk ] = valv
377+ for _ , vval := range svv {
378+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
374379 }
375380 }
376381 }
377382 if ! hit && defaultValue != nil {
378- svv , ok := defaultValue .(map [ interface {}] interface {} )
383+ svv , ok := defaultValue .(yml. MapSlice )
379384 if ! ok {
380385 return nil , fmt .Errorf ("@switch entry must be a mapping" )
381386 }
382- for valk , valv := range svv {
383- res [ valk ] = valv
387+ for _ , vval := range svv {
388+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
384389 }
385390 }
386391 continue
387392 }
388393 if strings .HasPrefix (trimed , "@for " ) {
389- mii , ok := v .(map [ interface {}] interface {} )
394+ mii , ok := v .(yml. MapSlice )
390395 if ! ok {
391396 return nil , fmt .Errorf ("@for value must be a mapping" )
392397 }
@@ -416,8 +421,8 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
416421 if err != nil {
417422 return nil , err
418423 }
419- for valk , valv := range val {
420- res [ valk ] = valv
424+ for _ , vval := range val {
425+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
421426 }
422427 }
423428 } else {
@@ -429,8 +434,8 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
429434 if err != nil {
430435 return nil , err
431436 }
432- for valk , valv := range val {
433- res [ valk ] = valv
437+ for _ , vval := range val {
438+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
434439 }
435440 }
436441 }
@@ -441,7 +446,7 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
441446 if err != nil {
442447 return nil , err
443448 }
444- mii , ok := v .(map [ interface {}] interface {} )
449+ mii , ok := v .(yml. MapSlice )
445450 if ! ok {
446451 return nil , fmt .Errorf ("@if value must be a mapping" )
447452 }
@@ -450,20 +455,26 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
450455 if err != nil {
451456 return nil , err
452457 }
453- for valk , valv := range val {
454- if valk != "@else" {
455- res [ valk ] = valv
458+ for _ , vval := range val {
459+ if vval . Key != "@else" {
460+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
456461 }
457462 }
458463 } else {
459- elseClause , ok := mii ["@else" ]
460- if ok {
461- elseDict , ok := elseClause .(map [interface {}]interface {})
464+ var elseClause interface {}
465+ for _ , miiv := range mii {
466+ if miiv .Key == "@else" {
467+ elseClause = miiv .Value
468+ break
469+ }
470+ }
471+ if elseClause != nil {
472+ elseDict , ok := elseClause .(yml.MapSlice )
462473 if ! ok {
463474 return nil , fmt .Errorf ("@else value must be a mapping" )
464475 }
465- for valk , valv := range elseDict {
466- res [ valk ] = valv
476+ for _ , vval := range elseDict {
477+ res = append ( res , yml. MapItem { Key : vval . Key , Value : vval . Value })
467478 }
468479 }
469480 }
@@ -476,26 +487,26 @@ func recurse(input map[interface{}]interface{}, settings map[string]interface{},
476487 rk = rstr
477488 }
478489 switch vv := v .(type ) {
479- case map [ interface {}] interface {} :
490+ case yml. MapSlice :
480491 newv , err := recurse (vv , settings , flattened , o )
481492 if err != nil {
482493 return nil , err
483494 }
484- res [ rk ] = newv
495+ res = append ( res , yml. MapItem { Key : rk , Value : newv })
485496 case []interface {}:
486497 newv , err := recurseList (vv , settings , flattened , o )
487498 if err != nil {
488499 return nil , err
489500 }
490- res [ rk ] = newv
501+ res = append ( res , yml. MapItem { Key : rk , Value : newv })
491502 case string :
492503 vvv , err := eval (vv , flattened , o )
493504 if err != nil {
494505 return nil , err
495506 }
496- res [ rk ] = vvv
507+ res = append ( res , yml. MapItem { Key : rk , Value : vvv })
497508 default :
498- res [ rk ] = v
509+ res = append ( res , yml. MapItem { Key : rk , Value : v })
499510 }
500511 }
501512 return res , nil
@@ -521,23 +532,55 @@ func ProcessStrings(input, settings string) (string, error) {
521532 return string (sres ), nil
522533}
523534
524- // Process resolves input templated yaml using values given in settings
525- func Process (inputString string , settings map [string ]interface {}, opts ... string ) (map [ interface {}] interface {} , error ) {
535+ // ProcessWithOrder resolves input templated yaml using values given in settings, returning a MapSlice with order preserved
536+ func ProcessWithOrder (inputString string , settings map [string ]interface {}, opts ... string ) (yml. MapSlice , error ) {
526537 var o options
527538 for _ , v := range opts {
528539 switch v {
529540 case OptionErrOnMissingKey :
530541 o .errOnMissingKey = true
531542 default :
532- return nil , fmt .Errorf ("unknown option '%s' " , v )
543+ return nil , fmt .Errorf ("unknown option %q " , v )
533544 }
534545 }
535- input := make ( map [ interface {}] interface {})
536- err := yaml .Unmarshal ([]byte (inputString ), input )
546+ var input yml. MapSlice
547+ err := yaml .Unmarshal ([]byte (inputString ), & input )
537548 if err != nil {
538549 return nil , err
539550 }
540551 flattened := make (map [string ]interface {})
541552 flatten (settings , flattened , "" )
542553 return recurse (input , settings , flattened , o )
543554}
555+
556+ // Process resolves input templated yaml using values given in settings, returning a map
557+ func Process (inputString string , settings map [string ]interface {}, opts ... string ) (map [interface {}]interface {}, error ) {
558+ mapSlice , err := ProcessWithOrder (inputString , settings , opts ... )
559+ if err != nil {
560+ return nil , err
561+ }
562+
563+ res , err := convert (mapSlice )
564+ if err != nil {
565+ return nil , err
566+ }
567+ return res , nil
568+ }
569+
570+ func convert (mapSlice yml.MapSlice ) (map [interface {}]interface {}, error ) {
571+ res := make (map [interface {}]interface {})
572+ for _ , kv := range mapSlice {
573+ v := kv .Value
574+ castValue , ok := v .(yml.MapSlice )
575+ if ! ok {
576+ res [kv .Key ] = kv .Value
577+ } else {
578+ recursed , err := convert (castValue )
579+ if err != nil {
580+ return nil , err
581+ }
582+ res [kv .Key ] = recursed
583+ }
584+ }
585+ return res , nil
586+ }
0 commit comments