implemented enableLabel by a Filter

pull/173/head
Fabrizio Steiner 6 years ago
parent f5fb4ed6a2
commit 026a04b59b

@ -129,9 +129,9 @@ docker run -d --label=com.centurylinklabs.watchtower.stop-signal=SIGHUP someimag
## Selectively Watching Containers
By default, watchtower will watch all containers.
However, sometimes only some containers should be updated.
If you need to selectively watch containers, pass the --label-enable flag on startup and set the *com.centurylinklabs.watchtower.enable* label with a value of true for the containers you want to watch.
By default, watchtower will watch all containers. However, sometimes only some containers should be updated.
If you need to only include only some containers, pass the --label-enable flag on startup and set the *com.centurylinklabs.watchtower.enable* label with a value of true for the containers you want to watch.
```docker
LABEL com.centurylinklabs.watchtower.enable="true"

@ -6,14 +6,12 @@ import (
"github.com/v2tec/watchtower/container"
)
func watchtowerContainersFilter(c container.Container) bool { return c.IsWatchtower() }
// CheckPrereqs will ensure that there are not multiple instances of the
// watchtower running simultaneously. If multiple watchtower containers are
// detected, this function will stop and remove all but the most recently
// started container.
func CheckPrereqs(client container.Client, cleanup bool) error {
containers, err := client.ListContainers(watchtowerContainersFilter)
containers, err := client.ListContainers(container.WatchtowerContainersFilter)
if err != nil {
return err
}

@ -12,31 +12,14 @@ var (
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
)
func allContainersFilter(container.Container) bool { return true }
func containerFilter(names []string) container.Filter {
if len(names) == 0 {
return allContainersFilter
}
return func(c container.Container) bool {
for _, name := range names {
if (name == c.Name()) || (name == c.Name()[1:]) {
return true
}
}
return false
}
}
// Update looks at the running Docker containers to see if any of the images
// used to start those containers have been updated. If a change is detected in
// any of the images, the associated containers are stopped and restarted with
// the new image.
func Update(client container.Client, names []string, cleanup bool, noRestart bool, timeout time.Duration) error {
func Update(client container.Client, filter container.Filter, cleanup bool, noRestart bool, timeout time.Duration) error {
log.Debug("Checking containers for updated images")
containers, err := client.ListContainers(containerFilter(names))
containers, err := client.ListContainers(filter)
if err != nil {
return err
}

@ -5,10 +5,10 @@ import (
"io/ioutil"
"time"
log "github.com/sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/network"
dockerclient "github.com/docker/docker/client"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
)
@ -16,10 +16,6 @@ const (
defaultStopSignal = "SIGTERM"
)
// A Filter is a prototype for a function that can be used to filter the
// results from a call to the ListContainers() method on the Client.
type Filter func(Container) bool
// A Client is the interface through which watchtower interacts with the
// Docker API.
type Client interface {
@ -37,20 +33,19 @@ type Client interface {
// * DOCKER_HOST the docker-engine host to send api requests to
// * DOCKER_TLS_VERIFY whether to verify tls certificates
// * DOCKER_API_VERSION the minimum docker api version to work with
func NewClient(pullImages, enableLabel bool) Client {
func NewClient(pullImages bool) Client {
cli, err := dockerclient.NewEnvClient()
if err != nil {
log.Fatalf("Error instantiating Docker client: %s", err)
}
return dockerClient{api: cli, pullImages: pullImages, enableLabel: enableLabel}
return dockerClient{api: cli, pullImages: pullImages}
}
type dockerClient struct {
api *dockerclient.Client
pullImages bool
enableLabel bool
api *dockerclient.Client
pullImages bool
}
func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
@ -62,6 +57,7 @@ func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
runningContainers, err := client.api.ContainerList(
bg,
types.ContainerListOptions{})
if err != nil {
return nil, err
}
@ -79,15 +75,6 @@ func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
c := Container{containerInfo: &containerInfo, imageInfo: &imageInfo}
if client.enableLabel {
// If label filtering is enabled, containers should only be enabled
// if the label is specifically set to true.
enabledLabel, ok := c.Enabled()
if !ok || !enabledLabel {
continue
}
}
if fn(c) {
cs = append(cs, c)
}

@ -0,0 +1,61 @@
package container
// A Filter is a prototype for a function that can be used to filter the
// results from a call to the ListContainers() method on the Client.
type Filter func(FilterableContainer) bool
// A FilterableContainer is the interface which is used to filter
// containers.
type FilterableContainer interface {
Name() string
IsWatchtower() bool
Enabled() (bool, bool)
}
// WatchtowerContainersFilter filters only watchtower containers
func WatchtowerContainersFilter(c FilterableContainer) bool { return c.IsWatchtower() }
// Filter no containers and returns all
func noFilter(FilterableContainer) bool { return true }
// Filters containers which don't have a specified name
func filterByNames(names []string, baseFilter Filter) Filter {
if len(names) == 0 {
return baseFilter
}
return func(c FilterableContainer) bool {
for _, name := range names {
if (name == c.Name()) || (name == c.Name()[1:]) {
return baseFilter(c)
}
}
return false
}
}
// Filters out containers that don't have the 'enableLabel'
func filterByEnableLabel(baseFilter Filter) Filter {
return func(c FilterableContainer) bool {
// If label filtering is enabled, containers should only be enabled
// if the label is specifically set to true.
enabledLabel, ok := c.Enabled()
if !ok || !enabledLabel {
return false
}
return baseFilter(c)
}
}
// BuildFilter creates the needed filter of containers
func BuildFilter(names []string, enableLabel bool) Filter {
filter := noFilter
filter = filterByNames(names, filter)
if enableLabel {
// If label filtering is enabled, containers should only be considered
// if the label is specifically set.
filter = filterByEnableLabel(filter)
}
return filter
}

@ -29,6 +29,7 @@ var (
scheduleSpec string
cleanup bool
noRestart bool
enableLabel bool
notifier *notifications.Notifier
timeout time.Duration
)
@ -189,6 +190,7 @@ func before(c *cli.Context) error {
if timeout < 0 {
log.Fatal("Please specify a positive value for timeout value.")
}
enableLabel = c.GlobalBool("label-enable")
// configure environment vars for client
err := envConfig(c)
@ -196,7 +198,7 @@ func before(c *cli.Context) error {
return err
}
client = container.NewClient(!c.GlobalBool("no-pull"), c.GlobalBool("label-enable"))
client = container.NewClient(!c.GlobalBool("no-pull"))
notifier = notifications.NewNotifier(c)
return nil
@ -209,6 +211,8 @@ func start(c *cli.Context) error {
log.Fatal(err)
}
filter := container.BuildFilter(names, enableLabel)
tryLockSem := make(chan bool, 1)
tryLockSem <- true
@ -220,7 +224,7 @@ func start(c *cli.Context) error {
case v := <-tryLockSem:
defer func() { tryLockSem <- v }()
notifier.StartNotification()
if err := actions.Update(client, names, cleanup, noRestart, timeout); err != nil {
if err := actions.Update(client, filter, cleanup, noRestart, timeout); err != nil {
log.Println(err)
}
notifier.SendNotification()

Loading…
Cancel
Save