From bfeb1dc2775c962c6994c662d063e18f2ac9956d Mon Sep 17 00:00:00 2001 From: Luis Rascao Date: Fri, 17 Mar 2023 09:49:39 +0000 Subject: [PATCH] Fix concurrent map read/write when recreating containers Signed-off-by: Luis Rascao --- pkg/compose/convergence.go | 33 +++++++++++++++++++++++++++------ pkg/compose/create.go | 22 ++++++++++------------ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index b473a00bd..5fbebd4c7 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -399,7 +399,8 @@ func (s *composeService) createContainer(ctx context.Context, project *types.Pro w := progress.ContextWriter(ctx) eventName := "Container " + name w.Event(progress.CreatingEvent(eventName)) - container, err = s.createMobyContainer(ctx, project, service, name, number, nil, autoRemove, useNetworkAliases, attachStdin, w) + container, err = s.createMobyContainer(ctx, project, service, name, number, nil, + autoRemove, useNetworkAliases, attachStdin, w, mergeLabels(service.Labels, service.CustomLabels)) if err != nil { return } @@ -424,8 +425,9 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P } name := getContainerName(project.Name, service, number) tmpName := fmt.Sprintf("%s_%s", replaced.ID[:12], name) - service.CustomLabels[api.ContainerReplaceLabel] = replaced.ID - created, err = s.createMobyContainer(ctx, project, service, tmpName, number, inherited, false, true, false, w) + created, err = s.createMobyContainer(ctx, project, service, tmpName, number, inherited, + false, true, false, w, + mergeLabels(service.Labels, service.CustomLabels).Add(api.ContainerReplaceLabel, replaced.ID)) if err != nil { return created, err } @@ -475,10 +477,19 @@ func (s *composeService) startContainer(ctx context.Context, container moby.Cont return nil } -func (s *composeService) createMobyContainer(ctx context.Context, project *types.Project, service types.ServiceConfig, - name string, number int, inherit *moby.Container, autoRemove bool, useNetworkAliases bool, attachStdin bool, w progress.Writer) (moby.Container, error) { +func (s *composeService) createMobyContainer(ctx context.Context, + project *types.Project, + service types.ServiceConfig, + name string, + number int, + inherit *moby.Container, + autoRemove, useNetworkAliases, attachStdin bool, + w progress.Writer, + labels types.Labels, +) (moby.Container, error) { var created moby.Container - containerConfig, hostConfig, networkingConfig, err := s.getCreateOptions(ctx, project, service, number, inherit, autoRemove, attachStdin) + containerConfig, hostConfig, networkingConfig, err := s.getCreateOptions(ctx, project, service, number, inherit, + autoRemove, attachStdin, labels) if err != nil { return created, err } @@ -725,3 +736,13 @@ func (s *composeService) startService(ctx context.Context, project *types.Projec } return nil } + +func mergeLabels(ls ...types.Labels) types.Labels { + merged := types.Labels{} + for _, l := range ls { + for k, v := range l { + merged[k] = v + } + } + return merged +} diff --git a/pkg/compose/create.go b/pkg/compose/create.go index 1a16a51cd..e35c41675 100644 --- a/pkg/compose/create.go +++ b/pkg/compose/create.go @@ -236,10 +236,16 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type return nil } -func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig, - number int, inherit *moby.Container, autoRemove bool, attachStdin bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { +func (s *composeService) getCreateOptions(ctx context.Context, + p *types.Project, + service types.ServiceConfig, + number int, + inherit *moby.Container, + autoRemove, attachStdin bool, + labels types.Labels, +) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { - labels, err := s.prepareLabels(service, number) + labels, err := s.prepareLabels(labels, service, number) if err != nil { return nil, nil, nil, err } @@ -451,15 +457,7 @@ func parseSecurityOpts(p *types.Project, securityOpts []string) ([]string, bool, return parsed, unconfined, nil } -func (s *composeService) prepareLabels(service types.ServiceConfig, number int) (map[string]string, error) { - labels := map[string]string{} - for k, v := range service.Labels { - labels[k] = v - } - for k, v := range service.CustomLabels { - labels[k] = v - } - +func (s *composeService) prepareLabels(labels types.Labels, service types.ServiceConfig, number int) (map[string]string, error) { hash, err := ServiceHash(service) if err != nil { return nil, err