mirror of
https://github.com/containrrr/watchtower.git
synced 2025-03-03 15:32:37 +02:00
implemented enableLabel by a Filter
This commit is contained in:
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)
|
||||
}
|
||||
|
61
container/filters.go
Normal file
61
container/filters.go
Normal file
@ -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
|
||||
}
|
8
main.go
8
main.go
@ -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…
x
Reference in New Issue
Block a user