From 97dd97b15b0a242b6401ca1dacc7dec73e445abe Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Fri, 13 Sep 2024 13:58:57 +0200 Subject: [PATCH] stop dependent containers before recreating diverged service Signed-off-by: Nicolas De Loof --- pkg/compose/convergence.go | 51 +++++++++++--------- pkg/e2e/compose_up_test.go | 20 ++++++++ pkg/e2e/fixtures/logging-driver/compose.yaml | 19 ++++++++ 3 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 pkg/e2e/fixtures/logging-driver/compose.yaml diff --git a/pkg/compose/convergence.go b/pkg/compose/convergence.go index a7c55d4caa8..5ad3c94b1f1 100644 --- a/pkg/compose/convergence.go +++ b/pkg/compose/convergence.go @@ -45,9 +45,6 @@ import ( ) const ( - extLifecycle = "x-lifecycle" - forceRecreate = "force_recreate" - doubledContainerNameWarning = "WARNING: The %q service is using the custom container name %q. " + "Docker requires each container to have a unique name. " + "Remove the custom name to scale the service.\n" @@ -108,9 +105,7 @@ func (c *convergence) apply(ctx context.Context, project *types.Project, options }) } -var mu sync.Mutex - -func (c *convergence) ensureService(ctx context.Context, project *types.Project, service types.ServiceConfig, recreate string, inherit bool, timeout *time.Duration) error { +func (c *convergence) ensureService(ctx context.Context, project *types.Project, service types.ServiceConfig, recreate string, inherit bool, timeout *time.Duration) error { //nolint:gocyclo expected, err := getScale(service) if err != nil { return err @@ -147,6 +142,7 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project, // If we don't get a container number (?) just sort by creation date return containers[i].Created < containers[j].Created }) + for i, container := range containers { if i >= expected { // Scale Down @@ -163,6 +159,11 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project, return err } if mustRecreate { + err := c.stopDependentContainers(ctx, project, service) + if err != nil { + return err + } + i, container := i, container eg.Go(tracing.SpanWrapFuncForErrGroup(ctx, "container/recreate", tracing.ContainerOptions(container), func(ctx context.Context) error { recreated, err := c.service.recreateContainer(ctx, project, service, container, inherit, timeout) @@ -217,6 +218,25 @@ func (c *convergence) ensureService(ctx context.Context, project *types.Project, return err } +func (c *convergence) stopDependentContainers(ctx context.Context, project *types.Project, service types.ServiceConfig) error { + w := progress.ContextWriter(ctx) + // Stop dependent containers, so they will be restarted after service is re-created + dependents := project.GetDependentsForService(service) + for _, name := range dependents { + dependents := c.observedState[name] + err := c.service.stopContainers(ctx, w, dependents, nil) + if err != nil { + return err + } + for i, dependent := range dependents { + dependent.State = ContainerExited + dependents[i] = dependent + } + c.observedState[name] = dependents + } + return nil +} + func getScale(config types.ServiceConfig) (int, error) { scale := config.GetScale() if scale > 1 && config.ContainerName != "" { @@ -296,7 +316,7 @@ func mustRecreate(expected types.ServiceConfig, actual moby.Container, policy st if policy == api.RecreateNever { return false, nil } - if policy == api.RecreateForce || expected.Extensions[extLifecycle] == forceRecreate { + if policy == api.RecreateForce { return true, nil } configHash, err := ServiceHash(expected) @@ -535,26 +555,9 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P } w.Event(progress.NewEvent(getContainerProgressName(replaced), progress.Done, "Recreated")) - setDependentLifecycle(project, service.Name, forceRecreate) return created, err } -// setDependentLifecycle define the Lifecycle strategy for all services to depend on specified service -func setDependentLifecycle(project *types.Project, service string, strategy string) { - mu.Lock() - defer mu.Unlock() - - for i, s := range project.Services { - if utils.StringContains(s.GetDependencies(), service) { - if s.Extensions == nil { - s.Extensions = map[string]interface{}{} - } - s.Extensions[extLifecycle] = strategy - project.Services[i] = s - } - } -} - func (s *composeService) startContainer(ctx context.Context, container moby.Container) error { w := progress.ContextWriter(ctx) w.Event(progress.NewEvent(getContainerProgressName(container), progress.Working, "Restart")) diff --git a/pkg/e2e/compose_up_test.go b/pkg/e2e/compose_up_test.go index 87cfebce255..95bb358f071 100644 --- a/pkg/e2e/compose_up_test.go +++ b/pkg/e2e/compose_up_test.go @@ -90,3 +90,23 @@ func TestStdoutStderr(t *testing.T) { c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans") } + +func TestLoggingDriver(t *testing.T) { + c := NewCLI(t) + const projectName = "e2e-logging-driver" + + host := "HOST=127.0.0.1" + res := c.RunDockerCmd(t, "info", "-f", "{{.OperatingSystem}}") + os := res.Stdout() + if strings.TrimSpace(os) == "Docker Desktop" { + host = "HOST=host.docker.internal" + } + + cmd := c.NewDockerComposeCmd(t, "-f", "fixtures/logging-driver/compose.yaml", "--project-name", projectName, "up", "-d") + cmd.Env = append(cmd.Env, host, "BAR=foo") + icmd.RunCmd(cmd).Assert(t, icmd.Success) + + cmd = c.NewDockerComposeCmd(t, "-f", "fixtures/logging-driver/compose.yaml", "--project-name", projectName, "up", "-d") + cmd.Env = append(cmd.Env, host, "BAR=zot") + icmd.RunCmd(cmd).Assert(t, icmd.Success) +} diff --git a/pkg/e2e/fixtures/logging-driver/compose.yaml b/pkg/e2e/fixtures/logging-driver/compose.yaml new file mode 100644 index 00000000000..37b3e8b3e4d --- /dev/null +++ b/pkg/e2e/fixtures/logging-driver/compose.yaml @@ -0,0 +1,19 @@ +services: + fluentbit: + image: fluent/fluent-bit:3.1.7-debug + ports: + - "24224:24224" + - "24224:24224/udp" + environment: + FOO: ${BAR} + + app: + image: nginx + depends_on: + fluentbit: + condition: service_started + restart: true + logging: + driver: fluentd + options: + fluentd-address: ${HOST:-127.0.0.1}:24224