@@ -16,6 +16,8 @@ package framework
16
16
17
17
import (
18
18
"fmt"
19
+ "io"
20
+ "os"
19
21
"os/exec"
20
22
"path/filepath"
21
23
"strings"
@@ -59,6 +61,8 @@ type Framework struct {
59
61
// we install a Cleanup action before each test and clear it after. If we
60
62
// should abort, the AfterSuite hook should run all Cleanup actions.
61
63
cleanupHandle CleanupActionHandle
64
+
65
+ werckerReportArtifactsDir string
62
66
}
63
67
64
68
// NewDefaultFramework constructs a new e2e test Framework with default options.
@@ -70,8 +74,9 @@ func NewDefaultFramework(baseName string) *Framework {
70
74
// NewFramework constructs a new e2e test Framework.
71
75
func NewFramework (baseName string , client clientset.Interface ) * Framework {
72
76
f := & Framework {
73
- BaseName : baseName ,
74
- ClientSet : client ,
77
+ BaseName : baseName ,
78
+ ClientSet : client ,
79
+ werckerReportArtifactsDir : os .Getenv ("WERCKER_REPORT_ARTIFACTS_DIR" ),
75
80
}
76
81
77
82
BeforeEach (f .BeforeEach )
@@ -248,6 +253,10 @@ func (f *Framework) BeforeEach() {
248
253
func (f * Framework ) AfterEach () {
249
254
RemoveCleanupAction (f .cleanupHandle )
250
255
256
+ if err := f .outputLogs (); err != nil {
257
+ Logf ("Failed to output container logs: %v" , err )
258
+ }
259
+
251
260
nsDeletionErrors := map [string ]error {}
252
261
253
262
// Whether to delete namespace is determined by 3 factors: delete-namespace flag, delete-namespace-on-failure flag and the test result
@@ -272,3 +281,74 @@ func (f *Framework) AfterEach() {
272
281
}
273
282
f .OperatorInstalled = false
274
283
}
284
+
285
+ func (f * Framework ) outputLogs () error {
286
+ pods , err := f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).List (metav1.ListOptions {})
287
+ if err != nil {
288
+ return errors .Wrap (err , "listing test Pods" )
289
+ }
290
+
291
+ var opPod v1.Pod
292
+ var agPods []v1.Pod
293
+ for _ , pod := range pods .Items {
294
+ if strings .Contains (pod .Spec .Containers [0 ].Image , "mysql-operator" ) {
295
+ opPod = pod
296
+ continue
297
+ }
298
+ if strings .Contains (pod .Spec .Containers [0 ].Image , "mysql-agent" ) || strings .Contains (pod .Spec .Containers [0 ].Image , "mysql-server" ) {
299
+ agPods = append (agPods , pod )
300
+ }
301
+ }
302
+
303
+ // Operator Logs
304
+ if opPod .Name != "" {
305
+ f .printContainerLogs (opPod .GetName (), & v1.PodLogOptions {})
306
+ }
307
+
308
+ for _ , agPod := range agPods {
309
+ // Server Logs
310
+ f .printContainerLogs (agPod .GetName (), & v1.PodLogOptions {Container : "mysql" })
311
+ // Agent Logs
312
+ f .printContainerLogs (agPod .GetName (), & v1.PodLogOptions {Container : "mysql-agent" })
313
+ }
314
+
315
+ return nil
316
+ }
317
+
318
+ func printLogs (read io.ReadCloser , filepath string ) error {
319
+ defer read .Close ()
320
+ dst := os .Stdout
321
+ if filepath != "" {
322
+ file , err := os .OpenFile (filepath , os .O_WRONLY | os .O_CREATE , 0666 )
323
+ if err != nil {
324
+ return errors .Wrapf (err , "opening log file %q" , filepath )
325
+ }
326
+ dst = file
327
+ defer dst .Close ()
328
+ }
329
+ _ , err := io .Copy (dst , read )
330
+ if err != nil {
331
+ var s string
332
+ if filepath != "" {
333
+ s = filepath
334
+ } else {
335
+ s = "stdout"
336
+ }
337
+ return errors .Wrapf (err , "writing logs to %q" , s )
338
+ }
339
+ return nil
340
+ }
341
+
342
+ func (f * Framework ) printContainerLogs (podName string , options * v1.PodLogOptions ) error {
343
+ podLogs := f .ClientSet .CoreV1 ().Pods (f .Namespace .Name ).GetLogs (podName , options )
344
+ if podLogs != nil {
345
+ Logf ("Writing %s container logs to file for %s" , options .Container , podName )
346
+ read , err := podLogs .Stream ()
347
+ if err != nil {
348
+ return errors .Wrapf (err , "streaming request response for %s" , podName )
349
+ }
350
+ printLogs (read , podName )
351
+ Logf ("Finished writing %s container logs for %s" , options .Container , podName )
352
+ }
353
+ return nil
354
+ }
0 commit comments