From b64b3a59b6befd63770c560d4d497b78c8c70694 Mon Sep 17 00:00:00 2001 From: Marcin Owsiany Date: Thu, 29 May 2025 11:01:36 +0200 Subject: [PATCH 1/3] tests: retry k8s ops related to env vars --- tests/common.go | 28 +++++++++++++++------------- tests/delegated_scanning_test.go | 4 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/common.go b/tests/common.go index 4a4a5cab5d666..8566a3d6632e7 100644 --- a/tests/common.go +++ b/tests/common.go @@ -579,25 +579,27 @@ func waitUntilCentralSensorConnectionIs(t *testing.T, ctx context.Context, statu func (ks *KubernetesSuite) mustSetDeploymentEnvVal(ctx context.Context, namespace string, deployment string, container string, envVar string, value string) { patch := []byte(fmt.Sprintf(`{"spec":{"template":{"spec":{"containers":[{"name":%q,"env":[{"name":%q,"value":%q}]}]}}}}`, container, envVar, value)) - ks.logf("Setting variable %q on deployment %q in namespace %q to %q", envVar, deployment, namespace, value) - _, err := ks.k8s.AppsV1().Deployments(namespace).Patch(ctx, deployment, types.StrategicMergePatchType, patch, metaV1.PatchOptions{}) - ks.Require().NoError(err, "cannot patch deployment %q in namespace %q", deployment, namespace) + whatVar := fmt.Sprintf("variable %q on deployment %q in namespace %q to %q", envVar, deployment, namespace, value) + ks.logf("Setting %s", whatVar) + mustEventually(ks.T(), ctx, func() error { + _, err := ks.k8s.AppsV1().Deployments(namespace).Patch(ctx, deployment, types.StrategicMergePatchType, patch, metaV1.PatchOptions{}) + return err + }, 5*time.Second, fmt.Sprintf("cannot set %s", whatVar)) } // mustGetDeploymentEnvVal retrieves the value of environment variable in a deployment, or fails the test. func (ks *KubernetesSuite) mustGetDeploymentEnvVal(ctx context.Context, namespace string, deployment string, container string, envVar string) string { - val, err := ks.getDeploymentEnvVal(ctx, namespace, deployment, container, envVar) - ks.Require().NoError(err, "cannot find envVar %q in container %q in deployment %q in namespace %q", envVar, container, deployment, namespace) - return val -} - -// getDeploymentEnvVal returns the value of an environment variable or the empty string if not found. -func (ks *KubernetesSuite) getDeploymentEnvVal(ctx context.Context, namespace string, deployment string, container string, envVar string) (string, error) { - d, err := ks.k8s.AppsV1().Deployments(namespace).Get(ctx, deployment, metaV1.GetOptions{}) - ks.Require().NoError(err, "cannot retrieve deployment %q in namespace %q", deployment, namespace) + var d *appsV1.Deployment + mustEventually(ks.T(), ctx, func() error { + var err error + d, err = ks.k8s.AppsV1().Deployments(namespace).Get(ctx, deployment, metaV1.GetOptions{}) + return err + }, 5*time.Second, fmt.Sprintf("cannot retrieve deployment %q in namespace %q", deployment, namespace)) c, err := getContainer(d, container) ks.Require().NoError(err, "cannot find container %q in deployment %q in namespace %q", container, deployment, namespace) - return getEnvVal(c, envVar) + val, err := getEnvVal(c, envVar) + ks.Require().NoError(err, "cannot find envVar %q in container %q in deployment %q in namespace %q", envVar, container, deployment, namespace) + return val } // mustDeleteDeploymentEnvVar deletes an env var from all containers of a deployment, if any errors diff --git a/tests/delegated_scanning_test.go b/tests/delegated_scanning_test.go index a50a8974e4630..79bf3048e72da 100644 --- a/tests/delegated_scanning_test.go +++ b/tests/delegated_scanning_test.go @@ -171,7 +171,7 @@ func (ts *DelegatedScanningSuite) SetupSuite() { // Get a reference to the Secured Cluster to send delegated scans too. // If a valid remote cluster is NOT available all tests in this suite will fail. logf(t, "Getting remote StackRox cluster details") - envVal, _ := ts.getDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, env.LocalImageScanningEnabled.EnvVar()) + envVal := ts.mustGetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, env.LocalImageScanningEnabled.EnvVar()) // Verify the StackRox installation supports delegated scanning, Central and Sensor // must have an active connection for this check to succeed, so wait for that connection. @@ -194,7 +194,7 @@ func (ts *DelegatedScanningSuite) SetupSuite() { ts.remoteCluster = cluster // Enable Sensor debug logs, some tests need this to accurately validate expected behaviors. - ts.origSensorLogLevel, _ = ts.getDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar) + ts.origSensorLogLevel = ts.mustGetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar) if ts.origSensorLogLevel != deleScanDesiredLogLevel { ts.mustSetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar, deleScanDesiredLogLevel) logf(t, "Log level env var changed from %q to %q on Sensor", ts.origSensorLogLevel, deleScanDesiredLogLevel) From f2036156a77d342883a73aee25108068383781ad Mon Sep 17 00:00:00 2001 From: Marcin Owsiany Date: Tue, 22 Jul 2025 10:13:32 +0200 Subject: [PATCH 2/3] retain getDeploymentEnvVal --- tests/common.go | 28 ++++++++++++++++++++++++---- tests/delegated_scanning_test.go | 6 ++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/tests/common.go b/tests/common.go index 8566a3d6632e7..2575a5bf4d854 100644 --- a/tests/common.go +++ b/tests/common.go @@ -589,6 +589,15 @@ func (ks *KubernetesSuite) mustSetDeploymentEnvVal(ctx context.Context, namespac // mustGetDeploymentEnvVal retrieves the value of environment variable in a deployment, or fails the test. func (ks *KubernetesSuite) mustGetDeploymentEnvVal(ctx context.Context, namespace string, deployment string, container string, envVar string) string { + val, err := ks.getDeploymentEnvVal(ctx, namespace, deployment, container, envVar) + ks.Require().NoError(err, "cannot find envVar %q in container %q in deployment %q in namespace %q", envVar, container, deployment, namespace) + return val +} + +// getDeploymentEnvVal returns the value of an environment variable or the empty string if not found. +// Fails the test if deployment or container are missing, or API call fails repeatedly. +// Please use mustGetDeploymentEnvVal instead, unless you must tolerate a missing env var definition in the container. +func (ks *KubernetesSuite) getDeploymentEnvVal(ctx context.Context, namespace string, deployment string, container string, envVar string) (string, error) { var d *appsV1.Deployment mustEventually(ks.T(), ctx, func() error { var err error @@ -597,9 +606,7 @@ func (ks *KubernetesSuite) mustGetDeploymentEnvVal(ctx context.Context, namespac }, 5*time.Second, fmt.Sprintf("cannot retrieve deployment %q in namespace %q", deployment, namespace)) c, err := getContainer(d, container) ks.Require().NoError(err, "cannot find container %q in deployment %q in namespace %q", container, deployment, namespace) - val, err := getEnvVal(c, envVar) - ks.Require().NoError(err, "cannot find envVar %q in container %q in deployment %q in namespace %q", envVar, container, deployment, namespace) - return val + return getEnvVal(c, envVar) } // mustDeleteDeploymentEnvVar deletes an env var from all containers of a deployment, if any errors @@ -735,6 +742,19 @@ func deleteRole(t *testing.T, ctx context.Context, name string) { } } +type EnvVarNotFound []string + +func (e EnvVarNotFound) Error() string { + return fmt.Sprintf("actual vars are: %q", []string(e)) +} + +func requireNoErrorOrEnvVarNotFound(t require.TestingT, err error) { + if err == nil { + return + } + require.ErrorAs(t, err, EnvVarNotFound{}) +} + // getEnvVal returns the value of envVar from a given container or returns a helpful error. func getEnvVal(c *coreV1.Container, envVar string) (string, error) { var vars []string @@ -744,7 +764,7 @@ func getEnvVal(c *coreV1.Container, envVar string) (string, error) { } vars = append(vars, v.Name) } - return "", fmt.Errorf("actual vars are %q", vars) + return "", EnvVarNotFound(vars) } // getContainer returns the given container from a deployment or returns a helpful error. diff --git a/tests/delegated_scanning_test.go b/tests/delegated_scanning_test.go index 79bf3048e72da..e596ce46962f0 100644 --- a/tests/delegated_scanning_test.go +++ b/tests/delegated_scanning_test.go @@ -171,7 +171,8 @@ func (ts *DelegatedScanningSuite) SetupSuite() { // Get a reference to the Secured Cluster to send delegated scans too. // If a valid remote cluster is NOT available all tests in this suite will fail. logf(t, "Getting remote StackRox cluster details") - envVal := ts.mustGetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, env.LocalImageScanningEnabled.EnvVar()) + envVal, err := ts.getDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, env.LocalImageScanningEnabled.EnvVar()) + requireNoErrorOrEnvVarNotFound(t, err) // Verify the StackRox installation supports delegated scanning, Central and Sensor // must have an active connection for this check to succeed, so wait for that connection. @@ -194,7 +195,8 @@ func (ts *DelegatedScanningSuite) SetupSuite() { ts.remoteCluster = cluster // Enable Sensor debug logs, some tests need this to accurately validate expected behaviors. - ts.origSensorLogLevel = ts.mustGetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar) + ts.origSensorLogLevel, err = ts.getDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar) + requireNoErrorOrEnvVarNotFound(t, err) if ts.origSensorLogLevel != deleScanDesiredLogLevel { ts.mustSetDeploymentEnvVal(ctx, ts.namespace, sensorDeployment, sensorContainer, deleScanLogLevelEnvVar, deleScanDesiredLogLevel) logf(t, "Log level env var changed from %q to %q on Sensor", ts.origSensorLogLevel, deleScanDesiredLogLevel) From 05977d705ad1c7d167edbc203ff0bf10a558547c Mon Sep 17 00:00:00 2001 From: Marcin Owsiany Date: Tue, 22 Jul 2025 15:07:15 +0200 Subject: [PATCH 3/3] test panicked: errors: target must be a non-nil pointer --- tests/common.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/common.go b/tests/common.go index 2575a5bf4d854..b5224bb550a9b 100644 --- a/tests/common.go +++ b/tests/common.go @@ -752,7 +752,7 @@ func requireNoErrorOrEnvVarNotFound(t require.TestingT, err error) { if err == nil { return } - require.ErrorAs(t, err, EnvVarNotFound{}) + require.ErrorAs(t, err, &EnvVarNotFound{}) } // getEnvVal returns the value of envVar from a given container or returns a helpful error.