diff --git a/docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go b/docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go index 164a7460021..bfc657fb749 100644 --- a/docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go +++ b/docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-controller-manager-metrics-service" const metricsRoleBindingName = "project-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -261,7 +303,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -273,11 +314,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -293,9 +332,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/docs/book/src/cronjob-tutorial/testdata/project/test/utils/utils.go b/docs/book/src/cronjob-tutorial/testdata/project/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/docs/book/src/cronjob-tutorial/testdata/project/test/utils/utils.go +++ b/docs/book/src/cronjob-tutorial/testdata/project/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/docs/book/src/getting-started/testdata/project/test/e2e/e2e_test.go b/docs/book/src/getting-started/testdata/project/test/e2e/e2e_test.go index a986ac7474e..eebb6bfa0ac 100644 --- a/docs/book/src/getting-started/testdata/project/test/e2e/e2e_test.go +++ b/docs/book/src/getting-started/testdata/project/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-controller-manager-metrics-service" const metricsRoleBindingName = "project-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -223,7 +265,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -235,11 +276,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -255,9 +294,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/docs/book/src/getting-started/testdata/project/test/utils/utils.go b/docs/book/src/getting-started/testdata/project/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/docs/book/src/getting-started/testdata/project/test/utils/utils.go +++ b/docs/book/src/getting-started/testdata/project/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/docs/book/src/multiversion-tutorial/testdata/project/test/e2e/e2e_test.go b/docs/book/src/multiversion-tutorial/testdata/project/test/e2e/e2e_test.go index 164a7460021..bfc657fb749 100644 --- a/docs/book/src/multiversion-tutorial/testdata/project/test/e2e/e2e_test.go +++ b/docs/book/src/multiversion-tutorial/testdata/project/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-controller-manager-metrics-service" const metricsRoleBindingName = "project-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -261,7 +303,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -273,11 +314,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -293,9 +332,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/docs/book/src/multiversion-tutorial/testdata/project/test/utils/utils.go b/docs/book/src/multiversion-tutorial/testdata/project/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/docs/book/src/multiversion-tutorial/testdata/project/test/utils/utils.go +++ b/docs/book/src/multiversion-tutorial/testdata/project/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/pkg/plugins/golang/v4/scaffolds/internal/templates/test/e2e/test.go b/pkg/plugins/golang/v4/scaffolds/internal/templates/test/e2e/test.go index 7781c336b6f..bf3ad3b53de 100644 --- a/pkg/plugins/golang/v4/scaffolds/internal/templates/test/e2e/test.go +++ b/pkg/plugins/golang/v4/scaffolds/internal/templates/test/e2e/test.go @@ -176,6 +176,8 @@ const metricsServiceName = "{{ .ProjectName }}-controller-manager-metrics-servic const metricsRoleBindingName = "{{ .ProjectName }}-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -215,12 +217,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -236,7 +279,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -248,9 +291,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -283,7 +325,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -292,7 +334,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -314,7 +356,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5 * time.Minute).Should(Succeed()) @@ -356,7 +398,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -368,11 +409,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -388,9 +427,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/pkg/plugins/golang/v4/scaffolds/internal/templates/test/utils/utils.go b/pkg/plugins/golang/v4/scaffolds/internal/templates/test/utils/utils.go index fd68964be6f..6d3dec530d6 100644 --- a/pkg/plugins/golang/v4/scaffolds/internal/templates/test/utils/utils.go +++ b/pkg/plugins/golang/v4/scaffolds/internal/templates/test/utils/utils.go @@ -66,7 +66,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -79,10 +79,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/testdata/project-v4-multigroup/test/e2e/e2e_test.go b/testdata/project-v4-multigroup/test/e2e/e2e_test.go index 6c32c749e06..b6aae66a78d 100644 --- a/testdata/project-v4-multigroup/test/e2e/e2e_test.go +++ b/testdata/project-v4-multigroup/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-v4-multigroup-controller-manager-metrics-ser const metricsRoleBindingName = "project-v4-multigroup-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -261,7 +303,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -273,11 +314,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -293,9 +332,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/testdata/project-v4-multigroup/test/utils/utils.go b/testdata/project-v4-multigroup/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/testdata/project-v4-multigroup/test/utils/utils.go +++ b/testdata/project-v4-multigroup/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/testdata/project-v4-with-plugins/test/e2e/e2e_test.go b/testdata/project-v4-with-plugins/test/e2e/e2e_test.go index 191a296fcfb..08f2abd755a 100644 --- a/testdata/project-v4-with-plugins/test/e2e/e2e_test.go +++ b/testdata/project-v4-with-plugins/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-v4-with-plugins-controller-manager-metrics-s const metricsRoleBindingName = "project-v4-with-plugins-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -247,7 +289,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -259,11 +300,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -279,9 +318,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/testdata/project-v4-with-plugins/test/utils/utils.go b/testdata/project-v4-with-plugins/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/testdata/project-v4-with-plugins/test/utils/utils.go +++ b/testdata/project-v4-with-plugins/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. diff --git a/testdata/project-v4/test/e2e/e2e_test.go b/testdata/project-v4/test/e2e/e2e_test.go index 05c8dd232d6..ae761d5b23e 100644 --- a/testdata/project-v4/test/e2e/e2e_test.go +++ b/testdata/project-v4/test/e2e/e2e_test.go @@ -43,6 +43,8 @@ const metricsServiceName = "project-v4-controller-manager-metrics-service" const metricsRoleBindingName = "project-v4-metrics-binding" var _ = Describe("Manager", Ordered, func() { + var controllerPodName string + // Before running the tests, set up the environment by creating the namespace, // installing CRDs, and deploying the controller. BeforeAll(func() { @@ -82,12 +84,53 @@ var _ = Describe("Manager", Ordered, func() { _, _ = utils.Run(cmd) }) + // After each test, check for failures and collect logs, events, + // and pod descriptions for debugging. + AfterEach(func() { + specReport := CurrentSpecReport() + if specReport.Failed() { + By("Fetching controller manager pod logs") + cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) + controllerLogs, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Controller logs:\n %s", controllerLogs)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Controller logs: %s", err)) + } + + By("Fetching Kubernetes events") + cmd = exec.Command("kubectl", "get", "events", "-n", namespace, "--sort-by=.lastTimestamp") + eventsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Kubernetes events:\n%s", eventsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get Kubernetes events: %s", err)) + } + + By("Fetching curl-metrics logs") + cmd = exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) + metricsOutput, err := utils.Run(cmd) + if err == nil { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Metrics logs:\n %s", metricsOutput)) + } else { + _, _ = fmt.Fprintf(GinkgoWriter, fmt.Sprintf("Failed to get curl-metrics logs: %s", err)) + } + + By("Fetching controller manager pod description") + cmd = exec.Command("kubectl", "describe", "pod", controllerPodName, "-n", namespace) + podDescription, err := utils.Run(cmd) + if err == nil { + fmt.Println("Pod description:\n", podDescription) + } else { + fmt.Println("Failed to describe controller pod") + } + } + }) + SetDefaultEventuallyTimeout(2 * time.Minute) SetDefaultEventuallyPollingInterval(time.Second) - // The Context block contains the actual tests that validate the manager's behavior. Context("Manager", func() { - var controllerPodName string It("should run successfully", func() { By("validating that the controller-manager pod is running as expected") verifyControllerUp := func(g Gomega) { @@ -103,7 +146,7 @@ var _ = Describe("Manager", Ordered, func() { podOutput, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred(), "Failed to retrieve controller-manager pod information") - podNames := utils.GetNonEmptyLines(string(podOutput)) + podNames := utils.GetNonEmptyLines(podOutput) g.Expect(podNames).To(HaveLen(1), "expected 1 controller pod running") controllerPodName = podNames[0] g.Expect(controllerPodName).To(ContainSubstring("controller-manager")) @@ -115,9 +158,8 @@ var _ = Describe("Manager", Ordered, func() { ) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(BeEquivalentTo("Running"), "Incorrect controller-manager pod status") + g.Expect(output).To(Equal("Running"), "Incorrect controller-manager pod status") } - // Repeatedly check if the controller-manager pod is running until it succeeds or times out. Eventually(verifyControllerUp).Should(Succeed()) }) @@ -150,7 +192,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "get", "endpoints", metricsServiceName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("8443"), "Metrics endpoint is not ready") + g.Expect(output).To(ContainSubstring("8443"), "Metrics endpoint is not ready") } Eventually(verifyMetricsEndpointReady).Should(Succeed()) @@ -159,7 +201,7 @@ var _ = Describe("Manager", Ordered, func() { cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), + g.Expect(output).To(ContainSubstring("controller-runtime.metrics\tServing metrics server"), "Metrics server not yet started") } Eventually(verifyMetricsServerStarted).Should(Succeed()) @@ -181,7 +223,7 @@ var _ = Describe("Manager", Ordered, func() { "-n", namespace) output, err := utils.Run(cmd) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(string(output)).To(Equal("Succeeded"), "curl pod in wrong status") + g.Expect(output).To(Equal("Succeeded"), "curl pod in wrong status") } Eventually(verifyCurlUp, 5*time.Minute).Should(Succeed()) @@ -261,7 +303,6 @@ func serviceAccountToken() (string, error) { } var out string - var rawJson string verifyTokenCreation := func(g Gomega) { // Execute kubectl command to create the token cmd := exec.Command("kubectl", "create", "--raw", fmt.Sprintf( @@ -273,11 +314,9 @@ func serviceAccountToken() (string, error) { output, err := cmd.CombinedOutput() g.Expect(err).NotTo(HaveOccurred()) - rawJson = string(output) - // Parse the JSON output to extract the token var token tokenRequest - err = json.Unmarshal([]byte(rawJson), &token) + err = json.Unmarshal([]byte(output), &token) g.Expect(err).NotTo(HaveOccurred()) out = token.Status.Token @@ -293,9 +332,8 @@ func getMetricsOutput() string { cmd := exec.Command("kubectl", "logs", "curl-metrics", "-n", namespace) metricsOutput, err := utils.Run(cmd) Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod") - metricsOutputStr := string(metricsOutput) - Expect(metricsOutputStr).To(ContainSubstring("< HTTP/1.1 200 OK")) - return metricsOutputStr + Expect(metricsOutput).To(ContainSubstring("< HTTP/1.1 200 OK")) + return metricsOutput } // tokenRequest is a simplified representation of the Kubernetes TokenRequest API response, diff --git a/testdata/project-v4/test/utils/utils.go b/testdata/project-v4/test/utils/utils.go index db4ad3f02f6..16a6383783a 100644 --- a/testdata/project-v4/test/utils/utils.go +++ b/testdata/project-v4/test/utils/utils.go @@ -41,7 +41,7 @@ func warnError(err error) { } // Run executes the provided command within this context -func Run(cmd *exec.Cmd) ([]byte, error) { +func Run(cmd *exec.Cmd) (string, error) { dir, _ := GetProjectDir() cmd.Dir = dir @@ -54,10 +54,10 @@ func Run(cmd *exec.Cmd) ([]byte, error) { _, _ = fmt.Fprintf(GinkgoWriter, "running: %s\n", command) output, err := cmd.CombinedOutput() if err != nil { - return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) + return string(output), fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) } - return output, nil + return string(output), nil } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics.