github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/dex_test.go (about)

     1  package argocd
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	appsv1 "k8s.io/api/apps/v1"
     9  	corev1 "k8s.io/api/core/v1"
    10  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    11  	resourcev1 "k8s.io/apimachinery/pkg/api/resource"
    12  	"k8s.io/apimachinery/pkg/runtime"
    13  	"k8s.io/apimachinery/pkg/types"
    14  	"k8s.io/apimachinery/pkg/util/intstr"
    15  	"sigs.k8s.io/controller-runtime/pkg/client"
    16  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    17  
    18  	argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
    19  	"github.com/argoproj-labs/argocd-operator/common"
    20  )
    21  
    22  func TestReconcileArgoCD_reconcileDexDeployment_with_dex_disabled(t *testing.T) {
    23  	logf.SetLogger(ZapLogger(true))
    24  
    25  	tests := []struct {
    26  		name       string
    27  		setEnvFunc func(*testing.T, string)
    28  		argoCD     *argoproj.ArgoCD
    29  	}{
    30  		{
    31  			name:       "dex disabled by not specifying .spec.sso.provider=dex",
    32  			setEnvFunc: nil,
    33  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
    34  				cr.Spec.SSO = nil
    35  			}),
    36  		},
    37  		{
    38  			name:       "dex disabled by specifying different provider",
    39  			setEnvFunc: nil,
    40  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
    41  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
    42  					Provider: argoproj.SSOProviderTypeKeycloak,
    43  				}
    44  			}),
    45  		},
    46  	}
    47  
    48  	for _, test := range tests {
    49  		t.Run(test.name, func(t *testing.T) {
    50  
    51  			resObjs := []client.Object{test.argoCD}
    52  			subresObjs := []client.Object{test.argoCD}
    53  			runtimeObjs := []runtime.Object{}
    54  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
    55  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
    56  			r := makeTestReconciler(cl, sch)
    57  
    58  			if test.setEnvFunc != nil {
    59  				test.setEnvFunc(t, "true")
    60  			}
    61  
    62  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
    63  
    64  			deployment := &appsv1.Deployment{}
    65  			err := r.Client.Get(context.TODO(), types.NamespacedName{Name: "argocd-dex-server", Namespace: test.argoCD.Namespace}, deployment)
    66  			assert.True(t, apierrors.IsNotFound(err))
    67  		})
    68  	}
    69  }
    70  
    71  // When Dex is enabled dex deployment should be created, when disabled the Dex deployment should be removed
    72  func TestReconcileArgoCD_reconcileDexDeployment_removes_dex_when_disabled(t *testing.T) {
    73  	logf.SetLogger(ZapLogger(true))
    74  
    75  	tests := []struct {
    76  		name                  string
    77  		setEnvFunc            func(*testing.T, string)
    78  		updateCrFunc          func(cr *argoproj.ArgoCD)
    79  		updateEnvFunc         func(*testing.T, string)
    80  		argoCD                *argoproj.ArgoCD
    81  		wantDeploymentDeleted bool
    82  	}{
    83  		{
    84  			name:       "dex disabled by removing .spec.sso",
    85  			setEnvFunc: nil,
    86  			updateCrFunc: func(cr *argoproj.ArgoCD) {
    87  				cr.Spec.SSO = nil
    88  			},
    89  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
    90  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
    91  					Provider: argoproj.SSOProviderTypeDex,
    92  					Dex: &argoproj.ArgoCDDexSpec{
    93  						OpenShiftOAuth: true,
    94  					},
    95  				}
    96  			}),
    97  			wantDeploymentDeleted: true,
    98  		},
    99  		{
   100  			name:       "dex disabled by switching provider",
   101  			setEnvFunc: nil,
   102  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   103  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   104  					Provider: argoproj.SSOProviderTypeKeycloak,
   105  				}
   106  			},
   107  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   108  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   109  					Provider: argoproj.SSOProviderTypeDex,
   110  					Dex: &argoproj.ArgoCDDexSpec{
   111  						OpenShiftOAuth: true,
   112  					},
   113  				}
   114  			}),
   115  			wantDeploymentDeleted: true,
   116  		},
   117  	}
   118  
   119  	for _, test := range tests {
   120  		t.Run(test.name, func(t *testing.T) {
   121  
   122  			resObjs := []client.Object{test.argoCD}
   123  			subresObjs := []client.Object{test.argoCD}
   124  			runtimeObjs := []runtime.Object{}
   125  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   126  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   127  			r := makeTestReconciler(cl, sch)
   128  
   129  			if test.setEnvFunc != nil {
   130  				test.setEnvFunc(t, "false")
   131  			}
   132  
   133  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
   134  
   135  			// ensure deployment was created correctly
   136  			deployment := &appsv1.Deployment{}
   137  			err := r.Client.Get(context.TODO(), types.NamespacedName{Name: "argocd-dex-server", Namespace: test.argoCD.Namespace}, deployment)
   138  			assert.NoError(t, err)
   139  
   140  			if test.updateEnvFunc != nil {
   141  				test.updateEnvFunc(t, "true")
   142  			}
   143  			if test.updateCrFunc != nil {
   144  				test.updateCrFunc(test.argoCD)
   145  			}
   146  
   147  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
   148  			deployment = &appsv1.Deployment{}
   149  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: "argocd-dex-server", Namespace: test.argoCD.Namespace}, deployment)
   150  
   151  			if test.wantDeploymentDeleted {
   152  				assertNotFound(t, err)
   153  			} else {
   154  				assert.NoError(t, err)
   155  			}
   156  		})
   157  	}
   158  }
   159  
   160  func TestReconcileArgoCD_reconcileDeployments_Dex_with_resources(t *testing.T) {
   161  	logf.SetLogger(ZapLogger(true))
   162  
   163  	tests := []struct {
   164  		name       string
   165  		setEnvFunc func(*testing.T, string)
   166  		argoCD     *argoproj.ArgoCD
   167  	}{
   168  		{
   169  			name:       "dex with resources - .spec.sso.provider=dex",
   170  			setEnvFunc: nil,
   171  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   172  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   173  					Provider: argoproj.SSOProviderTypeDex,
   174  					Dex: &argoproj.ArgoCDDexSpec{
   175  						Resources: &corev1.ResourceRequirements{
   176  							Requests: corev1.ResourceList{
   177  								corev1.ResourceMemory: resourcev1.MustParse("128Mi"),
   178  								corev1.ResourceCPU:    resourcev1.MustParse("250m"),
   179  							},
   180  							Limits: corev1.ResourceList{
   181  								corev1.ResourceMemory: resourcev1.MustParse("256Mi"),
   182  								corev1.ResourceCPU:    resourcev1.MustParse("500m"),
   183  							},
   184  						},
   185  					},
   186  				}
   187  			}),
   188  		},
   189  	}
   190  
   191  	for _, test := range tests {
   192  		t.Run(test.name, func(t *testing.T) {
   193  
   194  			resObjs := []client.Object{test.argoCD}
   195  			subresObjs := []client.Object{test.argoCD}
   196  			runtimeObjs := []runtime.Object{}
   197  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   198  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   199  			r := makeTestReconciler(cl, sch)
   200  
   201  			if test.setEnvFunc != nil {
   202  				test.setEnvFunc(t, "false")
   203  			}
   204  
   205  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
   206  
   207  			deployment := &appsv1.Deployment{}
   208  			assert.NoError(t, r.Client.Get(
   209  				context.TODO(),
   210  				types.NamespacedName{
   211  					Name:      test.argoCD.Name + "-dex-server",
   212  					Namespace: test.argoCD.Namespace,
   213  				},
   214  				deployment))
   215  
   216  			testResources := corev1.ResourceRequirements{
   217  				Requests: corev1.ResourceList{
   218  					corev1.ResourceMemory: resourcev1.MustParse("128Mi"),
   219  					corev1.ResourceCPU:    resourcev1.MustParse("250m"),
   220  				},
   221  				Limits: corev1.ResourceList{
   222  					corev1.ResourceMemory: resourcev1.MustParse("256Mi"),
   223  					corev1.ResourceCPU:    resourcev1.MustParse("500m"),
   224  				},
   225  			}
   226  			assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Resources, testResources)
   227  			assert.Equal(t, deployment.Spec.Template.Spec.InitContainers[0].Resources, testResources)
   228  		})
   229  	}
   230  }
   231  
   232  func TestReconcileArgoCD_reconcileDexDeployment(t *testing.T) {
   233  	logf.SetLogger(ZapLogger(true))
   234  	a := makeTestArgoCD()
   235  	a.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   236  		Provider: argoproj.SSOProviderTypeDex,
   237  	}
   238  
   239  	resObjs := []client.Object{a}
   240  	subresObjs := []client.Object{a}
   241  	runtimeObjs := []runtime.Object{}
   242  	sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   243  	cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   244  	r := makeTestReconciler(cl, sch)
   245  
   246  	assert.NoError(t, r.reconcileDexDeployment(a))
   247  
   248  	deployment := &appsv1.Deployment{}
   249  	assert.NoError(t, r.Client.Get(
   250  		context.TODO(),
   251  		types.NamespacedName{
   252  			Name:      "argocd-dex-server",
   253  			Namespace: a.Namespace,
   254  		},
   255  		deployment))
   256  	want := corev1.PodSpec{
   257  		Volumes: []corev1.Volume{
   258  			{
   259  				Name: "static-files",
   260  				VolumeSource: corev1.VolumeSource{
   261  					EmptyDir: &corev1.EmptyDirVolumeSource{},
   262  				},
   263  			},
   264  		},
   265  		InitContainers: []corev1.Container{
   266  			{
   267  				Name:  "copyutil",
   268  				Image: getArgoContainerImage(a),
   269  				Command: []string{
   270  					"cp",
   271  					"-n",
   272  					"/usr/local/bin/argocd",
   273  					"/shared/argocd-dex",
   274  				},
   275  				SecurityContext: &corev1.SecurityContext{
   276  					AllowPrivilegeEscalation: boolPtr(false),
   277  					Capabilities: &corev1.Capabilities{
   278  						Drop: []corev1.Capability{
   279  							"ALL",
   280  						},
   281  					},
   282  					RunAsNonRoot: boolPtr(true),
   283  				},
   284  				VolumeMounts: []corev1.VolumeMount{
   285  					{
   286  						Name:      "static-files",
   287  						MountPath: "/shared",
   288  					},
   289  				},
   290  				ImagePullPolicy: corev1.PullAlways,
   291  			},
   292  		},
   293  		Containers: []corev1.Container{
   294  			{
   295  				Name:  "dex",
   296  				Image: getDexContainerImage(a),
   297  				Command: []string{
   298  					"/shared/argocd-dex",
   299  					"rundex",
   300  				},
   301  				LivenessProbe: &corev1.Probe{
   302  					ProbeHandler: corev1.ProbeHandler{
   303  						HTTPGet: &corev1.HTTPGetAction{
   304  							Path: "/healthz/live",
   305  							Port: intstr.FromInt(5558),
   306  						},
   307  					},
   308  					InitialDelaySeconds: 60,
   309  					PeriodSeconds:       30,
   310  				},
   311  				Ports: []corev1.ContainerPort{
   312  					{
   313  						Name:          "http",
   314  						ContainerPort: 5556,
   315  					},
   316  					{
   317  						Name:          "grpc",
   318  						ContainerPort: 5557,
   319  					},
   320  					{
   321  						Name:          "metrics",
   322  						ContainerPort: 5558,
   323  					},
   324  				},
   325  				SecurityContext: &corev1.SecurityContext{
   326  					AllowPrivilegeEscalation: boolPtr(false),
   327  					Capabilities: &corev1.Capabilities{
   328  						Drop: []corev1.Capability{
   329  							"ALL",
   330  						},
   331  					},
   332  					RunAsNonRoot: boolPtr(true),
   333  				},
   334  				VolumeMounts: []corev1.VolumeMount{
   335  					{Name: "static-files", MountPath: "/shared"},
   336  				},
   337  			},
   338  		},
   339  		ServiceAccountName: "argocd-argocd-dex-server",
   340  		NodeSelector:       common.DefaultNodeSelector(),
   341  	}
   342  	assert.Equal(t, want, deployment.Spec.Template.Spec)
   343  }
   344  
   345  func TestReconcileArgoCD_reconcileDexDeployment_withUpdate(t *testing.T) {
   346  	logf.SetLogger(ZapLogger(true))
   347  
   348  	tests := []struct {
   349  		name         string
   350  		setEnvFunc   func(*testing.T, string)
   351  		updateCrFunc func(cr *argoproj.ArgoCD)
   352  		argoCD       *argoproj.ArgoCD
   353  		wantPodSpec  corev1.PodSpec
   354  	}{
   355  		{
   356  			name:       "update dex deployment - .spec.sso.provider=dex + .spec.sso.dex",
   357  			setEnvFunc: nil,
   358  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   359  				cr.Spec.Image = "justatest"
   360  				cr.Spec.Version = "latest"
   361  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   362  					Provider: argoproj.SSOProviderTypeDex,
   363  					Dex: &argoproj.ArgoCDDexSpec{
   364  						Image:   "testdex",
   365  						Version: "v0.0.1",
   366  					},
   367  				}
   368  			},
   369  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   370  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   371  					Provider: argoproj.SSOProviderTypeDex,
   372  					Dex: &argoproj.ArgoCDDexSpec{
   373  						OpenShiftOAuth: true,
   374  					},
   375  				}
   376  			}),
   377  			wantPodSpec: corev1.PodSpec{
   378  				Volumes: []corev1.Volume{
   379  					{
   380  						Name: "static-files",
   381  						VolumeSource: corev1.VolumeSource{
   382  							EmptyDir: &corev1.EmptyDirVolumeSource{},
   383  						},
   384  					},
   385  				},
   386  				InitContainers: []corev1.Container{
   387  					{
   388  						Name:  "copyutil",
   389  						Image: "justatest:latest",
   390  						Command: []string{
   391  							"cp",
   392  							"-n",
   393  							"/usr/local/bin/argocd",
   394  							"/shared/argocd-dex",
   395  						},
   396  						SecurityContext: &corev1.SecurityContext{
   397  							AllowPrivilegeEscalation: boolPtr(false),
   398  							Capabilities: &corev1.Capabilities{
   399  								Drop: []corev1.Capability{
   400  									"ALL",
   401  								},
   402  							},
   403  							RunAsNonRoot: boolPtr(true),
   404  						},
   405  						VolumeMounts: []corev1.VolumeMount{
   406  							{
   407  								Name:      "static-files",
   408  								MountPath: "/shared",
   409  							},
   410  						},
   411  						ImagePullPolicy: corev1.PullAlways,
   412  					},
   413  				},
   414  				Containers: []corev1.Container{
   415  					{
   416  						Name:  "dex",
   417  						Image: "testdex:v0.0.1",
   418  						Command: []string{
   419  							"/shared/argocd-dex",
   420  							"rundex",
   421  						},
   422  						LivenessProbe: &corev1.Probe{
   423  							ProbeHandler: corev1.ProbeHandler{
   424  								HTTPGet: &corev1.HTTPGetAction{
   425  									Path: "/healthz/live",
   426  									Port: intstr.FromInt(5558),
   427  								},
   428  							},
   429  							InitialDelaySeconds: 60,
   430  							PeriodSeconds:       30,
   431  						},
   432  						Ports: []corev1.ContainerPort{
   433  							{
   434  								Name:          "http",
   435  								ContainerPort: 5556,
   436  							},
   437  							{
   438  								Name:          "grpc",
   439  								ContainerPort: 5557,
   440  							},
   441  							{
   442  								Name:          "metrics",
   443  								ContainerPort: 5558,
   444  							},
   445  						},
   446  						SecurityContext: &corev1.SecurityContext{
   447  							AllowPrivilegeEscalation: boolPtr(false),
   448  							Capabilities: &corev1.Capabilities{
   449  								Drop: []corev1.Capability{
   450  									"ALL",
   451  								},
   452  							},
   453  							RunAsNonRoot: boolPtr(true),
   454  						},
   455  						VolumeMounts: []corev1.VolumeMount{
   456  							{Name: "static-files", MountPath: "/shared"},
   457  						},
   458  					},
   459  				},
   460  				ServiceAccountName: "argocd-argocd-dex-server",
   461  				NodeSelector:       common.DefaultNodeSelector(),
   462  			},
   463  		},
   464  		{
   465  			name:       "update dex deployment - .spec.sso.dex.env",
   466  			setEnvFunc: nil,
   467  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   468  				cr.Spec.SSO.Dex.Env = []corev1.EnvVar{
   469  					{
   470  						Name: "ARGO_WORKFLOWS_SSO_CLIENT_SECRET",
   471  						ValueFrom: &corev1.EnvVarSource{
   472  							SecretKeyRef: &corev1.SecretKeySelector{
   473  								LocalObjectReference: corev1.LocalObjectReference{
   474  									Name: "argo-workflows-sso",
   475  								},
   476  								Key: "client-secret",
   477  							},
   478  						},
   479  					},
   480  				}
   481  			},
   482  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   483  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   484  					Provider: argoproj.SSOProviderTypeDex,
   485  					Dex: &argoproj.ArgoCDDexSpec{
   486  						OpenShiftOAuth: true,
   487  					},
   488  				}
   489  			}),
   490  			wantPodSpec: corev1.PodSpec{
   491  				Volumes: []corev1.Volume{
   492  					{
   493  						Name: "static-files",
   494  						VolumeSource: corev1.VolumeSource{
   495  							EmptyDir: &corev1.EmptyDirVolumeSource{},
   496  						},
   497  					},
   498  				},
   499  				InitContainers: []corev1.Container{
   500  					{
   501  						Name:  "copyutil",
   502  						Image: "quay.io/argoproj/argocd@sha256:5f1de1b4d959868c1e006e08d46361c8f019d9730e74bc1feeab8c7b413f1187",
   503  						Command: []string{
   504  							"cp",
   505  							"-n",
   506  							"/usr/local/bin/argocd",
   507  							"/shared/argocd-dex",
   508  						},
   509  						SecurityContext: &corev1.SecurityContext{
   510  							AllowPrivilegeEscalation: boolPtr(false),
   511  							Capabilities: &corev1.Capabilities{
   512  								Drop: []corev1.Capability{
   513  									"ALL",
   514  								},
   515  							},
   516  							RunAsNonRoot: boolPtr(true),
   517  						},
   518  						VolumeMounts: []corev1.VolumeMount{
   519  							{
   520  								Name:      "static-files",
   521  								MountPath: "/shared",
   522  							},
   523  						},
   524  						ImagePullPolicy: corev1.PullAlways,
   525  					},
   526  				},
   527  				Containers: []corev1.Container{
   528  					{
   529  						Name:  "dex",
   530  						Image: "ghcr.io/dexidp/dex@sha256:d5f887574312f606c61e7e188cfb11ddb33ff3bf4bd9f06e6b1458efca75f604",
   531  						Command: []string{
   532  							"/shared/argocd-dex",
   533  							"rundex",
   534  						},
   535  						LivenessProbe: &corev1.Probe{
   536  							ProbeHandler: corev1.ProbeHandler{
   537  								HTTPGet: &corev1.HTTPGetAction{
   538  									Path: "/healthz/live",
   539  									Port: intstr.FromInt(5558),
   540  								},
   541  							},
   542  							InitialDelaySeconds: 60,
   543  							PeriodSeconds:       30,
   544  						},
   545  						Ports: []corev1.ContainerPort{
   546  							{
   547  								Name:          "http",
   548  								ContainerPort: 5556,
   549  							},
   550  							{
   551  								Name:          "grpc",
   552  								ContainerPort: 5557,
   553  							},
   554  							{
   555  								Name:          "metrics",
   556  								ContainerPort: 5558,
   557  							},
   558  						},
   559  						Env: []corev1.EnvVar{
   560  							{
   561  								Name: "ARGO_WORKFLOWS_SSO_CLIENT_SECRET",
   562  								ValueFrom: &corev1.EnvVarSource{
   563  									SecretKeyRef: &corev1.SecretKeySelector{
   564  										LocalObjectReference: corev1.LocalObjectReference{
   565  											Name: "argo-workflows-sso",
   566  										},
   567  										Key: "client-secret",
   568  									},
   569  								},
   570  							},
   571  						},
   572  						SecurityContext: &corev1.SecurityContext{
   573  							AllowPrivilegeEscalation: boolPtr(false),
   574  							Capabilities: &corev1.Capabilities{
   575  								Drop: []corev1.Capability{
   576  									"ALL",
   577  								},
   578  							},
   579  							RunAsNonRoot: boolPtr(true),
   580  						},
   581  						VolumeMounts: []corev1.VolumeMount{
   582  							{Name: "static-files", MountPath: "/shared"},
   583  						},
   584  					},
   585  				},
   586  				ServiceAccountName: "argocd-argocd-dex-server",
   587  				NodeSelector:       common.DefaultNodeSelector(),
   588  			},
   589  		},
   590  	}
   591  
   592  	for _, test := range tests {
   593  		t.Run(test.name, func(t *testing.T) {
   594  
   595  			resObjs := []client.Object{test.argoCD}
   596  			subresObjs := []client.Object{test.argoCD}
   597  			runtimeObjs := []runtime.Object{}
   598  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   599  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   600  			r := makeTestReconciler(cl, sch)
   601  
   602  			if test.setEnvFunc != nil {
   603  				test.setEnvFunc(t, "false")
   604  			}
   605  
   606  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
   607  
   608  			if test.updateCrFunc != nil {
   609  				test.updateCrFunc(test.argoCD)
   610  			}
   611  
   612  			assert.NoError(t, r.reconcileDexDeployment(test.argoCD))
   613  
   614  			// ensure deployment was created correctly
   615  			deployment := &appsv1.Deployment{}
   616  			assert.NoError(t, r.Client.Get(
   617  				context.TODO(),
   618  				types.NamespacedName{
   619  					Name:      "argocd-dex-server",
   620  					Namespace: test.argoCD.Namespace,
   621  				},
   622  				deployment))
   623  
   624  			assert.Equal(t, test.wantPodSpec, deployment.Spec.Template.Spec)
   625  		})
   626  	}
   627  }
   628  
   629  // When Dex is enabled dex service should be created, when disabled the Dex service should be removed
   630  func TestReconcileArgoCD_reconcileDexService_removes_dex_when_disabled(t *testing.T) {
   631  	logf.SetLogger(ZapLogger(true))
   632  
   633  	tests := []struct {
   634  		name               string
   635  		setEnvFunc         func(*testing.T, string)
   636  		updateCrFunc       func(cr *argoproj.ArgoCD)
   637  		updateEnvFunc      func(*testing.T, string)
   638  		argoCD             *argoproj.ArgoCD
   639  		wantServiceDeleted bool
   640  	}{
   641  		{
   642  			name:       "dex disabled by removing .spec.sso",
   643  			setEnvFunc: nil,
   644  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   645  				cr.Spec.SSO = nil
   646  			},
   647  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   648  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   649  					Provider: argoproj.SSOProviderTypeDex,
   650  					Dex: &argoproj.ArgoCDDexSpec{
   651  						OpenShiftOAuth: true,
   652  					},
   653  				}
   654  			}),
   655  			wantServiceDeleted: true,
   656  		},
   657  		{
   658  			name:       "dex disabled by switching provider",
   659  			setEnvFunc: nil,
   660  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   661  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   662  					Provider: argoproj.SSOProviderTypeKeycloak,
   663  				}
   664  			},
   665  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   666  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   667  					Provider: argoproj.SSOProviderTypeDex,
   668  					Dex: &argoproj.ArgoCDDexSpec{
   669  						OpenShiftOAuth: true,
   670  					},
   671  				}
   672  			}),
   673  			wantServiceDeleted: true,
   674  		},
   675  	}
   676  
   677  	for _, test := range tests {
   678  		t.Run(test.name, func(t *testing.T) {
   679  
   680  			resObjs := []client.Object{test.argoCD}
   681  			subresObjs := []client.Object{test.argoCD}
   682  			runtimeObjs := []runtime.Object{}
   683  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   684  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   685  			r := makeTestReconciler(cl, sch)
   686  
   687  			if test.setEnvFunc != nil {
   688  				test.setEnvFunc(t, "false")
   689  			}
   690  
   691  			assert.NoError(t, r.reconcileDexService(test.argoCD))
   692  
   693  			// ensure service was created correctly
   694  			service := &corev1.Service{}
   695  			err := r.Client.Get(context.TODO(), types.NamespacedName{Name: "argocd-dex-server", Namespace: test.argoCD.Namespace}, service)
   696  			assert.NoError(t, err)
   697  
   698  			if test.updateEnvFunc != nil {
   699  				test.updateEnvFunc(t, "true")
   700  			}
   701  			if test.updateCrFunc != nil {
   702  				test.updateCrFunc(test.argoCD)
   703  			}
   704  
   705  			assert.NoError(t, r.reconcileDexService(test.argoCD))
   706  			service = &corev1.Service{}
   707  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: "argocd-dex-server", Namespace: test.argoCD.Namespace}, service)
   708  
   709  			if test.wantServiceDeleted {
   710  				assertNotFound(t, err)
   711  			} else {
   712  				assert.NoError(t, err)
   713  			}
   714  		})
   715  	}
   716  }
   717  
   718  // When Dex is enabled dex serviceaccount should be created, when disabled the Dex serviceaccount should be removed
   719  func TestReconcileArgoCD_reconcileDexServiceAccount_removes_dex_when_disabled(t *testing.T) {
   720  	logf.SetLogger(ZapLogger(true))
   721  
   722  	tests := []struct {
   723  		name                      string
   724  		setEnvFunc                func(*testing.T, string)
   725  		updateCrFunc              func(cr *argoproj.ArgoCD)
   726  		updateEnvFunc             func(*testing.T, string)
   727  		argoCD                    *argoproj.ArgoCD
   728  		wantServiceAccountDeleted bool
   729  	}{
   730  		{
   731  			name:       "dex disabled by removing .spec.sso",
   732  			setEnvFunc: nil,
   733  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   734  				cr.Spec.SSO = nil
   735  			},
   736  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   737  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   738  					Provider: argoproj.SSOProviderTypeDex,
   739  					Dex: &argoproj.ArgoCDDexSpec{
   740  						OpenShiftOAuth: true,
   741  					},
   742  				}
   743  			}),
   744  			wantServiceAccountDeleted: true,
   745  		},
   746  		{
   747  			name:       "dex disabled by switching provider",
   748  			setEnvFunc: nil,
   749  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   750  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   751  					Provider: argoproj.SSOProviderTypeKeycloak,
   752  				}
   753  			},
   754  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   755  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   756  					Provider: argoproj.SSOProviderTypeDex,
   757  					Dex: &argoproj.ArgoCDDexSpec{
   758  						OpenShiftOAuth: true,
   759  					},
   760  				}
   761  			}),
   762  			wantServiceAccountDeleted: true,
   763  		},
   764  	}
   765  
   766  	for _, test := range tests {
   767  		t.Run(test.name, func(t *testing.T) {
   768  
   769  			resObjs := []client.Object{test.argoCD}
   770  			subresObjs := []client.Object{test.argoCD}
   771  			runtimeObjs := []runtime.Object{}
   772  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   773  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   774  			r := makeTestReconciler(cl, sch)
   775  
   776  			if test.setEnvFunc != nil {
   777  				test.setEnvFunc(t, "false")
   778  			}
   779  
   780  			sa, err := r.reconcileServiceAccount(common.ArgoCDDexServerComponent, test.argoCD)
   781  			assert.NoError(t, err)
   782  
   783  			// ensure serviceaccount was created correctly
   784  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: sa.Name, Namespace: test.argoCD.Namespace}, sa)
   785  			assert.NoError(t, err)
   786  
   787  			if test.updateEnvFunc != nil {
   788  				test.updateEnvFunc(t, "true")
   789  			}
   790  			if test.updateCrFunc != nil {
   791  				test.updateCrFunc(test.argoCD)
   792  			}
   793  
   794  			_, err = r.reconcileServiceAccount(common.ArgoCDDexServerComponent, test.argoCD)
   795  			assert.NoError(t, err)
   796  
   797  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: sa.Name, Namespace: test.argoCD.Namespace}, sa)
   798  
   799  			if test.wantServiceAccountDeleted {
   800  				assertNotFound(t, err)
   801  			} else {
   802  				assert.NoError(t, err)
   803  			}
   804  		})
   805  	}
   806  }
   807  
   808  // When Dex is enabled dex role should be created, when disabled the Dex role should be removed
   809  func TestReconcileArgoCD_reconcileRole_dex_disabled(t *testing.T) {
   810  	logf.SetLogger(ZapLogger(true))
   811  
   812  	tests := []struct {
   813  		name            string
   814  		setEnvFunc      func(*testing.T, string)
   815  		updateCrFunc    func(cr *argoproj.ArgoCD)
   816  		updateEnvFunc   func(*testing.T, string)
   817  		argoCD          *argoproj.ArgoCD
   818  		wantRoleDeleted bool
   819  	}{
   820  		{
   821  			name:       "dex disabled by removing .spec.sso",
   822  			setEnvFunc: nil,
   823  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   824  				cr.Spec.SSO = nil
   825  			},
   826  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   827  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   828  					Provider: argoproj.SSOProviderTypeDex,
   829  					Dex: &argoproj.ArgoCDDexSpec{
   830  						OpenShiftOAuth: true,
   831  					},
   832  				}
   833  			}),
   834  			wantRoleDeleted: true,
   835  		},
   836  		{
   837  			name:       "dex disabled by switching provider",
   838  			setEnvFunc: nil,
   839  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   840  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   841  					Provider: argoproj.SSOProviderTypeKeycloak,
   842  				}
   843  			},
   844  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   845  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   846  					Provider: argoproj.SSOProviderTypeDex,
   847  					Dex: &argoproj.ArgoCDDexSpec{
   848  						OpenShiftOAuth: true,
   849  					},
   850  				}
   851  			}),
   852  			wantRoleDeleted: true,
   853  		},
   854  	}
   855  
   856  	for _, test := range tests {
   857  		t.Run(test.name, func(t *testing.T) {
   858  
   859  			resObjs := []client.Object{test.argoCD}
   860  			subresObjs := []client.Object{test.argoCD}
   861  			runtimeObjs := []runtime.Object{}
   862  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   863  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   864  			r := makeTestReconciler(cl, sch)
   865  
   866  			assert.NoError(t, createNamespace(r, test.argoCD.Namespace, ""))
   867  
   868  			rules := policyRuleForDexServer()
   869  			role := newRole(common.ArgoCDDexServerComponent, rules, test.argoCD)
   870  
   871  			if test.setEnvFunc != nil {
   872  				test.setEnvFunc(t, "false")
   873  			}
   874  
   875  			_, err := r.reconcileRole(common.ArgoCDDexServerComponent, rules, test.argoCD)
   876  			assert.NoError(t, err)
   877  
   878  			// ensure role was created correctly
   879  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: role.Name, Namespace: test.argoCD.Namespace}, role)
   880  			assert.NoError(t, err)
   881  
   882  			if test.updateEnvFunc != nil {
   883  				test.updateEnvFunc(t, "true")
   884  			}
   885  			if test.updateCrFunc != nil {
   886  				test.updateCrFunc(test.argoCD)
   887  			}
   888  
   889  			_, err = r.reconcileRole(common.ArgoCDDexServerComponent, rules, test.argoCD)
   890  			assert.NoError(t, err)
   891  
   892  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: role.Name, Namespace: test.argoCD.Namespace}, role)
   893  
   894  			if test.wantRoleDeleted {
   895  				assertNotFound(t, err)
   896  			} else {
   897  				assert.NoError(t, err)
   898  			}
   899  		})
   900  	}
   901  }
   902  
   903  // When Dex is enabled dex roleBinding should be created, when disabled the Dex roleBinding should be removed
   904  func TestReconcileArgoCD_reconcileRoleBinding_dex_disabled(t *testing.T) {
   905  	logf.SetLogger(ZapLogger(true))
   906  
   907  	tests := []struct {
   908  		name                   string
   909  		setEnvFunc             func(*testing.T, string)
   910  		updateCrFunc           func(cr *argoproj.ArgoCD)
   911  		updateEnvFunc          func(*testing.T, string)
   912  		argoCD                 *argoproj.ArgoCD
   913  		wantRoleBindingDeleted bool
   914  	}{
   915  		{
   916  			name:       "dex disabled by removing .spec.sso",
   917  			setEnvFunc: nil,
   918  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   919  				cr.Spec.SSO = nil
   920  			},
   921  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   922  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   923  					Provider: argoproj.SSOProviderTypeDex,
   924  					Dex: &argoproj.ArgoCDDexSpec{
   925  						OpenShiftOAuth: true,
   926  					},
   927  				}
   928  			}),
   929  			wantRoleBindingDeleted: true,
   930  		},
   931  		{
   932  			name:       "dex disabled by switching provider",
   933  			setEnvFunc: nil,
   934  			updateCrFunc: func(cr *argoproj.ArgoCD) {
   935  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   936  					Provider: argoproj.SSOProviderTypeKeycloak,
   937  				}
   938  			},
   939  			argoCD: makeTestArgoCD(func(cr *argoproj.ArgoCD) {
   940  				cr.Spec.SSO = &argoproj.ArgoCDSSOSpec{
   941  					Provider: argoproj.SSOProviderTypeDex,
   942  					Dex: &argoproj.ArgoCDDexSpec{
   943  						OpenShiftOAuth: true,
   944  					},
   945  				}
   946  			}),
   947  			wantRoleBindingDeleted: true,
   948  		},
   949  	}
   950  
   951  	for _, test := range tests {
   952  		t.Run(test.name, func(t *testing.T) {
   953  
   954  			resObjs := []client.Object{test.argoCD}
   955  			subresObjs := []client.Object{test.argoCD}
   956  			runtimeObjs := []runtime.Object{}
   957  			sch := makeTestReconcilerScheme(argoproj.AddToScheme)
   958  			cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
   959  			r := makeTestReconciler(cl, sch)
   960  
   961  			assert.NoError(t, createNamespace(r, test.argoCD.Namespace, ""))
   962  
   963  			rules := policyRuleForDexServer()
   964  			roleBinding := newRoleBindingWithname(common.ArgoCDDexServerComponent, test.argoCD)
   965  
   966  			if test.setEnvFunc != nil {
   967  				test.setEnvFunc(t, "false")
   968  			}
   969  
   970  			assert.NoError(t, r.reconcileRoleBinding(common.ArgoCDDexServerComponent, rules, test.argoCD))
   971  			assert.NoError(t, r.Client.Get(context.TODO(), types.NamespacedName{Name: roleBinding.Name, Namespace: test.argoCD.Namespace}, roleBinding))
   972  
   973  			// ensure roleBinding was created correctly
   974  			err := r.Client.Get(context.TODO(), types.NamespacedName{Name: roleBinding.Name, Namespace: test.argoCD.Namespace}, roleBinding)
   975  			assert.NoError(t, err)
   976  
   977  			if test.updateEnvFunc != nil {
   978  				test.updateEnvFunc(t, "true")
   979  			}
   980  			if test.updateCrFunc != nil {
   981  				test.updateCrFunc(test.argoCD)
   982  			}
   983  
   984  			err = r.reconcileRoleBinding(common.ArgoCDDexServerComponent, rules, test.argoCD)
   985  			assert.NoError(t, err)
   986  
   987  			err = r.Client.Get(context.TODO(), types.NamespacedName{Name: roleBinding.Name, Namespace: test.argoCD.Namespace}, roleBinding)
   988  
   989  			if test.wantRoleBindingDeleted {
   990  				assertNotFound(t, err)
   991  			} else {
   992  				assert.NoError(t, err)
   993  			}
   994  		})
   995  	}
   996  }