From 9ef28893c4c7a7e4a38b9c04bad2a42a58e6e275 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Fri, 25 Sep 2026 14:35:05 +0200 Subject: [PATCH 1/9] use argocd-redis secret by default Signed-off-by: nodari-dev --- .../controllers/argocd/deployment_test.go | 4 ++-- argocd-operator/controllers/argocd/secret.go | 18 ++++++++++++++++-- .../controllers/argocd/secret_test.go | 5 ++--- .../controllers/argocd/statefulset_test.go | 2 +- .../controllers/argocd/status_test.go | 3 +++ argocd-operator/controllers/argocd/util.go | 1 + .../controllers/argocdagent/deployment_test.go | 2 +- argocd-operator/controllers/argoutil/redis.go | 2 +- .../controllers/argoutil/resource.go | 1 + argocd-operator/controllers/argoutil/secret.go | 2 ++ .../1-019_validate_volume_mounts_test.go | 6 +++--- ..._redis_secure_comm_no_autotls_no_ha_test.go | 2 +- ...051_validate_argocd_agent_principal_test.go | 2 +- .../1-052_validate_argocd_agent_agent_test.go | 2 +- ...ate_redis_secure_comm_no_autotls_ha_test.go | 2 +- .../1-019_validate_volume_mounts_test.go | 6 +++--- ..._redis_secure_comm_no_autotls_no_ha_test.go | 2 +- ...051_validate_argocd_agent_principal_test.go | 2 +- .../1-052_validate_argocd_agent_agent_test.go | 2 +- ...ate_redis_secure_comm_no_autotls_ha_test.go | 2 +- 20 files changed, 44 insertions(+), 24 deletions(-) diff --git a/argocd-operator/controllers/argocd/deployment_test.go b/argocd-operator/controllers/argocd/deployment_test.go index 0433cacf4b2..7f166b32db0 100644 --- a/argocd-operator/controllers/argocd/deployment_test.go +++ b/argocd-operator/controllers/argocd/deployment_test.go @@ -2399,7 +2399,7 @@ func repoServerDefaultVolumes() []corev1.Volume { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, {Key: "auth_username", Path: "auth_username"}, @@ -2506,7 +2506,7 @@ func serverDefaultVolumes() []corev1.Volume { Name: argoutil.RedisAuthVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, {Key: "auth_username", Path: "auth_username"}, diff --git a/argocd-operator/controllers/argocd/secret.go b/argocd-operator/controllers/argocd/secret.go index 05d40761407..4e0ed94a457 100644 --- a/argocd-operator/controllers/argocd/secret.go +++ b/argocd-operator/controllers/argocd/secret.go @@ -1143,7 +1143,13 @@ func (r *ReconcileArgoCD) getClusterSecrets(cr *argoproj.ArgoCD) (*corev1.Secret // reconcileRedisInitialPasswordSecret will ensure that the redis Secret is present for the cluster. func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoCD) error { - secret := argoutil.NewSecretWithSuffix(cr, "redis-initial-password") + // Fix for GITOPS-11058: + // 1. Create a new secret: argocd-redis to be compatible with argocd cli + // 2. Delete an old style secret: [id]-redis-initial-password in case it exists + + // Generate secret in new style: argocd-redis + secretName := "argocd-redis" + secret := argoutil.NewSecretWithName(cr, secretName) existed := true // Recreate if the secret or some of its keys are missing @@ -1166,7 +1172,7 @@ func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoC if existed { // Drop unsettable fields created by FetchObject - secret = argoutil.NewSecretWithSuffix(cr, "redis-initial-password") + secret = argoutil.NewSecretWithName(cr, secretName) } redisInitialPassword, err := generateRedisAdminPassword() @@ -1180,6 +1186,14 @@ func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoC return err } + // Generate secret in old style: [id]-redis-initial-password + oldSecretName := "redis-initial-password" + oldSecret := argoutil.NewSecretWithSuffix(cr, oldSecretName) + + // Silent deletion of old secret in case it exited before + argoutil.LogResourceDeletion(log, oldSecret) + _ = r.Delete(context.TODO(), oldSecret) + if existed { argoutil.LogResourceUpdate(log, secret) return r.Update(context.TODO(), secret) diff --git a/argocd-operator/controllers/argocd/secret_test.go b/argocd-operator/controllers/argocd/secret_test.go index 8d1e3724a5b..e24f0000dc7 100644 --- a/argocd-operator/controllers/argocd/secret_test.go +++ b/argocd-operator/controllers/argocd/secret_test.go @@ -524,14 +524,13 @@ func Test_ReconcileArgoCD_ReconcileShouldNotChangeWhenUpdatedAdminPass(t *testin } func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { - const suffix = "redis-initial-password" argocd := &argoproj.ArgoCD{ ObjectMeta: metav1.ObjectMeta{ Name: "argocd", Namespace: "argocd-operator", }, } - secretName := argoutil.NewSecretWithSuffix(argocd, suffix).Name + secretName := "argocd-redis" secretNN := types.NamespacedName{Name: secretName, Namespace: "argocd-operator"} resObjs := []client.Object{argocd} @@ -567,7 +566,7 @@ func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { t.Run("Update keys and regenerate on operator upgrade", func(t *testing.T) { const oldPwd = "asdfghjkl" - secret := argoutil.NewSecretWithSuffix(argocd, suffix) + secret := argoutil.NewSecretWithName(argocd, "argocd-redis") secret.Data = map[string][]byte{ "immutable": []byte("true"), common.ArgoCDKeyAdminPassword: []byte(oldPwd), diff --git a/argocd-operator/controllers/argocd/statefulset_test.go b/argocd-operator/controllers/argocd/statefulset_test.go index 974f779a658..5cdab1ff587 100644 --- a/argocd-operator/controllers/argocd/statefulset_test.go +++ b/argocd-operator/controllers/argocd/statefulset_test.go @@ -95,7 +95,7 @@ func controllerDefaultVolumes() []corev1.Volume { Name: argoutil.RedisAuthVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, {Key: "auth_username", Path: "auth_username"}, diff --git a/argocd-operator/controllers/argocd/status_test.go b/argocd-operator/controllers/argocd/status_test.go index 2ecf54c2fd5..bdede221d05 100644 --- a/argocd-operator/controllers/argocd/status_test.go +++ b/argocd-operator/controllers/argocd/status_test.go @@ -2,6 +2,7 @@ package argocd import ( "context" + "fmt" "testing" promoter "github.com/argoproj-labs/gitops-promoter/api/v1alpha1" @@ -23,6 +24,8 @@ import ( func TestReconcileArgoCD_reconcileStatusSSO(t *testing.T) { logf.SetLogger(ZapLogger(true)) + fmt.Println("===================== FAILING =====================") + tests := []struct { name string argoCD *argoproj.ArgoCD diff --git a/argocd-operator/controllers/argocd/util.go b/argocd-operator/controllers/argocd/util.go index 126e54b1f81..ba42175cb79 100644 --- a/argocd-operator/controllers/argocd/util.go +++ b/argocd-operator/controllers/argocd/util.go @@ -425,6 +425,7 @@ func getArgoControllerParallelismLimit(cr *argoproj.ArgoCD) int32 { // nameWithSuffix will return a name based on the given ArgoCD using the better truncation approach. // The CR name is truncated first, then the full suffix is appended to preserve suffix readability. +// CHANGE HERE // Example: Given a long ArgoCD name, this ensures suffixes like "redis-initial-password" remain intact. func nameWithSuffix(suffix string, cr *argoproj.ArgoCD) string { return argoutil.NameWithSuffix(cr.ObjectMeta, suffix) diff --git a/argocd-operator/controllers/argocdagent/deployment_test.go b/argocd-operator/controllers/argocdagent/deployment_test.go index 7c3b56746cc..9d4d434bace 100644 --- a/argocd-operator/controllers/argocdagent/deployment_test.go +++ b/argocd-operator/controllers/argocdagent/deployment_test.go @@ -442,7 +442,7 @@ func TestReconcilePrincipalDeployment_VerifyDeploymentSpec(t *testing.T) { redisAuthVolume := deployment.Spec.Template.Spec.Volumes[2] assert.Equal(t, "redis-initial-pass", redisAuthVolume.Name) assert.NotNil(t, redisAuthVolume.Secret) - assert.Equal(t, "argocd-redis-initial-password", redisAuthVolume.Secret.SecretName) + assert.Equal(t, "argocd-redis", redisAuthVolume.Secret.SecretName) assert.NotEqual(t, new(true), redisAuthVolume.Secret.Optional) assert.Len(t, redisAuthVolume.Secret.Items, 2) } diff --git a/argocd-operator/controllers/argoutil/redis.go b/argocd-operator/controllers/argoutil/redis.go index e1fbdfade74..4a4ce8aec2d 100644 --- a/argocd-operator/controllers/argoutil/redis.go +++ b/argocd-operator/controllers/argoutil/redis.go @@ -26,7 +26,7 @@ func MountRedisAuthToRedis(cr *argoproj.ArgoCD) (volume corev1.Volume, mount cor Name: RedisAuthVolumeName, VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: GetSecretNameWithSuffix(cr, "redis-initial-password"), + SecretName: "argocd-redis", }, }, } diff --git a/argocd-operator/controllers/argoutil/resource.go b/argocd-operator/controllers/argoutil/resource.go index 6044570be04..b209c0c88fd 100644 --- a/argocd-operator/controllers/argoutil/resource.go +++ b/argocd-operator/controllers/argoutil/resource.go @@ -315,6 +315,7 @@ func TruncateWithHash(input string, maxLength int) string { } // TruncateCRName truncates an ArgoCD CR name to allow for the longest possible suffix +// CHANGE ME HERE // This ensures that when suffixes like "redis-initial-password" are appended, // the total length stays within Kubernetes 63-character limit func TruncateCRName(crName string) string { diff --git a/argocd-operator/controllers/argoutil/secret.go b/argocd-operator/controllers/argoutil/secret.go index bb1ba8fa4c9..f333c719dff 100644 --- a/argocd-operator/controllers/argoutil/secret.go +++ b/argocd-operator/controllers/argoutil/secret.go @@ -77,6 +77,8 @@ func NewSecretWithSuffix(cr *argoproj.ArgoCD, suffix string) *corev1.Secret { // GetSecretNameWithSuffix returns the secret name using truncated CR name + full suffix. // This function should be used when referencing secret names in other resources. + +// seems I dont need to change it as it just a util and there is no hardcoded value func GetSecretNameWithSuffix(cr *argoproj.ArgoCD, suffix string) string { truncatedCRName := GetTruncatedCRName(cr) return fmt.Sprintf("%s-%s", truncatedCRName, suffix) diff --git a/argocd-operator/tests/ginkgo/parallel/1-019_validate_volume_mounts_test.go b/argocd-operator/tests/ginkgo/parallel/1-019_validate_volume_mounts_test.go index c3880e69b49..6d1b74bf6f4 100644 --- a/argocd-operator/tests/ginkgo/parallel/1-019_validate_volume_mounts_test.go +++ b/argocd-operator/tests/ginkgo/parallel/1-019_validate_volume_mounts_test.go @@ -135,7 +135,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, @@ -222,7 +222,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, @@ -297,7 +297,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, diff --git a/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go b/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go index 5fa818756a9..bd75c49dbd0 100644 --- a/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go +++ b/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go @@ -221,7 +221,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go b/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go index 8221252e96c..f39dee2b826 100644 --- a/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go +++ b/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go @@ -161,7 +161,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { PrincipalTLSSecretName: agentPrincipalTLSSecretName, RootCASecretName: agentRootCASecretName, ResourceProxyTLSSecretName: agentResourceProxyTLSSecretName, - RedisInitialPasswordSecretName: "example-redis-initial-password", + RedisInitialPasswordSecretName: "argocd-redis", } resourceProxyServiceName = fmt.Sprintf("%s-agent-principal-resource-proxy", argoCDName) diff --git a/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go b/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go index ba2f9d0b263..2213d3fe52c 100644 --- a/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go +++ b/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go @@ -149,7 +149,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { secretNames = []string{ agentClientTLSSecretName, agentRootCASecretName, - "example-redis-initial-password", + "argocd-redis", } serviceNames = []string{ diff --git a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go index c3659c6b308..6edf398abc9 100644 --- a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ b/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go @@ -269,7 +269,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/test/openshift/e2e/ginkgo/parallel/1-019_validate_volume_mounts_test.go b/test/openshift/e2e/ginkgo/parallel/1-019_validate_volume_mounts_test.go index 6a1a02171e7..93cc3b9e281 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-019_validate_volume_mounts_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-019_validate_volume_mounts_test.go @@ -134,7 +134,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, @@ -221,7 +221,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, @@ -296,7 +296,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { Name: "redis-initial-pass", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "argocd-redis-initial-password", + SecretName: "argocd-redis", DefaultMode: new(int32(420)), Items: []corev1.KeyToPath{ {Key: "auth", Path: "auth"}, diff --git a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go index f64fc106849..34f19d863ec 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go @@ -224,7 +224,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go index 06d97ad68e7..26efffce6e1 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go @@ -160,7 +160,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { PrincipalTLSSecretName: agentPrincipalTLSSecretName, RootCASecretName: agentRootCASecretName, ResourceProxyTLSSecretName: agentResourceProxyTLSSecretName, - RedisInitialPasswordSecretName: "example-redis-initial-password", + RedisInitialPasswordSecretName: "argocd-redis", } resourceProxyServiceName = fmt.Sprintf("%s-agent-principal-resource-proxy", argoCDName) diff --git a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go index fa1a7245f49..9f01f76562e 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go @@ -150,7 +150,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { secretNames = []string{ agentClientTLSSecretName, agentRootCASecretName, - "example-redis-initial-password", + "argocd-redis", } serviceNames = []string{ diff --git a/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go index f8b461bd342..d1c12e62892 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go @@ -310,7 +310,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "redis-initial-password"), + Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) From 38d6cfb7a0727eada75a871caf0b8b021d595a5a Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Fri, 25 Sep 2026 14:50:35 +0200 Subject: [PATCH 2/9] remove unused changes Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/status_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/argocd-operator/controllers/argocd/status_test.go b/argocd-operator/controllers/argocd/status_test.go index bdede221d05..2ecf54c2fd5 100644 --- a/argocd-operator/controllers/argocd/status_test.go +++ b/argocd-operator/controllers/argocd/status_test.go @@ -2,7 +2,6 @@ package argocd import ( "context" - "fmt" "testing" promoter "github.com/argoproj-labs/gitops-promoter/api/v1alpha1" @@ -24,8 +23,6 @@ import ( func TestReconcileArgoCD_reconcileStatusSSO(t *testing.T) { logf.SetLogger(ZapLogger(true)) - fmt.Println("===================== FAILING =====================") - tests := []struct { name string argoCD *argoproj.ArgoCD From c0f03f3f2c0370d0e9322b9fcc18818679a3c49b Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Fri, 25 Sep 2026 15:04:34 +0200 Subject: [PATCH 3/9] remove dev comments, updated e2e tests Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/util.go | 1 - argocd-operator/controllers/argoutil/resource.go | 1 - argocd-operator/controllers/argoutil/secret.go | 2 -- .../1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go | 2 +- .../1-067_validate_redis_secure_comm_no_autotls_ha_test.go | 2 +- .../1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go | 2 +- .../1-067_validate_redis_secure_comm_no_autotls_ha_test.go | 2 +- 7 files changed, 4 insertions(+), 8 deletions(-) diff --git a/argocd-operator/controllers/argocd/util.go b/argocd-operator/controllers/argocd/util.go index ba42175cb79..126e54b1f81 100644 --- a/argocd-operator/controllers/argocd/util.go +++ b/argocd-operator/controllers/argocd/util.go @@ -425,7 +425,6 @@ func getArgoControllerParallelismLimit(cr *argoproj.ArgoCD) int32 { // nameWithSuffix will return a name based on the given ArgoCD using the better truncation approach. // The CR name is truncated first, then the full suffix is appended to preserve suffix readability. -// CHANGE HERE // Example: Given a long ArgoCD name, this ensures suffixes like "redis-initial-password" remain intact. func nameWithSuffix(suffix string, cr *argoproj.ArgoCD) string { return argoutil.NameWithSuffix(cr.ObjectMeta, suffix) diff --git a/argocd-operator/controllers/argoutil/resource.go b/argocd-operator/controllers/argoutil/resource.go index b209c0c88fd..6044570be04 100644 --- a/argocd-operator/controllers/argoutil/resource.go +++ b/argocd-operator/controllers/argoutil/resource.go @@ -315,7 +315,6 @@ func TruncateWithHash(input string, maxLength int) string { } // TruncateCRName truncates an ArgoCD CR name to allow for the longest possible suffix -// CHANGE ME HERE // This ensures that when suffixes like "redis-initial-password" are appended, // the total length stays within Kubernetes 63-character limit func TruncateCRName(crName string) string { diff --git a/argocd-operator/controllers/argoutil/secret.go b/argocd-operator/controllers/argoutil/secret.go index f333c719dff..bb1ba8fa4c9 100644 --- a/argocd-operator/controllers/argoutil/secret.go +++ b/argocd-operator/controllers/argoutil/secret.go @@ -77,8 +77,6 @@ func NewSecretWithSuffix(cr *argoproj.ArgoCD, suffix string) *corev1.Secret { // GetSecretNameWithSuffix returns the secret name using truncated CR name + full suffix. // This function should be used when referencing secret names in other resources. - -// seems I dont need to change it as it just a util and there is no hardcoded value func GetSecretNameWithSuffix(cr *argoproj.ArgoCD, suffix string) string { truncatedCRName := GetTruncatedCRName(cr) return fmt.Sprintf("%s-%s", truncatedCRName, suffix) diff --git a/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go b/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go index bd75c49dbd0..412b031c7cc 100644 --- a/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go +++ b/argocd-operator/tests/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go @@ -221,7 +221,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), + Name: "argocd-redis", Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go index 6edf398abc9..6823d6f8821 100644 --- a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ b/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go @@ -269,7 +269,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), + Name: "argocd-redis", Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go index 34f19d863ec..e2687d95565 100644 --- a/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go +++ b/test/openshift/e2e/ginkgo/parallel/1-066_validate_redis_secure_comm_no_autotls_no_ha_test.go @@ -224,7 +224,7 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), + Name: "argocd-redis", Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) diff --git a/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go index d1c12e62892..ec686fd78ea 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go @@ -310,7 +310,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("verifying redis password is correct") redisInitialSecret := &corev1.Secret{} redisPwdSecretKey := client.ObjectKey{ - Name: argoutil.GetSecretNameWithSuffix(argoCD, "argocd-redis"), + Name: "argocd-redis", Namespace: ns.Name, } Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) From a23bfcc18e7884081c6f52e38639a35a6d6c8563 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Tue, 29 Sep 2026 13:55:39 +0200 Subject: [PATCH 4/9] added test for secret replacement Signed-off-by: nodari-dev --- .../controllers/argocd/secret_test.go | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/argocd-operator/controllers/argocd/secret_test.go b/argocd-operator/controllers/argocd/secret_test.go index e24f0000dc7..59233a8374c 100644 --- a/argocd-operator/controllers/argocd/secret_test.go +++ b/argocd-operator/controllers/argocd/secret_test.go @@ -134,6 +134,44 @@ func TestReconcileArgoCD_reconcileClusterCASecret(t *testing.T) { assert.True(t, apierrors.IsNotFound(err), "default-named CA secret must not be created when a custom name is set; got err: %v", err) }) + t.Run("deletes redis-initial-password secret and replaces it with argocd-redis", func(t *testing.T) { + argocd := &argoproj.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{ + Name: "argocd", + Namespace: "argocd-operator", + }, + } + + oldRedisSecret := argoutil.NewSecretWithSuffix(argocd, "redis-initial-password") + oldRedisSecret.Data = map[string][]byte{common.ArgoCDKeyAdminPassword: []byte("something")} + tlsSecret := argoutil.NewSecretWithSuffix(argocd, "tls") + + resObjs := []client.Object{argocd} + subresObjs := []client.Object{argocd} + runtimeObjs := []runtime.Object{} + sch := makeTestReconcilerScheme(argoproj.AddToScheme, promoter.AddToScheme, apiregistrationv1.AddToScheme) + cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs) + r := makeTestReconciler(cl, sch, testclient.NewSimpleClientset()) + + err := r.Create(context.TODO(), oldRedisSecret) + assert.NoError(t, err) + err = r.Create(context.TODO(), tlsSecret) + assert.NoError(t, err) + + err = r.reconcileRedisInitialPasswordSecret(argocd) + + assert.NoError(t, err) + + oldSecretErr := r.Get(context.TODO(), types.NamespacedName{Name: oldRedisSecret.Name, Namespace: "argocd-operator"}, oldRedisSecret) + assert.True(t, apierrors.IsNotFound(oldSecretErr)) + + newRedisSecret := argoutil.NewSecretWithName(argocd, "argocd-redis") + newRedisSecret.Data = map[string][]byte{common.ArgoCDKeyAdminPassword: []byte("something")} + + newSecretErr := r.Get(context.TODO(), types.NamespacedName{Name: newRedisSecret.Name, Namespace: "argocd-operator"}, newRedisSecret) + assert.NoError(t, newSecretErr) + }) + t.Run("skips creation when custom-named CA secret already exists", func(t *testing.T) { const customName = "my-custom-ca" a := makeTestArgoCD(func(a *argoproj.ArgoCD) { From f188d51713046b8b1463f69608fb3963ec6f8f19 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Wed, 30 Sep 2026 10:45:22 +0200 Subject: [PATCH 5/9] extend test for initial redis secret Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/secret_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argocd-operator/controllers/argocd/secret_test.go b/argocd-operator/controllers/argocd/secret_test.go index 59233a8374c..a8dcd505935 100644 --- a/argocd-operator/controllers/argocd/secret_test.go +++ b/argocd-operator/controllers/argocd/secret_test.go @@ -166,10 +166,10 @@ func TestReconcileArgoCD_reconcileClusterCASecret(t *testing.T) { assert.True(t, apierrors.IsNotFound(oldSecretErr)) newRedisSecret := argoutil.NewSecretWithName(argocd, "argocd-redis") - newRedisSecret.Data = map[string][]byte{common.ArgoCDKeyAdminPassword: []byte("something")} newSecretErr := r.Get(context.TODO(), types.NamespacedName{Name: newRedisSecret.Name, Namespace: "argocd-operator"}, newRedisSecret) assert.NoError(t, newSecretErr) + assert.Equal(t, newRedisSecret.Data[common.ArgoCDKeyAdminPassword], newRedisSecret.Data[common.ArgoCDKeyAdminPassword], "argocd-redis should contain admin redis password") }) t.Run("skips creation when custom-named CA secret already exists", func(t *testing.T) { From 6022d43303a1bed734d5b71162b396217ab78d28 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Wed, 30 Sep 2026 13:12:40 +0200 Subject: [PATCH 6/9] improve deletion flow and ignore only notfound Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/secret.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/argocd-operator/controllers/argocd/secret.go b/argocd-operator/controllers/argocd/secret.go index 4e0ed94a457..75ef33cb89e 100644 --- a/argocd-operator/controllers/argocd/secret.go +++ b/argocd-operator/controllers/argocd/secret.go @@ -1145,7 +1145,7 @@ func (r *ReconcileArgoCD) getClusterSecrets(cr *argoproj.ArgoCD) (*corev1.Secret func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoCD) error { // Fix for GITOPS-11058: // 1. Create a new secret: argocd-redis to be compatible with argocd cli - // 2. Delete an old style secret: [id]-redis-initial-password in case it exists + // 2. Delete an old style secret: [instance]-redis-initial-password in case it exists // Generate secret in new style: argocd-redis secretName := "argocd-redis" @@ -1186,13 +1186,18 @@ func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoC return err } - // Generate secret in old style: [id]-redis-initial-password + // Generate secret in old style: [instance]-redis-initial-password oldSecretName := "redis-initial-password" oldSecret := argoutil.NewSecretWithSuffix(cr, oldSecretName) - // Silent deletion of old secret in case it exited before + // Deletion of old secret in case it exited before argoutil.LogResourceDeletion(log, oldSecret) - _ = r.Delete(context.TODO(), oldSecret) + err = r.Delete(context.TODO(), oldSecret) + if err != nil { + if !apierrors.IsNotFound(err) { + return err + } + } if existed { argoutil.LogResourceUpdate(log, secret) From 9efdd3ab5634f6afe27c6c2f41651e25d7599c3d Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Wed, 28 Oct 2026 00:33:42 +0100 Subject: [PATCH 7/9] migrate old sected password into new one Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/secret.go | 212 +++++++++++++--- .../controllers/argocd/secret_test.go | 238 +++++++++++++++++- 2 files changed, 406 insertions(+), 44 deletions(-) diff --git a/argocd-operator/controllers/argocd/secret.go b/argocd-operator/controllers/argocd/secret.go index 21f4acde92d..60f5b841ad7 100644 --- a/argocd-operator/controllers/argocd/secret.go +++ b/argocd-operator/controllers/argocd/secret.go @@ -35,6 +35,7 @@ import ( "github.com/redhat-developer/gitops-operator/argocd-operator/common" "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argoutil" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -331,7 +332,7 @@ func (r *ReconcileArgoCD) reconcileClusterSecrets(cr *argoproj.ArgoCD) error { return err } - if err := r.reconcileRedisInitialPasswordSecret(cr); err != nil { + if err := r.reconcileRedisSecret(cr); err != nil { return err } @@ -1141,68 +1142,205 @@ func (r *ReconcileArgoCD) getClusterSecrets(cr *argoproj.ArgoCD) (*corev1.Secret return clusterSecrets, nil } -// reconcileRedisInitialPasswordSecret will ensure that the redis Secret is present for the cluster. -func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoCD) error { +// REDIS_INITIAL_PASSWORD is the suffix of the Secret that held the Redis password before +// GITOPS-11058, i.e. [instance]-redis-initial-password. +const REDIS_INITIAL_PASSWORD = "redis-initial-password" + +// ARGOCD_REDIS is the name of the Secret holding the Redis credentials. It deliberately does not +// carry the instance name, so that it is compatible with the argocd CLI. +const ARGOCD_REDIS = common.ArgoCDRedisComponent + +func (r *ReconcileArgoCD) reconcileRedisSecret(cr *argoproj.ArgoCD) error { // Fix for GITOPS-11058: - // 1. Create a new secret: argocd-redis to be compatible with argocd cli - // 2. Delete an old style secret: [instance]-redis-initial-password in case it exists + // PROVIDE A NEW DESCRIPTION + + new := argoutil.NewSecretWithName(cr, ARGOCD_REDIS) + newExists, err := r.checkSecretExistence(cr, new) + if err != nil { + return err + } + + if newExists && secretIsHealthy(new) { + // Healthy - keep it + return r.deleteLegacyRedisSecret(cr) + } else if newExists && !secretIsHealthy(new) { + // secret not healthy, update + new = argoutil.NewSecretWithName(cr, ARGOCD_REDIS) + err := prepareSecretForUpdateCreate(r, cr, new) + if err != nil { + return err + } + if err := r.deleteLegacyRedisSecret(cr); err != nil { + return err + } + argoutil.LogResourceUpdate(log, new) + return r.Update(context.TODO(), new) + } + + // argocd-redis secret does not exist + old := argoutil.NewSecretWithSuffix(cr, REDIS_INITIAL_PASSWORD) + oldExists, err := r.checkSecretExistence(cr, old) + if err != nil { + return err + } + if oldExists && secretIsHealthy(old) { + // Carry the password over from the legacy secret + new.Data = argoutil.GetRedisSecretData(old.Data[common.ArgoCDKeyAdminPassword]) + + if err := controllerutil.SetControllerReference(cr, new, r.Scheme); err != nil { + return err + } + } else { + if err := prepareSecretForUpdateCreate(r, cr, new); err != nil { + return err + } + } - // Generate secret in new style: argocd-redis - secretName := "argocd-redis" - secret := argoutil.NewSecretWithName(cr, secretName) + if err := r.deleteLegacyRedisSecret(cr); err != nil { + return err + } + argoutil.LogResourceCreation(log, new) + return r.Create(context.TODO(), new) +} +// checkSecretExistence reports whether the given Secret exists, populating it when it does. +func (r *ReconcileArgoCD) checkSecretExistence(cr *argoproj.ArgoCD, s *corev1.Secret) (bool, error) { existed := true - // Recreate if the secret or some of its keys are missing - err := argoutil.FetchObject(r.Client, cr.Namespace, secret.Name, secret) + err := argoutil.FetchObject(r.Client, cr.Namespace, s.Name, s) if err != nil { if !apierrors.IsNotFound(err) { - return err + return false, err } existed = false } - if secret.Data != nil { - _, hasPwd := secret.Data[common.ArgoCDKeyAdminPassword] - _, hasAuth := secret.Data["auth"] - _, hasUsername := secret.Data["auth_username"] - _, hasAcl := secret.Data["users.acl"] - if hasPwd && hasAuth && hasUsername && hasAcl { - return nil // Healthy - keep it + return existed, nil +} + +// Check usage of provided secret +// Checks in: Pod, Deployment or StatefulSet in the namespace +func (r *ReconcileArgoCD) secretInUse(namespace string, secretName string) (bool, error) { + pods := &corev1.PodList{} + if err := r.List(context.TODO(), pods, client.InNamespace(namespace)); err != nil { + return false, err + } + for i := range pods.Items { + if secretReferencedByPodSpec(&pods.Items[i].Spec, secretName) { + return true, nil } } - if existed { - // Drop unsettable fields created by FetchObject - secret = argoutil.NewSecretWithName(cr, secretName) + deployments := &appsv1.DeploymentList{} + if err := r.List(context.TODO(), deployments, client.InNamespace(namespace)); err != nil { + return false, err + } + for i := range deployments.Items { + if secretReferencedByPodSpec(&deployments.Items[i].Spec.Template.Spec, secretName) { + return true, nil + } } - redisInitialPassword, err := generateRedisAdminPassword() - if err != nil { - return err + statefulSets := &appsv1.StatefulSetList{} + if err := r.List(context.TODO(), statefulSets, client.InNamespace(namespace)); err != nil { + return false, err + } + for i := range statefulSets.Items { + if secretReferencedByPodSpec(&statefulSets.Items[i].Spec.Template.Spec, secretName) { + return true, nil + } } - secret.Data = argoutil.GetRedisSecretData(redisInitialPassword) + return false, nil +} - if err := controllerutil.SetControllerReference(cr, secret, r.Scheme); err != nil { +// Check if Spec mounts the named Secret +func secretReferencedByPodSpec(spec *corev1.PodSpec, secretName string) bool { + for _, volume := range spec.Volumes { + if volume.Secret != nil && volume.Secret.SecretName == secretName { + return true + } + if volume.Projected == nil { + continue + } + for _, source := range volume.Projected.Sources { + if source.Secret != nil && source.Secret.Name == secretName { + return true + } + } + } + + containers := append(append([]corev1.Container{}, spec.InitContainers...), spec.Containers...) + for _, container := range containers { + for _, env := range container.Env { + if env.ValueFrom != nil && env.ValueFrom.SecretKeyRef != nil && env.ValueFrom.SecretKeyRef.Name == secretName { + return true + } + } + for _, envFrom := range container.EnvFrom { + if envFrom.SecretRef != nil && envFrom.SecretRef.Name == secretName { + return true + } + } + } + + return false +} + +func (r *ReconcileArgoCD) deleteLegacyRedisSecret(cr *argoproj.ArgoCD) error { + // Delete [instance]-redis-initial-password + legacy := argoutil.NewSecretWithSuffix(cr, REDIS_INITIAL_PASSWORD) + + exists, err := r.checkSecretExistence(cr, legacy) + if err != nil { return err } + if !exists { + return nil + } - // Generate secret in old style: [instance]-redis-initial-password - oldSecretName := "redis-initial-password" - oldSecret := argoutil.NewSecretWithSuffix(cr, oldSecretName) + inUse, err := r.secretInUse(cr.Namespace, legacy.Name) + if err != nil { + return err + } + if inUse { + return nil + } - // Deletion of old secret in case it exited before - argoutil.LogResourceDeletion(log, oldSecret) - err = r.Delete(context.TODO(), oldSecret) + argoutil.LogResourceDeletion(log, legacy) + err = r.Delete(context.TODO(), legacy) if err != nil { if !apierrors.IsNotFound(err) { return err } } + return nil +} + +func secretIsHealthy(s *corev1.Secret) bool { + healthy := false + if s.Data != nil { + _, hasPwd := s.Data[common.ArgoCDKeyAdminPassword] + _, hasAuth := s.Data["auth"] + _, hasUsername := s.Data["auth_username"] + _, hasAcl := s.Data["users.acl"] - if existed { - argoutil.LogResourceUpdate(log, secret) - return r.Update(context.TODO(), secret) + if hasPwd && hasAuth && hasUsername && hasAcl { + healthy = true + } } - argoutil.LogResourceCreation(log, secret) - return r.Create(context.TODO(), secret) + return healthy +} + +func prepareSecretForUpdateCreate(r *ReconcileArgoCD, cr *argoproj.ArgoCD, s *corev1.Secret) error { + redisInitialPassword, err := generateRedisAdminPassword() + if err != nil { + return err + } + + s.Data = argoutil.GetRedisSecretData(redisInitialPassword) + + if err := controllerutil.SetControllerReference(cr, s, r.Scheme); err != nil { + return err + } + + return nil } diff --git a/argocd-operator/controllers/argocd/secret_test.go b/argocd-operator/controllers/argocd/secret_test.go index 8ea58774a2c..5cc4f39b03b 100644 --- a/argocd-operator/controllers/argocd/secret_test.go +++ b/argocd-operator/controllers/argocd/secret_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" testclient "k8s.io/client-go/kubernetes/fake" @@ -134,7 +135,7 @@ func TestReconcileArgoCD_reconcileClusterCASecret(t *testing.T) { assert.True(t, apierrors.IsNotFound(err), "default-named CA secret must not be created when a custom name is set; got err: %v", err) }) - t.Run("deletes redis-initial-password secret and replaces it with argocd-redis", func(t *testing.T) { + t.Run("replaces an incomplete redis-initial-password secret with a regenerated argocd-redis", func(t *testing.T) { argocd := &argoproj.ArgoCD{ ObjectMeta: metav1.ObjectMeta{ Name: "argocd", @@ -158,7 +159,7 @@ func TestReconcileArgoCD_reconcileClusterCASecret(t *testing.T) { err = r.Create(context.TODO(), tlsSecret) assert.NoError(t, err) - err = r.reconcileRedisInitialPasswordSecret(argocd) + err = r.reconcileRedisSecret(argocd) assert.NoError(t, err) @@ -169,7 +170,9 @@ func TestReconcileArgoCD_reconcileClusterCASecret(t *testing.T) { newSecretErr := r.Get(context.TODO(), types.NamespacedName{Name: newRedisSecret.Name, Namespace: "argocd-operator"}, newRedisSecret) assert.NoError(t, newSecretErr) - assert.Equal(t, newRedisSecret.Data[common.ArgoCDKeyAdminPassword], newRedisSecret.Data[common.ArgoCDKeyAdminPassword], "argocd-redis should contain admin redis password") + assert.NotEmpty(t, newRedisSecret.Data[common.ArgoCDKeyAdminPassword], "argocd-redis should contain admin redis password") + assert.NotEqual(t, []byte("something"), newRedisSecret.Data[common.ArgoCDKeyAdminPassword], + "the legacy secret was incomplete, so its password should not be carried over") }) t.Run("skips creation when custom-named CA secret already exists", func(t *testing.T) { @@ -561,7 +564,7 @@ func Test_ReconcileArgoCD_ReconcileShouldNotChangeWhenUpdatedAdminPass(t *testin assert.True(t, argoutil.IsTrackedByOperator(testSecret.Labels)) } -func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { +func Test_ReconcileArgoCD_ReconcileRedisSecret(t *testing.T) { argocd := &argoproj.ArgoCD{ ObjectMeta: metav1.ObjectMeta{ Name: "argocd", @@ -596,7 +599,7 @@ func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { t.Run("Create when does not exist", func(t *testing.T) { require.ErrorContains(t, fetchSecret(), fmt.Sprintf(`secrets "%s" not found`, secretName)) - require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd)) + require.NoError(t, r.reconcileRedisSecret(argocd)) require.NoError(t, fetchSecret()) assertSecretValid() @@ -611,7 +614,7 @@ func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { } require.NoError(t, r.Update(t.Context(), secret)) - require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd)) + require.NoError(t, r.reconcileRedisSecret(argocd)) require.NoError(t, fetchSecret()) actualPwd := assertSecretValid() @@ -623,7 +626,7 @@ func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { assertSecretValid() oldVersion := actual.ResourceVersion - require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd)) + require.NoError(t, r.reconcileRedisSecret(argocd)) require.NoError(t, fetchSecret()) assertSecretValid() @@ -631,6 +634,227 @@ func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) { }) } +func Test_secretReferencedByPodSpec(t *testing.T) { + const secretName = "argocd-redis-initial-password" + + secretVolume := func(name string) corev1.Volume { + return corev1.Volume{ + Name: "redis-auth", + VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: name}}, + } + } + + tests := []struct { + name string + spec corev1.PodSpec + expected bool + }{ + { + name: "no reference at all", + spec: corev1.PodSpec{ + Volumes: []corev1.Volume{secretVolume("argocd-redis")}, + Containers: []corev1.Container{{Name: "redis"}}, + }, + expected: false, + }, + { + name: "mounted as a secret volume", + spec: corev1.PodSpec{Volumes: []corev1.Volume{secretVolume(secretName)}}, + expected: true, + }, + { + name: "mounted through a projected volume", + spec: corev1.PodSpec{Volumes: []corev1.Volume{{ + Name: "redis-auth", + VolumeSource: corev1.VolumeSource{Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + {ConfigMap: &corev1.ConfigMapProjection{}}, + {Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{Name: secretName}, + }}, + }, + }}, + }}}, + expected: true, + }, + { + name: "injected through a secretKeyRef", + spec: corev1.PodSpec{Containers: []corev1.Container{{ + Name: "redis", + Env: []corev1.EnvVar{{ + Name: "REDIS_PASSWORD", + ValueFrom: &corev1.EnvVarSource{SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: secretName}, + Key: "auth", + }}, + }}, + }}}, + expected: true, + }, + { + name: "injected through envFrom", + spec: corev1.PodSpec{Containers: []corev1.Container{{ + Name: "redis", + EnvFrom: []corev1.EnvFromSource{{ + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: secretName}, + }, + }}, + }}}, + expected: true, + }, + { + name: "referenced only by an init container", + spec: corev1.PodSpec{ + InitContainers: []corev1.Container{{ + Name: "wait-for-redis", + EnvFrom: []corev1.EnvFromSource{{ + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: secretName}, + }, + }}, + }}, + Containers: []corev1.Container{{Name: "redis"}}, + }, + expected: true, + }, + { + name: "volume of another kind with no secret set", + spec: corev1.PodSpec{Volumes: []corev1.Volume{{ + Name: "tmp", + VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, + }}}, + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, secretReferencedByPodSpec(&tt.spec, secretName)) + }) + } +} + +func Test_ReconcileArgoCD_ReconcileRedisSecret_LegacyMigration(t *testing.T) { + const legacyPwd = "legacy-password" + const namespace = "argocd-operator" + + newArgoCD := func() *argoproj.ArgoCD { + return &argoproj.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: namespace}, + } + } + + newReconciler := func(cr *argoproj.ArgoCD, objs ...client.Object) *ReconcileArgoCD { + sch := makeTestReconcilerScheme(argoproj.AddToScheme, promoter.AddToScheme, apiregistrationv1.AddToScheme) + cl := makeTestReconcilerClient(sch, append([]client.Object{cr}, objs...), []client.Object{cr}, []runtime.Object{}) + return makeTestReconciler(cl, sch, testclient.NewSimpleClientset()) + } + + // A legacy secret holding every key the redis components expect. + newLegacySecret := func(cr *argoproj.ArgoCD) *corev1.Secret { + legacy := argoutil.NewSecretWithSuffix(cr, REDIS_INITIAL_PASSWORD) + legacy.Data = argoutil.GetRedisSecretData([]byte(legacyPwd)) + return legacy + } + + getSecret := func(t *testing.T, r *ReconcileArgoCD, name string) (*corev1.Secret, error) { + t.Helper() + secret := &corev1.Secret{} + err := r.Get(t.Context(), types.NamespacedName{Name: name, Namespace: namespace}, secret) + return secret, err + } + + t.Run("carries the password over from a healthy legacy secret", func(t *testing.T) { + argocd := newArgoCD() + legacy := newLegacySecret(argocd) + r := newReconciler(argocd, legacy) + + require.NoError(t, r.reconcileRedisSecret(argocd)) + + actual, err := getSecret(t, r, ARGOCD_REDIS) + require.NoError(t, err) + assert.Equal(t, legacyPwd, string(actual.Data[common.ArgoCDKeyAdminPassword]), "password should be carried over, not regenerated") + assert.Equal(t, legacyPwd, string(actual.Data["auth"])) + assert.Equal(t, "default", string(actual.Data["auth_username"])) + assert.Equal(t, "true", string(actual.Data["immutable"]), "keys derived by GetRedisSecretData must be present") + assert.Contains(t, string(actual.Data["users.acl"]), legacyPwd, "the ACL file must match the carried-over password") + + _, err = getSecret(t, r, legacy.Name) + assert.True(t, apierrors.IsNotFound(err), "legacy secret should be deleted once nothing references it") + }) + + t.Run("deletes the legacy secret when argocd-redis is already healthy", func(t *testing.T) { + argocd := newArgoCD() + existing := argoutil.NewSecretWithName(argocd, ARGOCD_REDIS) + existing.Data = argoutil.GetRedisSecretData([]byte("current-password")) + legacy := newLegacySecret(argocd) + r := newReconciler(argocd, existing, legacy) + + require.NoError(t, r.reconcileRedisSecret(argocd)) + + actual, err := getSecret(t, r, ARGOCD_REDIS) + require.NoError(t, err) + assert.Equal(t, "current-password", string(actual.Data[common.ArgoCDKeyAdminPassword]), "a healthy argocd-redis must be left alone") + + _, err = getSecret(t, r, legacy.Name) + assert.True(t, apierrors.IsNotFound(err), "legacy secret should still be cleaned up on the healthy path") + }) + + t.Run("keeps the legacy secret while a pod still mounts it", func(t *testing.T) { + argocd := newArgoCD() + legacy := newLegacySecret(argocd) + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd-redis-0", Namespace: namespace}, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{{ + Name: argoutil.RedisAuthVolumeName, + VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: legacy.Name}}, + }}, + Containers: []corev1.Container{{Name: "redis", Image: "redis"}}, + }, + } + r := newReconciler(argocd, legacy, pod) + + require.NoError(t, r.reconcileRedisSecret(argocd)) + + _, err := getSecret(t, r, legacy.Name) + assert.NoError(t, err, "legacy secret must survive while a running pod still mounts it") + + // The new secret is still created, so the rollout has something to switch onto. + actual, err := getSecret(t, r, ARGOCD_REDIS) + require.NoError(t, err) + assert.Equal(t, legacyPwd, string(actual.Data[common.ArgoCDKeyAdminPassword])) + }) + + t.Run("keeps the legacy secret while a scaled-to-zero deployment references it", func(t *testing.T) { + argocd := newArgoCD() + legacy := newLegacySecret(argocd) + replicas := int32(0) + deployment := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd-redis", Namespace: namespace}, + Spec: appsv1.DeploymentSpec{ + Replicas: &replicas, + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{{ + Name: argoutil.RedisAuthVolumeName, + VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: legacy.Name}}, + }}, + Containers: []corev1.Container{{Name: "redis", Image: "redis"}}, + }, + }, + }, + } + r := newReconciler(argocd, legacy, deployment) + + require.NoError(t, r.reconcileRedisSecret(argocd)) + + _, err := getSecret(t, r, legacy.Name) + assert.NoError(t, err, "a workload with no pods would still fail on scale-up, so the secret must survive") + }) +} + func Test_ReconcileArgoCD_ReconcileRedisTLSSecret(t *testing.T) { argocd := &argoproj.ArgoCD{ ObjectMeta: metav1.ObjectMeta{ From c9466d636e23735261882166b9a273e8e73137f8 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Wed, 28 Oct 2026 01:09:57 +0100 Subject: [PATCH 8/9] remove old test Signed-off-by: nodari-dev --- ...te_redis_secure_comm_no_autotls_ha_test.go | 299 ------------------ 1 file changed, 299 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go b/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go deleted file mode 100644 index 6823d6f8821..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-067_validate_redis_secure_comm_no_autotls_ha_test.go +++ /dev/null @@ -1,299 +0,0 @@ -/* -Copyright 2025. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sequential - -import ( - "context" - "os" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "github.com/argoproj-labs/gitops-operator/argocd-operator/controllers/argoutil" - - argov1beta1api "github.com/argoproj-labs/gitops-operator/argocd-operator/api/v1beta1" - "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture" - argocdFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - deplFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/deployment" - k8sFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - nodeFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/node" - osFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/os" - statefulsetFixture "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/statefulset" - fixtureUtils "github.com/argoproj-labs/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - - Context("1-067_validate_redis_secure_comm_no_autotls_ha", func() { - - var ( - k8sClient client.Client - ctx context.Context - ns *corev1.Namespace - cleanupFunc func() - ) - - BeforeEach(func() { - fixture.EnsureSequentialCleanSlate() - // - Was previously in parallel, moved to sequential due to it requiring a large resource (memory/cpu) commitment for pods - - k8sClient, _ = fixtureUtils.GetE2ETestKubeClient() - ctx = context.Background() - }) - - AfterEach(func() { - defer cleanupFunc() - fixture.OutputDebugOnFail(ns) - }) - - It("ensures that redis HA can be enabled with tls with generated certificate", func() { - By("verifying we are running on a cluster with at least 3 nodes. This is required for Redis HA") - nodeFixture.ExpectHasAtLeastXNodes(3) - - // Note: Redis HA requires a cluster which contains multiple nodes - - By("creating simple namespace-scoped Argo CD instance") - ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() - - argoCD := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name}, - Spec: argov1beta1api.ArgoCDSpec{ - HA: argov1beta1api.ArgoCDHASpec{ - Enabled: true, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - expectComponentsAreRunning := func() { - - // In BeAvailable() we wait 15 seconds for ArgoCD CR to be reconciled, this SHOULD be enough time. - - By("waiting for ArgoCD CR to be reconciled and the instance to be ready") - Eventually(argoCD, "10m", "10s").Should(argocdFixture.BeAvailable()) - - deploymentsShouldExist := []string{"argocd-redis-ha-haproxy", "argocd-server", "argocd-repo-server"} - for _, depl := range deploymentsShouldExist { - replicas := 1 - if depl == "argocd-redis-ha-haproxy" { - replicas = 3 - } - - depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: depl, Namespace: ns.Name}} - Eventually(depl).Should(k8sFixture.ExistByName()) - Eventually(depl).Should(deplFixture.HaveReadyReplicas(replicas)) - } - - statefulsetsShouldExist := []string{"argocd-redis-ha-server", "argocd-application-controller"} - for _, ss := range statefulsetsShouldExist { - - replicas := 1 - if ss == "argocd-redis-ha-server" { - replicas = 3 - } - - statefulSet := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: ss, Namespace: ns.Name}} - Eventually(statefulSet).Should(k8sFixture.ExistByName()) - Eventually(statefulSet).Should(statefulsetFixture.HaveReplicas(replicas)) - Eventually(statefulSet).Should(statefulsetFixture.HaveReadyReplicas(replicas)) - } - - } - - expectComponentsAreRunning() - - By("generating a test certificate to use with redis, using openssl") - - redis_crt_File, err := os.CreateTemp("", "redis.crt") - Expect(err).ToNot(HaveOccurred()) - - redis_key_File, err := os.CreateTemp("", "redis.key") - Expect(err).ToNot(HaveOccurred()) - - openssl_test_File, err := os.CreateTemp("", "openssl_test.cnf") - Expect(err).ToNot(HaveOccurred()) - - opensslTestCNFContents := "\n[SAN]\nsubjectAltName=DNS:argocd-redis." + ns.Name + ".svc.cluster.local\n[req]\ndistinguished_name=req" - - err = os.WriteFile(openssl_test_File.Name(), ([]byte)(opensslTestCNFContents), 0666) - Expect(err).ToNot(HaveOccurred()) - - _, err = osFixture.ExecCommandWithOutputParam(false, true, "openssl", "req", "-new", "-x509", "-sha256", - "-subj", "/C=XX/ST=XX/O=Testing/CN=redis", - "-reqexts", "SAN", - "-extensions", "SAN", - "-config", openssl_test_File.Name(), - "-keyout", redis_key_File.Name(), - "-out", redis_crt_File.Name(), - "-newkey", "rsa:4096", - "-nodes", - "-days", "10", - ) - Expect(err).ToNot(HaveOccurred()) - - By("creating argocd-operator-redis-tls secret from that cert") - - _, err = osFixture.ExecCommand("kubectl", "create", "secret", "tls", "argocd-operator-redis-tls", "--key="+redis_key_File.Name(), "--cert="+redis_crt_File.Name(), "-n", ns.Name) - Expect(err).ToNot(HaveOccurred()) - - expectComponentsAreRunning() - - By("adding argo cd label to argocd-operator-redis-tls secret") - _, err = osFixture.ExecCommand("kubectl", "annotate", "secret", "argocd-operator-redis-tls", "argocds.argoproj.io/name=argocd", "-n", ns.Name) - Expect(err).ToNot(HaveOccurred()) - - expectComponentsAreRunning() - - By("extracting the contents of /data/conf/redis.conf and checking it contains expected values") - redisConf, err := osFixture.ExecCommandWithOutputParam(false, true, "kubectl", "exec", "-i", "pod/argocd-redis-ha-server-0", "-n", ns.Name, "-c", "redis", "--", "cat", "/data/conf/redis.conf") - Expect(err).ToNot(HaveOccurred()) - expectedRedisConfig := []string{ - "port 0", - "tls-port 6379", - "tls-cert-file /app/config/redis/tls/tls.crt", - "tls-ca-cert-file /app/config/redis/tls/tls.crt", - "tls-key-file /app/config/redis/tls/tls.key", - "tls-replication yes", - "tls-auth-clients no", - } - for _, line := range expectedRedisConfig { - Expect(redisConf).To(ContainSubstring(line)) - } - - By("extracting the contents of /data/conf/sentinel.conf and checking it contains expected values") - sentinelConf, err := osFixture.ExecCommandWithOutputParam( - false, true, - "kubectl", "exec", "-i", "pod/argocd-redis-ha-server-0", "-n", ns.Name, "-c", "redis", - "--", "cat", "/data/conf/sentinel.conf", - ) - Expect(err).ToNot(HaveOccurred()) - expectedSentinelConfig := []string{ - "port 0", - "tls-port 26379", - // Dynamic changes to the config file can result in doublequptes added unpredictably - `tls-cert-file "?/app/config/redis/tls/tls.crt"?`, - `tls-ca-cert-file "?/app/config/redis/tls/tls.crt"?`, - `tls-key-file "?/app/config/redis/tls/tls.key"?`, - "tls-replication yes", - "tls-auth-clients no", - } - for _, line := range expectedSentinelConfig { - Expect(sentinelConf).To(MatchRegexp(line)) - } - - repoServerDepl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-repo-server", Namespace: ns.Name}} - Eventually(repoServerDepl).Should(k8sFixture.ExistByName()) - - By("expecting repo-server to have desired container process command/arguments") - Expect(repoServerDepl).To(deplFixture.HaveContainerCommandSubstring("uid_entrypoint.sh argocd-repo-server --redis argocd-redis-ha-haproxy."+ns.Name+".svc.cluster.local.:6379 --redis-use-tls --redis-ca-certificate /app/config/reposerver/tls/redis/tls.crt --loglevel info --logformat text", 0), - "TLS .spec.template.spec.containers.command for argocd-repo-server deployment is wrong") - - argocdServerDepl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-server", Namespace: ns.Name}} - Eventually(argocdServerDepl).Should(k8sFixture.ExistByName()) - - By("expecting argocd-server to have desired container process command/arguments") - Expect(argocdServerDepl).To(deplFixture.HaveContainerCommandSubstring("argocd-server --staticassets /shared/app --dex-server https://argocd-dex-server."+ns.Name+".svc.cluster.local.:5556 --repo-server argocd-repo-server."+ns.Name+".svc.cluster.local.:8081 --redis argocd-redis-ha-haproxy."+ns.Name+".svc.cluster.local.:6379 --redis-use-tls --redis-ca-certificate /app/config/server/tls/redis/tls.crt --loglevel info --logformat text", 0), - "TLS .spec.template.spec.containers.command for argocd-server deployment is wrong") - - By("expecting application-controller to have desired container process command/arguments") - applicationControllerSS := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: "argocd-application-controller", Namespace: ns.Name}} - Eventually(applicationControllerSS).Should(k8sFixture.ExistByName()) - - Expect(applicationControllerSS).To(statefulsetFixture.HaveContainerCommandSubstring("argocd-application-controller --operation-processors 10 --redis argocd-redis-ha-haproxy."+ns.Name+".svc.cluster.local.:6379 --redis-use-tls --redis-ca-certificate /app/config/controller/tls/redis/tls.crt --repo-server argocd-repo-server."+ns.Name+".svc.cluster.local.:8081 --status-processors 20 --kubectl-parallelism-limit 10 --loglevel info --logformat text", 0), - "TLS .spec.template.spec.containers.command for argocd-application-controller statefulsets is wrong") - }) - - It("verify redis HA credential distribution", func() { - By("verifying we are running on a cluster with at least 3 nodes. This is required for Redis HA") - nodeFixture.ExpectHasAtLeastXNodes(3) - - By("creating simple Argo CD instance") - ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() - - argoCD := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name}, - Spec: argov1beta1api.ArgoCDSpec{ - HA: argov1beta1api.ArgoCDHASpec{ - Enabled: true, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("waiting for ArgoCD CR to be reconciled and the instance to be ready") - Eventually(argoCD, "10m", "10s").Should(argocdFixture.BeAvailable()) - - By("verify redis creds are correctly passed to pods") - const expectedMsg = "Loading Redis credentials from mounted directory: /app/config/redis-auth/" - expectedComponents := []string{ - "statefulset/" + argoCD.Name + "-" + "application-controller", - "deployment/" + argoCD.Name + "-" + "repo-server", - "deployment/" + argoCD.Name + "-" + "server", - } - for _, component := range expectedComponents { - logOutput, err := osFixture.ExecCommandWithOutputParam(false, true, - "kubectl", "logs", component, "-n", ns.Name, - ) - Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) - Expect(logOutput).To(ContainSubstring(expectedMsg)) - // This is how redis disconnect manifests - Expect(logOutput).ToNot(ContainSubstring("manifest cache error")) - Expect(logOutput).ToNot(ContainSubstring("WRONGPASS")) - - mountedFiles, err := osFixture.ExecCommandWithOutputParam(false, true, - "kubectl", "exec", component, "-n", ns.Name, "--", "ls", "-1", argoutil.RedisAuthMountPath, - ) - Expect(err).ToNot(HaveOccurred(), "Output: "+logOutput) - Expect(mountedFiles).ToNot(ContainSubstring("users.acl")) - } - - By("verifying redis password is correct") - redisInitialSecret := &corev1.Secret{} - redisPwdSecretKey := client.ObjectKey{ - Name: "argocd-redis", - Namespace: ns.Name, - } - Expect(k8sClient.Get(ctx, redisPwdSecretKey, redisInitialSecret)).Should(Succeed()) - expectedRedisPwd := string(redisInitialSecret.Data["auth"]) - Expect(expectedRedisPwd).ShouldNot(Equal("")) - - redisPingOut, err := osFixture.ExecCommandWithOutputParam(false, false, - "kubectl", "exec", "-n", ns.Name, "-c", "redis", "pod/argocd-redis-ha-server-0", "--", - "redis-cli", "-a", expectedRedisPwd, "--no-auth-warning", "ping", - ) - - Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) - Expect(redisPingOut).NotTo(ContainSubstring("NOAUTH Authentication required")) - Expect(redisPingOut).To(ContainSubstring("PONG")) - - By("verifying redis rejects unauthenticated requests") - redisPingOut, err = osFixture.ExecCommandWithOutputParam(false, false, - "kubectl", "exec", "-n", ns.Name, "-c", "redis", "pod/argocd-redis-ha-server-0", "--", - "redis-cli", "ping", // no auth provided - ) - - Expect(err).ToNot(HaveOccurred(), "Output: "+redisPingOut) - Expect(redisPingOut).To(ContainSubstring("NOAUTH Authentication required")) - Expect(redisPingOut).NotTo(ContainSubstring("PONG")) - }) - }) -}) From 11b828843f8ee431f1c87541297daf3af3ef59f8 Mon Sep 17 00:00:00 2001 From: nodari-dev Date: Wed, 28 Oct 2026 01:51:41 +0100 Subject: [PATCH 9/9] minor changes Signed-off-by: nodari-dev --- argocd-operator/controllers/argocd/secret.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/argocd-operator/controllers/argocd/secret.go b/argocd-operator/controllers/argocd/secret.go index 60f5b841ad7..19a38723325 100644 --- a/argocd-operator/controllers/argocd/secret.go +++ b/argocd-operator/controllers/argocd/secret.go @@ -1142,17 +1142,13 @@ func (r *ReconcileArgoCD) getClusterSecrets(cr *argoproj.ArgoCD) (*corev1.Secret return clusterSecrets, nil } -// REDIS_INITIAL_PASSWORD is the suffix of the Secret that held the Redis password before -// GITOPS-11058, i.e. [instance]-redis-initial-password. const REDIS_INITIAL_PASSWORD = "redis-initial-password" - -// ARGOCD_REDIS is the name of the Secret holding the Redis credentials. It deliberately does not -// carry the instance name, so that it is compatible with the argocd CLI. -const ARGOCD_REDIS = common.ArgoCDRedisComponent +const ARGOCD_REDIS = "argocd-redis" func (r *ReconcileArgoCD) reconcileRedisSecret(cr *argoproj.ArgoCD) error { - // Fix for GITOPS-11058: - // PROVIDE A NEW DESCRIPTION + // Fix for GITOPS-11058 to be compatible with upstream Argo CD naming conventions and Argo CD CLI in core mode. + // Old secret name [instance]-redis-initial-password + // New secret name argocd-redis - upstream new := argoutil.NewSecretWithName(cr, ARGOCD_REDIS) newExists, err := r.checkSecretExistence(cr, new) @@ -1203,7 +1199,6 @@ func (r *ReconcileArgoCD) reconcileRedisSecret(cr *argoproj.ArgoCD) error { return r.Create(context.TODO(), new) } -// checkSecretExistence reports whether the given Secret exists, populating it when it does. func (r *ReconcileArgoCD) checkSecretExistence(cr *argoproj.ArgoCD, s *corev1.Secret) (bool, error) { existed := true err := argoutil.FetchObject(r.Client, cr.Namespace, s.Name, s) @@ -1216,8 +1211,7 @@ func (r *ReconcileArgoCD) checkSecretExistence(cr *argoproj.ArgoCD, s *corev1.Se return existed, nil } -// Check usage of provided secret -// Checks in: Pod, Deployment or StatefulSet in the namespace +// Checks secret usage in: Pod, Deployment or StatefulSet in the namespace func (r *ReconcileArgoCD) secretInUse(namespace string, secretName string) (bool, error) { pods := &corev1.PodList{} if err := r.List(context.TODO(), pods, client.InNamespace(namespace)); err != nil { @@ -1252,7 +1246,6 @@ func (r *ReconcileArgoCD) secretInUse(namespace string, secretName string) (bool return false, nil } -// Check if Spec mounts the named Secret func secretReferencedByPodSpec(spec *corev1.PodSpec, secretName string) bool { for _, volume := range spec.Volumes { if volume.Secret != nil && volume.Secret.SecretName == secretName { @@ -1338,7 +1331,8 @@ func prepareSecretForUpdateCreate(r *ReconcileArgoCD, cr *argoproj.ArgoCD, s *co s.Data = argoutil.GetRedisSecretData(redisInitialPassword) - if err := controllerutil.SetControllerReference(cr, s, r.Scheme); err != nil { + err = controllerutil.SetControllerReference(cr, s, r.Scheme) + if err != nil { return err }