From 89a63b79cb15e08ec48fb9c4595c23e26dd9c8b9 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 11 Jun 2021 10:34:47 +0200 Subject: [PATCH] define compose labels within the compose API Signed-off-by: Nicolas De Loof --- api/compose/labels.go | 44 +++++++++++++++++++++++++ api/compose/tags.go | 30 ----------------- ecs/awsResources.go | 8 ++--- ecs/cloudformation_test.go | 10 +++--- ecs/sdk.go | 12 +++---- ecs/tags.go | 10 +++--- ecs/volumes.go | 4 +-- kube/client/client.go | 14 ++++---- kube/client/client_test.go | 4 +-- kube/client/utils.go | 6 ++-- kube/resources/kube.go | 4 +-- local/compose/attach.go | 2 +- local/compose/compose.go | 4 +-- local/compose/containers.go | 20 +++++------ local/compose/convergence.go | 6 ++-- local/compose/cp.go | 2 +- local/compose/create.go | 31 ++++++++--------- local/compose/create_test.go | 4 ++- local/compose/down.go | 8 ++--- local/compose/events.go | 2 +- local/compose/exec.go | 2 +- local/compose/{labels.go => filters.go} | 42 +++++++++++------------ local/compose/images.go | 2 +- local/compose/kill_test.go | 6 +++- local/compose/logs.go | 2 +- local/compose/ls.go | 2 +- local/compose/ls_test.go | 6 ++-- local/compose/port.go | 2 +- local/compose/ps.go | 4 +-- local/compose/run.go | 10 +++--- local/compose/start.go | 2 +- 31 files changed, 160 insertions(+), 145 deletions(-) create mode 100644 api/compose/labels.go delete mode 100644 api/compose/tags.go rename local/compose/{labels.go => filters.go} (51%) diff --git a/api/compose/labels.go b/api/compose/labels.go new file mode 100644 index 00000000..dbe762b5 --- /dev/null +++ b/api/compose/labels.go @@ -0,0 +1,44 @@ +/* + Copyright 2020 Docker Compose CLI authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package compose + +const ( + // ProjectLabel allow to track resource related to a compose project + ProjectLabel = "com.docker.compose.project" + // ServiceLabel allow to track resource related to a compose service + ServiceLabel = "com.docker.compose.service" + // ConfigHashLabel stores configuration hash for a compose service + ConfigHashLabel = "com.docker.compose.config-hash" + // ContainerNumberLabel stores the container index of a replicated service + ContainerNumberLabel = "com.docker.compose.container-number" + // VolumeLabel allow to track resource related to a compose volume + VolumeLabel = "com.docker.compose.volume" + // NetworkLabel allow to track resource related to a compose network + NetworkLabel = "com.docker.compose.network" + // WorkingDirLabel stores absolute path to compose project working directory + WorkingDirLabel = "com.docker.compose.project.working_dir" + // ConfigFilesLabel stores absolute path to compose project configuration files + ConfigFilesLabel = "com.docker.compose.project.config_files" + // EnvironmentFileLabel stores absolute path to compose project env file set by `--env-file` + EnvironmentFileLabel = "com.docker.compose.project.environment_file" + // OneoffLabel stores value 'True' for one-off containers created by `compose run` + OneoffLabel = "com.docker.compose.oneoff" + // SlugLabel stores unique slug used for one-off container identity + SlugLabel = "com.docker.compose.slug" + // VersionLabel stores the compose tool version used to run application + VersionLabel = "com.docker.compose.version" +) diff --git a/api/compose/tags.go b/api/compose/tags.go deleted file mode 100644 index b790e570..00000000 --- a/api/compose/tags.go +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2020 Docker Compose CLI authors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package compose - -const ( - // ProjectTag allow to track resource related to a compose project - ProjectTag = "com.docker.compose.project" - // NetworkTag allow to track resource related to a compose network - NetworkTag = "com.docker.compose.network" - // ServiceTag allow to track resource related to a compose service - ServiceTag = "com.docker.compose.service" - // VolumeTag allow to track resource related to a compose volume - VolumeTag = "com.docker.compose.volume" - // EnvironmentFileLabel is set in containers with the option "--env-file" when set - EnvironmentFileLabel = "com.docker.compose.project.environment_file" -) diff --git a/ecs/awsResources.go b/ecs/awsResources.go index 71d9d477..bdc50592 100644 --- a/ecs/awsResources.go +++ b/ecs/awsResources.go @@ -289,8 +289,8 @@ func (b *ecsAPIService) parseExternalVolumes(ctx context.Context, project *types logrus.Debugf("searching for existing filesystem as volume %q", name) tags := map[string]string{ - compose.ProjectTag: project.Name, - compose.VolumeTag: name, + compose.ProjectLabel: project.Name, + compose.VolumeLabel: name, } previous, err := b.aws.ListFileSystems(ctx, tags) if err != nil { @@ -397,11 +397,11 @@ func (b *ecsAPIService) ensureVolumes(r *awsResources, project *types.Project, t FileSystemPolicy: nil, FileSystemTags: []efs.FileSystem_ElasticFileSystemTag{ { - Key: compose.ProjectTag, + Key: compose.ProjectLabel, Value: project.Name, }, { - Key: compose.VolumeTag, + Key: compose.VolumeLabel, Value: name, }, { diff --git a/ecs/cloudformation_test.go b/ecs/cloudformation_test.go index a2caa586..f0000423 100644 --- a/ecs/cloudformation_test.go +++ b/ecs/cloudformation_test.go @@ -406,8 +406,8 @@ volumes: provisioned_throughput: 1024 `, useDefaultVPC, func(m *MockAPIMockRecorder) { m.ListFileSystems(gomock.Any(), map[string]string{ - compose.ProjectTag: t.Name(), - compose.VolumeTag: "db-data", + compose.ProjectLabel: t.Name(), + compose.VolumeLabel: "db-data", }).Return(nil, nil) }) n := volumeResourceName("db-data") @@ -452,8 +452,8 @@ volumes: db-data: {} `, useDefaultVPC, func(m *MockAPIMockRecorder) { m.ListFileSystems(gomock.Any(), map[string]string{ - compose.ProjectTag: t.Name(), - compose.VolumeTag: "db-data", + compose.ProjectLabel: t.Name(), + compose.VolumeLabel: "db-data", }).Return([]awsResource{ existingAWSResource{ id: "fs-123abc", @@ -521,7 +521,7 @@ services: for i := 0; i < tags.Len(); i++ { k := tags.Index(i).FieldByName("Key").String() v := tags.Index(i).FieldByName("Value").String() - if k == compose.ProjectTag { + if k == compose.ProjectLabel { assert.Equal(t, v, t.Name()) } } diff --git a/ecs/sdk.go b/ecs/sdk.go index 5f836274..c9d656eb 100644 --- a/ecs/sdk.go +++ b/ecs/sdk.go @@ -341,7 +341,7 @@ func (s sdk) CreateStack(ctx context.Context, name string, region string, templa }, Tags: []*cloudformation.Tag{ { - Key: aws.String(compose.ProjectTag), + Key: aws.String(compose.ProjectLabel), Value: aws.String(name), }, }, @@ -455,7 +455,7 @@ func (s sdk) ListStacks(ctx context.Context) ([]compose.Stack, error) { } for _, stack := range response.Stacks { for _, t := range stack.Tags { - if *t.Key == compose.ProjectTag { + if *t.Key == compose.ProjectLabel { status := compose.RUNNING switch aws.StringValue(stack.StackStatus) { case "CREATE_IN_PROGRESS": @@ -860,12 +860,12 @@ func (s sdk) DescribeService(ctx context.Context, cluster string, arn string) (c service := services.Services[0] var name string for _, t := range service.Tags { - if *t.Key == compose.ServiceTag { + if *t.Key == compose.ServiceLabel { name = aws.StringValue(t.Value) } } if name == "" { - return compose.ServiceStatus{}, fmt.Errorf("service %s doesn't have a %s tag", *service.ServiceArn, compose.ServiceTag) + return compose.ServiceStatus{}, fmt.Errorf("service %s doesn't have a %s tag", *service.ServiceArn, compose.ServiceLabel) } targetGroupArns := []string{} for _, lb := range service.LoadBalancers { @@ -919,9 +919,9 @@ func (s sdk) DescribeServiceTasks(ctx context.Context, cluster string, project s var service string for _, tag := range t.Tags { switch aws.StringValue(tag.Key) { - case compose.ProjectTag: + case compose.ProjectLabel: project = aws.StringValue(tag.Value) - case compose.ServiceTag: + case compose.ServiceLabel: service = aws.StringValue(tag.Value) } } diff --git a/ecs/tags.go b/ecs/tags.go index 6e7206ee..882742cf 100644 --- a/ecs/tags.go +++ b/ecs/tags.go @@ -26,7 +26,7 @@ import ( func projectTags(project *types.Project) []tags.Tag { return []tags.Tag{ { - Key: compose.ProjectTag, + Key: compose.ProjectLabel, Value: project.Name, }, } @@ -35,11 +35,11 @@ func projectTags(project *types.Project) []tags.Tag { func serviceTags(project *types.Project, service types.ServiceConfig) []tags.Tag { return []tags.Tag{ { - Key: compose.ProjectTag, + Key: compose.ProjectLabel, Value: project.Name, }, { - Key: compose.ServiceTag, + Key: compose.ServiceLabel, Value: service.Name, }, } @@ -48,11 +48,11 @@ func serviceTags(project *types.Project, service types.ServiceConfig) []tags.Tag func networkTags(project *types.Project, net types.NetworkConfig) []tags.Tag { return []tags.Tag{ { - Key: compose.ProjectTag, + Key: compose.ProjectLabel, Value: project.Name, }, { - Key: compose.NetworkTag, + Key: compose.NetworkLabel, Value: net.Name, }, } diff --git a/ecs/volumes.go b/ecs/volumes.go index df1a296f..90c0acdb 100644 --- a/ecs/volumes.go +++ b/ecs/volumes.go @@ -63,11 +63,11 @@ func (b *ecsAPIService) createAccessPoints(project *types.Project, r awsResource ap := efs.AccessPoint{ AccessPointTags: []efs.AccessPoint_AccessPointTag{ { - Key: compose.ProjectTag, + Key: compose.ProjectLabel, Value: project.Name, }, { - Key: compose.VolumeTag, + Key: compose.VolumeLabel, Value: name, }, { diff --git a/kube/client/client.go b/kube/client/client.go index 8cfda956..f80ee9dd 100644 --- a/kube/client/client.go +++ b/kube/client/client.go @@ -77,7 +77,7 @@ func NewKubeClient(config genericclioptions.RESTClientGetter) (*KubeClient, erro // GetPod retrieves a service pod func (kc KubeClient) GetPod(ctx context.Context, projectName, serviceName string) (*corev1.Pod, error) { pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectTag, projectName), + LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectLabel, projectName), }) if err != nil { return nil, err @@ -87,7 +87,7 @@ func (kc KubeClient) GetPod(ctx context.Context, projectName, serviceName string } var pod corev1.Pod for _, p := range pods.Items { - service := p.Labels[compose.ServiceTag] + service := p.Labels[compose.ServiceLabel] if service == serviceName { pod = p break @@ -155,7 +155,7 @@ func (kc KubeClient) GetContainers(ctx context.Context, projectName string, all } pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectTag, projectName), + LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectLabel, projectName), FieldSelector: fieldSelector, }) if err != nil { @@ -165,7 +165,7 @@ func (kc KubeClient) GetContainers(ctx context.Context, projectName string, all result := []compose.ContainerSummary{} for _, pod := range pods.Items { summary := podToContainerSummary(pod) - serviceName := pod.GetObjectMeta().GetLabels()[compose.ServiceTag] + serviceName := pod.GetObjectMeta().GetLabels()[compose.ServiceLabel] ports, ok := services[serviceName] if !ok { s, err := kc.client.CoreV1().Services(kc.namespace).Get(ctx, serviceName, metav1.GetOptions{}) @@ -202,7 +202,7 @@ func (kc KubeClient) GetContainers(ctx context.Context, projectName string, all // GetLogs retrieves pod logs func (kc *KubeClient) GetLogs(ctx context.Context, projectName string, consumer compose.LogConsumer, follow bool) error { pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectTag, projectName), + LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectLabel, projectName), }) if err != nil { return err @@ -210,7 +210,7 @@ func (kc *KubeClient) GetLogs(ctx context.Context, projectName string, consumer eg, ctx := errgroup.WithContext(ctx) for _, pod := range pods.Items { request := kc.client.CoreV1().Pods(kc.namespace).GetLogs(pod.Name, &corev1.PodLogOptions{Follow: follow}) - service := pod.Labels[compose.ServiceTag] + service := pod.Labels[compose.ServiceLabel] w := utils.GetWriter(func(line string) { consumer.Log(pod.Name, service, line) }) @@ -243,7 +243,7 @@ func (kc KubeClient) WaitForPodState(ctx context.Context, opts WaitForStatusOpti time.Sleep(500 * time.Millisecond) pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectTag, opts.ProjectName), + LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectLabel, opts.ProjectName), }) if err != nil { errch <- err diff --git a/kube/client/client_test.go b/kube/client/client_test.go index bd063dfa..0b86d1bb 100644 --- a/kube/client/client_test.go +++ b/kube/client/client_test.go @@ -34,8 +34,8 @@ func TestPodToContainerSummary(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "c1-123", Labels: map[string]string{ - compose.ProjectTag: "myproject", - compose.ServiceTag: "service1", + compose.ProjectLabel: "myproject", + compose.ServiceLabel: "service1", }, }, Status: v1.PodStatus{ diff --git a/kube/client/utils.go b/kube/client/utils.go index e93e087b..d147d98e 100644 --- a/kube/client/utils.go +++ b/kube/client/utils.go @@ -47,9 +47,9 @@ func podToContainerSummary(pod corev1.Pod) compose.ContainerSummary { return compose.ContainerSummary{ ID: pod.GetObjectMeta().GetName(), Name: pod.GetObjectMeta().GetName(), - Service: pod.GetObjectMeta().GetLabels()[compose.ServiceTag], + Service: pod.GetObjectMeta().GetLabels()[compose.ServiceLabel], State: state, - Project: pod.GetObjectMeta().GetLabels()[compose.ProjectTag], + Project: pod.GetObjectMeta().GetLabels()[compose.ProjectLabel], } } @@ -57,7 +57,7 @@ func checkPodsState(services []string, pods []corev1.Pod, status string) (bool, servicePods := map[string]string{} stateReached := true for _, pod := range pods { - service := pod.Labels[compose.ServiceTag] + service := pod.Labels[compose.ServiceLabel] if len(services) > 0 && !utils.StringContains(services, service) { continue diff --git a/kube/resources/kube.go b/kube/resources/kube.go index bbbe6b35..0763cb28 100644 --- a/kube/resources/kube.go +++ b/kube/resources/kube.go @@ -151,8 +151,8 @@ func mapToDeployment(project *types.Project, service types.ServiceConfig) (*apps func selectorLabels(projectName string, serviceName string) map[string]string { return map[string]string{ - compose.ProjectTag: projectName, - compose.ServiceTag: serviceName, + compose.ProjectLabel: projectName, + compose.ServiceLabel: serviceName, } } diff --git a/local/compose/attach.go b/local/compose/attach.go index 1114be9b..266d1441 100644 --- a/local/compose/attach.go +++ b/local/compose/attach.go @@ -57,7 +57,7 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, lis } func (s *composeService) attachContainer(ctx context.Context, container moby.Container, listener compose.ContainerEventListener, project *types.Project) error { - serviceName := container.Labels[serviceLabel] + serviceName := container.Labels[compose.ServiceLabel] containerName := getContainerNameWithoutProject(container) service, err := project.GetService(serviceName) if err != nil { diff --git a/local/compose/compose.go b/local/compose/compose.go index f2567801..ec71399e 100644 --- a/local/compose/compose.go +++ b/local/compose/compose.go @@ -56,8 +56,8 @@ func getCanonicalContainerName(c moby.Container) string { func getContainerNameWithoutProject(c moby.Container) string { name := getCanonicalContainerName(c) - project := c.Labels[projectLabel] - prefix := fmt.Sprintf("%s_%s_", project, c.Labels[serviceLabel]) + project := c.Labels[compose.ProjectLabel] + prefix := fmt.Sprintf("%s_%s_", project, c.Labels[compose.ServiceLabel]) if strings.HasPrefix(name, prefix) { return name[len(project)+1:] } diff --git a/local/compose/containers.go b/local/compose/containers.go index 588b3ce1..b49f689e 100644 --- a/local/compose/containers.go +++ b/local/compose/containers.go @@ -18,12 +18,12 @@ package compose import ( "context" - "fmt" "sort" moby "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" + "github.com/docker/compose-cli/api/compose" "github.com/docker/compose-cli/utils" ) @@ -40,21 +40,19 @@ const ( func (s *composeService) getContainers(ctx context.Context, project string, oneOff oneOff, stopped bool, selectedServices ...string) (Containers, error) { var containers Containers - f := filters.NewArgs( - projectFilter(project), - ) + f := []filters.KeyValuePair{projectFilter(project)} if len(selectedServices) == 1 { - f.Add("label", fmt.Sprintf("%s=%s", serviceLabel, selectedServices[0])) + f = append(f, serviceFilter(selectedServices[0])) } switch oneOff { case oneOffOnly: - f.Add("label", fmt.Sprintf("%s=%s", oneoffLabel, "True")) + f = append(f, oneOffFilter(true)) case oneOffExclude: - f.Add("label", fmt.Sprintf("%s=%s", oneoffLabel, "False")) + f = append(f, oneOffFilter(false)) case oneOffInclude: } containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{ - Filters: f, + Filters: filters.NewArgs(f...), All: stopped, }) if err != nil { @@ -71,20 +69,20 @@ type containerPredicate func(c moby.Container) bool func isService(services ...string) containerPredicate { return func(c moby.Container) bool { - service := c.Labels[serviceLabel] + service := c.Labels[compose.ServiceLabel] return utils.StringContains(services, service) } } func isNotService(services ...string) containerPredicate { return func(c moby.Container) bool { - service := c.Labels[serviceLabel] + service := c.Labels[compose.ServiceLabel] return !utils.StringContains(services, service) } } func isNotOneOff(c moby.Container) bool { - v, ok := c.Labels[oneoffLabel] + v, ok := c.Labels[compose.OneoffLabel] return !ok || v == "False" } diff --git a/local/compose/convergence.go b/local/compose/convergence.go index 09c5b8c7..a6779b2c 100644 --- a/local/compose/convergence.go +++ b/local/compose/convergence.go @@ -108,7 +108,7 @@ func (s *composeService) ensureService(ctx context.Context, project *types.Proje container := container name := getContainerProgressName(container) - diverged := container.Labels[configHashLabel] != expected + diverged := container.Labels[compose.ConfigHashLabel] != expected if diverged || recreate == compose.RecreateForce || service.Extensions[extLifecycle] == forceRecreate { eg.Go(func() error { return s.recreateContainer(ctx, project, service, container, inherit, timeout) @@ -190,7 +190,7 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr func nextContainerNumber(containers []moby.Container) (int, error) { max := 0 for _, c := range containers { - n, err := strconv.Atoi(c.Labels[containerNumberLabel]) + n, err := strconv.Atoi(c.Labels[compose.ContainerNumberLabel]) if err != nil { return 0, err } @@ -245,7 +245,7 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P if err != nil { return err } - number, err := strconv.Atoi(container.Labels[containerNumberLabel]) + number, err := strconv.Atoi(container.Labels[compose.ContainerNumberLabel]) if err != nil { return err } diff --git a/local/compose/cp.go b/local/compose/cp.go index ee5bd3f2..1d5dc39a 100644 --- a/local/compose/cp.go +++ b/local/compose/cp.go @@ -69,7 +69,7 @@ func (s *composeService) Copy(ctx context.Context, project *types.Project, opts serviceFilter(serviceName), ) if !opts.All { - f.Add("label", fmt.Sprintf("%s=%d", containerNumberLabel, opts.Index)) + f.Add("label", fmt.Sprintf("%s=%d", compose.ContainerNumberLabel, opts.Index)) } containers, err := s.apiClient.ContainerList(ctx, apitypes.ContainerListOptions{Filters: f}) if err != nil { diff --git a/local/compose/create.go b/local/compose/create.go index 136aadf5..d4c9ddd0 100644 --- a/local/compose/create.go +++ b/local/compose/create.go @@ -39,6 +39,7 @@ import ( "github.com/docker/compose-cli/api/compose" "github.com/docker/compose-cli/api/progress" + "github.com/docker/compose-cli/internal" convert "github.com/docker/compose-cli/local/moby" "github.com/docker/compose-cli/utils" ) @@ -138,9 +139,9 @@ func prepareVolumes(p *types.Project) error { func prepareNetworks(project *types.Project) { for k, network := range project.Networks { - network.Labels = network.Labels.Add(networkLabel, k) - network.Labels = network.Labels.Add(projectLabel, project.Name) - network.Labels = network.Labels.Add(versionLabel, ComposeVersion) + network.Labels = network.Labels.Add(compose.NetworkLabel, k) + network.Labels = network.Labels.Add(compose.ProjectLabel, project.Name) + network.Labels = network.Labels.Add(compose.VersionLabel, internal.Version) project.Networks[k] = network } } @@ -181,9 +182,9 @@ func (s *composeService) ensureNetworks(ctx context.Context, networks types.Netw func (s *composeService) ensureProjectVolumes(ctx context.Context, project *types.Project) error { for k, volume := range project.Volumes { - volume.Labels = volume.Labels.Add(volumeLabel, k) - volume.Labels = volume.Labels.Add(projectLabel, project.Name) - volume.Labels = volume.Labels.Add(versionLabel, ComposeVersion) + volume.Labels = volume.Labels.Add(compose.VolumeLabel, k) + volume.Labels = volume.Labels.Add(compose.ProjectLabel, project.Name) + volume.Labels = volume.Labels.Add(compose.VersionLabel, internal.Version) err := s.ensureVolume(ctx, volume) if err != nil { return err @@ -213,16 +214,16 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, labels[k] = v } - labels[projectLabel] = p.Name - labels[serviceLabel] = service.Name - labels[versionLabel] = ComposeVersion - if _, ok := service.Labels[oneoffLabel]; !ok { - labels[oneoffLabel] = "False" + labels[compose.ProjectLabel] = p.Name + labels[compose.ServiceLabel] = service.Name + labels[compose.VersionLabel] = internal.Version + if _, ok := service.Labels[compose.OneoffLabel]; !ok { + labels[compose.OneoffLabel] = "False" } - labels[configHashLabel] = hash - labels[workingDirLabel] = p.WorkingDir - labels[configFilesLabel] = strings.Join(p.ComposeFiles, ",") - labels[containerNumberLabel] = strconv.Itoa(number) + labels[compose.ConfigHashLabel] = hash + labels[compose.WorkingDirLabel] = p.WorkingDir + labels[compose.ConfigFilesLabel] = strings.Join(p.ComposeFiles, ",") + labels[compose.ContainerNumberLabel] = strconv.Itoa(number) var ( runCmd strslice.StrSlice diff --git a/local/compose/create_test.go b/local/compose/create_test.go index b8cd32a4..1b77f689 100644 --- a/local/compose/create_test.go +++ b/local/compose/create_test.go @@ -21,6 +21,8 @@ import ( "path/filepath" "testing" + "github.com/docker/compose-cli/internal" + "github.com/compose-spec/compose-go/types" composetypes "github.com/compose-spec/compose-go/types" mountTypes "github.com/docker/docker/api/types/mount" @@ -76,6 +78,6 @@ func TestPrepareNetworkLabels(t *testing.T) { assert.DeepEqual(t, project.Networks["skynet"].Labels, types.Labels(map[string]string{ "com.docker.compose.network": "skynet", "com.docker.compose.project": "myProject", - "com.docker.compose.version": "1.0-alpha", + "com.docker.compose.version": internal.Version, })) } diff --git a/local/compose/down.go b/local/compose/down.go index 1464ec35..c4f42178 100644 --- a/local/compose/down.go +++ b/local/compose/down.go @@ -259,7 +259,7 @@ func (s *composeService) projectFromContainerLabels(containers Containers, proje if options.ConfigPaths[0] == "-" { for _, container := range containers { fakeProject.Services = append(fakeProject.Services, types.ServiceConfig{ - Name: container.Labels[serviceLabel], + Name: container.Labels[compose.ServiceLabel], }) } return fakeProject, nil @@ -273,8 +273,8 @@ func (s *composeService) projectFromContainerLabels(containers Containers, proje } func loadProjectOptionsFromLabels(c moby.Container) (*cli.ProjectOptions, error) { - return cli.NewProjectOptions(strings.Split(c.Labels[configFilesLabel], ","), + return cli.NewProjectOptions(strings.Split(c.Labels[compose.ConfigFilesLabel], ","), cli.WithOsEnv, - cli.WithWorkingDirectory(c.Labels[workingDirLabel]), - cli.WithName(c.Labels[projectLabel])) + cli.WithWorkingDirectory(c.Labels[compose.WorkingDirLabel]), + cli.WithName(c.Labels[compose.ProjectLabel])) } diff --git a/local/compose/events.go b/local/compose/events.go index 8024622d..4b03c13e 100644 --- a/local/compose/events.go +++ b/local/compose/events.go @@ -40,7 +40,7 @@ func (s *composeService) Events(ctx context.Context, project string, options com continue } - service := event.Actor.Attributes[serviceLabel] + service := event.Actor.Attributes[compose.ServiceLabel] if len(options.Services) > 0 && !utils.StringContains(options.Services, service) { continue } diff --git a/local/compose/exec.go b/local/compose/exec.go index e76ad50d..98236cbe 100644 --- a/local/compose/exec.go +++ b/local/compose/exec.go @@ -127,7 +127,7 @@ func (s *composeService) getExecTarget(ctx context.Context, project *types.Proje Filters: filters.NewArgs( projectFilter(project.Name), serviceFilter(service.Name), - filters.Arg("label", fmt.Sprintf("%s=%d", containerNumberLabel, opts.Index)), + containerNumberFilter(opts.Index), ), }) if err != nil { diff --git a/local/compose/labels.go b/local/compose/filters.go similarity index 51% rename from local/compose/labels.go rename to local/compose/filters.go index c658c1df..e64f69e6 100644 --- a/local/compose/labels.go +++ b/local/compose/filters.go @@ -19,36 +19,34 @@ package compose import ( "fmt" - "github.com/docker/docker/api/types/filters" - "github.com/docker/compose-cli/api/compose" -) - -const ( - containerNumberLabel = "com.docker.compose.container-number" - oneoffLabel = "com.docker.compose.oneoff" - slugLabel = "com.docker.compose.slug" - projectLabel = compose.ProjectTag - volumeLabel = compose.VolumeTag - workingDirLabel = "com.docker.compose.project.working_dir" - configFilesLabel = "com.docker.compose.project.config_files" - serviceLabel = compose.ServiceTag - versionLabel = "com.docker.compose.version" - configHashLabel = "com.docker.compose.config-hash" - networkLabel = compose.NetworkTag - - // ComposeVersion Compose version - ComposeVersion = "1.0-alpha" + "github.com/docker/docker/api/types/filters" ) func projectFilter(projectName string) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%s", projectLabel, projectName)) + return filters.Arg("label", fmt.Sprintf("%s=%s", compose.ProjectLabel, projectName)) } func serviceFilter(serviceName string) filters.KeyValuePair { - return filters.Arg("label", fmt.Sprintf("%s=%s", serviceLabel, serviceName)) + return filters.Arg("label", fmt.Sprintf("%s=%s", compose.ServiceLabel, serviceName)) +} + +func slugFilter(slug string) filters.KeyValuePair { + return filters.Arg("label", fmt.Sprintf("%s=%s", compose.SlugLabel, slug)) +} + +func oneOffFilter(b bool) filters.KeyValuePair { + v := "False" + if b { + v = "True" + } + return filters.Arg("label", fmt.Sprintf("%s=%s", compose.OneoffLabel, v)) +} + +func containerNumberFilter(index int) filters.KeyValuePair { + return filters.Arg("label", fmt.Sprintf("%s=%d", compose.ContainerNumberLabel, index)) } func hasProjectLabelFilter() filters.KeyValuePair { - return filters.Arg("label", projectLabel) + return filters.Arg("label", compose.ProjectLabel) } diff --git a/local/compose/images.go b/local/compose/images.go index dd27cafc..311f6791 100644 --- a/local/compose/images.go +++ b/local/compose/images.go @@ -42,7 +42,7 @@ func (s *composeService) Images(ctx context.Context, projectName string, options if len(options.Services) > 0 { // filter service containers for _, c := range allContainers { - if utils.StringContains(options.Services, c.Labels[compose.ServiceTag]) { + if utils.StringContains(options.Services, c.Labels[compose.ServiceLabel]) { containers = append(containers, c) } diff --git a/local/compose/kill_test.go b/local/compose/kill_test.go index 81caeb51..69bb01e8 100644 --- a/local/compose/kill_test.go +++ b/local/compose/kill_test.go @@ -86,7 +86,11 @@ func testContainer(service string, id string) apitypes.Container { func containerLabels(service string) map[string]string { workingdir, _ := filepath.Abs("testdata") composefile := filepath.Join(workingdir, "docker-compose.yml") - return map[string]string{serviceLabel: service, configFilesLabel: composefile, workingDirLabel: workingdir, projectLabel: testProject} + return map[string]string{ + compose.ServiceLabel: service, + compose.ConfigFilesLabel: composefile, + compose.WorkingDirLabel: workingdir, + compose.ProjectLabel: testProject} } func anyCancellableContext() gomock.Matcher { diff --git a/local/compose/logs.go b/local/compose/logs.go index 5cb55336..3d0323fc 100644 --- a/local/compose/logs.go +++ b/local/compose/logs.go @@ -37,7 +37,7 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer eg, ctx := errgroup.WithContext(ctx) for _, c := range list { c := c - service := c.Labels[serviceLabel] + service := c.Labels[compose.ServiceLabel] container, err := s.apiClient.ContainerInspect(ctx, c.ID) if err != nil { return err diff --git a/local/compose/ls.go b/local/compose/ls.go index 64a4eb6f..62d49b26 100644 --- a/local/compose/ls.go +++ b/local/compose/ls.go @@ -40,7 +40,7 @@ func (s *composeService) List(ctx context.Context, opts compose.ListOptions) ([] } func containersToStacks(containers []moby.Container) ([]compose.Stack, error) { - containersByLabel, keys, err := groupContainerByLabel(containers, projectLabel) + containersByLabel, keys, err := groupContainerByLabel(containers, compose.ProjectLabel) if err != nil { return nil, err } diff --git a/local/compose/ls_test.go b/local/compose/ls_test.go index 9d9ea9e9..c6a465a0 100644 --- a/local/compose/ls_test.go +++ b/local/compose/ls_test.go @@ -30,17 +30,17 @@ func TestContainersToStacks(t *testing.T) { { ID: "service1", State: "running", - Labels: map[string]string{projectLabel: "project1"}, + Labels: map[string]string{compose.ProjectLabel: "project1"}, }, { ID: "service2", State: "running", - Labels: map[string]string{projectLabel: "project1"}, + Labels: map[string]string{compose.ProjectLabel: "project1"}, }, { ID: "service3", State: "running", - Labels: map[string]string{projectLabel: "project2"}, + Labels: map[string]string{compose.ProjectLabel: "project2"}, }, } stacks, err := containersToStacks(containers) diff --git a/local/compose/port.go b/local/compose/port.go index c1023515..01207521 100644 --- a/local/compose/port.go +++ b/local/compose/port.go @@ -31,7 +31,7 @@ func (s *composeService) Port(ctx context.Context, project string, service strin Filters: filters.NewArgs( projectFilter(project), serviceFilter(service), - filters.Arg("label", fmt.Sprintf("%s=%d", containerNumberLabel, options.Index)), + containerNumberFilter(options.Index), ), }) if err != nil { diff --git a/local/compose/ps.go b/local/compose/ps.go index 95b0f4dd..a226db12 100644 --- a/local/compose/ps.go +++ b/local/compose/ps.go @@ -81,8 +81,8 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options com summary[i] = compose.ContainerSummary{ ID: container.ID, Name: getCanonicalContainerName(container), - Project: container.Labels[projectLabel], - Service: container.Labels[serviceLabel], + Project: container.Labels[compose.ProjectLabel], + Service: container.Labels[compose.ServiceLabel], State: container.State, Health: health, ExitCode: exitCode, diff --git a/local/compose/run.go b/local/compose/run.go index bc02d9fd..81a0c22e 100644 --- a/local/compose/run.go +++ b/local/compose/run.go @@ -50,8 +50,8 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types. } service.Scale = 1 service.StdinOpen = true - service.Labels = service.Labels.Add(slugLabel, slug) - service.Labels = service.Labels.Add(oneoffLabel, "True") + service.Labels = service.Labels.Add(compose.SlugLabel, slug) + service.Labels = service.Labels.Add(compose.OneoffLabel, "True") if err := s.ensureImagesExists(ctx, project, observedState, false); err != nil { // all dependencies already checked, but might miss service img return 0, err @@ -74,10 +74,8 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types. } containers, err := s.apiClient.ContainerList(ctx, apitypes.ContainerListOptions{ - Filters: filters.NewArgs( - filters.Arg("label", fmt.Sprintf("%s=%s", slugLabel, slug)), - ), - All: true, + Filters: filters.NewArgs(slugFilter(slug)), + All: true, }) if err != nil { return 0, err diff --git a/local/compose/start.go b/local/compose/start.go index 08b758e3..edd8c3e2 100644 --- a/local/compose/start.go +++ b/local/compose/start.go @@ -95,7 +95,7 @@ func (s *composeService) watchContainers(project *types.Project, services []stri listener(compose.ContainerEvent{ Type: compose.ContainerEventExit, Container: name, - Service: container.Labels[serviceLabel], + Service: container.Labels[compose.ServiceLabel], ExitCode: inspected.State.ExitCode, Restarting: willRestart, })