Skip to content
This repository was archived by the owner on May 28, 2021. It is now read-only.

Export logs as wercker artifacts and delete e2e namespace on test failure #188

Merged
merged 1 commit into from
Aug 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions test/e2e/framework/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package framework

import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
Expand Down Expand Up @@ -59,6 +61,8 @@ type Framework struct {
// we install a Cleanup action before each test and clear it after. If we
// should abort, the AfterSuite hook should run all Cleanup actions.
cleanupHandle CleanupActionHandle

werckerReportArtifactsDir string
}

// NewDefaultFramework constructs a new e2e test Framework with default options.
Expand All @@ -70,8 +74,9 @@ func NewDefaultFramework(baseName string) *Framework {
// NewFramework constructs a new e2e test Framework.
func NewFramework(baseName string, client clientset.Interface) *Framework {
f := &Framework{
BaseName: baseName,
ClientSet: client,
BaseName: baseName,
ClientSet: client,
werckerReportArtifactsDir: os.Getenv("WERCKER_REPORT_ARTIFACTS_DIR"),
}

BeforeEach(f.BeforeEach)
Expand Down Expand Up @@ -248,6 +253,10 @@ func (f *Framework) BeforeEach() {
func (f *Framework) AfterEach() {
RemoveCleanupAction(f.cleanupHandle)

if err := f.outputLogs(); err != nil {
Logf("Failed to output container logs: %v", err)
}

nsDeletionErrors := map[string]error{}

// Whether to delete namespace is determined by 3 factors: delete-namespace flag, delete-namespace-on-failure flag and the test result
Expand All @@ -272,3 +281,82 @@ func (f *Framework) AfterEach() {
}
f.OperatorInstalled = false
}

func (f *Framework) outputLogs() error {
pods, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).List(metav1.ListOptions{})
if err != nil {
return errors.Wrap(err, "listing test Pods")
}

var opPod v1.Pod
var agPods []v1.Pod
for _, pod := range pods.Items {
if strings.Contains(pod.Spec.Containers[0].Image, "mysql-operator") {
opPod = pod
continue
}
if strings.Contains(pod.Spec.Containers[0].Image, "mysql-agent") || strings.Contains(pod.Spec.Containers[0].Image, "mysql-server") {
agPods = append(agPods, pod)
}
}

// Operator Logs
if opPod.Name != "" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably need else block to handle opPod.Name being empty?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@simonlord Good point. I have just logged a message here as there is no need for a fail.

if err := f.printContainerLogs(opPod.GetName(), &v1.PodLogOptions{}); err != nil {
return errors.Wrapf(err, "exporting mysql operator container logs for %s", opPod.GetName())
}
} else {
Logf("MySQL Operator Pod could not be found. Logs have not been exported.")
}

for _, agPod := range agPods {
// Server Logs
if err := f.printContainerLogs(agPod.GetName(), &v1.PodLogOptions{Container: "mysql"}); err != nil {
return errors.Wrapf(err, "exporting mysql server container logs for %s", agPod.GetName())
}
// Agent Logs
if err := f.printContainerLogs(agPod.GetName(), &v1.PodLogOptions{Container: "mysql-agent"}); err != nil {
return errors.Wrapf(err, "exporting mysql agent container logs for %s", agPod.GetName())
}
}

return nil
}

func (f *Framework) printLogs(read io.ReadCloser, filepath string) error {
defer read.Close()
dst := os.Stdout
if f.werckerReportArtifactsDir != "" {
file, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return errors.Wrapf(err, "opening log file %q", filepath)
}
dst = file
defer dst.Close()
}
_, err := io.Copy(dst, read)
if err != nil {
var s string
if filepath != "" {
s = filepath
} else {
s = "stdout"
}
return errors.Wrapf(err, "writing logs to %q", s)
}
return nil
}

func (f *Framework) printContainerLogs(podName string, options *v1.PodLogOptions) error {
podLogs := f.ClientSet.CoreV1().Pods(f.Namespace.Name).GetLogs(podName, options)
if podLogs != nil {
Logf("Writing %s container logs to file for %s", options.Container, podName)
read, err := podLogs.Stream()
if err != nil {
return errors.Wrapf(err, "streaming request response for %s", podName)
}
f.printLogs(read, fmt.Sprintf("%s/%s%s", f.werckerReportArtifactsDir, podName, ".log"))
Logf("Finished writing %s container logs for %s", options.Container, podName)
}
return nil
}
1 change: 0 additions & 1 deletion wercker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ e2e-test:
--operator-version="$(cat dist/version.txt)" \
--s3-access-key="${S3_ACCESS_KEY}" \
--s3-secret-key="${S3_SECRET_KEY}" \
--delete-namespace-on-failure=false

release:
box:
Expand Down