@@ -36,6 +36,7 @@ import (
3636 "github.com/compose-spec/compose-go/types"
3737 "github.com/sirupsen/logrus"
3838 "github.com/spf13/cobra"
39+ "golang.org/x/sync/errgroup"
3940)
4041
4142// composeOptions hold options common to `up` and `run` to run compose project
@@ -57,6 +58,8 @@ type upOptions struct {
5758 cascadeStop bool
5859 exitCodeFrom string
5960 scale []string
61+ noColor bool
62+ noPrefix bool
6063}
6164
6265func (o upOptions ) recreateStrategy () string {
@@ -102,6 +105,8 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
102105 flags .BoolVar (& opts .Build , "build" , false , "Build images before starting containers." )
103106 flags .BoolVar (& opts .removeOrphans , "remove-orphans" , false , "Remove containers for services not defined in the Compose file." )
104107 flags .StringArrayVar (& opts .scale , "scale" , []string {}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present." )
108+ flags .BoolVar (& opts .noColor , "no-color" , false , "Produce monochrome output." )
109+ flags .BoolVar (& opts .noPrefix , "no-log-prefix" , false , "Don't print prefix in logs." )
105110
106111 switch contextType {
107112 case store .AciContextType :
@@ -199,6 +204,16 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
199204 stopFunc () // nolint:errcheck
200205 }()
201206
207+ consumer := formatter .NewLogConsumer (ctx , os .Stdout , ! opts .noColor , ! opts .noPrefix )
208+
209+ var exitCode int
210+ eg , ctx := errgroup .WithContext (ctx )
211+ eg .Go (func () error {
212+ code , err := printer .run (ctx , opts .cascadeStop , opts .exitCodeFrom , consumer , stopFunc )
213+ exitCode = code
214+ return err
215+ })
216+
202217 err = c .ComposeService ().Start (ctx , project , compose.StartOptions {
203218 Attach : func (event compose.ContainerEvent ) {
204219 queue <- event
@@ -208,7 +223,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
208223 return err
209224 }
210225
211- exitCode , err := printer . run ( ctx , opts . cascadeStop , opts . exitCodeFrom , stopFunc )
226+ err = eg . Wait ( )
212227 if exitCode != 0 {
213228 return cmd.ExitCodeError {ExitCode : exitCode }
214229 }
@@ -298,27 +313,37 @@ type printer struct {
298313 queue chan compose.ContainerEvent
299314}
300315
301- func (p printer ) run (ctx context.Context , cascadeStop bool , exitCodeFrom string , stopFn func () error ) (int , error ) { //nolint:unparam
302- consumer := formatter .NewLogConsumer (ctx , os .Stdout )
316+ func (p printer ) run (ctx context.Context , cascadeStop bool , exitCodeFrom string , consumer compose.LogConsumer , stopFn func () error ) (int , error ) { //nolint:unparam
303317 var aborting bool
318+ var count int
304319 for {
305320 event := <- p .queue
306321 switch event .Type {
322+ case compose .ContainerEventAttach :
323+ consumer .Register (event .Service , event .Source )
324+ count ++
307325 case compose .ContainerEventExit :
308326 if ! aborting {
309327 consumer .Status (event .Service , event .Source , fmt .Sprintf ("exited with code %d" , event .ExitCode ))
310328 }
311- if cascadeStop && ! aborting {
312- aborting = true
313- fmt .Println ("Aborting on container exit..." )
314- err := stopFn ()
315- if err != nil {
316- return 0 , err
329+ if cascadeStop {
330+ if ! aborting {
331+ aborting = true
332+ fmt .Println ("Aborting on container exit..." )
333+ err := stopFn ()
334+ if err != nil {
335+ return 0 , err
336+ }
337+ }
338+ if exitCodeFrom == "" || exitCodeFrom == event .Service {
339+ logrus .Error (event .ExitCode )
340+ return event .ExitCode , nil
317341 }
318342 }
319- if exitCodeFrom == "" || exitCodeFrom == event .Service {
320- logrus .Error (event .ExitCode )
321- return event .ExitCode , nil
343+ count --
344+ if count == 0 {
345+ // Last container terminated, done
346+ return 0 , nil
322347 }
323348 case compose .ContainerEventLog :
324349 if ! aborting {
0 commit comments