diff --git a/cmd/compose/start.go b/cmd/compose/start.go index 45da76122..7b7a96265 100644 --- a/cmd/compose/start.go +++ b/cmd/compose/start.go @@ -51,5 +51,6 @@ func runStart(ctx context.Context, backend api.Service, opts startOptions, servi return backend.Start(ctx, name, api.StartOptions{ AttachTo: services, Project: project, + Services: services, }) } diff --git a/pkg/api/api.go b/pkg/api/api.go index 38af772ca..5e75cd571 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -129,6 +129,8 @@ type StartOptions struct { ExitCodeFrom string // Wait won't return until containers reached the running|healthy state Wait bool + // Services passed in the command line to be started + Services []string } // RestartOptions group options of the Restart API diff --git a/pkg/compose/dependencies.go b/pkg/compose/dependencies.go index ed33ec2b2..75e08914f 100644 --- a/pkg/compose/dependencies.go +++ b/pkg/compose/dependencies.go @@ -63,21 +63,24 @@ var ( ) // InDependencyOrder applies the function to the services of the project taking in account the dependency order -func InDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error) error { - return visit(ctx, project, upDirectionTraversalConfig, fn, ServiceStopped) +func InDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error, options ...func(*graphTraversalConfig)) error { + graph, err := NewGraph(project.Services, ServiceStopped) + if err != nil { + return err + } + return visit(ctx, graph, upDirectionTraversalConfig, fn) } // InReverseDependencyOrder applies the function to the services of the project in reverse order of dependencies func InReverseDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error) error { - return visit(ctx, project, downDirectionTraversalConfig, fn, ServiceStarted) -} - -func visit(ctx context.Context, project *types.Project, traversalConfig graphTraversalConfig, fn func(context.Context, string) error, initialStatus ServiceStatus) error { - g := NewGraph(project.Services, initialStatus) - if b, err := g.HasCycles(); b { + graph, err := NewGraph(project.Services, ServiceStarted) + if err != nil { return err } + return visit(ctx, graph, downDirectionTraversalConfig, fn) +} +func visit(ctx context.Context, g *Graph, traversalConfig graphTraversalConfig, fn func(context.Context, string) error) error { nodes := traversalConfig.extremityNodesFn(g) eg, _ := errgroup.WithContext(ctx) @@ -155,7 +158,7 @@ func (v *Vertex) GetChildren() []*Vertex { } // NewGraph returns the dependency graph of the services -func NewGraph(services types.Services, initialStatus ServiceStatus) *Graph { +func NewGraph(services types.Services, initialStatus ServiceStatus) (*Graph, error) { graph := &Graph{ lock: sync.RWMutex{}, Vertices: map[string]*Vertex{}, @@ -171,7 +174,11 @@ func NewGraph(services types.Services, initialStatus ServiceStatus) *Graph { } } - return graph + if b, err := graph.HasCycles(); b { + return nil, err + } + + return graph, nil } // NewVertex is the constructor function for the Vertex diff --git a/pkg/compose/start.go b/pkg/compose/start.go index d1af0637c..0dcef8ded 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -50,6 +50,13 @@ func (s *composeService) start(ctx context.Context, projectName string, options } } + if len(options.Services) > 0 { + err := project.ForServices(options.Services) + if err != nil { + return err + } + } + eg, ctx := errgroup.WithContext(ctx) if listener != nil { attached, err := s.attach(ctx, project, listener, options.AttachTo)