diff --git a/cmd/docker-gen/main.go b/cmd/docker-gen/main.go index a28deeac..01cf4310 100644 --- a/cmd/docker-gen/main.go +++ b/cmd/docker-gen/main.go @@ -7,6 +7,7 @@ import ( "os" "os/signal" "path/filepath" + "strings" "syscall" "github.com/BurntSushi/toml" @@ -16,6 +17,7 @@ import ( ) type stringslice []string +type notifyfilter map[string][]string var ( buildVersion string @@ -26,6 +28,7 @@ var ( notifyOutput bool notifyContainerID string notifyContainerSignal int + notifyContainerFilter notifyfilter = make(notifyfilter) onlyExposed bool onlyPublished bool includeStopped bool @@ -50,6 +53,16 @@ func (strings *stringslice) Set(value string) error { return nil } +func (filter *notifyfilter) String() string { + return "[string][]string" +} + +func (filter *notifyfilter) Set(value string) error { + name, value, _ := strings.Cut(value, "=") + (*filter)[name] = append((*filter)[name], value) + return nil +} + func usage() { println(`Usage: docker-gen [options] template [dest] @@ -102,6 +115,8 @@ func initFlags() { "container to send a signal to") flag.IntVar(¬ifyContainerSignal, "notify-signal", int(docker.SIGHUP), "signal to send to the notify-container. Defaults to SIGHUP") + flag.Var(¬ifyContainerFilter, "notify-filter", + "container filter for notification (e.g -notify-filter name=foo). You can have multiple of these. https://docs.docker.com/engine/reference/commandline/ps/#filter") flag.Var(&configFiles, "config", "config files with template directives. Config files will be merged if this option is specified multiple times.") flag.IntVar(&interval, "interval", 0, "notify command interval (secs)") flag.BoolVar(&keepBlankLines, "keep-blank-lines", false, "keep blank lines in the output file") @@ -161,6 +176,10 @@ func main() { if notifyContainerID != "" { cfg.NotifyContainers[notifyContainerID] = notifyContainerSignal } + if len(notifyContainerFilter) > 0 { + cfg.NotifyContainersFilter = notifyContainerFilter + cfg.NotifyContainersSignal = notifyContainerSignal + } configs = config.ConfigFile{ Config: []config.Config{cfg}} } diff --git a/internal/config/config.go b/internal/config/config.go index 03403022..38ac223c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,18 +7,20 @@ import ( ) type Config struct { - Template string - Dest string - Watch bool - Wait *Wait - NotifyCmd string - NotifyOutput bool - NotifyContainers map[string]int - OnlyExposed bool - OnlyPublished bool - IncludeStopped bool - Interval int - KeepBlankLines bool + Template string + Dest string + Watch bool + Wait *Wait + NotifyCmd string + NotifyOutput bool + NotifyContainers map[string]int + NotifyContainersFilter map[string][]string + NotifyContainersSignal int + OnlyExposed bool + OnlyPublished bool + IncludeStopped bool + Interval int + KeepBlankLines bool } type ConfigFile struct { diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 6d5cb15e..fb9cea12 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -133,6 +133,7 @@ func (g *generator) generateFromContainers() { } g.runNotifyCmd(config) g.sendSignalToContainer(config) + g.sendSignalToContainers(config) } } @@ -163,6 +164,7 @@ func (g *generator) generateAtInterval() { template.GenerateFile(cfg, containers) g.runNotifyCmd(cfg) g.sendSignalToContainer(cfg) + g.sendSignalToContainers(cfg) case sig := <-sigChan: log.Printf("Received signal: %s\n", sig) switch sig { @@ -211,6 +213,7 @@ func (g *generator) generateFromEvents() { } g.runNotifyCmd(cfg) g.sendSignalToContainer(cfg) + g.sendSignalToContainers(cfg) } }(cfg) } @@ -357,6 +360,36 @@ func (g *generator) sendSignalToContainer(config config.Config) { } } +func (g *generator) sendSignalToContainers(config config.Config) { + if len(config.NotifyContainersFilter) < 1 { + return + } + + containers, err := g.Client.ListContainers(docker.ListContainersOptions{ + Filters: config.NotifyContainersFilter, + }) + if err != nil { + log.Printf("Error getting containers: %s", err) + return + } + for _, container := range containers { + log.Printf("Sending container '%s' signal '%v'", container.ID, config.NotifyContainersSignal) + if config.NotifyContainersSignal == -1 { + if err := g.Client.RestartContainer(container.ID, 10); err != nil { + log.Printf("Error sending restarting container: %s", err) + } + } else { + killOpts := docker.KillContainerOptions{ + ID: container.ID, + Signal: docker.Signal(config.NotifyContainersSignal), + } + if err := g.Client.KillContainer(killOpts); err != nil { + log.Printf("Error sending signal to container: %s", err) + } + } + } +} + func (g *generator) getContainers() ([]*context.RuntimeContainer, error) { apiInfo, err := g.Client.Info() if err != nil {