From 58c26a6b9298d8b454deb100a0a9985f40dc1289 Mon Sep 17 00:00:00 2001 From: Quan Tian Date: Thu, 25 Apr 2024 19:48:54 +0800 Subject: [PATCH] Improve the readability of post-installation test results * Test results will be displayed in green, red, and yellow to indicate success, failure, and skipped, respectively. * Show the total number of success, failure, and skipped tests in the end. * Return error if any test fails. Otherwise, it would be hard for automation tools to detect whether the check succeeds or not. Signed-off-by: Quan Tian --- go.mod | 4 +-- pkg/antctl/raw/check/installation/command.go | 34 ++++++++++++++++--- .../check/installation/test_podtointernet.go | 6 ++-- .../installation/test_podtopodinternode.go | 8 ++--- .../installation/test_podtopodintranode.go | 6 ++-- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index b0e0a36305a..9a9886de3c0 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/containernetworking/plugins v1.1.1 github.com/coreos/go-iptables v0.7.0 github.com/davecgh/go-spew v1.1.1 + github.com/fatih/color v1.15.0 github.com/fsnotify/fsnotify v1.7.0 github.com/gammazero/deque v0.1.2 github.com/go-logr/logr v1.4.1 @@ -41,6 +42,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/onsi/ginkgo/v2 v2.17.2 github.com/onsi/gomega v1.33.1 + github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.6 github.com/prometheus/client_golang v1.18.0 github.com/prometheus/common v0.47.0 @@ -126,7 +128,6 @@ require ( github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect - github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect github.com/go-errors/errors v1.4.2 // indirect @@ -186,7 +187,6 @@ require ( github.com/pion/logging v0.2.2 // indirect github.com/pion/transport/v2 v2.0.0 // indirect github.com/pion/udp v0.1.4 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect diff --git a/pkg/antctl/raw/check/installation/command.go b/pkg/antctl/raw/check/installation/command.go index 405f7b13f04..2b8a434e683 100644 --- a/pkg/antctl/raw/check/installation/command.go +++ b/pkg/antctl/raw/check/installation/command.go @@ -22,6 +22,7 @@ import ( "os" "time" + "github.com/fatih/color" "github.com/spf13/cobra" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -69,7 +70,9 @@ const ( ) type Test interface { - Run(ctx context.Context, testContext *testContext) error + // Run executes the test using the provided testContext. + // It returns a non-nil error when the test doesn't succeed and a bool indicating whether the test is skipped or not. + Run(ctx context.Context, testContext *testContext) (error, bool) } var testsRegistry = make(map[string]Test) @@ -99,16 +102,25 @@ func Run(o *options) error { if err := testContext.setup(ctx); err != nil { return err } + var numSuccess, numFailure, numSkipped int for name, test := range testsRegistry { testContext.Header("Running test: %s", name) - if err := test.Run(ctx, testContext); err != nil { - testContext.Header("Test %s failed: %s", name, err) + if err, skipped := test.Run(ctx, testContext); skipped { + testContext.Warning("Test %s was skipped: %v", name, err) + numSkipped++ + } else if err != nil { + testContext.Fail("Test %s failed: %v", name, err) + numFailure++ } else { - testContext.Header("Test %s passed", name) + testContext.Success("Test %s passed", name) + numSuccess++ } } - testContext.Log("Test finished") + testContext.Log("Test finished: %v tests succeeded, %v tests failed, %v tests were skipped", numSuccess, numFailure, numSkipped) testContext.teardown(ctx) + if numFailure > 0 { + return fmt.Errorf("%v/%v tests failed", numFailure, len(testsRegistry)) + } return nil } @@ -397,6 +409,18 @@ func (t *testContext) Log(format string, a ...interface{}) { fmt.Fprintf(os.Stdout, fmt.Sprintf("[%s] ", t.clusterName)+format+"\n", a...) } +func (t *testContext) Success(format string, a ...interface{}) { + fmt.Fprintf(os.Stdout, fmt.Sprintf("[%s] ", t.clusterName)+color.GreenString(format, a...)+"\n") +} + +func (t *testContext) Fail(format string, a ...interface{}) { + fmt.Fprintf(os.Stdout, fmt.Sprintf("[%s] ", t.clusterName)+color.RedString(format, a...)+"\n") +} + +func (t *testContext) Warning(format string, a ...interface{}) { + fmt.Fprintf(os.Stdout, fmt.Sprintf("[%s] ", t.clusterName)+color.YellowString(format, a...)+"\n") +} + func (t *testContext) Header(format string, a ...interface{}) { t.Log("-------------------------------------------------------------------------------------------") t.Log(format, a...) diff --git a/pkg/antctl/raw/check/installation/test_podtointernet.go b/pkg/antctl/raw/check/installation/test_podtointernet.go index 50bc7978d54..43d99a22a32 100644 --- a/pkg/antctl/raw/check/installation/test_podtointernet.go +++ b/pkg/antctl/raw/check/installation/test_podtointernet.go @@ -27,15 +27,15 @@ func init() { RegisterTest("pod-to-internet-connectivity", &PodToInternetConnectivityTest{}) } -func (t *PodToInternetConnectivityTest) Run(ctx context.Context, testContext *testContext) error { +func (t *PodToInternetConnectivityTest) Run(ctx context.Context, testContext *testContext) (error, bool) { for _, clientPod := range testContext.clientPods { srcPod := testContext.namespace + "/" + clientPod.Name testContext.Log("Validating connectivity from Pod %s to the world (google.com)...", srcPod) _, _, err := check.ExecInPod(ctx, testContext.client, testContext.config, testContext.namespace, clientPod.Name, clientDeploymentName, agnhostConnectCommand("google.com", "80")) if err != nil { - return fmt.Errorf("Pod %s was not able to connect to google.com: %w", srcPod, err) + return fmt.Errorf("Pod %s was not able to connect to google.com: %w", srcPod, err), false } testContext.Log("Pod %s was able to connect to google.com", srcPod) } - return nil + return nil, false } diff --git a/pkg/antctl/raw/check/installation/test_podtopodinternode.go b/pkg/antctl/raw/check/installation/test_podtopodinternode.go index b40f7719a17..daa9ecad2e8 100644 --- a/pkg/antctl/raw/check/installation/test_podtopodinternode.go +++ b/pkg/antctl/raw/check/installation/test_podtopodinternode.go @@ -27,9 +27,9 @@ func init() { RegisterTest("pod-to-pod-internode-connectivity", &PodToPodInterNodeConnectivityTest{}) } -func (t *PodToPodInterNodeConnectivityTest) Run(ctx context.Context, testContext *testContext) error { +func (t *PodToPodInterNodeConnectivityTest) Run(ctx context.Context, testContext *testContext) (error, bool) { if testContext.echoOtherNodePod == nil { - return fmt.Errorf("Skipping Inter-Node test because multiple Nodes are not available") + return fmt.Errorf("Inter-Node test requires multiple Nodes"), true } for _, clientPod := range testContext.clientPods { srcPod := testContext.namespace + "/" + clientPod.Name @@ -39,10 +39,10 @@ func (t *PodToPodInterNodeConnectivityTest) Run(ctx context.Context, testContext testContext.Log("Validating from Pod %s to Pod %s at IP %s...", srcPod, dstPod, echoIP) _, _, err := check.ExecInPod(ctx, testContext.client, testContext.config, testContext.namespace, clientPod.Name, "", agnhostConnectCommand(echoIP, "80")) if err != nil { - return fmt.Errorf("client Pod %s was not able to communicate with echo Pod %s (%s): %w", clientPod.Name, testContext.echoOtherNodePod.Name, echoIP, err) + return fmt.Errorf("client Pod %s was not able to communicate with echo Pod %s (%s): %w", clientPod.Name, testContext.echoOtherNodePod.Name, echoIP, err), false } testContext.Log("client Pod %s was able to communicate with echo Pod %s (%s)", clientPod.Name, testContext.echoOtherNodePod.Name, echoIP) } } - return nil + return nil, false } diff --git a/pkg/antctl/raw/check/installation/test_podtopodintranode.go b/pkg/antctl/raw/check/installation/test_podtopodintranode.go index 5fae4cbe947..08e83ec83d6 100644 --- a/pkg/antctl/raw/check/installation/test_podtopodintranode.go +++ b/pkg/antctl/raw/check/installation/test_podtopodintranode.go @@ -27,7 +27,7 @@ func init() { RegisterTest("pod-to-pod-intranode-connectivity", &PodToPodIntraNodeConnectivityTest{}) } -func (t *PodToPodIntraNodeConnectivityTest) Run(ctx context.Context, testContext *testContext) error { +func (t *PodToPodIntraNodeConnectivityTest) Run(ctx context.Context, testContext *testContext) (error, bool) { for _, clientPod := range testContext.clientPods { srcPod := testContext.namespace + "/" + clientPod.Name dstPod := testContext.namespace + "/" + testContext.echoSameNodePod.Name @@ -36,10 +36,10 @@ func (t *PodToPodIntraNodeConnectivityTest) Run(ctx context.Context, testContext testContext.Log("Validating from Pod %s to Pod %s at IP %s...", srcPod, dstPod, echoIP) _, _, err := check.ExecInPod(ctx, testContext.client, testContext.config, testContext.namespace, clientPod.Name, "", agnhostConnectCommand(echoIP, "80")) if err != nil { - return fmt.Errorf("client Pod %s was not able to communicate with echo Pod %s (%s): %w", clientPod.Name, testContext.echoSameNodePod.Name, echoIP, err) + return fmt.Errorf("client Pod %s was not able to communicate with echo Pod %s (%s): %w", clientPod.Name, testContext.echoSameNodePod.Name, echoIP, err), false } testContext.Log("client Pod %s was able to communicate with echo Pod %s (%s)", clientPod.Name, testContext.echoSameNodePod.Name, echoIP) } } - return nil + return nil, false }