From c2dd40c161bef6a2c03e5d05f7218cf6e07e0a09 Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Wed, 13 Oct 2021 12:20:24 +0200 Subject: [PATCH] Fix network_mode "service:x" Signed-off-by: Ulysses Souza --- pkg/compose/convergence.go | 87 ++++++++++++++++++++------------------ pkg/compose/run.go | 7 +++ pkg/e2e/networks_test.go | 16 +++++++ 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index 0652cc585..29e76a87d 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -109,56 +109,61 @@ func (c *convergence) apply(ctx context.Context, project *types.Project, options var mu sync.Mutex // updateProject updates project after service converged, so dependent services relying on `service:xx` can refer to actual containers. -func (c *convergence) updateProject(project *types.Project, service string) { - containers := c.getObservedState(service) - if len(containers) == 0 { - return - } - container := containers[0] - +func (c *convergence) updateProject(project *types.Project, serviceName string) { // operation is protected by a Mutex so that we can safely update project.Services while running concurrent convergence on services mu.Lock() defer mu.Unlock() + cnts := c.getObservedState(serviceName) for i, s := range project.Services { - if d := getDependentServiceFromMode(s.NetworkMode); d == service { - s.NetworkMode = types.NetworkModeContainerPrefix + container.ID - } - if d := getDependentServiceFromMode(s.Ipc); d == service { - s.Ipc = types.NetworkModeContainerPrefix + container.ID - } - if d := getDependentServiceFromMode(s.Pid); d == service { - s.Pid = types.NetworkModeContainerPrefix + container.ID - } - var links []string - for _, serviceLink := range s.Links { - parts := strings.Split(serviceLink, ":") - serviceName := serviceLink - serviceAlias := "" - if len(parts) == 2 { - serviceName = parts[0] - serviceAlias = parts[1] - } - if serviceName != service { - links = append(links, serviceLink) - continue - } - for _, container := range containers { - name := getCanonicalContainerName(container) - if serviceAlias != "" { - links = append(links, - fmt.Sprintf("%s:%s", name, serviceAlias)) - } - links = append(links, - fmt.Sprintf("%s:%s", name, name), - fmt.Sprintf("%s:%s", name, getContainerNameWithoutProject(container))) - } - s.Links = links - } + updateServices(&s, cnts) project.Services[i] = s } } +func updateServices(service *types.ServiceConfig, cnts Containers) { + if len(cnts) == 0 { + return + } + cnt := cnts[0] + serviceName := cnt.Labels[api.ServiceLabel] + + if d := getDependentServiceFromMode(service.NetworkMode); d == serviceName { + service.NetworkMode = types.NetworkModeContainerPrefix + cnt.ID + } + if d := getDependentServiceFromMode(service.Ipc); d == serviceName { + service.Ipc = types.NetworkModeContainerPrefix + cnt.ID + } + if d := getDependentServiceFromMode(service.Pid); d == serviceName { + service.Pid = types.NetworkModeContainerPrefix + cnt.ID + } + var links []string + for _, serviceLink := range service.Links { + parts := strings.Split(serviceLink, ":") + serviceName := serviceLink + serviceAlias := "" + if len(parts) == 2 { + serviceName = parts[0] + serviceAlias = parts[1] + } + if serviceName != service.Name { + links = append(links, serviceLink) + continue + } + for _, container := range cnts { + name := getCanonicalContainerName(container) + if serviceAlias != "" { + links = append(links, + fmt.Sprintf("%s:%s", name, serviceAlias)) + } + links = append(links, + fmt.Sprintf("%s:%s", name, name), + fmt.Sprintf("%s:%s", name, getContainerNameWithoutProject(container))) + } + service.Links = links + } +} + func (c *convergence) ensureService(ctx context.Context, project *types.Project, service types.ServiceConfig, recreate string, inherit bool, timeout *time.Duration) error { expected, err := getScale(service) if err != nil { diff --git a/pkg/compose/run.go b/pkg/compose/run.go index 8722e7c10..4ad8bf2f9 100644 --- a/pkg/compose/run.go +++ b/pkg/compose/run.go @@ -164,6 +164,13 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project, return "", err } } + + observedState, err := s.getContainers(ctx, project.Name, oneOffInclude, true) + if err != nil { + return "", err + } + updateServices(&service, observedState) + created, err := s.createContainer(ctx, project, service, service.ContainerName, 1, opts.Detach && opts.AutoRemove, opts.UseNetworkAliases, true) if err != nil { return "", err diff --git a/pkg/e2e/networks_test.go b/pkg/e2e/networks_test.go index 3ebaedea1..3f979bc50 100644 --- a/pkg/e2e/networks_test.go +++ b/pkg/e2e/networks_test.go @@ -115,3 +115,19 @@ func TestIPAMConfig(t *testing.T) { _ = c.RunDockerCmd("compose", "--project-name", projectName, "down") }) } + +func TestNetworkModes(t *testing.T) { + c := NewParallelE2eCLI(t, binDir) + + const projectName = "network_mode_service_run" + + t.Run("run with service mode dependency", func(t *testing.T) { + res := c.RunDockerOrExitError("compose", "-f", "./fixtures/network-test/compose.yaml", "--project-name", projectName, "run", "mydb", "echo", "success") + res.Assert(t, icmd.Expected{Out: "success"}) + + }) + + t.Run("down", func(t *testing.T) { + _ = c.RunDockerCmd("compose", "--project-name", projectName, "down") + }) +}