github.com/verrazzano/verrazzano@v1.7.0/platform-operator/controllers/secrets/secrets_controller_test.go (about) 1 // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package secrets 5 6 import ( 7 "context" 8 "crypto/x509" 9 "fmt" 10 "testing" 11 "time" 12 13 cmutil "github.com/cert-manager/cert-manager/pkg/api/util" 14 certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" 15 cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" 16 certv1fake "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/fake" 17 certv1client "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned/typed/certmanager/v1" 18 "github.com/golang/mock/gomock" 19 "github.com/stretchr/testify/assert" 20 constants2 "github.com/verrazzano/verrazzano/pkg/constants" 21 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 22 vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 23 "github.com/verrazzano/verrazzano/platform-operator/constants" 24 cmcommonfake "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/certmanager/common/fake" 25 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/certmanager/issuer" 26 vzstatus "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/healthcheck" 27 "github.com/verrazzano/verrazzano/platform-operator/internal/config" 28 "github.com/verrazzano/verrazzano/platform-operator/mocks" 29 appsv1 "k8s.io/api/apps/v1" 30 corev1 "k8s.io/api/core/v1" 31 "k8s.io/apimachinery/pkg/api/errors" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/runtime" 34 "k8s.io/apimachinery/pkg/types" 35 ctrl "sigs.k8s.io/controller-runtime" 36 "sigs.k8s.io/controller-runtime/pkg/client" 37 "sigs.k8s.io/controller-runtime/pkg/client/fake" 38 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 39 ) 40 41 var vzTLSSecret = types.NamespacedName{Name: constants.VerrazzanoIngressSecret, Namespace: constants.VerrazzanoSystemNamespace} 42 var vzPrivateCABundleSecret = types.NamespacedName{Name: constants2.PrivateCABundle, Namespace: constants.VerrazzanoSystemNamespace} 43 var additionalTLSSecret = types.NamespacedName{Name: "tls-ca-additional", Namespace: constants2.RancherSystemNamespace} 44 var unwatchedSecret = types.NamespacedName{Name: "any-secret", Namespace: "any-namespace"} 45 46 // TestReconcileConfiguredCASecret tests the Reconcile method 47 // GIVEN a request to reconcile the secret configured in ClusterIssuer 48 // WHEN the secret has changed 49 // THEN verify all certificates managed by ClusterIssuer are rotated 50 // THEN verify the verrazzano-system/verrazzano-tls-ca secret is updated with the changes 51 // THEN verify the cattle-system/tls-ca secret is updated with the changes 52 // THEN verify the verrazzano-mc/verrazzano-local-ca-bundle secret is updated with the changes 53 func TestReconcileConfiguredCASecret(t *testing.T) { 54 const caCertCommonName = "verrazzano-root-ca" 55 asserts := assert.New(t) 56 config.TestProfilesDir = "../../manifests/profiles" 57 defer func() { config.TestProfilesDir = "" }() 58 scheme := newScheme() 59 vz := newVZ() 60 61 // Create a CA certificate 62 commonName := caCertCommonName + "-a23asdfa" 63 caIssuerCert := cmcommonfake.CreateFakeCertificate(commonName) 64 caSecret, caCert, err := newCertificateWithSecret("verrazzano-selfsigned-issuer", commonName, "verrazzano-ca-certificate", constants2.CertManagerNamespace, nil) 65 asserts.NoError(err) 66 67 // Create a leaf certificate signed by the CA 68 leaf1Secret, leaf1Cert, err := newCertificateWithSecret("verrazzano-cluster-issuer", "common-name", "tls-rancher-ingress", constants2.RancherSystemNamespace, caIssuerCert) 69 assert.NoError(t, err) 70 leaf1Secret.Data[constants2.CACertKey] = caSecret.Data[corev1.TLSCertKey] 71 72 // Create the verrazzano-tls-ca secret 73 v8oTLSCASecret := newCertSecret(constants2.PrivateCABundle, constants2.VerrazzanoSystemNamespace, constants2.CABundleKey, caSecret.Data[corev1.TLSCertKey]) 74 75 // Create the Rancher tls-ca secret 76 cattleTLSSecret := newCertSecret(constants2.RancherTLSCA, constants2.RancherSystemNamespace, constants2.RancherTLSCAKey, caSecret.Data[corev1.TLSCertKey]) 77 78 // Create the Rancher deployment 79 cattleDeployment := &appsv1.Deployment{ 80 ObjectMeta: metav1.ObjectMeta{ 81 Namespace: constants2.RancherSystemNamespace, 82 Name: rancherDeploymentName, 83 }, 84 } 85 86 // Create the multi-cluster namespace 87 multiClusterNamespace := &corev1.Namespace{ 88 ObjectMeta: metav1.ObjectMeta{ 89 Name: constants2.VerrazzanoMultiClusterNamespace, 90 }, 91 } 92 93 // Create the multi-cluster verrazzano-local-ca-bundle secret 94 mcSecret := newCertSecret(constants.VerrazzanoLocalCABundleSecret, constants.VerrazzanoMultiClusterNamespace, mcCABundleKey, caSecret.Data[corev1.TLSCertKey]) 95 96 // Simulate rotate of the CA cert 97 fakeIssuerCertBytes, err := cmcommonfake.CreateFakeCertBytes(commonName+"foo", nil) 98 assert.NoError(t, err) 99 caSecret.Data[corev1.TLSCertKey] = fakeIssuerCertBytes 100 101 // Fake ControllerRuntime client 102 fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(vz, caSecret, caCert, leaf1Secret, leaf1Cert, 103 v8oTLSCASecret, cattleTLSSecret, cattleDeployment, multiClusterNamespace, mcSecret).Build() 104 r := newSecretsReconciler(fakeClient) 105 106 // Fake Go client for the CertManager clientSet 107 cmClient := certv1fake.NewSimpleClientset(caCert, leaf1Cert) 108 defer issuer.ResetCMClientFunc() 109 issuer.SetCMClientFunc(func() (certv1client.CertmanagerV1Interface, error) { 110 return cmClient.CertmanagerV1(), nil 111 }) 112 113 // First reconcile the change to the ClusterIssuer secret 114 request := newRequest(caSecret.Namespace, caSecret.Name) 115 result, err := r.Reconcile(context.TODO(), request) 116 asserts.NoError(err) 117 asserts.NotNil(result) 118 119 // Next reconcile the change to the verrazzano-tls-ca secret 120 request = newRequest(v8oTLSCASecret.Namespace, v8oTLSCASecret.Name) 121 result, err = r.Reconcile(context.TODO(), request) 122 asserts.NoError(err) 123 asserts.NotNil(result) 124 125 // Confirm the expected certificates were marked to be rotated 126 updatedCert, err := cmClient.CertmanagerV1().Certificates(leaf1Cert.Namespace).Get(context.TODO(), leaf1Cert.Name, metav1.GetOptions{}) 127 asserts.NoError(err) 128 asserts.True(cmutil.CertificateHasCondition(updatedCert, certv1.CertificateCondition{ 129 Type: certv1.CertificateConditionIssuing, 130 Status: cmmeta.ConditionTrue, 131 })) 132 133 // Confirm the verrazzano-tls-ca secret got updated 134 secret := &corev1.Secret{} 135 err = fakeClient.Get(context.TODO(), types.NamespacedName{Namespace: v8oTLSCASecret.Namespace, Name: v8oTLSCASecret.Name}, secret) 136 asserts.NoError(err) 137 asserts.Equal(caSecret.Data[corev1.TLSCertKey], secret.Data[constants2.CABundleKey]) 138 139 // Confirm the Rancher tls-ca secret got updated 140 secret = &corev1.Secret{} 141 err = fakeClient.Get(context.TODO(), types.NamespacedName{Namespace: cattleTLSSecret.Namespace, Name: cattleTLSSecret.Name}, secret) 142 asserts.NoError(err) 143 asserts.Equal(caSecret.Data[corev1.TLSCertKey], secret.Data[constants2.RancherTLSCAKey]) 144 145 // Confirm the Rancher deployment was annotated to restart 146 deployment := &appsv1.Deployment{} 147 err = fakeClient.Get(context.TODO(), types.NamespacedName{Namespace: cattleDeployment.Namespace, Name: cattleDeployment.Name}, deployment) 148 asserts.NoError(err) 149 annotations := deployment.Spec.Template.ObjectMeta.Annotations 150 asserts.NotNil(annotations) 151 asserts.NotEmpty(annotations[constants2.VerrazzanoRestartAnnotation]) 152 153 // Confirm the multi-cluster verrazzano-local-ca-bundle secret got updated 154 secret = &corev1.Secret{} 155 err = fakeClient.Get(context.TODO(), types.NamespacedName{Namespace: mcSecret.Namespace, Name: mcSecret.Name}, secret) 156 asserts.NoError(err) 157 asserts.Equal(caSecret.Data[corev1.TLSCertKey], secret.Data[mcCABundleKey]) 158 } 159 160 // TestIgnoresOtherSecrets tests the Reconcile method for the following use case 161 // GIVEN a request to reconcile the additional TLS secret or a secret other than verrazzano TLS secret 162 // WHEN any conditions 163 // THEN the request is ignored 164 func TestIgnoresOtherSecrets(t *testing.T) { 165 tests := []struct { 166 secretName string 167 secretNS string 168 }{ 169 // Additional TLS secret no longer watched 170 { 171 secretName: additionalTLSSecret.Name, 172 secretNS: additionalTLSSecret.Namespace, 173 }, 174 // VZ TLS secret name in wrong NS 175 { 176 secretName: vzTLSSecret.Name, 177 secretNS: additionalTLSSecret.Namespace, 178 }, 179 // Additional TLS secret name in wrong NS 180 { 181 secretName: additionalTLSSecret.Name, 182 secretNS: vzTLSSecret.Namespace, 183 }, 184 // A totally different secret name and NS 185 { 186 secretName: unwatchedSecret.Name, 187 secretNS: unwatchedSecret.Namespace, 188 }, 189 } 190 for _, tt := range tests { 191 asserts := assert.New(t) 192 mocker := gomock.NewController(t) 193 mock := mocks.NewMockClient(mocker) 194 195 expectNothingForWrongSecret(mock) 196 197 // Create and make the request 198 request := newRequest(tt.secretNS, tt.secretName) 199 reconciler := newSecretsReconciler(mock) 200 result, err := reconciler.Reconcile(context.TODO(), request) 201 202 // Validate the results 203 mocker.Finish() 204 asserts.NoError(err) 205 asserts.NotNil(result) 206 } 207 } 208 209 // TestSecretReconciler tests the Reconciler method for the following use case 210 // GIVEN a request to reconcile a Secret 211 // WHEN the Secret is referenced in the Verrazzano CR under a component and is also present the CR namespace 212 // THEN the ReconcilingGeneration of the target component is set to 1 213 func TestSecretReconciler(t *testing.T) { 214 asserts := assert.New(t) 215 secret := testSecret 216 secret.Finalizers = append(secret.Finalizers, constants.OverridesFinalizer) 217 cli := fake.NewClientBuilder().WithObjects(&testVZ, &secret).WithScheme(newScheme()).Build() 218 219 config.TestProfilesDir = "../../manifests/profiles" 220 defer func() { config.TestProfilesDir = "" }() 221 222 request := newRequest(testNS, testSecretName) 223 reconciler := newSecretsReconciler(cli) 224 res0, err0 := reconciler.Reconcile(context.TODO(), request) 225 226 asserts.NoError(err0) 227 asserts.Empty(res0) 228 229 vz := vzapi.Verrazzano{} 230 err := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testVZName}, &vz) 231 asserts.NoError(err) 232 asserts.Equal(int64(1), vz.Status.Components["prometheus-operator"].ReconcilingGeneration) 233 234 } 235 236 // TestSecretRequeue tests the Reconcile method for the following use case 237 // GIVEN a request to reconcile a Secret that qualifies as an override 238 // WHEN the status of the Verrazzano CR is found without the Component Status details 239 // THEN a requeue request is returned with an error 240 func TestSecretRequeue(t *testing.T) { 241 asserts := assert.New(t) 242 vz := testVZ 243 vz.Status.Components = nil 244 asserts.Nil(vz.Status.Components) 245 secret := testSecret 246 secret.Finalizers = append(secret.Finalizers, constants.OverridesFinalizer) 247 cli := fake.NewClientBuilder().WithObjects(&vz, &secret).WithScheme(newScheme()).Build() 248 249 config.TestProfilesDir = "../../manifests/profiles" 250 defer func() { config.TestProfilesDir = "" }() 251 252 request0 := newRequest(testNS, testSecretName) 253 reconciler := newSecretsReconciler(cli) 254 res0, err0 := reconciler.Reconcile(context.TODO(), request0) 255 256 asserts.Error(err0) 257 asserts.Contains(err0.Error(), "Components not initialized") 258 asserts.Equal(true, res0.Requeue) 259 } 260 261 // TestAddFinalizer tests the Reconciler for the following use case 262 // GIVEN a request to reconcile a Secret that qualifies as an override 263 // WHEN the Secret is found without the overrides finalizer 264 // THEN the overrides finalizer is added and we requeue without an error 265 func TestAddFinalizer(t *testing.T) { 266 asserts := assert.New(t) 267 cli := fake.NewClientBuilder().WithObjects(&testVZ, &testSecret).WithScheme(newScheme()).Build() 268 269 config.TestProfilesDir = "../../manifests/profiles" 270 defer func() { config.TestProfilesDir = "" }() 271 272 request0 := newRequest(testNS, testSecretName) 273 reconciler := newSecretsReconciler(cli) 274 res0, err0 := reconciler.Reconcile(context.TODO(), request0) 275 276 asserts.NoError(err0) 277 asserts.Equal(true, res0.Requeue) 278 279 secret := corev1.Secret{} 280 err := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testSecretName}, &secret) 281 asserts.NoError(err) 282 asserts.True(controllerutil.ContainsFinalizer(&secret, constants.OverridesFinalizer)) 283 } 284 285 // TestOtherFinalizers tests the Reconcile loop for the following use case 286 // GIVEN a request to reconcile a Secret that qualifies as an override resource and is scheduled for deletion 287 // WHEN the Secret is found with finalizers but the override finalizer is missing 288 // THEN without updating the Verrazzano CR a requeue request is returned without an error 289 func TestOtherFinalizers(t *testing.T) { 290 asserts := assert.New(t) 291 secret := testSecret 292 secret.Finalizers = append(secret.Finalizers, "test") 293 secret.DeletionTimestamp = &metav1.Time{Time: time.Now()} 294 cli := fake.NewClientBuilder().WithObjects(&testVZ, &secret).WithScheme(newScheme()).Build() 295 296 config.TestProfilesDir = "../../manifests/profiles" 297 defer func() { config.TestProfilesDir = "" }() 298 299 request0 := newRequest(testNS, testSecretName) 300 reconciler := newSecretsReconciler(cli) 301 res0, err0 := reconciler.Reconcile(context.TODO(), request0) 302 303 asserts.NoError(err0) 304 asserts.Equal(true, res0.Requeue) 305 306 vz := &vzapi.Verrazzano{} 307 err1 := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testVZName}, vz) 308 asserts.NoError(err1) 309 asserts.NotEqual(int64(1), vz.Status.Components["prometheus-operator"].ReconcilingGeneration) 310 } 311 312 // TestSecretNotFound tests the Reconcile method for the following use cases 313 // GIVEN requests to reconcile a ConfigMap 314 // WHEN the Secret is not found in the cluster 315 // THEN Verrazzano is updated if it's listed as an override, otherwise the request is ignored 316 func TestSecretNotFound(t *testing.T) { 317 tests := []struct { 318 nsn types.NamespacedName 319 }{ 320 { 321 nsn: types.NamespacedName{Namespace: testNS, Name: testSecretName}, 322 }, 323 { 324 nsn: types.NamespacedName{Namespace: testNS, Name: "test"}, 325 }, 326 } 327 328 for i, tt := range tests { 329 asserts := assert.New(t) 330 cli := fake.NewClientBuilder().WithObjects(&testVZ).WithScheme(newScheme()).Build() 331 config.Set(config.OperatorConfig{CloudCredentialWatchEnabled: false}) 332 config.TestProfilesDir = "../../manifests/profiles" 333 defer func() { config.TestProfilesDir = "" }() 334 335 request0 := newRequest(tt.nsn.Namespace, tt.nsn.Name) 336 reconciler := newSecretsReconciler(cli) 337 res0, err0 := reconciler.Reconcile(context.TODO(), request0) 338 339 asserts.NoError(err0) 340 asserts.Equal(false, res0.Requeue) 341 342 vz := &vzapi.Verrazzano{} 343 err1 := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testVZName}, vz) 344 asserts.NoError(err1) 345 if i == 0 { 346 asserts.Equal(int64(1), vz.Status.Components["prometheus-operator"].ReconcilingGeneration) 347 } else { 348 asserts.NotEqual(int64(1), vz.Status.Components["prometheus-operator"].ReconcilingGeneration) 349 } 350 } 351 352 } 353 354 // TestVerrazzanoResourcesNotFound tests the Reconcile method for the following use cases 355 // GIVEN a request to reconcile 356 // WHEN no verrazzano resources are found 357 // THEN the secrets reconciler returns a result of ctrl.Result{} 358 func TestVerrazzanoResourcesNotFound(t *testing.T) { 359 asserts := assert.New(t) 360 mocker := gomock.NewController(t) 361 mock := mocks.NewMockClient(mocker) 362 363 // Expect a call to get a list of verrazzano resources 364 mock.EXPECT(). 365 List(gomock.Any(), gomock.Any(), gomock.Any()). 366 DoAndReturn(func(ctx context.Context, list runtime.Object, opts ...client.ListOption) error { 367 // return no resources 368 return nil 369 }) 370 371 // Create and make the request 372 request := newRequest(vzTLSSecret.Namespace, vzTLSSecret.Name) 373 reconciler := newSecretsReconciler(mock) 374 result, err := reconciler.Reconcile(context.TODO(), request) 375 376 // Validate the results 377 mocker.Finish() 378 asserts.NoError(err) 379 asserts.NotNil(result) 380 asserts.Equal(ctrl.Result{}, result) 381 } 382 383 // TestVerrazzanoVerrazzanoResourceBeingDeleted tests the Reconcile method for the following use cases 384 // GIVEN a request to reconcile 385 // WHEN the verrazzano resource is marked for deletion 386 // THEN the secrets reconciler returns a result of ctrl.Result{} 387 func TestVerrazzanoVerrazzanoResourceBeingDeleted(t *testing.T) { 388 asserts := assert.New(t) 389 mocker := gomock.NewController(t) 390 mock := mocks.NewMockClient(mocker) 391 392 // Expect a call to get a list of verrazzano resources 393 mock.EXPECT(). 394 List(gomock.Any(), gomock.Any(), gomock.Any()). 395 DoAndReturn(func(ctx context.Context, vzList *vzapi.VerrazzanoList, opts ...client.ListOption) error { 396 vzList.Items = []vzapi.Verrazzano{{ 397 ObjectMeta: metav1.ObjectMeta{ 398 Namespace: constants.DefaultNamespace, 399 Name: "verrazzano", 400 DeletionTimestamp: &metav1.Time{Time: time.Now()}, 401 }, 402 }} 403 return nil 404 }) 405 406 // Create and make the request 407 request := newRequest(vzTLSSecret.Namespace, vzTLSSecret.Name) 408 reconciler := newSecretsReconciler(mock) 409 result, err := reconciler.Reconcile(context.TODO(), request) 410 411 // Validate the results 412 mocker.Finish() 413 asserts.NoError(err) 414 asserts.NotNil(result) 415 asserts.Equal(ctrl.Result{}, result) 416 } 417 418 // TestDeletion tests the Reconcile loop for the following use case 419 // GIVEN a request to reconcile a Secret that qualifies as an override 420 // WHEN we find that it is scheduled for deletion and contains overrides finalizer 421 // THEN the override finalizer is removed from the Secret and Verrazzano CR is updated and request is returned without an error 422 func TestDeletion(t *testing.T) { 423 asserts := assert.New(t) 424 secret := testSecret 425 secret.Finalizers = append(secret.Finalizers, constants.OverridesFinalizer) 426 secret.DeletionTimestamp = &metav1.Time{Time: time.Now()} 427 cli := fake.NewClientBuilder().WithObjects(&testVZ, &secret).WithScheme(newScheme()).Build() 428 429 config.TestProfilesDir = "../../manifests/profiles" 430 defer func() { config.TestProfilesDir = "" }() 431 432 request0 := newRequest(testNS, testSecretName) 433 reconciler := newSecretsReconciler(cli) 434 res0, err0 := reconciler.Reconcile(context.TODO(), request0) 435 436 asserts.NoError(err0) 437 asserts.Equal(false, res0.Requeue) 438 439 sec1 := &corev1.Secret{} 440 err1 := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testSecretName}, sec1) 441 asserts.True(errors.IsNotFound(err1)) 442 443 vz := &vzapi.Verrazzano{} 444 err2 := cli.Get(context.TODO(), types.NamespacedName{Namespace: testNS, Name: testVZName}, vz) 445 asserts.NoError(err2) 446 asserts.Equal(int64(1), vz.Status.Components["prometheus-operator"].ReconcilingGeneration) 447 } 448 449 // TestSecretCall tests the reconcileInstallOverrideSecret for the following use case 450 // GIVEN a request to reconcile a Secret 451 // WHEN the request namespace matches the Verrazzano CR namespace 452 // THEN expect a call to get the Secret 453 func TestSecretCall(t *testing.T) { 454 asserts := assert.New(t) 455 mocker := gomock.NewController(t) 456 mock := mocks.NewMockClient(mocker) 457 mockStatus := mocks.NewMockStatusWriter(mocker) 458 asserts.NotNil(mockStatus) 459 460 config.TestProfilesDir = "../../manifests/profiles" 461 defer func() { config.TestProfilesDir = "" }() 462 463 expectGetSecretExists(mock, testNS, testSecretName) 464 465 request := newRequest(testNS, testSecretName) 466 reconciler := newSecretsReconciler(mock) 467 result, err := reconciler.reconcileInstallOverrideSecret(context.TODO(), request, &testVZ) 468 asserts.NoError(err) 469 mocker.Finish() 470 asserts.Equal(false, result.Requeue) 471 asserts.Equal(time.Duration(0), result.RequeueAfter) 472 } 473 474 // TestOtherNS tests the reconcileInstallOverrideSecret for the following use case 475 // GIVEN a request to reconcile a Secret 476 // WHEN the request namespace does not match with the CR namespace 477 // THEN the request is ignored 478 func TestOtherNS(t *testing.T) { 479 asserts := assert.New(t) 480 mocker := gomock.NewController(t) 481 mock := mocks.NewMockClient(mocker) 482 mockStatus := mocks.NewMockStatusWriter(mocker) 483 asserts.NotNil(mockStatus) 484 485 // Do not expect a call to get the Secret if it's a different namespace 486 mock.EXPECT(). 487 Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).MaxTimes(0) 488 489 request := newRequest("test0", "test1") 490 reconciler := newSecretsReconciler(mock) 491 result, err := reconciler.reconcileInstallOverrideSecret(context.TODO(), request, &testVZ) 492 asserts.NoError(err) 493 mocker.Finish() 494 asserts.Equal(false, result.Requeue) 495 asserts.Equal(time.Duration(0), result.RequeueAfter) 496 497 } 498 499 // mock client request to get the secret 500 func expectGetSecretExists(mock *mocks.MockClient, namespace string, name string) { 501 mock.EXPECT(). 502 Get(gomock.Any(), types.NamespacedName{Namespace: namespace, Name: name}, gomock.Not(gomock.Nil()), gomock.Any()). 503 DoAndReturn(func(ctx context.Context, name types.NamespacedName, secret *corev1.Secret, opts ...client.GetOption) error { 504 return nil 505 }) 506 } 507 508 func expectNothingForWrongSecret(mock *mocks.MockClient) { 509 510 mock.EXPECT(). 511 List(gomock.Any(), &vzapi.VerrazzanoList{}, gomock.Any()). 512 DoAndReturn(func(ctx context.Context, verrazzanoList *vzapi.VerrazzanoList, options ...client.ListOption) error { 513 return nil 514 }) 515 516 // Expect no calls to get a secret 517 mock.EXPECT(). 518 Get(gomock.Any(), gomock.Any(), gomock.Not(gomock.Nil()), gomock.Any()).MaxTimes(0) 519 520 // Expect no calls to get update 521 mock.EXPECT(). 522 Update(gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(0) 523 } 524 525 // newScheme creates a new scheme that includes this package's object to use for testing 526 func newScheme() *runtime.Scheme { 527 scheme := runtime.NewScheme() 528 _ = corev1.AddToScheme(scheme) 529 _ = vzapi.AddToScheme(scheme) 530 _ = appsv1.AddToScheme(scheme) 531 _ = certv1.AddToScheme(scheme) 532 return scheme 533 } 534 535 // newRequest creates a new reconciler request for testing 536 // namespace - The namespace to use in the request 537 // name - The name to use in the request 538 func newRequest(namespace string, name string) ctrl.Request { 539 return ctrl.Request{ 540 NamespacedName: types.NamespacedName{ 541 Namespace: namespace, 542 Name: name}} 543 } 544 545 // newSecretsReconciler creates a new reconciler for testing 546 // c - The Kerberos client to inject into the reconciler 547 func newSecretsReconciler(c client.Client) VerrazzanoSecretsReconciler { 548 scheme := newScheme() 549 reconciler := VerrazzanoSecretsReconciler{ 550 Client: c, 551 Scheme: scheme, 552 log: vzlog.DefaultLogger(), 553 StatusUpdater: &vzstatus.FakeVerrazzanoStatusUpdater{Client: c}, 554 } 555 return reconciler 556 } 557 558 // newVZ - create a Verrazzano custom resource 559 func newVZ() *vzapi.Verrazzano { 560 return &vzapi.Verrazzano{ 561 ObjectMeta: metav1.ObjectMeta{ 562 Name: "verrazzano", 563 }, 564 Spec: vzapi.VerrazzanoSpec{ 565 Components: vzapi.ComponentSpec{ 566 ClusterIssuer: &vzapi.ClusterIssuerComponent{ 567 IssuerConfig: vzapi.IssuerConfig{ 568 CA: &vzapi.CAIssuer{ 569 SecretName: constants2.DefaultVerrazzanoCASecretName, 570 }, 571 }, 572 ClusterResourceNamespace: constants2.CertManagerNamespace, 573 }, 574 }, 575 }, 576 } 577 } 578 579 // newCertificateWithSecret - Create a new certificate and secret that is optionally signed by a parent 580 func newCertificateWithSecret(issuerName string, commonName string, certName string, certNamespace string, parent *x509.Certificate) (*corev1.Secret, *certv1.Certificate, error) { 581 fakeIssuerCertBytes, err := cmcommonfake.CreateFakeCertBytes(commonName, parent) 582 if err != nil { 583 return nil, nil, err 584 } 585 secret := newCertSecret(fmt.Sprintf("%s-secret", certName), certNamespace, corev1.TLSCertKey, fakeIssuerCertBytes) 586 certificate := &certv1.Certificate{ 587 ObjectMeta: metav1.ObjectMeta{ 588 Name: certName, 589 Namespace: certNamespace, 590 }, 591 Spec: certv1.CertificateSpec{ 592 CommonName: commonName, 593 IsCA: true, 594 IssuerRef: cmmeta.ObjectReference{ 595 Name: issuerName, 596 }, 597 SecretName: secret.Name, 598 }, 599 } 600 601 return secret, certificate, nil 602 } 603 604 func newCertSecret(name string, namespace string, certKey string, certBytes []byte) *corev1.Secret { 605 return &corev1.Secret{ 606 TypeMeta: metav1.TypeMeta{}, 607 ObjectMeta: metav1.ObjectMeta{ 608 Name: name, 609 Namespace: namespace, 610 }, 611 Data: map[string][]byte{ 612 certKey: certBytes, 613 }, 614 Type: corev1.SecretTypeTLS, 615 } 616 }