introduce `--exit-code-from`

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2021-02-09 19:17:12 +01:00
parent a4b003ecfa
commit 752edcce65
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
3 changed files with 24 additions and 7 deletions

View File

@ -76,7 +76,7 @@ func runStart(ctx context.Context, opts startOptions, services []string) error {
return err
}
_, err = printer.run(ctx, false, func() error {
_, err = printer.run(ctx, false, "", func() error {
ctx := context.Background()
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
return "", c.ComposeService().Stop(ctx, project)

View File

@ -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)
}
}
}
}

View File

@ -56,6 +56,7 @@ func (s *composeService) Start(ctx context.Context, project *types.Project, opti
options.Attach <- compose.ContainerEvent{
Type: compose.ContainerEventExit,
Source: getCanonicalContainerName(c),
Service: c.Labels[serviceLabel],
ExitCode: int(status.StatusCode),
}
case err := <-errC: