From fd63d2d960e01fd89af4f39e30a9856d7e40d3b2 Mon Sep 17 00:00:00 2001
From: Dmitriy Tarasov <tarasov65536@gmail.com>
Date: Sat, 26 Aug 2023 15:26:14 +0300
Subject: [PATCH 1/2] -notify-filter argument

---
 cmd/docker-gen/main.go          | 19 +++++++++++++++++++
 internal/config/config.go       | 26 ++++++++++++++------------
 internal/generator/generator.go | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 12 deletions(-)

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(&notifyContainerSignal, "notify-signal", int(docker.SIGHUP),
 		"signal to send to the notify-container. Defaults to SIGHUP")
+	flag.Var(&notifyContainerFilter, "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 240de21a..92941453 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,35 @@ 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 {
+		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 {

From 18f7234d8f0ba82f13a42898676c9d3ee17c1b1e Mon Sep 17 00:00:00 2001
From: Dmitriy Tarasov <tarasov65536@gmail.com>
Date: Sat, 26 Aug 2023 18:13:59 +0300
Subject: [PATCH 2/2] add missing log in sendSignalToContainers

---
 internal/generator/generator.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/internal/generator/generator.go b/internal/generator/generator.go
index 92941453..d440939c 100644
--- a/internal/generator/generator.go
+++ b/internal/generator/generator.go
@@ -373,6 +373,7 @@ func (g *generator) sendSignalToContainers(config config.Config) {
 		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)