Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ spec:
- apiGroups:
- config.openshift.io
resources:
- authentications
- clusterversions
- ingresses
verbs:
Expand Down
1 change: 1 addition & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ rules:
- apiGroups:
- config.openshift.io
resources:
- authentications
- clusterversions
- ingresses
verbs:
Expand Down
14 changes: 10 additions & 4 deletions controllers/argocd/argocd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ limitations under the License.
package argocd

import (
"context"

argoapp "github.com/argoproj-labs/argocd-operator/api/v1beta1"
argoappController "github.com/argoproj-labs/argocd-operator/controllers/argocd"
v1 "k8s.io/api/core/v1"
resourcev1 "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -86,7 +89,10 @@ func getArgoDexSpec() *argoapp.ArgoCDDexSpec {
}
}

func getArgoSSOSpec() *argoapp.ArgoCDSSOSpec {
func getArgoSSOSpec(client client.Client) *argoapp.ArgoCDSSOSpec {
if argoappController.IsOpenShiftCluster() && argoappController.IsExternalAuthenticationEnabledOnCluster(context.TODO(), client) {
return nil
}
return &argoapp.ArgoCDSSOSpec{
Provider: argoapp.SSOProviderTypeDex,
Dex: getArgoDexSpec(),
Expand Down Expand Up @@ -180,7 +186,7 @@ func getDefaultRBAC() argoapp.ArgoCDRBACSpec {

// NewCR returns an ArgoCD reference optimized for use in OpenShift
// with comprehensive default resource exclusions
func NewCR(name, ns string) (*argoapp.ArgoCD, error) {
func NewCR(name, ns string, client client.Client) (*argoapp.ArgoCD, error) {
b, err := yaml.Marshal([]resource{
{
APIGroups: []string{"", "discovery.k8s.io"},
Expand Down Expand Up @@ -239,7 +245,7 @@ func NewCR(name, ns string) (*argoapp.ArgoCD, error) {
Spec: argoapp.ArgoCDSpec{
ApplicationSet: getArgoApplicationSetSpec(),
Controller: getArgoControllerSpec(),
SSO: getArgoSSOSpec(),
SSO: getArgoSSOSpec(client),
Grafana: getArgoGrafanaSpec(),
HA: getArgoHASpec(),
Redis: getArgoRedisSpec(),
Expand Down
21 changes: 19 additions & 2 deletions controllers/argocd/argocd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@ import (
"testing"

argoapp "github.com/argoproj-labs/argocd-operator/api/v1beta1"
configv1 "github.com/openshift/api/config/v1"
"gotest.tools/assert"
v1 "k8s.io/api/core/v1"
resourcev1 "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestArgoCD(t *testing.T) {
testArgoCD, _ := NewCR("openshift-gitops", "openshift-gitops")
scheme := runtime.NewScheme()
_ = argoapp.AddToScheme(scheme)
_ = configv1.AddToScheme(scheme)

fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()

testArgoCD, _ := NewCR("openshift-gitops", "openshift-gitops", fakeClient)

testApplicationSetResources := &v1.ResourceRequirements{
Requests: v1.ResourceList{
Expand Down Expand Up @@ -190,7 +199,15 @@ func TestArgoCD(t *testing.T) {
}

func TestDexConfiguration(t *testing.T) {
testArgoCD, _ := NewCR("openshift-gitops", "openshift-gitops")
scheme := runtime.NewScheme()
_ = argoapp.AddToScheme(scheme)
_ = configv1.AddToScheme(scheme)

fakeClient := fake.NewClientBuilder().
WithScheme(scheme).
Build()

testArgoCD, _ := NewCR("openshift-gitops", "openshift-gitops", fakeClient)

// Verify Dex OpenShift Configuration
assert.Equal(t, testArgoCD.Spec.SSO.Dex.OpenShiftOAuth, true)
Expand Down
5 changes: 3 additions & 2 deletions controllers/gitopsservice_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ type ReconcileGitopsService struct {
DisableDefaultInstall bool
}

// +kubebuilder:rbac:groups=config.openshift.io,resources=authentications,verbs=get;list;watch
//+kubebuilder:rbac:groups=pipelines.openshift.io,resources=gitopsservices,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=pipelines.openshift.io,resources=gitopsservices/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=pipelines.openshift.io,resources=gitopsservices/finalizers,verbs=update
Expand Down Expand Up @@ -313,7 +314,7 @@ func (r *ReconcileGitopsService) Reconcile(ctx context.Context, request reconcil

func (r *ReconcileGitopsService) ensureDefaultArgoCDInstanceDoesntExist() error {

defaultArgoCDInstance, err := argocd.NewCR(common.ArgoCDInstanceName, serviceNamespace)
defaultArgoCDInstance, err := argocd.NewCR(common.ArgoCDInstanceName, serviceNamespace, r.Client)
if err != nil {
return err
}
Expand Down Expand Up @@ -349,7 +350,7 @@ func (r *ReconcileGitopsService) ensureDefaultArgoCDInstanceDoesntExist() error

func (r *ReconcileGitopsService) reconcileDefaultArgoCDInstance(instance *pipelinesv1alpha1.GitopsService, reqLogger logr.Logger) (reconcile.Result, error) {

defaultArgoCDInstance, err := argocd.NewCR(common.ArgoCDInstanceName, serviceNamespace)
defaultArgoCDInstance, err := argocd.NewCR(common.ArgoCDInstanceName, serviceNamespace, r.Client)
if err != nil {
return reconcile.Result{}, err
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.25.5

require (
github.com/argoproj-labs/argo-rollouts-manager v0.0.8-0.20260218104514-432c01ce417a
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260211145236-4c05ef8fa3d7
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260225073619-a52ee52d3941
github.com/argoproj/argo-cd/v3 v3.3.0
github.com/argoproj/gitops-engine v0.7.1-0.20251217140045-5baed5604d2d
github.com/go-logr/logr v1.4.3
Expand Down Expand Up @@ -43,7 +43,7 @@ require (
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/argoproj-labs/argocd-image-updater v1.1.0 // indirect
github.com/argoproj-labs/argocd-image-updater v1.1.1 // indirect
github.com/argoproj/pkg v0.13.7-0.20250305113207-cbc37dc61de5 // indirect
github.com/argoproj/pkg/v2 v2.0.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/argoproj-labs/argo-rollouts-manager v0.0.8-0.20260218104514-432c01ce417a h1:USjEzxbs2lZtx7+Hp9u5dYgu7pf/9XnDUSc9+Hmulmo=
github.com/argoproj-labs/argo-rollouts-manager v0.0.8-0.20260218104514-432c01ce417a/go.mod h1:WPyZkNHZjir/OTt8mrRwcUZKe1euHrHPJsRv1Wp/F/0=
github.com/argoproj-labs/argocd-image-updater v1.1.0 h1:XR+xZf8bDFBaTpVdVpe06t/DPmrIG4BG3HukUXul6X0=
github.com/argoproj-labs/argocd-image-updater v1.1.0/go.mod h1:RbPRnEqWBPq1OP29vlZjmfL+/NfonpoagH8SInP/YHc=
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260211145236-4c05ef8fa3d7 h1:SF89hDvomBhku9IjRO60fzeS8ZdwHgmo7KhfTLF4tYo=
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260211145236-4c05ef8fa3d7/go.mod h1:G9rmG9/3gV899eg8wL/4YQYTBSq5M+xEwfVBMuE8RlA=
github.com/argoproj-labs/argocd-image-updater v1.1.1 h1:7YDaR3WX2NMsDKp0wN7TRaRRHaVHQ94tSybi2P99MGk=
github.com/argoproj-labs/argocd-image-updater v1.1.1/go.mod h1:gMHiNrGNwNSt4ljf0ykcnmNvXBk/NJ+Z17AnZVe7V7I=
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260225073619-a52ee52d3941 h1:wkBZFBhSxIpaOfQOwQT44kgwkI/UC7IxM85GJ8w+nHI=
github.com/argoproj-labs/argocd-operator v0.17.0-rc1.0.20260225073619-a52ee52d3941/go.mod h1:3/Y9YWMU+DHC+onOQVXPAxrNkoBAGZD+UQui9BgJBjY=
github.com/argoproj/argo-cd/v3 v3.3.0 h1:9UlruTd5cC/MyvorTXgAIblfZTy63MF5FYvvoAaUvwU=
github.com/argoproj/argo-cd/v3 v3.3.0/go.mod h1:5VAfe0s/a4VY5GmAIFK76FtW6xn7zAcLmaw25bOL/2g=
github.com/argoproj/gitops-engine v0.7.1-0.20251217140045-5baed5604d2d h1:iUJYrbSvpV9n8vyl1sBt1GceM60HhHfnHxuzcm5apDg=
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/gitopsservice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ var _ = Describe("GitOpsServiceController", func() {
}

By("create a new Argo CD instance in test ns")
argocdNonDefaultNamespaceInstance, err := argocd.NewCR(argocdNonDefaultInstanceName, argocdNonDefaultNamespace)
argocdNonDefaultNamespaceInstance, err := argocd.NewCR(argocdNonDefaultInstanceName, argocdNonDefaultNamespace, k8sClient)
Expect(err).NotTo(HaveOccurred())

err = k8sClient.Create(context.TODO(), argocdNonDefaultNamespaceInstance)
Expand Down Expand Up @@ -344,7 +344,7 @@ var _ = Describe("GitOpsServiceController", func() {
}

// create an ArgoCD instance in the source namespace
argoCDInstanceObj, err := argocd.NewCR(argocdInstance, sourceNS)
argoCDInstanceObj, err := argocd.NewCR(argocdInstance, sourceNS, k8sClient)
Expect(err).NotTo(HaveOccurred())
err = k8sClient.Create(context.TODO(), argoCDInstanceObj)
if !kubeerrors.IsAlreadyExists(err) {
Expand Down Expand Up @@ -523,7 +523,7 @@ var _ = Describe("GitOpsServiceController", func() {
}

By("create an Argo CD instance in source namespace")
argoCDInstanceObj, err := argocd.NewCR(argocdNonDefaultNamespaceInstanceName, argocdNonDefaultNamespace)
argoCDInstanceObj, err := argocd.NewCR(argocdNonDefaultNamespaceInstanceName, argocdNonDefaultNamespace, k8sClient)
Expect(err).NotTo(HaveOccurred())
err = k8sClient.Create(context.TODO(), argoCDInstanceObj)
Expect(err).NotTo(HaveOccurred())
Expand Down
35 changes: 35 additions & 0 deletions test/openshift/e2e/ginkgo/fixture/argocd/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,41 @@ func HaveApplicationControllerOperationProcessors(operationProcessors int) match
})
}

func HaveExternalAuthenticationCondition(expected metav1.Condition) matcher.GomegaMatcher {
return fetchArgoCD(func(argocd *argov1beta1api.ArgoCD) bool {
for _, c := range argocd.Status.Conditions {
// FIRST match by Type
if c.Type != expected.Type {
continue
}
GinkgoWriter.Println("Matched condition type:", c.Type)
// Then check Reason
if c.Reason != expected.Reason {
GinkgoWriter.Println("HaveCondition: reason does not match", c.Reason, expected.Reason)
return false
}

// Then check Status
if c.Status != expected.Status {
GinkgoWriter.Println("HaveCondition: status does not match", c.Status, expected.Status)
return false
}

// Message check is optional (can be multiline)
if expected.Message != "" && c.Message != expected.Message {
GinkgoWriter.Println("HaveCondition: message does not match")
return false
}

// ✅ Found correct condition
return true
}

GinkgoWriter.Println("HaveCondition: condition type not found:", expected.Type)
return false
})
}

func HaveCondition(condition metav1.Condition) matcher.GomegaMatcher {
return fetchArgoCD(func(argocd *argov1beta1api.ArgoCD) bool {

Expand Down
62 changes: 62 additions & 0 deletions test/openshift/e2e/ginkgo/parallel/1-050_validate_sso_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package parallel

import (
"context"
"strings"

argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1"
. "github.com/onsi/ginkgo/v2"
Expand All @@ -10,14 +11,27 @@ import (
argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd"
deploymentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/deployment"
k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s"
osFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/os"
"github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func getOCPVersion() string {
output, err := osFixture.ExecCommand("oc", "version")
Expect(err).ToNot(HaveOccurred())
for _, line := range strings.Split(output, "\n") {
if strings.Contains(line, "Server Version:") {
return strings.TrimSpace(line[strings.Index(line, ":")+1:])
}
}
return ""
}

var _ = Describe("GitOps Operator Parallel E2E Tests", func() {

Context("1-050_validate_sso", func() {
Expand All @@ -44,6 +58,54 @@ var _ = Describe("GitOps Operator Parallel E2E Tests", func() {
cleanupFunc()
}
})
It("ensures the conditions in status when external Authentication is enabled on clusters; above 4.20 by default in openshit is enabled", func() {
By("creating simple namespace-scoped Argo CD instance")
ocVersion := getOCPVersion()
Expect(ocVersion).ToNot(BeEmpty())
if ocVersion < "4.20" {
Skip("skipping this test as OCP version is less than 4.20")
return
}
ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc()

argoCD := &argov1beta1api.ArgoCD{
ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: ns.Name},
Spec: argov1beta1api.ArgoCDSpec{},
}
argoCD.Spec.SSO = &argov1beta1api.ArgoCDSSOSpec{
Provider: argov1beta1api.SSOProviderTypeDex,
Dex: &argov1beta1api.ArgoCDDexSpec{
OpenShiftOAuth: true,
},
}
Expect(k8sClient.Create(ctx, argoCD)).To(Succeed())
Eventually(argoCD, "5m", "5s").Should(argocdFixture.HaveSSOStatus("Failed"))

By("verifying the conditions in status")
Eventually(argoCD).Should(argocdFixture.HaveExternalAuthenticationCondition(metav1.Condition{
Reason: "UnsupportedSSOConfiguration",
Status: "True",
Type: "UnsupportedConfiguration",
}))

argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) {
ac.Spec.SSO = nil
})
Eventually(func() []metav1.Condition {
fresh := &argov1beta1api.ArgoCD{}
err := k8sClient.Get(ctx, types.NamespacedName{Name: argoCD.Name, Namespace: argoCD.Namespace}, fresh)
Expect(err).NotTo(HaveOccurred())
return fresh.Status.Conditions
}, "2m", "5s").ShouldNot(
ContainElement(
WithTransform(func(c metav1.Condition) string {
return c.Type
}, Equal("UnsupportedConfiguration")),
),
)
Eventually(argoCD, "5m", "5s").Should(argocdFixture.HaveSSOStatus("Unknown"))

})

It("ensures Dex/Keycloak SSO can be enabled and disabled on a namespace-scoped Argo CD instance", func() {

Expand Down