From 65ed8cf4c29925c387d51906ebd260627d3bd20b Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Sat, 5 Feb 2022 10:27:52 +0330 Subject: [PATCH 01/10] Implemented #9147 Signed-off-by: Mehrad Dadar --- cmd/compose/remove.go | 2 +- cmd/compose/restart.go | 4 ++-- cmd/compose/run.go | 2 +- cmd/compose/start.go | 6 ++++-- cmd/compose/stop.go | 4 ++-- pkg/api/api.go | 6 +++--- pkg/api/proxy.go | 27 +++++++++------------------ pkg/compose/compose.go | 31 +++++++++++++++++++++++++++++++ pkg/compose/restart.go | 12 +++++++----- pkg/compose/start.go | 16 ++++++++++------ pkg/compose/stop.go | 16 +++++++++------- pkg/compose/stop_test.go | 9 +-------- pkg/compose/up.go | 6 +++--- 13 files changed, 83 insertions(+), 58 deletions(-) diff --git a/cmd/compose/remove.go b/cmd/compose/remove.go index f84621387..b4b61d580 100644 --- a/cmd/compose/remove.go +++ b/cmd/compose/remove.go @@ -65,7 +65,7 @@ func runRemove(ctx context.Context, backend api.Service, opts removeOptions, ser } if opts.stop { - err := backend.Stop(ctx, project, api.StopOptions{ + err := backend.Stop(ctx, project.Name, api.StopOptions{ Services: services, }) if err != nil { diff --git a/cmd/compose/restart.go b/cmd/compose/restart.go index 600d2b6fa..f691c31fb 100644 --- a/cmd/compose/restart.go +++ b/cmd/compose/restart.go @@ -49,13 +49,13 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error { - project, err := opts.toProject(services) + projectName, err := opts.toProjectName() if err != nil { return err } timeout := time.Duration(opts.timeout) * time.Second - return backend.Restart(ctx, project, api.RestartOptions{ + return backend.Restart(ctx, projectName, api.RestartOptions{ Timeout: &timeout, Services: services, }) diff --git a/cmd/compose/run.go b/cmd/compose/run.go index fc5f76421..575026204 100644 --- a/cmd/compose/run.go +++ b/cmd/compose/run.go @@ -240,5 +240,5 @@ func startDependencies(ctx context.Context, backend api.Service, project types.P if err := backend.Create(ctx, &project, api.CreateOptions{}); err != nil { return err } - return backend.Start(ctx, &project, api.StartOptions{}) + return backend.Start(ctx, project.Name, api.StartOptions{}) } diff --git a/cmd/compose/start.go b/cmd/compose/start.go index 8ad99c566..e9b67ae44 100644 --- a/cmd/compose/start.go +++ b/cmd/compose/start.go @@ -43,10 +43,12 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error { - project, err := opts.toProject(services) + projectName, err := opts.toProjectName() if err != nil { return err } - return backend.Start(ctx, project, api.StartOptions{}) + return backend.Start(ctx, projectName, api.StartOptions{ + AttachTo: services, + }) } diff --git a/cmd/compose/stop.go b/cmd/compose/stop.go index d00d94f9d..39861cd68 100644 --- a/cmd/compose/stop.go +++ b/cmd/compose/stop.go @@ -53,7 +53,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runStop(ctx context.Context, backend api.Service, opts stopOptions, services []string) error { - project, err := opts.toProject(services) + projectName, err := opts.toProjectName() if err != nil { return err } @@ -63,7 +63,7 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service timeoutValue := time.Duration(opts.timeout) * time.Second timeout = &timeoutValue } - return backend.Stop(ctx, project, api.StopOptions{ + return backend.Stop(ctx, projectName, api.StopOptions{ Timeout: timeout, Services: services, }) diff --git a/pkg/api/api.go b/pkg/api/api.go index 5d963569c..9f9f0c038 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -37,11 +37,11 @@ type Service interface { // Create executes the equivalent to a `compose create` Create(ctx context.Context, project *types.Project, opts CreateOptions) error // Start executes the equivalent to a `compose start` - Start(ctx context.Context, project *types.Project, options StartOptions) error + Start(ctx context.Context, projectName string, options StartOptions) error // Restart restarts containers - Restart(ctx context.Context, project *types.Project, options RestartOptions) error + Restart(ctx context.Context, projectName string, options RestartOptions) error // Stop executes the equivalent to a `compose stop` - Stop(ctx context.Context, project *types.Project, options StopOptions) error + Stop(ctx context.Context, projectName string, options StopOptions) error // Up executes the equivalent to a `compose up` Up(ctx context.Context, project *types.Project, options UpOptions) error // Down executes the equivalent to a `compose down` diff --git a/pkg/api/proxy.go b/pkg/api/proxy.go index 6c3fe22f3..9a06b9cb4 100644 --- a/pkg/api/proxy.go +++ b/pkg/api/proxy.go @@ -28,9 +28,9 @@ type ServiceProxy struct { PushFn func(ctx context.Context, project *types.Project, options PushOptions) error PullFn func(ctx context.Context, project *types.Project, opts PullOptions) error CreateFn func(ctx context.Context, project *types.Project, opts CreateOptions) error - StartFn func(ctx context.Context, project *types.Project, options StartOptions) error - RestartFn func(ctx context.Context, project *types.Project, options RestartOptions) error - StopFn func(ctx context.Context, project *types.Project, options StopOptions) error + StartFn func(ctx context.Context, projectName string, options StartOptions) error + RestartFn func(ctx context.Context, projectName string, options RestartOptions) error + StopFn func(ctx context.Context, projectName string, options StopOptions) error UpFn func(ctx context.Context, project *types.Project, options UpOptions) error DownFn func(ctx context.Context, projectName string, options DownOptions) error LogsFn func(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error @@ -141,36 +141,27 @@ func (s *ServiceProxy) Create(ctx context.Context, project *types.Project, optio } // Start implements Service interface -func (s *ServiceProxy) Start(ctx context.Context, project *types.Project, options StartOptions) error { +func (s *ServiceProxy) Start(ctx context.Context, projectName string, options StartOptions) error { if s.StartFn == nil { return ErrNotImplemented } - for _, i := range s.interceptors { - i(ctx, project) - } - return s.StartFn(ctx, project, options) + return s.StartFn(ctx, projectName, options) } // Restart implements Service interface -func (s *ServiceProxy) Restart(ctx context.Context, project *types.Project, options RestartOptions) error { +func (s *ServiceProxy) Restart(ctx context.Context, projectName string, options RestartOptions) error { if s.RestartFn == nil { return ErrNotImplemented } - for _, i := range s.interceptors { - i(ctx, project) - } - return s.RestartFn(ctx, project, options) + return s.RestartFn(ctx, projectName, options) } // Stop implements Service interface -func (s *ServiceProxy) Stop(ctx context.Context, project *types.Project, options StopOptions) error { +func (s *ServiceProxy) Stop(ctx context.Context, projectName string, options StopOptions) error { if s.StopFn == nil { return ErrNotImplemented } - for _, i := range s.interceptors { - i(ctx, project) - } - return s.StopFn(ctx, project, options) + return s.StopFn(ctx, projectName, options) } // Up implements Service interface diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 7c31218cd..0a7781ae8 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -92,3 +92,34 @@ func escapeDollarSign(marshal []byte) []byte { escDollar := []byte{'$', '$'} return bytes.ReplaceAll(marshal, dollar, escDollar) } + +// projectFromName builds a types.Project based on actual resources with compose labels set +func (s *composeService) projectFromName(containers Containers, projectName string) *types.Project { + project := &types.Project{ + Name: projectName, + } + if len(containers) == 0 { + return project + } + set := map[string]moby.Container{} + for _, c := range containers { + set[c.Labels[api.ServiceLabel]] = c + } + for s, c := range set { + service := types.ServiceConfig{ + Name: s, + Image: c.Image, + Labels: c.Labels, + } + dependencies := c.Labels[api.DependenciesLabel] + if len(dependencies) > 0 { + service.DependsOn = types.DependsOnConfig{} + for _, d := range strings.Split(dependencies, ",") { + service.DependsOn[d] = types.ServiceDependency{} + } + } + project.Services = append(project.Services, service) + } + + return project +} diff --git a/pkg/compose/restart.go b/pkg/compose/restart.go index 44592c62f..4de3022e6 100644 --- a/pkg/compose/restart.go +++ b/pkg/compose/restart.go @@ -19,7 +19,6 @@ package compose import ( "context" - "github.com/compose-spec/compose-go/types" "github.com/docker/compose/v2/pkg/api" "golang.org/x/sync/errgroup" @@ -27,18 +26,21 @@ import ( "github.com/docker/compose/v2/pkg/utils" ) -func (s *composeService) Restart(ctx context.Context, project *types.Project, options api.RestartOptions) error { +func (s *composeService) Restart(ctx context.Context, projectName string, options api.RestartOptions) error { return progress.Run(ctx, func(ctx context.Context) error { - return s.restart(ctx, project, options) + return s.restart(ctx, projectName, options) }) } -func (s *composeService) restart(ctx context.Context, project *types.Project, options api.RestartOptions) error { - observedState, err := s.getContainers(ctx, project.Name, oneOffInclude, true) +func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error { + + observedState, err := s.getContainers(ctx, projectName, oneOffInclude, true) if err != nil { return err } + project := s.projectFromName(observedState, projectName) + if len(options.Services) == 0 { options.Services = project.ServiceNames() } diff --git a/pkg/compose/start.go b/pkg/compose/start.go index de31b3ea7..a42f4fcc6 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -28,17 +28,21 @@ import ( "github.com/docker/compose/v2/pkg/progress" ) -func (s *composeService) Start(ctx context.Context, project *types.Project, options api.StartOptions) error { +func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error { return progress.Run(ctx, func(ctx context.Context) error { - return s.start(ctx, project, options, nil) + return s.start(ctx, projectName, options, nil) }) } -func (s *composeService) start(ctx context.Context, project *types.Project, options api.StartOptions, listener api.ContainerEventListener) error { - if len(options.AttachTo) == 0 { - options.AttachTo = project.ServiceNames() +func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error { + var containers Containers + containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, options.AttachTo...) + if err != nil { + return err } + project := s.projectFromName(containers, projectName) + eg, ctx := errgroup.WithContext(ctx) if listener != nil { attached, err := s.attach(ctx, project, listener, options.AttachTo) @@ -53,7 +57,7 @@ func (s *composeService) start(ctx context.Context, project *types.Project, opti }) } - err := InDependencyOrder(ctx, project, func(c context.Context, name string) error { + err = InDependencyOrder(ctx, project, func(c context.Context, name string) error { service, err := project.GetService(name) if err != nil { return err diff --git a/pkg/compose/stop.go b/pkg/compose/stop.go index 6655aa2b1..54c29dd08 100644 --- a/pkg/compose/stop.go +++ b/pkg/compose/stop.go @@ -21,29 +21,31 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" - - "github.com/compose-spec/compose-go/types" + //"github.com/compose-spec/compose-go/types" ) -func (s *composeService) Stop(ctx context.Context, project *types.Project, options api.StopOptions) error { +func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error { return progress.Run(ctx, func(ctx context.Context) error { - return s.stop(ctx, project, options) + return s.stop(ctx, projectName, options) }) } -func (s *composeService) stop(ctx context.Context, project *types.Project, options api.StopOptions) error { +func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error { w := progress.ContextWriter(ctx) services := options.Services if len(services) == 0 { - services = project.ServiceNames() + services = []string{} } + var containers Containers - containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...) + containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, services...) if err != nil { return err } + project := s.projectFromName(containers, projectName) + return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error { return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout) }) diff --git a/pkg/compose/stop_test.go b/pkg/compose/stop_test.go index 4b8e345b6..29cecbd3f 100644 --- a/pkg/compose/stop_test.go +++ b/pkg/compose/stop_test.go @@ -25,7 +25,6 @@ import ( compose "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/mocks" - "github.com/compose-spec/compose-go/types" moby "github.com/docker/docker/api/types" "github.com/golang/mock/gomock" "gotest.tools/v3/assert" @@ -50,13 +49,7 @@ func TestStopTimeout(t *testing.T) { api.EXPECT().ContainerStop(gomock.Any(), "456", &timeout).Return(nil) api.EXPECT().ContainerStop(gomock.Any(), "789", &timeout).Return(nil) - err := tested.Stop(ctx, &types.Project{ - Name: strings.ToLower(testProject), - Services: []types.ServiceConfig{ - {Name: "service1"}, - {Name: "service2"}, - }, - }, compose.StopOptions{ + err := tested.Stop(ctx, strings.ToLower(testProject), compose.StopOptions{ Timeout: &timeout, }) assert.NilError(t, err) diff --git a/pkg/compose/up.go b/pkg/compose/up.go index 88d0df1f8..3ee07f1cc 100644 --- a/pkg/compose/up.go +++ b/pkg/compose/up.go @@ -38,7 +38,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options return err } if options.Start.Attach == nil { - return s.start(ctx, project, options.Start, nil) + return s.start(ctx, project.Name, options.Start, nil) } return nil }) @@ -65,7 +65,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options }) }() - return s.Stop(ctx, project, api.StopOptions{ + return s.Stop(ctx, project.Name, api.StopOptions{ Services: options.Create.Services, }) }) @@ -85,7 +85,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options return err }) - err = s.start(ctx, project, options.Start, printer.HandleEvent) + err = s.start(ctx, project.Name, options.Start, printer.HandleEvent) if err != nil { return err } From ced9eba9408e21b6a8a094ef13b1e3131ab29605 Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Thu, 17 Feb 2022 07:55:11 +0330 Subject: [PATCH 02/10] refactor: removed redundant code Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 2 +- pkg/compose/down.go | 37 ++++++------------------------------- pkg/compose/start.go | 2 +- 3 files changed, 8 insertions(+), 33 deletions(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 0a7781ae8..1a8d73645 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -115,7 +115,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri if len(dependencies) > 0 { service.DependsOn = types.DependsOnConfig{} for _, d := range strings.Split(dependencies, ",") { - service.DependsOn[d] = types.ServiceDependency{} + service.DependsOn[d] = types.ServiceDependency{Condition: ServiceConditionRunningOrHealthy} } } project.Services = append(project.Services, service) diff --git a/pkg/compose/down.go b/pkg/compose/down.go index fda34fbd9..5b52e19a6 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -41,6 +41,7 @@ func (s *composeService) Down(ctx context.Context, projectName string, options a } func (s *composeService) down(ctx context.Context, projectName string, options api.DownOptions) error { + builtFromResources := options.Project == nil w := progress.ContextWriter(ctx) resourceToRemove := false @@ -50,8 +51,8 @@ func (s *composeService) down(ctx context.Context, projectName string, options a return err } - if options.Project == nil { - options.Project, err = s.projectFromLabels(ctx, containers.filter(isNotOneOff), projectName) + if builtFromResources { + options.Project, err = s.getProjectWithVolumes(ctx, containers, projectName) if err != nil { return err } @@ -232,34 +233,9 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer return eg.Wait() } -// projectFromLabels builds a types.Project based on actual resources with compose labels set -func (s *composeService) projectFromLabels(ctx context.Context, containers Containers, projectName string) (*types.Project, error) { - project := &types.Project{ - Name: projectName, - } - if len(containers) == 0 { - return project, nil - } - set := map[string]moby.Container{} - for _, c := range containers { - set[c.Labels[api.ServiceLabel]] = c - } - for s, c := range set { - service := types.ServiceConfig{ - Name: s, - Image: c.Image, - Labels: c.Labels, - } - dependencies := c.Labels[api.DependenciesLabel] - if len(dependencies) > 0 { - service.DependsOn = types.DependsOnConfig{} - for _, d := range strings.Split(dependencies, ",") { - service.DependsOn[d] = types.ServiceDependency{} - } - } - project.Services = append(project.Services, service) - } - +func (s *composeService) getProjectWithVolumes(ctx context.Context, containers Containers, projectName string) (*types.Project, error) { + containers = containers.filter(isNotOneOff) + project := s.projectFromName(containers, projectName) volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName))) if err != nil { return nil, err @@ -273,6 +249,5 @@ func (s *composeService) projectFromLabels(ctx context.Context, containers Conta Labels: vol.Labels, } } - return project, nil } diff --git a/pkg/compose/start.go b/pkg/compose/start.go index a42f4fcc6..3c271e33d 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -36,7 +36,7 @@ func (s *composeService) Start(ctx context.Context, projectName string, options func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error { var containers Containers - containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, options.AttachTo...) + containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.AttachTo...) if err != nil { return err } From 67f7b84829bbfc82f05dcc52e6971c2f14d902c0 Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Wed, 23 Feb 2022 21:34:34 +0330 Subject: [PATCH 03/10] modified com.docker.compose.depends_on label to contain dependency type Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 12 ++++++++++-- pkg/compose/create.go | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 1a8d73645..886ae9f73 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -114,8 +114,16 @@ func (s *composeService) projectFromName(containers Containers, projectName stri dependencies := c.Labels[api.DependenciesLabel] if len(dependencies) > 0 { service.DependsOn = types.DependsOnConfig{} - for _, d := range strings.Split(dependencies, ",") { - service.DependsOn[d] = types.ServiceDependency{Condition: ServiceConditionRunningOrHealthy} + for _, dc := range strings.Split(dependencies, ",") { + dcArr := strings.Split(dc, ":") + condition := ServiceConditionRunningOrHealthy + dependency := dcArr[0] + + // backward compatibility + if len(dcArr) > 1 { + condition = dcArr[1] + } + service.DependsOn[dependency] = types.ServiceDependency{Condition: condition} } } project.Services = append(project.Services, service) diff --git a/pkg/compose/create.go b/pkg/compose/create.go index d77e075db..7c3cbfd33 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -433,7 +433,7 @@ func (s *composeService) prepareLabels(service types.ServiceConfig, number int) var dependencies []string for s := range service.DependsOn { - dependencies = append(dependencies, s) + dependencies = append(dependencies, s+":"+service.DependsOn[s].Condition) } labels[api.DependenciesLabel] = strings.Join(dependencies, ",") return labels, nil From ce1c7882376d5f8e016bd544e09480100ad7b8e1 Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Thu, 24 Feb 2022 14:50:50 +0330 Subject: [PATCH 04/10] minor code cleanup Signed-off-by: Mehrad Dadar --- pkg/compose/create.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/compose/create.go b/pkg/compose/create.go index 7c3cbfd33..ce2551251 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -432,8 +432,8 @@ func (s *composeService) prepareLabels(service types.ServiceConfig, number int) labels[api.ContainerNumberLabel] = strconv.Itoa(number) var dependencies []string - for s := range service.DependsOn { - dependencies = append(dependencies, s+":"+service.DependsOn[s].Condition) + for s, d := range service.DependsOn { + dependencies = append(dependencies, s+":"+d.Condition) } labels[api.DependenciesLabel] = strings.Join(dependencies, ",") return labels, nil From 32d44dfc255988fe0dcfdc6986daa14687d2c60b Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Thu, 24 Feb 2022 22:39:38 +0330 Subject: [PATCH 05/10] added scale to toProjectName Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 16 +++++++++------- pkg/compose/stop.go | 1 - 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 886ae9f73..822159b4d 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -101,17 +101,19 @@ func (s *composeService) projectFromName(containers Containers, projectName stri if len(containers) == 0 { return project } - set := map[string]moby.Container{} + set := map[string]types.ServiceConfig{} for _, c := range containers { - set[c.Labels[api.ServiceLabel]] = c - } - for s, c := range set { - service := types.ServiceConfig{ - Name: s, + sc := types.ServiceConfig{ + Name: c.Labels[api.ServiceLabel], Image: c.Image, Labels: c.Labels, } - dependencies := c.Labels[api.DependenciesLabel] + sc.Scale += 1 + set[sc.Name] = sc + + } + for _, service := range set { + dependencies := service.Labels[api.DependenciesLabel] if len(dependencies) > 0 { service.DependsOn = types.DependsOnConfig{} for _, dc := range strings.Split(dependencies, ",") { diff --git a/pkg/compose/stop.go b/pkg/compose/stop.go index 54c29dd08..4543defc1 100644 --- a/pkg/compose/stop.go +++ b/pkg/compose/stop.go @@ -21,7 +21,6 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" - //"github.com/compose-spec/compose-go/types" ) func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error { From c0465616bb1a71523a2469d491f639887bf5ba97 Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Thu, 24 Feb 2022 23:46:07 +0330 Subject: [PATCH 06/10] check service existence in project Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 16 +++++++++++++--- pkg/compose/down.go | 2 +- pkg/compose/restart.go | 5 ++++- pkg/compose/start.go | 5 ++++- pkg/compose/stop.go | 5 ++++- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 822159b4d..c0501fb42 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/docker/compose/v2/pkg/api" + "github.com/pkg/errors" "github.com/compose-spec/compose-go/types" "github.com/docker/cli/cli/config/configfile" @@ -94,12 +95,12 @@ func escapeDollarSign(marshal []byte) []byte { } // projectFromName builds a types.Project based on actual resources with compose labels set -func (s *composeService) projectFromName(containers Containers, projectName string) *types.Project { +func (s *composeService) projectFromName(containers Containers, projectName string, services ...string) (*types.Project, error) { project := &types.Project{ Name: projectName, } if len(containers) == 0 { - return project + return project, nil } set := map[string]types.ServiceConfig{} for _, c := range containers { @@ -130,6 +131,15 @@ func (s *composeService) projectFromName(containers Containers, projectName stri } project.Services = append(project.Services, service) } +SERVICES: + for _, qs := range services { + for _, es := range project.Services { + if es.Name == qs { + continue SERVICES + } + } + return project, errors.New("no such service: " + qs) + } - return project + return project, nil } diff --git a/pkg/compose/down.go b/pkg/compose/down.go index 5b52e19a6..60498ffa3 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -235,7 +235,7 @@ func (s *composeService) removeContainers(ctx context.Context, w progress.Writer func (s *composeService) getProjectWithVolumes(ctx context.Context, containers Containers, projectName string) (*types.Project, error) { containers = containers.filter(isNotOneOff) - project := s.projectFromName(containers, projectName) + project, _ := s.projectFromName(containers, projectName) volumes, err := s.apiClient.VolumeList(ctx, filters.NewArgs(projectFilter(projectName))) if err != nil { return nil, err diff --git a/pkg/compose/restart.go b/pkg/compose/restart.go index 4de3022e6..306b4d413 100644 --- a/pkg/compose/restart.go +++ b/pkg/compose/restart.go @@ -39,7 +39,10 @@ func (s *composeService) restart(ctx context.Context, projectName string, option return err } - project := s.projectFromName(observedState, projectName) + project, err := s.projectFromName(observedState, projectName, options.Services...) + if err != nil { + return err + } if len(options.Services) == 0 { options.Services = project.ServiceNames() diff --git a/pkg/compose/start.go b/pkg/compose/start.go index 3c271e33d..0d0b493a8 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -41,7 +41,10 @@ func (s *composeService) start(ctx context.Context, projectName string, options return err } - project := s.projectFromName(containers, projectName) + project, err := s.projectFromName(containers, projectName, options.AttachTo...) + if err != nil { + return err + } eg, ctx := errgroup.WithContext(ctx) if listener != nil { diff --git a/pkg/compose/stop.go b/pkg/compose/stop.go index 4543defc1..9f3943783 100644 --- a/pkg/compose/stop.go +++ b/pkg/compose/stop.go @@ -43,7 +43,10 @@ func (s *composeService) stop(ctx context.Context, projectName string, options a return err } - project := s.projectFromName(containers, projectName) + project, err := s.projectFromName(containers, projectName, services...) + if err != nil { + return err + } return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error { return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout) From 35f37cd1f776a6db0377e2ac88b28bfe9c9e0d2c Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Fri, 25 Feb 2022 00:00:36 +0330 Subject: [PATCH 07/10] fix lint Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index c0501fb42..36376e273 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -109,7 +109,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri Image: c.Image, Labels: c.Labels, } - sc.Scale += 1 + sc.Scale++ set[sc.Name] = sc } From 42c3adb23699b6fe90c7b336dc5391205408c713 Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Fri, 25 Feb 2022 05:36:22 +0330 Subject: [PATCH 08/10] project existence check: added error message Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 36376e273..780aa459e 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -100,7 +100,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri Name: projectName, } if len(containers) == 0 { - return project, nil + return project, errors.New("no such project: " + projectName) } set := map[string]types.ServiceConfig{} for _, c := range containers { From aeb74484496bc17a03c9ed8dd53b38d481f71e1c Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Fri, 25 Feb 2022 06:26:05 +0330 Subject: [PATCH 09/10] minor improvement and fix Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index 780aa459e..f71978e2b 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -102,16 +102,18 @@ func (s *composeService) projectFromName(containers Containers, projectName stri if len(containers) == 0 { return project, errors.New("no such project: " + projectName) } - set := map[string]types.ServiceConfig{} + set := map[string]*types.ServiceConfig{} for _, c := range containers { - sc := types.ServiceConfig{ - Name: c.Labels[api.ServiceLabel], - Image: c.Image, - Labels: c.Labels, + serviceLabel := c.Labels[api.ServiceLabel] + _, ok := set[serviceLabel] + if !ok { + set[serviceLabel] = &types.ServiceConfig{ + Name: serviceLabel, + Image: c.Image, + Labels: c.Labels, + } } - sc.Scale++ - set[sc.Name] = sc - + set[serviceLabel].Scale++ } for _, service := range set { dependencies := service.Labels[api.DependenciesLabel] @@ -129,7 +131,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri service.DependsOn[dependency] = types.ServiceDependency{Condition: condition} } } - project.Services = append(project.Services, service) + project.Services = append(project.Services, *service) } SERVICES: for _, qs := range services { From 9c68c76bea52c407ba3f164afa497da246b0caee Mon Sep 17 00:00:00 2001 From: Mehrad Dadar Date: Sun, 27 Feb 2022 03:40:46 +0330 Subject: [PATCH 10/10] minor improvement and fix Signed-off-by: Mehrad Dadar --- pkg/compose/compose.go | 4 ++++ pkg/compose/start.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index f71978e2b..7c3c96a2b 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -142,6 +142,10 @@ SERVICES: } return project, errors.New("no such service: " + qs) } + err := project.ForServices(services) + if err != nil { + return project, err + } return project, nil } diff --git a/pkg/compose/start.go b/pkg/compose/start.go index 0d0b493a8..dca5358eb 100644 --- a/pkg/compose/start.go +++ b/pkg/compose/start.go @@ -36,7 +36,7 @@ func (s *composeService) Start(ctx context.Context, projectName string, options func (s *composeService) start(ctx context.Context, projectName string, options api.StartOptions, listener api.ContainerEventListener) error { var containers Containers - containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.AttachTo...) + containers, err := s.getContainers(ctx, projectName, oneOffExclude, true) if err != nil { return err }