@@ -358,140 +358,148 @@ func loadYamlModel(ctx context.Context, config types.ConfigDetails, opts *Option
358
358
dict = map [string ]interface {}{}
359
359
err error
360
360
)
361
+ workingDir , environment := config .WorkingDir , config .Environment
362
+
361
363
for _ , file := range config .ConfigFiles {
362
- fctx := context .WithValue (ctx , consts.ComposeFileKey {}, file .Filename )
363
- if file .Content == nil && file .Config == nil {
364
- content , err := os .ReadFile (file .Filename )
365
- if err != nil {
366
- return nil , err
367
- }
368
- file .Content = content
364
+ dict , _ , err = loadYamlFile (ctx , file , opts , workingDir , environment , ct , dict , included )
365
+ if err != nil {
366
+ return nil , err
369
367
}
368
+ }
370
369
371
- processRawYaml := func (raw interface {}, processors ... PostProcessor ) error {
372
- converted , err := convertToStringKeysRecursive (raw , "" )
373
- if err != nil {
374
- return err
375
- }
376
- cfg , ok := converted .(map [string ]interface {})
377
- if ! ok {
378
- return errors .New ("Top-level object must be a mapping" )
379
- }
370
+ if ! opts .SkipDefaultValues {
371
+ dict , err = transform .SetDefaultValues (dict )
372
+ if err != nil {
373
+ return nil , err
374
+ }
375
+ }
380
376
381
- if opts .Interpolate != nil && ! opts .SkipInterpolation {
382
- cfg , err = interp .Interpolate (cfg , * opts .Interpolate )
383
- if err != nil {
384
- return err
385
- }
386
- }
377
+ if ! opts .SkipValidation {
378
+ if err := validation .Validate (dict ); err != nil {
379
+ return nil , err
380
+ }
381
+ }
387
382
388
- fixEmptyNotNull (cfg )
383
+ if opts .ResolvePaths {
384
+ var remotes []paths.RemoteResource
385
+ for _ , loader := range opts .RemoteResourceLoaders () {
386
+ remotes = append (remotes , loader .Accept )
387
+ }
388
+ err = paths .ResolveRelativePaths (dict , config .WorkingDir , remotes )
389
+ if err != nil {
390
+ return nil , err
391
+ }
392
+ }
393
+ resolveServicesEnvironment (dict , config )
389
394
390
- if ! opts .SkipExtends {
391
- err = ApplyExtends (fctx , cfg , opts , ct , processors ... )
392
- if err != nil {
393
- return err
394
- }
395
- }
395
+ return dict , nil
396
+ }
396
397
397
- for _ , processor := range processors {
398
- if err := processor .Apply (dict ); err != nil {
399
- return err
400
- }
401
- }
398
+ func loadYamlFile (ctx context.Context , file types.ConfigFile , opts * Options , workingDir string , environment types.Mapping , ct * cycleTracker , dict map [string ]interface {}, included []string ) (map [string ]interface {}, PostProcessor , error ) {
399
+ ctx = context .WithValue (ctx , consts.ComposeFileKey {}, file .Filename )
400
+ if file .Content == nil && file .Config == nil {
401
+ content , err := os .ReadFile (file .Filename )
402
+ if err != nil {
403
+ return nil , nil , err
404
+ }
405
+ file .Content = content
406
+ }
402
407
403
- if ! opts .SkipInclude {
404
- included = append (included , config .ConfigFiles [0 ].Filename )
405
- err = ApplyInclude (ctx , config , cfg , opts , included )
406
- if err != nil {
407
- return err
408
- }
409
- }
408
+ processRawYaml := func (raw interface {}, processors ... PostProcessor ) error {
409
+ converted , err := convertToStringKeysRecursive (raw , "" )
410
+ if err != nil {
411
+ return err
412
+ }
413
+ cfg , ok := converted .(map [string ]interface {})
414
+ if ! ok {
415
+ return errors .New ("Top-level object must be a mapping" )
416
+ }
410
417
411
- dict , err = override .Merge (dict , cfg )
418
+ if opts .Interpolate != nil && ! opts .SkipInterpolation {
419
+ cfg , err = interp .Interpolate (cfg , * opts .Interpolate )
412
420
if err != nil {
413
421
return err
414
422
}
423
+ }
415
424
416
- dict , err = override .EnforceUnicity (dict )
425
+ fixEmptyNotNull (cfg )
426
+
427
+ if ! opts .SkipExtends {
428
+ err = ApplyExtends (ctx , cfg , opts , ct , processors ... )
417
429
if err != nil {
418
430
return err
419
431
}
432
+ }
420
433
421
- if ! opts .SkipValidation {
422
- if err := schema .Validate (dict ); err != nil {
423
- return fmt .Errorf ("validating %s: %w" , file .Filename , err )
424
- }
425
- if _ , ok := dict ["version" ]; ok {
426
- opts .warnObsoleteVersion (file .Filename )
427
- delete (dict , "version" )
428
- }
434
+ for _ , processor := range processors {
435
+ if err := processor .Apply (dict ); err != nil {
436
+ return err
437
+ }
438
+ }
439
+
440
+ if ! opts .SkipInclude {
441
+ included = append (included , file .Filename )
442
+ err = ApplyInclude (ctx , workingDir , environment , cfg , opts , included )
443
+ if err != nil {
444
+ return err
429
445
}
446
+ }
430
447
448
+ dict , err = override .Merge (dict , cfg )
449
+ if err != nil {
431
450
return err
432
451
}
433
452
434
- if file .Config == nil {
435
- r := bytes .NewReader (file .Content )
436
- decoder := yaml .NewDecoder (r )
437
- for {
438
- var raw interface {}
439
- processor := & ResetProcessor {target : & raw }
440
- err := decoder .Decode (processor )
441
- if err != nil && errors .Is (err , io .EOF ) {
442
- break
443
- }
444
- if err != nil {
445
- return nil , err
446
- }
447
- if err := processRawYaml (raw , processor ); err != nil {
448
- return nil , err
449
- }
453
+ dict , err = override .EnforceUnicity (dict )
454
+ if err != nil {
455
+ return err
456
+ }
457
+
458
+ if ! opts .SkipValidation {
459
+ if err := schema .Validate (dict ); err != nil {
460
+ return fmt .Errorf ("validating %s: %w" , file .Filename , err )
450
461
}
451
- } else {
452
- if err := processRawYaml (file .Config ); err != nil {
453
- return nil , err
462
+ if _ , ok := dict [ "version" ]; ok {
463
+ opts . warnObsoleteVersion (file .Filename )
464
+ delete ( dict , "version" )
454
465
}
455
466
}
456
- }
457
-
458
- dict , err = transform .Canonical (dict , opts .SkipInterpolation )
459
- if err != nil {
460
- return nil , err
461
- }
462
467
463
- // Canonical transformation can reveal duplicates, typically as ports can be a range and conflict with an override
464
- dict , err = override .EnforceUnicity (dict )
465
- if err != nil {
466
- return nil , err
467
- }
468
-
469
- if ! opts .SkipDefaultValues {
470
- dict , err = transform .SetDefaultValues (dict )
468
+ dict , err = transform .Canonical (dict , opts .SkipInterpolation )
471
469
if err != nil {
472
- return nil , err
470
+ return err
473
471
}
474
- }
475
472
476
- if ! opts .SkipValidation {
477
- if err := validation .Validate (dict ); err != nil {
478
- return nil , err
479
- }
473
+ // Canonical transformation can reveal duplicates, typically as ports can be a range and conflict with an override
474
+ dict , err = override .EnforceUnicity (dict )
475
+ return err
480
476
}
481
477
482
- if opts .ResolvePaths {
483
- var remotes []paths.RemoteResource
484
- for _ , loader := range opts .RemoteResourceLoaders () {
485
- remotes = append (remotes , loader .Accept )
478
+ var processor PostProcessor
479
+ if file .Config == nil {
480
+ r := bytes .NewReader (file .Content )
481
+ decoder := yaml .NewDecoder (r )
482
+ for {
483
+ var raw interface {}
484
+ reset := & ResetProcessor {target : & raw }
485
+ err := decoder .Decode (reset )
486
+ if err != nil && errors .Is (err , io .EOF ) {
487
+ break
488
+ }
489
+ if err != nil {
490
+ return nil , nil , err
491
+ }
492
+ processor = reset
493
+ if err := processRawYaml (raw , processor ); err != nil {
494
+ return nil , nil , err
495
+ }
486
496
}
487
- err = paths . ResolveRelativePaths ( dict , config . WorkingDir , remotes )
488
- if err != nil {
489
- return nil , err
497
+ } else {
498
+ if err := processRawYaml ( file . Config ); err != nil {
499
+ return nil , nil , err
490
500
}
491
501
}
492
- resolveServicesEnvironment (dict , config )
493
-
494
- return dict , nil
502
+ return dict , processor , nil
495
503
}
496
504
497
505
func load (ctx context.Context , configDetails types.ConfigDetails , opts * Options , loaded []string ) (map [string ]interface {}, error ) {
0 commit comments