From 71a9f778087000b6be153739009800d1e5c00e9e Mon Sep 17 00:00:00 2001 From: Tim Ebert Date: Wed, 12 Jun 2024 15:41:07 +0200 Subject: [PATCH] Dump namespace contents of failed tests --- .github/workflows/e2e.yaml | 4 +-- test/e2e/workload/namespace.go | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index ef55e4d..afa4b2f 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -14,7 +14,7 @@ jobs: e2e-kind: runs-on: ubuntu-latest env: - ARTIFACTS: artifacts + ARTIFACTS: ${{github.workspace}}/artifacts steps: - uses: actions/checkout@v4 @@ -26,5 +26,5 @@ jobs: if: always() with: name: e2e-artifacts - path: artifacts + path: ${{env.ARTIFACTS}} if-no-files-found: error diff --git a/test/e2e/workload/namespace.go b/test/e2e/workload/namespace.go index ae5c694..d1876b9 100644 --- a/test/e2e/workload/namespace.go +++ b/test/e2e/workload/namespace.go @@ -2,9 +2,13 @@ package workload import ( "context" + "os" + "os/exec" + "path/filepath" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -27,6 +31,10 @@ func PrepareTestNamespace() string { Expect(testClient.Create(context.Background(), namespace)).To(Succeed()) logf.Log.Info("Created test namespace", "namespace", namespace.Name) + DeferCleanup(func() { + DumpNamespaceContents(namespace.Name) + }) + DeferCleanup(func() { logf.Log.Info("Deleting test namespace", "namespace", namespace.Name) Expect(testClient.Delete(context.Background(), namespace)).To(Or(Succeed(), BeNotFoundError())) @@ -34,3 +42,51 @@ func PrepareTestNamespace() string { return namespace.Name } + +// DumpNamespaceContents dumps all relevant objects in the test namespace to a dedicated ARTIFACTS directory if the +// spec failed to help deflaking/debugging tests. +func DumpNamespaceContents(namespace string) { + dir := os.Getenv("ARTIFACTS") + if !CurrentSpecReport().Failed() || dir == "" { + return + } + + dir = filepath.Join(dir, namespace) + logf.Log.Info("Dumping contents of test namespace", "namespace", namespace, "dir", dir) + + // nolint:gosec // this is test code + Expect(os.MkdirAll(dir, 0755)).To(Succeed()) + + DumpEventsInNamespace(namespace, dir) + + for _, kind := range []string{ + "pods", + "deployments", + "replicasets", + "statefulsets", + "daemonsets", + "controllerrevisions", + } { + DumpObjectsInNamespace(namespace, kind, dir) + } +} + +func DumpEventsInNamespace(namespace, dir string) { + // nolint:gosec // this is test code + file, err := os.OpenFile(filepath.Join(dir, "events.log"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + Expect(err).NotTo(HaveOccurred()) + + session, err := gexec.Start(exec.Command("kubectl", "-n", namespace, "get", "events"), file, GinkgoWriter) + Expect(err).NotTo(HaveOccurred()) + Eventually(session).Should(gexec.Exit(0)) +} + +func DumpObjectsInNamespace(namespace, kind, dir string) { + // nolint:gosec // this is test code + file, err := os.OpenFile(filepath.Join(dir, kind+".yaml"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + Expect(err).NotTo(HaveOccurred()) + + session, err := gexec.Start(exec.Command("kubectl", "-n", namespace, "get", kind, "-oyaml"), file, GinkgoWriter) + Expect(err).NotTo(HaveOccurred()) + Eventually(session).Should(gexec.Exit(0)) +}