diff --git a/Makefile b/Makefile index 464df997f43..a36ad830b6b 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,9 @@ GINKGO_VERSION := $(shell go list -m -f '{{.Version}}' github.com/onsi/ginkgo/v2 # XKS_LABEL_FILTER is the label filter for XKS tests. XKS_LABEL_FILTER ?= "!openshift" +# OCP_LABEL_FILTER is the label filter for OCP tests. +OCP_LABEL_FILTER ?= "!xks" + .PHONY: all all: build @@ -166,12 +169,12 @@ e2e-tests-ginkgo: e2e-tests-sequential-ginkgo e2e-tests-parallel-ginkgo ## Runs .PHONY: e2e-tests-sequential-ginkgo e2e-tests-sequential-ginkgo: ginkgo ## Runs Ginkgo e2e sequential tests @echo "Running GitOps Operator sequential Ginkgo E2E tests..." - $(GINKGO_CLI) -v --trace --timeout 240m -r ./test/openshift/e2e/ginkgo/sequential + $(GINKGO_CLI) -v --trace --label-filter=$(OCP_LABEL_FILTER) --no-color --timeout 240m -r ./test/openshift/e2e/ginkgo/sequential .PHONY: e2e-tests-parallel-ginkgo ## Runs Ginkgo e2e parallel tests, (Defaults to 5 runs at a time) e2e-tests-parallel-ginkgo: ginkgo @echo "Running GitOps Operator parallel Ginkgo E2E tests..." - $(GINKGO_CLI) -p -v -procs=5 --trace --timeout 60m -r ./test/openshift/e2e/ginkgo/parallel + $(GINKGO_CLI) -p -v -procs=5 --trace --label-filter=$(OCP_LABEL_FILTER) --no-color --timeout 60m -r ./test/openshift/e2e/ginkgo/parallel .PHONY: e2e-tests-sequential e2e-tests-sequential: @@ -184,12 +187,12 @@ e2e-tests-parallel: .PHONY: e2e-xks-tests-sequential-ginkgo e2e-xks-tests-sequential-ginkgo: ginkgo ## Runs Ginkgo e2e sequential tests @echo "Running GitOps Operator sequential Ginkgo E2E tests..." - $(GINKGO_CLI) -v --trace --label-filter=$(XKS_LABEL_FILTER) --timeout 240m -r ./test/openshift/e2e/ginkgo/sequential + $(GINKGO_CLI) -v --trace --label-filter=$(XKS_LABEL_FILTER) --no-color --timeout 240m -r ./test/openshift/e2e/ginkgo/sequential .PHONY: e2e-xks-tests-parallel-ginkgo ## Runs Ginkgo e2e parallel tests, (Defaults to 5 runs at a time) e2e-xks-tests-parallel-ginkgo: ginkgo @echo "Running GitOps Operator parallel Ginkgo E2E tests..." - $(GINKGO_CLI) -p -v -procs=5 --trace --label-filter=$(XKS_LABEL_FILTER) --timeout 60m -r ./test/openshift/e2e/ginkgo/parallel + $(GINKGO_CLI) -p -v -procs=5 --trace --label-filter=$(XKS_LABEL_FILTER) --no-color --timeout 60m -r ./test/openshift/e2e/ginkgo/parallel ##@ Build @@ -199,7 +202,7 @@ build: generate fmt vet ## Build manager binary. .PHONY: run run: manifests generate fmt vet ## Run a controller from your host. - CLUSTER_SCOPED_ARGO_ROLLOUTS_NAMESPACES=argo-rollouts,test-rom-ns-1,rom-ns-1,openshift-gitops ARGOCD_CLUSTER_CONFIG_NAMESPACES="openshift-gitops, argocd-e2e-cluster-config, argocd-test-impersonation-1-046, argocd-agent-principal-1-051, argocd-agent-agent-1-052, appset-argocd, appset-old-ns, appset-new-ns, ns-hosting-principal, ns-hosting-managed-agent, ns-hosting-autonomous-agent, appset-argocd-clusterrole, gitops-promoter-1-134" REDIS_CONFIG_PATH="build/redis" go run ./cmd/main.go + ARGOCD_OPERATOR_NAMESPACE=openshift-gitops-operator CLUSTER_SCOPED_ARGO_ROLLOUTS_NAMESPACES=argo-rollouts,test-rom-ns-1,rom-ns-1,openshift-gitops ARGOCD_CLUSTER_CONFIG_NAMESPACES="openshift-gitops, argocd-e2e-cluster-config, argocd-test-impersonation-1-046, argocd-agent-principal-1-051, argocd-agent-agent-1-052, appset-argocd, appset-old-ns, appset-new-ns, ns-hosting-principal, ns-hosting-managed-agent, ns-hosting-autonomous-agent, appset-argocd-clusterrole, gitops-promoter-1-134" REDIS_CONFIG_PATH="build/redis" go run ./cmd/main.go .PHONY: docker-build docker-build: test ## Build container image with the manager. diff --git a/go.mod b/go.mod index 9ce0b597d23..16a4424593b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.26.5 require ( github.com/argoproj-labs/argo-rollouts-manager v0.0.10-0.20260826124203-67002e569d7f github.com/argoproj-labs/argocd-image-updater v1.3.0 - github.com/argoproj-labs/argocd-operator v0.19.0-rc1.0.20260903101506-65e1565dae0e + github.com/argoproj-labs/argocd-operator v0.20.0-rc1 github.com/argoproj-labs/gitops-promoter v0.35.0 github.com/argoproj/argo-cd/gitops-engine v0.7.1-0.20250908182407-97ad5b59a627 github.com/argoproj/argo-cd/v3 v3.5.2 @@ -16,14 +16,14 @@ require ( github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 github.com/hashicorp/go-version v1.9.0 github.com/onsi/ginkgo/v2 v2.32.0 - github.com/onsi/gomega v1.42.1 + github.com/onsi/gomega v1.43.0 github.com/openshift/api v0.0.0-20260619095050-5346161d1bf2 github.com/openshift/controller-runtime-common v0.0.0-20260428152732-64ee174f5e2e github.com/operator-framework/api v0.17.5 github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.74.0 github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.28.0 - golang.org/x/crypto v0.55.0 + golang.org/x/crypto v0.56.0 golang.org/x/mod v0.40.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools v2.2.0+incompatible diff --git a/go.sum b/go.sum index f9d78ba4f05..1065c25c877 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/argoproj-labs/argo-rollouts-manager v0.0.10-0.20260826124203-67002e56 github.com/argoproj-labs/argo-rollouts-manager v0.0.10-0.20260826124203-67002e569d7f/go.mod h1:P51MRErJxlueBd9YD/5yOxf2ygwCtMcKku7mPJfFagY= github.com/argoproj-labs/argocd-image-updater v1.3.0 h1:MFqUKURoh14wV1ansPGFnzLIvUGhzWOMU8L2x96041U= github.com/argoproj-labs/argocd-image-updater v1.3.0/go.mod h1:7h1LqHoKavqo8rofiSPnzMK55n77WrnwCLxtgOb3AtI= -github.com/argoproj-labs/argocd-operator v0.19.0-rc1.0.20260903101506-65e1565dae0e h1:cxMesXEtRgOW0j5CO3otBMSgeJ+h2GlhnGr4SkB4IcQ= -github.com/argoproj-labs/argocd-operator v0.19.0-rc1.0.20260903101506-65e1565dae0e/go.mod h1:SeW4a79vL2YxoDXnXrv9Qzc3UGcB3XHsbJfG028CaD4= +github.com/argoproj-labs/argocd-operator v0.20.0-rc1 h1:wdTV72+rurg0a1zu+WZx9GhqkXpI2OLsA/dnqkyzt6Q= +github.com/argoproj-labs/argocd-operator v0.20.0-rc1/go.mod h1:a5QbpV5CWplHV3m194Zl1Lq4TOQvbnSUsC+5xLfCZls= github.com/argoproj-labs/gitops-promoter v0.35.0 h1:uma781gA0XW9Or0RuMnQFwe6ikZUAz/tmStRDSR44r4= github.com/argoproj-labs/gitops-promoter v0.35.0/go.mod h1:t6ndi4HS6lixaYyFpNALRQd8R34jbCXsZMxWvOT4dzk= github.com/argoproj/argo-cd/gitops-engine v0.0.0-20260827090335-e258ee23c3e5 h1:8vyBhWiaNxZrYw1jN1Qznp6xOWHUTisseNKUPEV+HXM= @@ -372,8 +372,8 @@ github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I= -github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg= +github.com/onsi/gomega v1.43.0 h1:VlG/1FxqNxhSO+lq/OHBNaaqwiBK/mO8JbVkX9Y+FeU= +github.com/onsi/gomega v1.43.0/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -521,8 +521,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= diff --git a/test/openshift/e2e/ginkgo/sequential/1-135-validate-imagepullsecret-propagation.go b/test/openshift/e2e/ginkgo/sequential/1-135-validate-imagepullsecret-propagation.go new file mode 100644 index 00000000000..ee225dcc316 --- /dev/null +++ b/test/openshift/e2e/ginkgo/sequential/1-135-validate-imagepullsecret-propagation.go @@ -0,0 +1,386 @@ +/* +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" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1" + "github.com/argoproj-labs/argocd-operator/common" + "github.com/argoproj-labs/argocd-operator/tests/ginkgo/fixture" + argocdFixture "github.com/argoproj-labs/argocd-operator/tests/ginkgo/fixture/argocd" + fixtureUtils "github.com/argoproj-labs/argocd-operator/tests/ginkgo/fixture/utils" +) + +// The e2e operator runs as a local process (make start-e2e), so it has no operator +// namespace and reconcileImagePullSecrets skips the operator-NS->instance-NS copy. +// The in-namespace path is what is exercised here: a Secret labeled +// propagate-image-pull-secret=true in the instance namespace is resolved by +// getImagePullSecretRefs and set as imagePullSecrets on the component ServiceAccounts. +var _ = Describe("GitOps Operator Parallel E2E Tests", func() { + + Context("1-135_validate_image_pull_secret_propagation", Label("xks"), func() { + + var ( + k8sClient client.Client + ctx context.Context + ns string + ) + + // dockerCfg is a minimal valid .dockerconfigjson payload. + dockerCfg := map[string][]byte{".dockerconfigjson": []byte(`{"auths":{}}`)} + + newLabeledPullSecret := func(name, ns string) *corev1.Secret { + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + Labels: map[string]string{common.ArgoCDImagePullSecretPropagateLabel: "true"}, + }, + Type: corev1.SecretTypeDockerConfigJson, + Data: dockerCfg, + } + } + + // expectSAPullSecret asserts (eventually) whether the named ServiceAccount's + // imagePullSecrets contains secretName. There is no ServiceAccount fixture matcher. + expectSAPullSecret := func(saName, ns, secretName string, present bool) { + Eventually(func(g Gomega) { + sa := &corev1.ServiceAccount{} + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: saName, Namespace: ns}, sa)).To(Succeed()) + names := make([]string, 0, len(sa.ImagePullSecrets)) + for _, r := range sa.ImagePullSecrets { + names = append(names, r.Name) + } + if present { + g.Expect(names).To(ContainElement(secretName)) + } else { + g.Expect(names).NotTo(ContainElement(secretName)) + } + }, "5m", "3s").Should(Succeed()) + } + BeforeEach(func() { + fixture.EnsureSequentialCleanSlate() + var err error + k8sClient, _, err = fixtureUtils.GetE2ETestKubeClientWithError() + Expect(err).NotTo(HaveOccurred()) + ctx = context.Background() + ns = "openshift-gitops-operator" + + By("CleanUp") + for _, name := range []string{"my-pull-secret", "pull-secret-1", "pull-secret-2"} { + s := newLabeledPullSecret(name, ns) + err = k8sClient.Get(ctx, types.NamespacedName{Name: name, Namespace: ns}, s) + if err == nil { + Expect(k8sClient.Delete(ctx, s)).To(Succeed()) + } else { + Expect(apierrors.IsNotFound(err)).To(BeTrue()) + } + } + }) + + It("sets imagePullSecrets on component ServiceAccounts from an in-namespace labeled Secret", func() { + + By("creating a labeled pull Secret before the ArgoCD instance") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("creating the ArgoCD instance") + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("verifying server and application-controller ServiceAccounts carry the pull secret") + serverSA := "example-argocd-" + common.ArgoCDServerComponent + appCtrlSA := "example-argocd-" + common.ArgoCDApplicationControllerComponent + expectSAPullSecret(serverSA, ns, "my-pull-secret", true) + expectSAPullSecret(appCtrlSA, ns, "my-pull-secret", true) + + By("verifying the reference is stable") + Consistently(func(g Gomega) { + sa := &corev1.ServiceAccount{} + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: serverSA, Namespace: ns}, sa)).To(Succeed()) + names := make([]string, 0, len(sa.ImagePullSecrets)) + for _, r := range sa.ImagePullSecrets { + names = append(names, r.Name) + } + g.Expect(names).To(ContainElement("my-pull-secret")) + }, "30s", "5s").Should(Succeed()) + }) + + It("skips propagation when multiple labeled pull Secrets exist in the namespace", func() { + + By("creating two labeled pull Secrets before the ArgoCD instance") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("pull-secret-1", ns))).To(Succeed()) + Expect(k8sClient.Create(ctx, newLabeledPullSecret("pull-secret-2", ns))).To(Succeed()) + + By("creating the ArgoCD instance") + argocdNS, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer cleanupFunc() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("verifying the server ServiceAccount carries neither pull secret") + serverSA := "example-argocd-" + common.ArgoCDServerComponent + Consistently(func(g Gomega) { + sa := &corev1.ServiceAccount{} + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: serverSA, Namespace: argocdNS.Name}, sa)).To(Succeed()) + names := make([]string, 0, len(sa.ImagePullSecrets)) + for _, r := range sa.ImagePullSecrets { + names = append(names, r.Name) + } + g.Expect(names).NotTo(ContainElement("pull-secret-1")) + g.Expect(names).NotTo(ContainElement("pull-secret-2")) + }, "1m", "5s").Should(Succeed()) + }) + + It("removes imagePullSecrets from ServiceAccounts when the labeled Secret is deleted", func() { + + By("creating a labeled pull Secret before the ArgoCD instance") + pullSecret := newLabeledPullSecret("my-pull-secret", ns) + Expect(k8sClient.Create(ctx, pullSecret)).To(Succeed()) + + By("creating the ArgoCD instance") + argocdNS, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer cleanupFunc() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + serverSA := "example-argocd-" + common.ArgoCDServerComponent + expectSAPullSecret(serverSA, argocdNS.Name, "my-pull-secret", true) + + By("deleting the labeled pull Secret") + Expect(k8sClient.Delete(ctx, pullSecret)).To(Succeed()) + + By("verifying the pull secret is removed from the server ServiceAccount") + expectSAPullSecret(serverSA, argocdNS.Name, "my-pull-secret", false) + }) + + It("propagates the pull secret to all component ServiceAccounts and removes it when the label is set to false", func() { + + By("creating a labeled pull Secret before the ArgoCD instance") + pullSecret := newLabeledPullSecret("my-pull-secret", ns) + Expect(k8sClient.Create(ctx, pullSecret)).To(Succeed()) + + By("creating the ArgoCD instance a new namespace") + argocdNS, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer cleanupFunc() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + } + argoCD.Spec = argov1beta1api.ArgoCDSpec{ + Controller: argov1beta1api.ArgoCDApplicationControllerSpec{ + Enabled: new(true), + }, + Redis: argov1beta1api.ArgoCDRedisSpec{ + Enabled: new(true), + }, + Repo: argov1beta1api.ArgoCDRepoSpec{ + Enabled: new(true), + }, + Server: argov1beta1api.ArgoCDServerSpec{ + Enabled: new(true), + }, + ApplicationSet: &argov1beta1api.ArgoCDApplicationSet{ + Enabled: new(true), + }, + Notifications: argov1beta1api.ArgoCDNotifications{ + Enabled: true, + }, + Promoter: &argov1beta1api.PromoterSpec{ + Enabled: new(true), + }, + ImageUpdater: argov1beta1api.ArgoCDImageUpdaterSpec{ + Enabled: true, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + //list all service accounts in the namespace + serviceAccounts := &corev1.ServiceAccountList{} + Expect(k8sClient.List(ctx, serviceAccounts, client.InNamespace(argocdNS.Name))).To(Succeed()) + for _, sa := range serviceAccounts.Items { + if sa.Name == "default" { + continue + } + By("verifying the " + sa.Name + " ServiceAccount carries the pull secret") + expectSAPullSecret(sa.Name, argocdNS.Name, "my-pull-secret", true) + } + + By("labeling the pull Secret with propagate-image-pull-secret to false") + pullSecret.Labels[common.ArgoCDImagePullSecretPropagateLabel] = "false" + Expect(k8sClient.Update(ctx, pullSecret)).To(Succeed()) + + for _, sa := range serviceAccounts.Items { + if sa.Name == "default" { + continue + } + By("verifying the " + sa.Name + " ServiceAccount does not carry the pull secret") + expectSAPullSecret(sa.Name, argocdNS.Name, "my-pull-secret", false) + } + + By("deleting the pull Secret and ArgoCD instance") + Expect(k8sClient.Delete(ctx, pullSecret)).To(Succeed()) + Expect(k8sClient.Delete(ctx, argoCD)).To(Succeed()) + }) + It("sets imagePullSecrets on agent principal ServiceAccount", func() { + + By("creating a labeled pull Secret in the operator namespace") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("creating the ArgoCD instance in a separate namespace") + argocdNS, argocdNSCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer argocdNSCleanup() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("enabling agent principal") + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: argoCD.Name, Namespace: argocdNS.Name}, argoCD)).To(Succeed()) + argoCD.Spec.ArgoCDAgent = &argov1beta1api.ArgoCDAgentSpec{ + Principal: &argov1beta1api.PrincipalSpec{ + Enabled: new(true), + }, + } + Expect(k8sClient.Update(ctx, argoCD)).To(Succeed()) + + By("verifying the agent principal ServiceAccount carries the copied pull secret") + principalSA := argoCD.Name + "-agent-principal" + expectSAPullSecret(principalSA, argocdNS.Name, "my-pull-secret", true) + }) + + It("sets imagePullSecrets on agent ServiceAccount", func() { + + By("creating a labeled pull Secret in the operator namespace") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("creating the ArgoCD instance in a separate namespace") + argocdNS, argocdNSCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer argocdNSCleanup() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("enabling agent") + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: argoCD.Name, Namespace: argocdNS.Name}, argoCD)).To(Succeed()) + argoCD.Spec.ArgoCDAgent = &argov1beta1api.ArgoCDAgentSpec{ + Agent: &argov1beta1api.AgentSpec{ + Enabled: new(true), + }, + } + Expect(k8sClient.Update(ctx, argoCD)).To(Succeed()) + + By("verifying the agent ServiceAccount carries the copied pull secret") + agentSA := argoCD.Name + "-agent-agent" + expectSAPullSecret(agentSA, argocdNS.Name, "my-pull-secret", true) + }) + + It("sets imagePullSecrets on Redis HA ServiceAccount", func() { + + By("creating a labeled pull Secret in the operator namespace") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("creating the ArgoCD instance with HA enabled in a separate namespace") + argocdNS, argocdNSCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer argocdNSCleanup() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + Spec: argov1beta1api.ArgoCDSpec{ + HA: argov1beta1api.ArgoCDHASpec{Enabled: true}, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("verifying the redis-ha ServiceAccount carries the copied pull secret") + redisSA := "example-argocd-" + common.ArgoCDRedisHAComponent + expectSAPullSecret(redisSA, argocdNS.Name, "my-pull-secret", true) + }) + + It("sets imagePullSecrets on Dex ServiceAccount", func() { + + By("creating a labeled pull Secret in the operator namespace") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("creating the ArgoCD instance with Dex SSO enabled in a separate namespace") + argocdNS, argocdNSCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer argocdNSCleanup() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + Spec: argov1beta1api.ArgoCDSpec{ + SSO: &argov1beta1api.ArgoCDSSOSpec{ + Provider: argov1beta1api.SSOProviderTypeDex, + Dex: &argov1beta1api.ArgoCDDexSpec{ + Config: "connectors: []", + }, + }, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + By("verifying the dex-server ServiceAccount carries the copied pull secret") + dexSA := "example-argocd-" + common.ArgoCDDexServerComponent + expectSAPullSecret(dexSA, argocdNS.Name, "my-pull-secret", true) + }) + + It("should propagate if pullsecret is created after the ArgoCD instance", func() { + + By("creating the ArgoCD instance with Dex SSO enabled in a separate namespace") + argocdNS, argocdNSCleanup := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer argocdNSCleanup() + argoCD := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: argocdNS.Name}, + Spec: argov1beta1api.ArgoCDSpec{ + SSO: &argov1beta1api.ArgoCDSSOSpec{ + Provider: argov1beta1api.SSOProviderTypeDex, + Dex: &argov1beta1api.ArgoCDDexSpec{ + Config: "connectors: []", + }, + }, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + By("creating a labeled pull Secret in the operator namespace") + Expect(k8sClient.Create(ctx, newLabeledPullSecret("my-pull-secret", ns))).To(Succeed()) + + By("verifying the dex-server ServiceAccount carries the copied pull secret") + dexSA := "example-argocd-" + common.ArgoCDDexServerComponent + expectSAPullSecret(dexSA, argocdNS.Name, "my-pull-secret", true) + }) + }) +})