@@ -13,9 +13,10 @@ import (
1313 "os"
1414 "os/exec"
1515 "os/signal"
16-
1716 "strings"
17+ "sync"
1818 "syscall"
19+ "time"
1920)
2021
2122var (
2425 onlyExposed bool
2526 configFile string
2627 configs ConfigFile
28+ interval int
29+ wg sync.WaitGroup
2730)
2831
2932type Event struct {
@@ -49,6 +52,7 @@ type Config struct {
4952 Watch bool
5053 NotifyCmd string
5154 OnlyExposed bool
55+ Interval int
5256}
5357
5458type ConfigFile struct {
@@ -73,7 +77,7 @@ func (r *RuntimeContainer) Equals(o RuntimeContainer) bool {
7377}
7478
7579func usage () {
76- println ("Usage: docker-gen [-config file] [-watch=false] [-notify=\" restart xyz\" ] <template> [<dest>]" )
80+ println ("Usage: docker-gen [-config file] [-watch=false] [-notify=\" restart xyz\" ] [-interval=0] <template> [<dest>]" )
7781}
7882
7983func newConn () (* httputil.ClientConn , error ) {
@@ -141,13 +145,12 @@ func getEvents() chan *Event {
141145 return eventChan
142146}
143147
144- func generateFromContainers (client * docker.Client ) {
148+ func getContainers (client * docker.Client ) ([] * RuntimeContainer , error ) {
145149 apiContainers , err := client .ListContainers (docker.ListContainersOptions {
146150 All : false ,
147151 })
148152 if err != nil {
149- fmt .Printf ("error listing containers: %s\n " , err )
150- return
153+ return nil , err
151154 }
152155
153156 containers := []* RuntimeContainer {}
@@ -179,15 +182,21 @@ func generateFromContainers(client *docker.Client) {
179182
180183 containers = append (containers , runtimeContainer )
181184 }
185+ return containers , nil
182186
187+ }
188+ func generateFromContainers (client * docker.Client ) {
189+ containers , err := getContainers (client )
190+ if err != nil {
191+ fmt .Printf ("error listing containers: %s\n " , err )
192+ return
193+ }
183194 for _ , config := range configs .Config {
184195 changed := generateFile (config , containers )
185196 if changed {
186197 runNotifyCmd (config )
187198 }
188-
189199 }
190-
191200}
192201
193202func runNotifyCmd (config Config ) {
@@ -212,11 +221,62 @@ func loadConfig(file string) error {
212221 return nil
213222}
214223
224+ func generateAtInterval (client * docker.Client , configs ConfigFile ) {
225+ for _ , config := range configs .Config {
226+
227+ if config .Interval == 0 {
228+ continue
229+ }
230+
231+ wg .Add (1 )
232+ ticker := time .NewTicker (time .Duration (config .Interval ) * time .Second )
233+ quit := make (chan struct {})
234+ go func () {
235+ for {
236+ select {
237+ case <- ticker .C :
238+ containers , err := getContainers (client )
239+ if err != nil {
240+ fmt .Printf ("error listing containers: %s\n " , err )
241+ continue
242+ }
243+ // ignore changed return value. always run notify command
244+ generateFile (config , containers )
245+ runNotifyCmd (config )
246+ case <- quit :
247+ ticker .Stop ()
248+ return
249+ }
250+ }
251+ wg .Done ()
252+ }()
253+ }
254+ }
255+
256+ func generateFromEvents (client * docker.Client , configs ConfigFile ) {
257+ configs = configs .filterWatches ()
258+ if len (configs .Config ) == 0 {
259+ return
260+ }
261+
262+ wg .Add (1 )
263+ eventChan := getEvents ()
264+ for {
265+ event := <- eventChan
266+ if event .Status == "start" || event .Status == "stop" || event .Status == "die" {
267+ generateFromContainers (client )
268+ }
269+ }
270+ wg .Done ()
271+
272+ }
273+
215274func main () {
216275 flag .BoolVar (& watch , "watch" , false , "watch for container changes" )
217276 flag .BoolVar (& onlyExposed , "only-exposed" , false , "only include containers with exposed ports" )
218277 flag .StringVar (& notifyCmd , "notify" , "" , "run command after template is regenerated" )
219278 flag .StringVar (& configFile , "config" , "" , "config file with template directives" )
279+ flag .IntVar (& interval , "interval" , 0 , "notify command interval (s)" )
220280 flag .Parse ()
221281
222282 if flag .NArg () < 1 && configFile == "" {
@@ -237,6 +297,7 @@ func main() {
237297 Watch : watch ,
238298 NotifyCmd : notifyCmd ,
239299 OnlyExposed : onlyExposed ,
300+ Interval : interval ,
240301 }
241302 configs = ConfigFile {
242303 Config : []Config {config }}
@@ -250,19 +311,7 @@ func main() {
250311 }
251312
252313 generateFromContainers (client )
253-
254- configs = configs .filterWatches ()
255-
256- if len (configs .Config ) == 0 {
257- return
258- }
259-
260- eventChan := getEvents ()
261- for {
262- event := <- eventChan
263- if event .Status == "start" || event .Status == "stop" || event .Status == "die" {
264- generateFromContainers (client )
265- }
266- }
267-
314+ generateAtInterval (client , configs )
315+ generateFromEvents (client , configs )
316+ wg .Wait ()
268317}
0 commit comments