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 | 79 ++++++++++++++++++++------------------ pkg/compose/run.go | 7 ++++ pkg/e2e/networks_test.go | 16 ++++++++ 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index 0652cc585fa..29e76a87d67 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -109,53 +109,58 @@ 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 + 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 d := getDependentServiceFromMode(s.Pid); d == service { - s.Pid = types.NetworkModeContainerPrefix + container.ID + if serviceName != service.Name { + links = append(links, serviceLink) + continue } - 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)) - } + for _, container := range cnts { + name := getCanonicalContainerName(container) + if serviceAlias != "" { links = append(links, - fmt.Sprintf("%s:%s", name, name), - fmt.Sprintf("%s:%s", name, getContainerNameWithoutProject(container))) + fmt.Sprintf("%s:%s", name, serviceAlias)) } - s.Links = links + links = append(links, + fmt.Sprintf("%s:%s", name, name), + fmt.Sprintf("%s:%s", name, getContainerNameWithoutProject(container))) } - project.Services[i] = s + service.Links = links } } diff --git a/pkg/compose/run.go b/pkg/compose/run.go index 8722e7c1018..4ad8bf2f9d1 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 3ebaedea132..3f979bc50e1 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") + }) +}