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 return err
} }
_, err = printer.run(ctx, false, func() error { _, err = printer.run(ctx, false, "", func() error {
ctx := context.Background() ctx := context.Background()
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) { _, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
return "", c.ComposeService().Stop(ctx, project) return "", c.ComposeService().Stop(ctx, project)

View File

@ -52,6 +52,7 @@ type upOptions struct {
noRecreate bool noRecreate bool
noStart bool noStart bool
cascadeStop bool cascadeStop bool
exitCodeFrom string
} }
func (o upOptions) recreateStrategy() 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 { RunE: func(cmd *cobra.Command, args []string) error {
switch contextType { switch contextType {
case store.LocalContextType, store.DefaultContextType, store.EcsLocalSimulationContextType: case store.LocalContextType, store.DefaultContextType, store.EcsLocalSimulationContextType:
if opts.exitCodeFrom != "" {
opts.cascadeStop = true
}
if opts.cascadeStop && opts.Detach { if opts.cascadeStop && opts.Detach {
return fmt.Errorf("--abort-on-container-exit and --detach are incompatible") 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.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.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.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 return upCmd
@ -179,7 +184,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
return err return err
} }
_, err = printer.run(ctx, opts.cascadeStop, stopFunc) _, err = printer.run(ctx, opts.cascadeStop, opts.exitCodeFrom, stopFunc)
// FIXME os.Exit // FIXME os.Exit
return err return err
} }
@ -229,21 +234,32 @@ type printer struct {
queue chan compose.ContainerEvent 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) consumer := formatter.NewLogConsumer(ctx, os.Stdout)
var aborting bool
for { for {
event := <-p.queue event := <-p.queue
switch event.Type { switch event.Type {
case compose.ContainerEventExit: case compose.ContainerEventExit:
if !aborting {
consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode)) consumer.Status(event.Service, event.Source, fmt.Sprintf("exited with code %d", event.ExitCode))
if cascadeStop { }
if cascadeStop && !aborting {
aborting = true
fmt.Println("Aborting on container exit...") fmt.Println("Aborting on container exit...")
err := stopFn() err := stopFn()
if err != nil {
return 0, err
}
}
if exitCodeFrom == "" || exitCodeFrom == event.Service {
logrus.Error(event.ExitCode) logrus.Error(event.ExitCode)
return event.ExitCode, err return event.ExitCode, nil
} }
case compose.ContainerEventLog: case compose.ContainerEventLog:
if !aborting {
consumer.Log(event.Service, event.Source, event.Line) 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{ options.Attach <- compose.ContainerEvent{
Type: compose.ContainerEventExit, Type: compose.ContainerEventExit,
Source: getCanonicalContainerName(c), Source: getCanonicalContainerName(c),
Service: c.Labels[serviceLabel],
ExitCode: int(status.StatusCode), ExitCode: int(status.StatusCode),
} }
case err := <-errC: case err := <-errC: