fix: linked/depends-on container restarting (#1103)

This commit is contained in:
nils måsén 2022-01-11 17:15:22 +01:00 committed by GitHub
parent aa02d8d31b
commit 084249c5fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 358 additions and 21 deletions

View file

@ -9,6 +9,7 @@ import (
"github.com/containrrr/watchtower/pkg/sorter"
"github.com/containrrr/watchtower/pkg/types"
log "github.com/sirupsen/logrus"
"strings"
)
// Update looks at the running Docker containers to see if any of the images
@ -68,7 +69,7 @@ func Update(client container.Client, params types.UpdateParams) (types.Report, e
return nil, err
}
checkDependencies(containers)
UpdateImplicitRestart(containers)
var containersToUpdate []container.Container
if !params.MonitorOnly {
@ -216,24 +217,41 @@ func restartStaleContainer(container container.Container, client container.Clien
return nil
}
func checkDependencies(containers []container.Container) {
// UpdateImplicitRestart iterates through the passed containers, setting the
// `LinkedToRestarting` flag if any of it's linked containers are marked for restart
func UpdateImplicitRestart(containers []container.Container) {
for _, c := range containers {
for ci, c := range containers {
if c.ToRestart() {
// The container is already marked for restart, no need to check
continue
}
LinkLoop:
for _, linkName := range c.Links() {
for _, candidate := range containers {
if candidate.Name() != linkName {
continue
}
if candidate.ToRestart() {
c.LinkedToRestarting = true
break LinkLoop
}
if link := linkedContainerMarkedForRestart(c.Links(), containers); link != "" {
log.WithFields(log.Fields{
"restarting": link,
"linked": c.Name(),
}).Debug("container is linked to restarting")
// NOTE: To mutate the array, the `c` variable cannot be used as it's a copy
containers[ci].LinkedToRestarting = true
}
}
}
// linkedContainerMarkedForRestart returns the name of the first link that matches a
// container marked for restart
func linkedContainerMarkedForRestart(links []string, containers []container.Container) string {
for _, linkName := range links {
// Since the container names need to start with '/', let's prepend it if it's missing
if !strings.HasPrefix(linkName, "/") {
linkName = "/" + linkName
}
for _, candidate := range containers {
if candidate.Name() == linkName && candidate.ToRestart() {
return linkName
}
}
}
return ""
}

View file

@ -20,6 +20,7 @@ var _ = Describe("the update action", func() {
BeforeEach(func() {
pullImages := false
removeVolumes := false
//goland:noinspection GoBoolExpressions
client = CreateMockClient(
&TestData{
NameOfContainerToKeep: "test-container-02",
@ -255,6 +256,54 @@ var _ = Describe("the update action", func() {
})
})
When("container is linked to restarting containers", func() {
It("should be marked for restart", func() {
provider := CreateMockContainerWithConfig(
"test-container-provider",
"/test-container-provider",
"fake-image2:latest",
true,
false,
time.Now(),
&dockerContainer.Config{
Labels: map[string]string{},
ExposedPorts: map[nat.Port]struct{}{},
})
provider.Stale = true
consumer := CreateMockContainerWithConfig(
"test-container-consumer",
"/test-container-consumer",
"fake-image3:latest",
true,
false,
time.Now(),
&dockerContainer.Config{
Labels: map[string]string{
"com.centurylinklabs.watchtower.depends-on": "test-container-provider",
},
ExposedPorts: map[nat.Port]struct{}{},
})
containers := []container.Container{
provider,
consumer,
}
Expect(provider.ToRestart()).To(BeTrue())
Expect(consumer.ToRestart()).To(BeFalse())
actions.UpdateImplicitRestart(containers)
Expect(containers[0].ToRestart()).To(BeTrue())
Expect(containers[1].ToRestart()).To(BeTrue())
})
})
When("container is not running", func() {
BeforeEach(func() {
client = CreateMockClient(