Browse Source

restart only needed services by checking depends_on relations

Signed-off-by: Guillaume Lours <[email protected]>
Guillaume Lours 2 years ago
parent
commit
3cfbac6624

+ 7 - 1
pkg/compose/compose.go

@@ -21,6 +21,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"strconv"
 	"strings"
 
 	"github.com/compose-spec/compose-go/types"
@@ -181,13 +182,18 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
 			for _, dc := range strings.Split(dependencies, ",") {
 				dcArr := strings.Split(dc, ":")
 				condition := ServiceConditionRunningOrHealthy
+				// Let's restart the dependency by default if we don't have the info stored in the label
+				restart := true
 				dependency := dcArr[0]
 
 				// backward compatibility
 				if len(dcArr) > 1 {
 					condition = dcArr[1]
+					if len(dcArr) > 2 {
+						restart, _ = strconv.ParseBool(dcArr[2])
+					}
 				}
-				service.DependsOn[dependency] = types.ServiceDependency{Condition: condition}
+				service.DependsOn[dependency] = types.ServiceDependency{Condition: condition, Restart: restart}
 			}
 		}
 		project.Services = append(project.Services, *service)

+ 1 - 1
pkg/compose/create.go

@@ -470,7 +470,7 @@ func (s *composeService) prepareLabels(service types.ServiceConfig, number int)
 
 	var dependencies []string
 	for s, d := range service.DependsOn {
-		dependencies = append(dependencies, s+":"+d.Condition)
+		dependencies = append(dependencies, fmt.Sprintf("%s:%s:%t", s, d.Condition, d.Restart))
 	}
 	labels[api.DependenciesLabel] = strings.Join(dependencies, ",")
 	return labels, nil

+ 3 - 2
pkg/compose/restart.go

@@ -20,6 +20,7 @@ import (
 	"context"
 	"strings"
 
+	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/progress"
 	"github.com/docker/compose/v2/pkg/utils"
@@ -57,8 +58,8 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
 		project.Services[i] = service
 	}
 
-	if len(options.Services) == 0 {
-		err = project.ForServices(options.Services)
+	if len(options.Services) != 0 {
+		err = project.ForServices(options.Services, types.IncludeDependents)
 		if err != nil {
 			return err
 		}

+ 20 - 0
pkg/e2e/fixtures/restart-test/compose-depends-on.yaml

@@ -0,0 +1,20 @@
+services:
+  with-restart:
+    image: alpine
+    command: tail -f /dev/null
+    depends_on:
+      nginx: {condition: service_healthy, restart: true}
+
+  no-restart:
+    image: alpine
+    command: tail -f /dev/null
+    depends_on:
+      nginx: { condition: service_healthy }
+
+  nginx:
+    image: nginx:alpine
+    healthcheck:
+      test:     "echo | nc -w 5 localhost:80"
+      interval: 2s
+      timeout:  1s
+      retries:  10

+ 21 - 0
pkg/e2e/restart_test.go

@@ -63,3 +63,24 @@ func TestRestart(t *testing.T) {
 		c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
 	})
 }
+
+func TestRestartWithDependencies(t *testing.T) {
+	c := NewParallelCLI(t, WithEnv(
+		"COMPOSE_PROJECT_NAME=e2e-restart-deps",
+	))
+	baseService := "nginx"
+	depWithRestart := "with-restart"
+	depNoRestart := "no-restart"
+
+	t.Cleanup(func() {
+		c.RunDockerComposeCmd(t, "down", "--remove-orphans")
+	})
+
+	c.RunDockerComposeCmd(t, "-f", "./fixtures/restart-test/compose-depends-on.yaml", "up", "-d")
+
+	res := c.RunDockerComposeCmd(t, "restart", baseService)
+	fmt.Println(res.Combined())
+	assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf("Container e2e-restart-deps-%s-1  Started", baseService)), res.Combined())
+	assert.Assert(t, strings.Contains(res.Combined(), fmt.Sprintf("Container e2e-restart-deps-%s-1  Started", depWithRestart)), res.Combined())
+	assert.Assert(t, !strings.Contains(res.Combined(), depNoRestart), res.Combined())
+}