@@ -94,6 +94,29 @@ func NewLocalRunner(out *output, manifest *Manifest, overrides map[string]string
94
94
overrides [k ] = v
95
95
}
96
96
97
+ // Now, the override can either be one of two things (we are overloading the override map):
98
+ // - docker image: In that case, change the manifest and remove from override map
99
+ // - a path to an executable: In that case, we need to run it on the host machine
100
+ // and use the override map <- We only check this case, and if it is not a path, we assume
101
+ // it is a docker image. If it is not a docker image either, the error will be catched during the execution
102
+ for k , v := range overrides {
103
+ if _ , err := os .Stat (v ); err != nil {
104
+ // this is a path to an executable, remove it from the overrides since we
105
+ // assume it s a docker image and add it to manifest
106
+ parts := strings .Split (v , ":" )
107
+ if len (parts ) != 2 {
108
+ return nil , fmt .Errorf ("invalid override docker image %s, expected image:tag" , v )
109
+ }
110
+
111
+ srv := manifest .MustGetService (k )
112
+ srv .image = parts [0 ]
113
+ srv .tag = parts [1 ]
114
+
115
+ delete (overrides , k )
116
+ continue
117
+ }
118
+ }
119
+
97
120
tasks := map [string ]* task {}
98
121
for _ , svc := range manifest .services {
99
122
tasks [svc .Name ] = & task {
@@ -428,6 +451,27 @@ func (d *LocalRunner) applyTemplate(s *service) ([]string, map[string]string, er
428
451
return argsResult , envs , nil
429
452
}
430
453
454
+ func (d * LocalRunner ) validateImageExists (image string ) error {
455
+ // check locally
456
+ _ , err := d .client .ImageInspect (context .Background (), image )
457
+ if err == nil {
458
+ return nil
459
+ }
460
+ if ! client .IsErrNotFound (err ) {
461
+ return err
462
+ }
463
+
464
+ // check remotely
465
+ if _ , err = d .client .DistributionInspect (context .Background (), image , "" ); err == nil {
466
+ return nil
467
+ }
468
+ if ! client .IsErrNotFound (err ) {
469
+ return err
470
+ }
471
+
472
+ return fmt .Errorf ("image %s not found: %w" , image )
473
+ }
474
+
431
475
func (d * LocalRunner ) toDockerComposeService (s * service ) (map [string ]interface {}, error ) {
432
476
// apply the template again on the arguments to figure out the connections
433
477
// at this point all of them are valid, we just have to resolve them again. We assume for now
@@ -444,8 +488,14 @@ func (d *LocalRunner) toDockerComposeService(s *service) (map[string]interface{}
444
488
return nil , fmt .Errorf ("failed to get absolute path for output folder: %w" , err )
445
489
}
446
490
491
+ // Validate that the image exists
492
+ imageName := fmt .Sprintf ("%s:%s" , s .image , s .tag )
493
+ if err := d .validateImageExists (imageName ); err != nil {
494
+ return nil , fmt .Errorf ("failed to validate image %s: %w" , imageName , err )
495
+ }
496
+
447
497
service := map [string ]interface {}{
448
- "image" : fmt . Sprintf ( "%s:%s" , s . image , s . tag ) ,
498
+ "image" : imageName ,
449
499
"command" : args ,
450
500
// Add volume mount for the output directory
451
501
"volumes" : []string {
0 commit comments