1
1
package main
2
2
3
3
import (
4
- "errors"
5
4
"flag"
6
5
"fmt"
7
6
"log"
8
7
"os"
9
- "os/exec"
10
8
"path/filepath"
11
- "strings"
12
9
"sync"
13
- "time"
14
10
15
11
"github.com/BurntSushi/toml"
16
12
docker "github.com/fsouza/go-dockerclient"
41
37
wg sync.WaitGroup
42
38
)
43
39
44
- type Event struct {
45
- ContainerID string `json:"id"`
46
- Status string `json:"status"`
47
- Image string `json:"from"`
48
- }
49
-
50
40
func (strings * stringslice ) String () string {
51
41
return "[]"
52
42
}
@@ -73,90 +63,12 @@ Arguments:
73
63
println (`
74
64
Environment Variables:
75
65
DOCKER_HOST - default value for -endpoint
76
- DOCKER_CERT_PATH - directory path containing key.pem, cert.pm and ca.pem
66
+ DOCKER_CERT_PATH - directory path containing key.pem, cert.pem and ca.pem
77
67
DOCKER_TLS_VERIFY - enable client TLS verification
78
68
` )
79
69
println (`For more information, see https://github.com/jwilder/docker-gen` )
80
70
}
81
71
82
- func tlsEnabled () bool {
83
- for _ , v := range []string {tlsCert , tlsCaCert , tlsKey } {
84
- if e , err := pathExists (v ); e && err == nil {
85
- return true
86
- }
87
- }
88
- return false
89
- }
90
-
91
- func NewDockerClient (endpoint string ) (* docker.Client , error ) {
92
- if strings .HasPrefix (endpoint , "unix:" ) {
93
- return docker .NewClient (endpoint )
94
- } else if tlsVerify || tlsEnabled () {
95
- if tlsVerify {
96
- if e , err := pathExists (tlsCaCert ); ! e || err != nil {
97
- return nil , errors .New ("TLS verification was requested, but CA cert does not exist" )
98
- }
99
- }
100
-
101
- return docker .NewTLSClient (endpoint , tlsCert , tlsKey , tlsCaCert )
102
- }
103
- return docker .NewClient (endpoint )
104
- }
105
-
106
- func generateFromContainers (client * docker.Client ) {
107
- containers , err := dockergen .GetContainers (client )
108
- if err != nil {
109
- log .Printf ("error listing containers: %s\n " , err )
110
- return
111
- }
112
- for _ , config := range configs .Config {
113
- changed := dockergen .GenerateFile (config , containers )
114
- if ! changed {
115
- log .Printf ("Contents of %s did not change. Skipping notification '%s'" , config .Dest , config .NotifyCmd )
116
- continue
117
- }
118
- runNotifyCmd (config )
119
- sendSignalToContainer (client , config )
120
- }
121
- }
122
-
123
- func runNotifyCmd (config dockergen.Config ) {
124
- if config .NotifyCmd == "" {
125
- return
126
- }
127
-
128
- log .Printf ("Running '%s'" , config .NotifyCmd )
129
- cmd := exec .Command ("/bin/sh" , "-c" , config .NotifyCmd )
130
- out , err := cmd .CombinedOutput ()
131
- if err != nil {
132
- log .Printf ("Error running notify command: %s, %s\n " , config .NotifyCmd , err )
133
- }
134
- if config .NotifyOutput {
135
- for _ , line := range strings .Split (string (out ), "\n " ) {
136
- if line != "" {
137
- log .Printf ("[%s]: %s" , config .NotifyCmd , line )
138
- }
139
- }
140
- }
141
- }
142
-
143
- func sendSignalToContainer (client * docker.Client , config dockergen.Config ) {
144
- if len (config .NotifyContainers ) < 1 {
145
- return
146
- }
147
-
148
- for container , signal := range config .NotifyContainers {
149
- log .Printf ("Sending container '%s' signal '%v'" , container , signal )
150
- killOpts := docker.KillContainerOptions {
151
- ID : container ,
152
- Signal : signal ,
153
- }
154
- if err := client .KillContainer (killOpts ); err != nil {
155
- log .Printf ("Error sending signal to container: %s" , err )
156
- }
157
- }
158
- }
159
-
160
72
func loadConfig (file string ) error {
161
73
_ , err := toml .DecodeFile (file , & configs )
162
74
if err != nil {
@@ -165,126 +77,6 @@ func loadConfig(file string) error {
165
77
return nil
166
78
}
167
79
168
- func generateAtInterval (client * docker.Client , configs dockergen.ConfigFile ) {
169
- for _ , config := range configs .Config {
170
-
171
- if config .Interval == 0 {
172
- continue
173
- }
174
-
175
- log .Printf ("Generating every %d seconds" , config .Interval )
176
- wg .Add (1 )
177
- ticker := time .NewTicker (time .Duration (config .Interval ) * time .Second )
178
- quit := make (chan struct {})
179
- configCopy := config
180
- go func () {
181
- defer wg .Done ()
182
- for {
183
- select {
184
- case <- ticker .C :
185
- containers , err := dockergen .GetContainers (client )
186
- if err != nil {
187
- log .Printf ("Error listing containers: %s\n " , err )
188
- continue
189
- }
190
- // ignore changed return value. always run notify command
191
- dockergen .GenerateFile (configCopy , containers )
192
- runNotifyCmd (configCopy )
193
- sendSignalToContainer (client , configCopy )
194
- case <- quit :
195
- ticker .Stop ()
196
- return
197
- }
198
- }
199
- }()
200
- }
201
- }
202
-
203
- func generateFromEvents (client * docker.Client , configs dockergen.ConfigFile ) {
204
- configs = configs .FilterWatches ()
205
- if len (configs .Config ) == 0 {
206
- return
207
- }
208
-
209
- wg .Add (1 )
210
- defer wg .Done ()
211
-
212
- for {
213
- if client == nil {
214
- var err error
215
- endpoint , err := dockergen .GetEndpoint (endpoint )
216
- if err != nil {
217
- log .Printf ("Bad endpoint: %s" , err )
218
- time .Sleep (10 * time .Second )
219
- continue
220
- }
221
-
222
- client , err = NewDockerClient (endpoint )
223
- if err != nil {
224
- log .Printf ("Unable to connect to docker daemon: %s" , err )
225
- time .Sleep (10 * time .Second )
226
- continue
227
- }
228
- generateFromContainers (client )
229
- }
230
-
231
- eventChan := make (chan * docker.APIEvents , 100 )
232
- defer close (eventChan )
233
-
234
- watching := false
235
- for {
236
-
237
- if client == nil {
238
- break
239
- }
240
- err := client .Ping ()
241
- if err != nil {
242
- log .Printf ("Unable to ping docker daemon: %s" , err )
243
- if watching {
244
- client .RemoveEventListener (eventChan )
245
- watching = false
246
- client = nil
247
- }
248
- time .Sleep (10 * time .Second )
249
- break
250
-
251
- }
252
-
253
- if ! watching {
254
- err = client .AddEventListener (eventChan )
255
- if err != nil && err != docker .ErrListenerAlreadyExists {
256
- log .Printf ("Error registering docker event listener: %s" , err )
257
- time .Sleep (10 * time .Second )
258
- continue
259
- }
260
- watching = true
261
- log .Println ("Watching docker events" )
262
- }
263
-
264
- select {
265
-
266
- case event := <- eventChan :
267
- if event == nil {
268
- if watching {
269
- client .RemoveEventListener (eventChan )
270
- watching = false
271
- client = nil
272
- }
273
- break
274
- }
275
-
276
- if event .Status == "start" || event .Status == "stop" || event .Status == "die" {
277
- log .Printf ("Received event %s for container %s" , event .Status , event .ID [:12 ])
278
- generateFromContainers (client )
279
- }
280
- case <- time .After (10 * time .Second ):
281
- // check for docker liveness
282
- }
283
-
284
- }
285
- }
286
- }
287
-
288
80
func initFlags () {
289
81
290
82
certPath := filepath .Join (os .Getenv ("DOCKER_CERT_PATH" ))
@@ -354,30 +146,20 @@ func main() {
354
146
Config : []dockergen.Config {config }}
355
147
}
356
148
357
- endpoint , err := dockergen .GetEndpoint (endpoint )
358
- if err != nil {
359
- log .Fatalf ("Bad endpoint: %s" , err )
360
- }
149
+ generator , err := dockergen .NewGenerator (dockergen.GeneratorConfig {
150
+ Endpoint : endpoint ,
151
+ TLSKey : tlsKey ,
152
+ TLSCert : tlsCert ,
153
+ TLSCACert : tlsCaCert ,
154
+ TLSVerify : tlsVerify ,
155
+ ConfigFile : configs ,
156
+ })
361
157
362
- client , err := NewDockerClient (endpoint )
363
158
if err != nil {
364
- log .Fatalf ("Unable to create docker client : %s " , err )
159
+ log .Fatalf ("error creating generator : %v " , err )
365
160
}
366
161
367
- generateFromContainers (client )
368
- generateAtInterval (client , configs )
369
- generateFromEvents (client , configs )
370
- wg .Wait ()
371
- }
372
-
373
- // pathExists returns whether the given file or directory exists or not
374
- func pathExists (path string ) (bool , error ) {
375
- _ , err := os .Stat (path )
376
- if err == nil {
377
- return true , nil
378
- }
379
- if os .IsNotExist (err ) {
380
- return false , nil
162
+ if err := generator .Generate (); err != nil {
163
+ log .Fatalf ("error running generate: %v" , err )
381
164
}
382
- return false , err
383
165
}
0 commit comments