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 }