@@ -3,7 +3,6 @@ package main
3
3
import (
4
4
"context"
5
5
"fmt"
6
- "log"
7
6
"os"
8
7
"os/exec"
9
8
"os/signal"
@@ -14,6 +13,7 @@ import (
14
13
15
14
"github.com/fsnotify/fsnotify"
16
15
"github.com/karlkfi/kubexit/pkg/kubernetes"
16
+ "github.com/karlkfi/kubexit/pkg/log"
17
17
"github.com/karlkfi/kubexit/pkg/supervisor"
18
18
"github.com/karlkfi/kubexit/pkg/tombstone"
19
19
@@ -24,21 +24,23 @@ import (
24
24
func main () {
25
25
var err error
26
26
27
- // remove log timestamp
28
- log .SetFlags (log .Flags () &^ (log .Ldate | log .Ltime ))
27
+ ctx := log .WithLogger (context .Background (), log .L )
29
28
30
29
args := os .Args [1 :]
31
30
if len (args ) == 0 {
32
- log .Println ( " Error: no arguments found" )
31
+ log .G ( ctx ). Error ( " no arguments found" )
33
32
os .Exit (2 )
34
33
}
35
34
36
35
name := os .Getenv ("KUBEXIT_NAME" )
37
36
if name == "" {
38
- log .Println ( " Error: missing env var: KUBEXIT_NAME" )
37
+ log .G ( ctx ). Error ( " missing env var: KUBEXIT_NAME" )
39
38
os .Exit (2 )
40
39
}
41
- log .Printf ("Name: %s\n " , name )
40
+
41
+ // add field to the context logger to differentiate when pod container logs are intermingled
42
+ ctx = log .WithLogger (ctx , log .G (ctx ).WithField ("container_name" , name ))
43
+ log .G (ctx ).Info ("KUBEXIT_NAME parsed" )
42
44
43
45
graveyard := os .Getenv ("KUBEXIT_GRAVEYARD" )
44
46
if graveyard == "" {
@@ -47,85 +49,78 @@ func main() {
47
49
graveyard = strings .TrimRight (graveyard , "/" )
48
50
graveyard = filepath .Clean (graveyard )
49
51
}
50
- log .Printf ("Graveyard: %s\n " , graveyard )
51
-
52
52
ts := & tombstone.Tombstone {
53
53
Graveyard : graveyard ,
54
54
Name : name ,
55
55
}
56
- log .Printf ("Tombstone: %s\n " , ts .Path ())
56
+ log .G (ctx ).
57
+ WithField ("graveyard" , graveyard ).
58
+ WithField ("tombstone" , ts .Path ()).
59
+ Info ("KUBEXIT_GRAVEYARD parsed" )
57
60
58
61
birthDepsStr := os .Getenv ("KUBEXIT_BIRTH_DEPS" )
59
62
var birthDeps []string
60
- if birthDepsStr == "" {
61
- log .Println ("Birth Deps: N/A" )
62
- } else {
63
+ if birthDepsStr != "" {
63
64
birthDeps = strings .Split (birthDepsStr , "," )
64
- log .Printf ("Birth Deps: %s\n " , strings .Join (birthDeps , "," ))
65
65
}
66
+ log .G (ctx ).WithField ("birth_deps" , birthDeps ).Info ("KUBEXIT_BIRTH_DEPS parsed" )
66
67
67
68
deathDepsStr := os .Getenv ("KUBEXIT_DEATH_DEPS" )
68
69
var deathDeps []string
69
- if deathDepsStr == "" {
70
- log .Println ("Death Deps: N/A" )
71
- } else {
70
+ if deathDepsStr != "" {
72
71
deathDeps = strings .Split (deathDepsStr , "," )
73
- log .Printf ("Death Deps: %s\n " , strings .Join (deathDeps , "," ))
74
72
}
73
+ log .G (ctx ).WithField ("death_deps" , deathDeps ).Info ("KUBEXIT_DEATH_DEPS parsed" )
75
74
76
75
birthTimeout := 30 * time .Second
77
76
birthTimeoutStr := os .Getenv ("KUBEXIT_BIRTH_TIMEOUT" )
78
77
if birthTimeoutStr != "" {
79
78
birthTimeout , err = time .ParseDuration (birthTimeoutStr )
80
79
if err != nil {
81
- log .Printf ( "Error: failed to parse birth timeout: %v\n " , err )
80
+ log .G ( ctx ). Errorf ( " failed to parse birth timeout: %v\n " , err )
82
81
os .Exit (2 )
83
82
}
84
83
}
85
- log .Printf ( "Birth Timeout: %s \n " , birthTimeout )
84
+ log .G ( ctx ). WithField ( "birth_timeout " , birthTimeout ). Info ( "KUBEXIT_BIRTH_TIMEOUT parsed" )
86
85
87
86
gracePeriod := 30 * time .Second
88
87
gracePeriodStr := os .Getenv ("KUBEXIT_GRACE_PERIOD" )
89
88
if gracePeriodStr != "" {
90
89
gracePeriod , err = time .ParseDuration (gracePeriodStr )
91
90
if err != nil {
92
- log .Printf ("Error: failed to parse grace period: %v\n " , err )
91
+ log .G ( ctx ). Printf ("Error: failed to parse grace period: %v\n " , err )
93
92
os .Exit (2 )
94
93
}
95
94
}
96
- log .Printf ( "Grace Period: %s \n " , gracePeriod )
95
+ log .G ( ctx ). WithField ( "grace_period " , gracePeriod ). Info ( "KUBEXIT_GRACE_PERIOD parsed" )
97
96
98
97
podName := os .Getenv ("KUBEXIT_POD_NAME" )
99
98
if podName == "" {
100
99
if len (birthDeps ) > 0 {
101
- log .Println ( " Error: missing env var: KUBEXIT_POD_NAME" )
100
+ log .G ( ctx ). Error ( " missing env var: KUBEXIT_POD_NAME" )
102
101
os .Exit (2 )
103
102
}
104
- log .Println ("Pod Name: N/A" )
105
- } else {
106
- log .Printf ("Pod Name: %s\n " , podName )
107
103
}
104
+ log .G (ctx ).WithField ("pod_name" , podName ).Info ("KUBEXIT_POD_NAME parsed" )
108
105
109
106
namespace := os .Getenv ("KUBEXIT_NAMESPACE" )
110
107
if namespace == "" {
111
108
if len (birthDeps ) > 0 {
112
- log .Println ( " Error: missing env var: KUBEXIT_NAMESPACE" )
109
+ log .G ( ctx ). Error ( " missing env var: KUBEXIT_NAMESPACE" )
113
110
os .Exit (2 )
114
111
}
115
- log .Println ("Namespace: N/A" )
116
- } else {
117
- log .Printf ("Namespace: %s\n " , namespace )
118
112
}
113
+ log .G (ctx ).WithField ("namespace" , namespace ).Info ("KUBEXIT_POD_NAME parsed" )
119
114
120
- child := supervisor .New (args [0 ], args [1 :]... )
115
+ child := supervisor .New (ctx , args [0 ], args [1 :]... )
121
116
122
117
// watch for death deps early, so they can interrupt waiting for birth deps
123
118
if len (deathDeps ) > 0 {
124
- ctx , stopGraveyardWatcher := context .WithCancel (context . Background () )
119
+ ctx , stopGraveyardWatcher := context .WithCancel (ctx )
125
120
// stop graveyard watchers on exit, if not sooner
126
121
defer stopGraveyardWatcher ()
127
122
128
- log .Println ("Watching graveyard..." )
123
+ log .G ( ctx ). Info ("Watching graveyard..." )
129
124
err = tombstone .Watch (ctx , graveyard , onDeathOfAny (deathDeps , func () error {
130
125
stopGraveyardWatcher ()
131
126
// trigger graceful shutdown
@@ -138,32 +133,32 @@ func main() {
138
133
return nil
139
134
}))
140
135
if err != nil {
141
- fatalf ( child , ts , "Error: failed to watch graveyard: %v\n " , err )
136
+ fatal ( ctx , child , ts , fmt . Errorf ( " failed to watch graveyard: %v" , err ) )
142
137
}
143
138
}
144
139
145
140
if len (birthDeps ) > 0 {
146
141
err = waitForBirthDeps (birthDeps , namespace , podName , birthTimeout )
147
142
if err != nil {
148
- fatalf ( child , ts , "Error: %v \n " , err )
143
+ fatal ( ctx , child , ts , err )
149
144
}
150
145
}
151
146
152
147
err = child .Start ()
153
148
if err != nil {
154
- fatalf ( child , ts , "Error: %v \n " , err )
149
+ fatal ( ctx , child , ts , err )
155
150
}
156
151
157
- err = ts .RecordBirth ()
152
+ err = ts .RecordBirth (ctx )
158
153
if err != nil {
159
- fatalf ( child , ts , "Error: %v \n " , err )
154
+ fatal ( ctx , child , ts , err )
160
155
}
161
156
162
- code := waitForChildExit (child )
157
+ code := waitForChildExit (ctx , child )
163
158
164
- err = ts .RecordDeath (code )
159
+ err = ts .RecordDeath (ctx , code )
165
160
if err != nil {
166
- log .Printf ("Error: %v\n " , err )
161
+ log .G ( ctx ). Printf ("Error: %v\n " , err )
167
162
os .Exit (1 )
168
163
}
169
164
@@ -178,9 +173,9 @@ func waitForBirthDeps(birthDeps []string, namespace, podName string, timeout tim
178
173
// Stop pod watcher on exit, if not sooner
179
174
defer stopPodWatcher ()
180
175
181
- log .Println ("Watching pod updates..." )
176
+ log .G ( ctx ). Info ("Watching pod updates..." )
182
177
err := kubernetes .WatchPod (ctx , namespace , podName ,
183
- onReadyOfAll (birthDeps , stopPodWatcher ),
178
+ onReadyOfAll (ctx , birthDeps , stopPodWatcher ),
184
179
)
185
180
if err != nil {
186
181
return fmt .Errorf ("failed to watch pod: %v" , err )
@@ -196,7 +191,7 @@ func waitForBirthDeps(birthDeps []string, namespace, podName string, timeout tim
196
191
return fmt .Errorf ("waiting for birth deps to be ready: %v" , err )
197
192
}
198
193
199
- log .Printf ("All birth deps ready: %v\n " , strings .Join (birthDeps , ", " ))
194
+ log .G ( ctx ). Printf ("All birth deps ready: %v\n " , strings .Join (birthDeps , ", " ))
200
195
return nil
201
196
}
202
197
@@ -215,7 +210,7 @@ func withCancelOnSignal(ctx context.Context, signals ...os.Signal) context.Conte
215
210
if ! ok {
216
211
return
217
212
}
218
- log .Printf ("Received shutdown signal: %v" , s )
213
+ log .G ( ctx ). Printf ("Received shutdown signal: %v" , s )
219
214
cancel ()
220
215
case <- ctx .Done ():
221
216
signal .Reset ()
@@ -228,7 +223,7 @@ func withCancelOnSignal(ctx context.Context, signals ...os.Signal) context.Conte
228
223
}
229
224
230
225
// wait for the child to exit and return the exit code
231
- func waitForChildExit (child * supervisor.Supervisor ) int {
226
+ func waitForChildExit (ctx context. Context , child * supervisor.Supervisor ) int {
232
227
var code int
233
228
err := child .Wait ()
234
229
if err != nil {
@@ -237,35 +232,37 @@ func waitForChildExit(child *supervisor.Supervisor) int {
237
232
} else {
238
233
code = - 1
239
234
}
240
- log .Printf ("Child Exited(%d): %v\n " , code , err )
241
235
} else {
242
236
code = 0
243
- log .Println ("Child Exited(0)" )
244
237
}
238
+ log .G (ctx ).
239
+ WithField ("exit_code" , code ).
240
+ WithField ("error" , err ).
241
+ Info ("child exited" )
245
242
return code
246
243
}
247
244
248
- // fatalf is for terminal errors .
245
+ // fatal logs a terminal error and exits .
249
246
// The child process may or may not be running.
250
- func fatalf ( child * supervisor.Supervisor , ts * tombstone.Tombstone , msg string , args ... interface {} ) {
251
- log .Printf ( msg , args ... )
247
+ func fatal ( ctx context. Context , child * supervisor.Supervisor , ts * tombstone.Tombstone , err error ) {
248
+ log .G ( ctx ). Error ( err )
252
249
253
250
// Skipped if not started.
254
- err : = child .ShutdownNow ()
251
+ err = child .ShutdownNow ()
255
252
if err != nil {
256
- log .Printf ( "Error: failed to shutdown child process: %v" , err )
253
+ log .G ( ctx ). Errorf ( " failed to shutdown child process: %v" , err )
257
254
os .Exit (1 )
258
255
}
259
256
260
257
// Wait for shutdown...
261
258
//TODO: timout in case the process is zombie?
262
- code := waitForChildExit (child )
259
+ code := waitForChildExit (ctx , child )
263
260
264
261
// Attempt to record death, if possible.
265
262
// Another process may be waiting for it.
266
- err = ts .RecordDeath (code )
263
+ err = ts .RecordDeath (ctx , code )
267
264
if err != nil {
268
- log .Printf ( "Error : %v\n " , err )
265
+ log .G ( ctx ). Errorf ( "failed to record death of child process : %v" , err )
269
266
os .Exit (1 )
270
267
}
271
268
@@ -274,22 +271,22 @@ func fatalf(child *supervisor.Supervisor, ts *tombstone.Tombstone, msg string, a
274
271
275
272
// onReadyOfAll returns an EventHandler that executes the callback when all of
276
273
// the birthDeps containers are ready.
277
- func onReadyOfAll (birthDeps []string , callback func ()) kubernetes.EventHandler {
274
+ func onReadyOfAll (ctx context. Context , birthDeps []string , callback func ()) kubernetes.EventHandler {
278
275
birthDepSet := map [string ]struct {}{}
279
276
for _ , depName := range birthDeps {
280
277
birthDepSet [depName ] = struct {}{}
281
278
}
282
279
283
280
return func (event watch.Event ) {
284
- fmt . Printf ( "Event Type: %v \n " , event .Type )
281
+ log . G ( ctx ). WithField ( "event_type " , event .Type ). Info ( "recieved pod watch event" )
285
282
// ignore Deleted (Watch will auto-stop on delete)
286
283
if event .Type == watch .Deleted {
287
284
return
288
285
}
289
286
290
287
pod , ok := event .Object .(* corev1.Pod )
291
288
if ! ok {
292
- log .Printf ( "Error: unexpected non-pod object type: %+v \n " , event . Object )
289
+ log .G ( ctx ). WithField ( "object" , event . Object ). Warn ( "recieved unexpected non-pod object type" )
293
290
return
294
291
}
295
292
@@ -321,33 +318,34 @@ func onDeathOfAny(deathDeps []string, callback func() error) tombstone.EventHand
321
318
deathDepSet [depName ] = struct {}{}
322
319
}
323
320
324
- return func (event fsnotify.Event ) error {
321
+ return func (ctx context. Context , event fsnotify.Event ) error {
325
322
if event .Op & fsnotify .Create != fsnotify .Create && event .Op & fsnotify .Write != fsnotify .Write {
326
323
// ignore other events
327
324
return nil
328
325
}
329
326
graveyard := filepath .Dir (event .Name )
330
327
name := filepath .Base (event .Name )
331
328
332
- log .Printf ( "Tombstone modified: %s \n " , name )
329
+ log .G ( ctx ). WithField ( "tombstone " , name ). Info ( "recieved tombstone watch event" )
333
330
if _ , ok := deathDepSet [name ]; ! ok {
334
331
// ignore other tombstones
335
332
return nil
336
333
}
337
334
338
- log .Printf ("Reading tombstone: %s\n " , name )
339
335
ts , err := tombstone .Read (graveyard , name )
340
336
if err != nil {
341
- log .Printf ( "Error: failed to read tombstone: %v\n " , err )
337
+ log .G ( ctx ). WithField ( "tombstone" , name ). Errorf ( " failed to read tombstone: %v" , err )
342
338
return nil
343
339
}
344
340
345
341
if ts .Died == nil {
346
342
// still alive
347
343
return nil
348
344
}
349
- log .Printf ("New death: %s\n " , name )
350
- log .Printf ("Tombstone(%s): %s\n " , name , ts )
345
+ log .G (ctx ).
346
+ WithField ("tombstone" , name ).
347
+ WithField ("tombstone_content" , ts ).
348
+ Errorf ("recieved new death event" )
351
349
352
350
return callback ()
353
351
}
0 commit comments