@@ -13,14 +13,16 @@ import (
13
13
"os/exec"
14
14
"os/signal"
15
15
"path/filepath"
16
+ "reflect"
16
17
"strings"
17
18
"syscall"
18
19
"text/template"
19
20
)
20
21
21
22
var (
22
- watch bool
23
- notifyCmd string
23
+ watch bool
24
+ notifyCmd string
25
+ onlyExposed bool
24
26
)
25
27
26
28
type Event struct {
@@ -37,19 +39,70 @@ type RuntimeContainer struct {
37
39
ID string
38
40
Addresses []Address
39
41
Image string
42
+ Env map [string ]string
43
+ }
44
+
45
+ func deepGet (item interface {}, path string ) interface {} {
46
+ if path == "" {
47
+ return item
48
+ }
49
+
50
+ parts := strings .Split (path , "." )
51
+ itemValue := reflect .ValueOf (item )
52
+
53
+ if len (parts ) > 0 {
54
+ switch itemValue .Kind () {
55
+ case reflect .Struct :
56
+ fieldValue := itemValue .FieldByName (parts [0 ])
57
+ if fieldValue .IsValid () {
58
+ return deepGet (fieldValue .Interface (), strings .Join (parts [1 :], "." ))
59
+ }
60
+ case reflect .Map :
61
+ mapValue := itemValue .MapIndex (reflect .ValueOf (parts [0 ]))
62
+ if mapValue .IsValid () {
63
+ return deepGet (mapValue .Interface (), strings .Join (parts [1 :], "." ))
64
+ }
65
+ default :
66
+ fmt .Printf ("can't group by %s" , path )
67
+ }
68
+ return nil
69
+ }
70
+
71
+ return itemValue .Interface ()
72
+ }
73
+
74
+ func groupBy (entries []* RuntimeContainer , key string ) map [string ][]* RuntimeContainer {
75
+ groups := make (map [string ][]* RuntimeContainer )
76
+ for _ , v := range entries {
77
+ value := deepGet (* v , key )
78
+ if value != nil {
79
+ groups [value .(string )] = append (groups [value .(string )], v )
80
+ }
81
+ }
82
+ return groups
83
+ }
84
+
85
+ func contains (a map [string ]string , b string ) bool {
86
+ if _ , ok := a [b ]; ok {
87
+ return true
88
+ }
89
+ return false
40
90
}
41
91
42
92
func usage () {
43
93
println ("Usage: docker-gen [-watch=false] [-notify=\" restart xyz\" ] <template> [<dest>]" )
44
94
}
45
95
46
96
func generateFile (templatePath string , containers []* RuntimeContainer ) {
47
-
48
- tmpl , err := template .ParseFiles (templatePath )
97
+ tmpl , err := template .New (filepath .Base (templatePath )).Funcs (template.FuncMap {
98
+ "contains" : contains ,
99
+ "groupBy" : groupBy ,
100
+ }).ParseFiles (templatePath )
49
101
if err != nil {
50
102
panic (err )
51
103
}
52
104
105
+ tmpl = tmpl
53
106
dest := os .Stdout
54
107
if flag .NArg () == 2 {
55
108
dest , err = os .Create (flag .Arg (1 ))
@@ -149,6 +202,7 @@ func generateFromContainers(client *docker.Client) {
149
202
ID : container .ID ,
150
203
Image : container .Config .Image ,
151
204
Addresses : []Address {},
205
+ Env : make (map [string ]string ),
152
206
}
153
207
for k , _ := range container .NetworkSettings .Ports {
154
208
runtimeContainer .Addresses = append (runtimeContainer .Addresses ,
@@ -157,7 +211,21 @@ func generateFromContainers(client *docker.Client) {
157
211
Port : k .Port (),
158
212
})
159
213
}
160
- containers = append (containers , runtimeContainer )
214
+
215
+ for _ , entry := range container .Config .Env {
216
+ parts := strings .Split (entry , "=" )
217
+ runtimeContainer .Env [parts [0 ]] = parts [1 ]
218
+ }
219
+
220
+ if ! onlyExposed {
221
+ containers = append (containers , runtimeContainer )
222
+ continue
223
+ }
224
+
225
+ if onlyExposed && len (runtimeContainer .Addresses ) > 0 {
226
+ containers = append (containers , runtimeContainer )
227
+ }
228
+
161
229
}
162
230
163
231
generateFile (flag .Arg (0 ), containers )
@@ -179,8 +247,8 @@ func runNotifyCmd() {
179
247
}
180
248
181
249
func main () {
182
-
183
250
flag .BoolVar (& watch , "watch" , false , "watch for container changes" )
251
+ flag .BoolVar (& onlyExposed , "only-exposed" , false , "only include containers with exposed ports" )
184
252
flag .StringVar (& notifyCmd , "notify" , "" , "run command after template is regenerated" )
185
253
flag .Parse ()
186
254
@@ -205,9 +273,11 @@ func main() {
205
273
eventChan := getEvents ()
206
274
for {
207
275
event := <- eventChan
208
- if event .Status == "start" || event .Status == "stop" {
276
+ if event .Status == "start" || event .Status == "stop" || event . Status == "die" {
209
277
generateFromContainers (client )
210
278
runNotifyCmd ()
279
+ } else {
280
+ println (event .Status )
211
281
}
212
282
}
213
283
0 commit comments