Fix concurrent map read/write when recreating containers

Signed-off-by: Luis Rascao <luis.rascao@gmail.com>
This commit is contained in:
Luis Rascao 2023-03-17 09:49:39 +00:00 committed by Nicolas De loof
parent 9ec43973e2
commit bfeb1dc277
2 changed files with 37 additions and 18 deletions

View File

@ -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
}

View File

@ -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