|
|
@@ -52,6 +52,7 @@ type upOptions struct {
|
|
|
noRecreate bool
|
|
|
noStart bool
|
|
|
cascadeStop bool
|
|
|
+ exitCodeFrom string
|
|
|
}
|
|
|
|
|
|
func (o upOptions) recreateStrategy() string {
|
|
|
@@ -76,6 +77,9 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
switch contextType {
|
|
|
case store.LocalContextType, store.DefaultContextType, store.EcsLocalSimulationContextType:
|
|
|
+ if opts.exitCodeFrom != "" {
|
|
|
+ opts.cascadeStop = true
|
|
|
+ }
|
|
|
if opts.cascadeStop && opts.Detach {
|
|
|
return fmt.Errorf("--abort-on-container-exit and --detach are incompatible")
|
|
|
}
|
|
|
@@ -102,6 +106,7 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
|
|
flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
|
|
|
flags.BoolVar(&opts.noStart, "no-start", false, "Don't start the services after creating them.")
|
|
|
flags.BoolVar(&opts.cascadeStop, "abort-on-container-exit", false, "Stops all containers if any container was stopped. Incompatible with -d")
|
|
|
+ flags.StringVar(&opts.exitCodeFrom, "exit-code-from", "", "Return the exit code of the selected service container. Implies --abort-on-container-exit")
|
|
|
}
|
|
|
|
|
|
return upCmd
|
|
|
@@ -179,7 +184,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
- _, err = printer.run(ctx, opts.cascadeStop, stopFunc)
|
|
|
+ _, err = printer.run(ctx, opts.cascadeStop, opts.exitCodeFrom, stopFunc)
|
|
|
// FIXME os.Exit
|
|
|
return err
|
|
|
}
|
|
|
@@ -229,21 +234,32 @@ type printer struct {
|
|
|
queue chan compose.ContainerEvent
|
|
|
}
|
|
|
|
|
|
-func (p printer) run(ctx context.Context, cascadeStop bool, stopFn func() error) (int, error) { //nolint:unparam
|
|
|
+func (p printer) run(ctx context.Context, cascadeStop bool, exitCodeFrom string, stopFn func() error) (int, error) { //nolint:unparam
|
|
|
consumer := formatter.NewLogConsumer(ctx, os.Stdout)
|
|
|
+ var aborting bool
|
|
|
for {
|
|
|
event := <-p.queue
|
|
|
switch event.Type {
|
|
|
case compose.ContainerEventExit:
|
|
|
- consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode))
|
|
|
- if cascadeStop {
|
|
|
+ if !aborting {
|
|
|
+ consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode))
|
|
|
+ }
|
|
|
+ if cascadeStop && !aborting {
|
|
|
+ aborting = true
|
|
|
fmt.Println("Aborting on container exit...")
|
|
|
err := stopFn()
|
|
|
+ if err != nil {
|
|
|
+ return 0, err
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if exitCodeFrom == "" || exitCodeFrom == event.Service {
|
|
|
logrus.Error(event.ExitCode)
|
|
|
- return event.ExitCode, err
|
|
|
+ return event.ExitCode, nil
|
|
|
}
|
|
|
case compose.ContainerEventLog:
|
|
|
- consumer.Log(event.Service, event.Source, event.Line)
|
|
|
+ if !aborting {
|
|
|
+ consumer.Log(event.Service, event.Source, event.Line)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|