1
0
mirror of https://github.com/containrrr/watchtower.git synced 2024-12-15 09:14:13 +02:00
watchtower/actions/update.go
Brian DeHamer b7424e5c47 Fix issue where updated containers aren't stopped
Used 'break' instead of 'continue' resulting in the termination of the
stop container loop any time the watchtower container is encountered.
2015-07-24 21:11:49 +00:00

104 lines
2.2 KiB
Go

package actions
import (
"math/rand"
"github.com/CenturyLinkLabs/watchtower/container"
log "github.com/Sirupsen/logrus"
)
var (
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
func allContainersFilter(container.Container) bool { return true }
func Update(client container.Client) error {
log.Info("Checking containers for updated images")
containers, err := client.ListContainers(allContainersFilter)
if err != nil {
return err
}
for i, container := range containers {
stale, err := client.IsContainerStale(container)
if err != nil {
return err
}
containers[i].Stale = stale
}
containers, err = container.SortByDependencies(containers)
if err != nil {
return err
}
checkDependencies(containers)
// Stop stale containers in reverse order
for i := len(containers) - 1; i >= 0; i-- {
container := containers[i]
if container.IsWatchtower() {
continue
}
if container.Stale {
if err := client.StopContainer(container, 10); err != nil {
return err
}
}
}
// Restart stale containers in sorted order
for _, container := range containers {
if container.Stale {
// Since we can't shutdown a watchtower container immediately, we need to
// start the new one while the old one is still running. This prevents us
// from re-using the same container name so we first rename the current
// instance so that the new one can adopt the old name.
if container.IsWatchtower() {
if err := client.RenameContainer(container, randName()); err != nil {
return err
}
}
if err := client.StartContainer(container); err != nil {
return err
}
}
}
return nil
}
func checkDependencies(containers []container.Container) {
for i, parent := range containers {
if parent.Stale {
continue
}
LinkLoop:
for _, linkName := range parent.Links() {
for _, child := range containers {
if child.Name() == linkName && child.Stale {
containers[i].Stale = true
break LinkLoop
}
}
}
}
}
// Generates a random, 32-character, Docker-compatible container name.
func randName() string {
b := make([]rune, 32)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}