restart only needed services by checking depends_on relations

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
Guillaume Lours 2023-03-01 17:34:33 +01:00
parent a3bed265f2
commit 3cfbac6624
No known key found for this signature in database
5 changed files with 52 additions and 4 deletions

View File

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

View File

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

View File

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

View File

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

View File

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