github.com/verrazzano/verrazzano@v1.7.0/cluster-operator/controllers/vmc/argocd_test.go (about) 1 // Copyright (c) 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 vmc 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "io" 10 "net/http" 11 "os" 12 "testing" 13 "time" 14 15 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 16 "k8s.io/apimachinery/pkg/runtime" 17 "k8s.io/apimachinery/pkg/runtime/schema" 18 19 "github.com/Jeffail/gabs/v2" 20 "github.com/golang/mock/gomock" 21 "github.com/stretchr/testify/assert" 22 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1" 23 "github.com/verrazzano/verrazzano/pkg/constants" 24 "github.com/verrazzano/verrazzano/pkg/log/vzlog" 25 "github.com/verrazzano/verrazzano/pkg/rancherutil" 26 "github.com/verrazzano/verrazzano/pkg/test/mockmatchers" 27 "github.com/verrazzano/verrazzano/platform-operator/mocks" 28 corev1 "k8s.io/api/core/v1" 29 networkv1 "k8s.io/api/networking/v1" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/apimachinery/pkg/util/wait" 32 "sigs.k8s.io/controller-runtime/pkg/client" 33 "sigs.k8s.io/controller-runtime/pkg/client/fake" 34 ) 35 36 const ( 37 tokensPath = "/v3/tokens" 38 clusterID = "cluster-id" 39 rancherURL = "https://rancher-url" 40 ) 41 42 // TestMutateArgoCDClusterSecretWithoutRefresh tests no POST call to obtain new token when we are within 3/4 lifespan of the token 43 // GIVEN a call to mutateArgCDClusterSecret 44 // 45 // WHEN the secret annotation createTimestamp/expiresAtTimestamp is x(s) and x+4(s) respectively 46 // and mutateArgoCDClusterSecret is called immediately 47 // THEN we skip obtaining new token 48 func TestMutateArgoCDClusterSecretWithoutRefresh(t *testing.T) { 49 // clear any cached user auth tokens when the test completes 50 defer rancherutil.DeleteStoredTokens() 51 52 cli := generateClientObject() 53 log := vzlog.DefaultLogger() 54 55 savedRancherHTTPClient := rancherutil.RancherHTTPClient 56 defer func() { 57 rancherutil.RancherHTTPClient = savedRancherHTTPClient 58 }() 59 60 savedRetry := rancherutil.DefaultRetry 61 defer func() { 62 rancherutil.DefaultRetry = savedRetry 63 }() 64 rancherutil.DefaultRetry = wait.Backoff{ 65 Steps: 1, 66 Duration: 1 * time.Millisecond, 67 Factor: 1.0, 68 Jitter: 0.1, 69 } 70 71 vmc := &v1alpha1.VerrazzanoManagedCluster{ 72 ObjectMeta: metav1.ObjectMeta{ 73 Namespace: constants.VerrazzanoMultiClusterNamespace, 74 Name: "cluster", 75 }, 76 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 77 RancherRegistration: v1alpha1.RancherRegistration{ 78 ClusterID: clusterID, 79 }, 80 }, 81 } 82 r := &VerrazzanoManagedClusterReconciler{ 83 Client: cli, 84 log: vzlog.DefaultLogger(), 85 } 86 secret := &corev1.Secret{ 87 ObjectMeta: metav1.ObjectMeta{ 88 Name: "demo" + "-" + clusterSecretName, 89 Namespace: constants.ArgoCDNamespace, 90 Annotations: map[string]string{createTimestamp: time.Now().Format(time.RFC3339), expiresAtTimestamp: time.Now().Add(10 * time.Hour).Format(time.RFC3339)}, 91 }, 92 Data: map[string][]byte{ 93 "password": []byte("foobar"), 94 }, 95 } 96 97 mocker := gomock.NewController(t) 98 httpMock := mocks.NewMockRequestSender(mocker) 99 // Expect an HTTP request to fetch the token from Rancher only 100 expectHTTPLoginRequests(httpMock) 101 rancherutil.RancherHTTPClient = httpMock 102 103 caData := []byte("ca") 104 105 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 106 assert.NoError(t, err) 107 108 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 109 assert.NoError(t, err) 110 111 var rancherConfig ArgoCDRancherConfig 112 err = json.Unmarshal([]byte(secret.StringData["config"]), &rancherConfig) 113 if err != nil { 114 assert.Equal(t, &rancherConfig.BearerToken, "unit-test-token") 115 } 116 } 117 118 // TestMutateArgoCDClusterSecretWithRefresh tests POST/GET calls to obtain new token and attrs when we breach 3/4 lifespan of the token 119 // GIVEN a call to mutateArgoCDClusterSecret 120 // 121 // WHEN the secret annotation createTimestamp/expiresAtTimestamp is x(s) and x+4(s) respectively 122 // and we sleep for 4(s) 123 // THEN we obtain new token and the annotation createTimestamp/expiresAtTimestamp are updated accordingly 124 func TestMutateArgoCDClusterSecretWithRefresh(t *testing.T) { 125 // clear any cached user auth tokens when the test completes 126 defer rancherutil.DeleteStoredTokens() 127 128 cli := generateClientObject() 129 log := vzlog.DefaultLogger() 130 131 savedRancherHTTPClient := rancherutil.RancherHTTPClient 132 defer func() { 133 rancherutil.RancherHTTPClient = savedRancherHTTPClient 134 }() 135 136 savedRetry := rancherutil.DefaultRetry 137 defer func() { 138 rancherutil.DefaultRetry = savedRetry 139 }() 140 rancherutil.DefaultRetry = wait.Backoff{ 141 Steps: 1, 142 Duration: 1 * time.Millisecond, 143 Factor: 1.0, 144 Jitter: 0.1, 145 } 146 147 vmc := &v1alpha1.VerrazzanoManagedCluster{ 148 ObjectMeta: metav1.ObjectMeta{ 149 Namespace: constants.VerrazzanoMultiClusterNamespace, 150 Name: "cluster", 151 }, 152 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 153 RancherRegistration: v1alpha1.RancherRegistration{ 154 ClusterID: clusterID, 155 }, 156 }, 157 } 158 r := &VerrazzanoManagedClusterReconciler{ 159 Client: cli, 160 log: vzlog.DefaultLogger(), 161 } 162 163 secret := &corev1.Secret{ 164 ObjectMeta: metav1.ObjectMeta{ 165 Name: "demo" + "-" + clusterSecretName, 166 Namespace: constants.ArgoCDNamespace, 167 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339), expiresAtTimestamp: time.Now().Format(time.RFC3339)}, 168 }, 169 Data: map[string][]byte{ 170 "password": []byte("foobar"), 171 }, 172 } 173 174 mocker := gomock.NewController(t) 175 httpMock := mocks.NewMockRequestSender(mocker) 176 httpMock = expectHTTPRequests(httpMock) 177 rancherutil.RancherHTTPClient = httpMock 178 179 caData := []byte("ca") 180 181 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 182 assert.NoError(t, err) 183 184 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 185 assert.NoError(t, err) 186 } 187 188 // TestMutateArgoCDClusterSecretNoTokenMatch tests a call to the reconciler when a token has a create timestamp annotation, but not an expired annotation and assures that a new token is created 189 // Given a call to TestMutateArgoCDClusterSecretNoTokenMatch 190 // When a secret annotation has a create timestamp annotation and not an existing timestamp annotation 191 // Then a new token is created without any error 192 func TestMutateArgoCDClusterSecretNoTokenMatch(t *testing.T) { 193 // clear any cached user auth tokens when the test completes 194 defer rancherutil.DeleteStoredTokens() 195 196 cli := generateClientObject() 197 log := vzlog.DefaultLogger() 198 199 savedRancherHTTPClient := rancherutil.RancherHTTPClient 200 defer func() { 201 rancherutil.RancherHTTPClient = savedRancherHTTPClient 202 }() 203 204 savedRetry := rancherutil.DefaultRetry 205 defer func() { 206 rancherutil.DefaultRetry = savedRetry 207 }() 208 rancherutil.DefaultRetry = wait.Backoff{ 209 Steps: 1, 210 Duration: 1 * time.Millisecond, 211 Factor: 1.0, 212 Jitter: 0.1, 213 } 214 215 loginURIPath := loginURLParts[0] 216 testBodyForTokens, _ := os.Open("testdata/bodyfortokentest.json") 217 arrayBytes, _ := io.ReadAll(testBodyForTokens) 218 clusterIDForTest := "clusteridfortest" 219 220 mocker := gomock.NewController(t) 221 httpMock := mocks.NewMockRequestSender(mocker) 222 httpMock.EXPECT(). 223 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(loginURIPath)). 224 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 225 r := io.NopCloser(bytes.NewReader([]byte(`{"token":"unit-test-token"}`))) 226 resp := &http.Response{ 227 StatusCode: http.StatusCreated, 228 Body: r, 229 Request: &http.Request{Method: http.MethodPost}, 230 } 231 return resp, nil 232 }).Times(1) 233 234 // This is the request to get tokens for the cluster and the user 235 httpMock.EXPECT(). 236 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURIMethod(http.MethodGet, tokensPath)). 237 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 238 var resp *http.Response 239 r := io.NopCloser(bytes.NewReader([]byte(arrayBytes))) 240 resp = &http.Response{ 241 StatusCode: http.StatusOK, 242 Body: r, 243 } 244 return resp, nil 245 }).Times(1) 246 // This is the request to create a new token 247 httpMock.EXPECT(). 248 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURIMethod(http.MethodPost, tokensPath)). 249 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 250 body, err := io.ReadAll(req.Body) 251 assert.NoError(t, err) 252 jsonString, err := gabs.ParseJSON(body) 253 assert.NoError(t, err) 254 _, ok := jsonString.Path("clusterID").Data().(string) 255 assert.True(t, ok) 256 _, ok = jsonString.Path("ttl").Data().(float64) 257 assert.True(t, ok) 258 var resp *http.Response 259 r := io.NopCloser(bytes.NewReader([]byte(`{"token":"testoken", "Created": "2023-08-13T15:32:38Z"}`))) 260 resp = &http.Response{ 261 StatusCode: http.StatusCreated, 262 Body: r, 263 } 264 return resp, nil 265 }).Times(1) 266 267 vmc := &v1alpha1.VerrazzanoManagedCluster{ 268 ObjectMeta: metav1.ObjectMeta{ 269 Namespace: constants.VerrazzanoMultiClusterNamespace, 270 Name: "cluster", 271 }, 272 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 273 RancherRegistration: v1alpha1.RancherRegistration{ 274 ClusterID: clusterID, 275 }, 276 }, 277 } 278 r := &VerrazzanoManagedClusterReconciler{ 279 Client: cli, 280 log: vzlog.DefaultLogger(), 281 } 282 283 secret := &corev1.Secret{ 284 ObjectMeta: metav1.ObjectMeta{ 285 Name: "demo" + "-" + clusterSecretName, 286 Namespace: constants.ArgoCDNamespace, 287 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339)}, 288 }, 289 Data: map[string][]byte{ 290 "password": []byte("foobar"), 291 }, 292 } 293 rancherutil.RancherHTTPClient = httpMock 294 295 caData := []byte("ca") 296 297 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 298 assert.NoError(t, err) 299 initalTimestamp := secret.Annotations[createTimestamp] 300 301 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterIDForTest, rancherURL, caData) 302 newTimestamp := secret.Annotations[createTimestamp] 303 assert.NoError(t, err) 304 assert.NotEqual(t, newTimestamp, initalTimestamp) 305 assert.Empty(t, secret.Annotations[expiresAtTimestamp]) 306 } 307 308 func expectHTTPLoginRequests(httpMock *mocks.MockRequestSender) *mocks.MockRequestSender { 309 httpMock.EXPECT(). 310 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(loginURIPath)). 311 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 312 r := io.NopCloser(bytes.NewReader([]byte(`{"token":"unit-test-token"}`))) 313 resp := &http.Response{ 314 StatusCode: http.StatusCreated, 315 Body: r, 316 Request: &http.Request{Method: http.MethodPost}, 317 } 318 return resp, nil 319 }) 320 return httpMock 321 } 322 323 func expectHTTPClusterRoleTemplateUpdateRequests(httpMock *mocks.MockRequestSender) *mocks.MockRequestSender { 324 httpMock.EXPECT(). 325 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURIMethod(http.MethodPost, clusterroletemplatebindingsPath)). 326 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 327 r := io.NopCloser(bytes.NewReader([]byte(`{}`))) 328 resp := &http.Response{ 329 StatusCode: http.StatusCreated, 330 Body: r, 331 Request: &http.Request{Method: http.MethodPost}, 332 } 333 return resp, nil 334 }) 335 httpMock.EXPECT(). 336 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURIMethod(http.MethodGet, clusterroletemplatebindingsPath)). 337 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 338 r := io.NopCloser(bytes.NewReader([]byte(`{"data":[]}`))) 339 resp := &http.Response{ 340 StatusCode: http.StatusOK, 341 Body: r, 342 Request: &http.Request{Method: http.MethodGet}, 343 } 344 return resp, nil 345 }) 346 return httpMock 347 } 348 349 func expectHTTPRequests(httpMock *mocks.MockRequestSender) *mocks.MockRequestSender { 350 // Expect an HTTP request to obtain a new token 351 httpMock.EXPECT(). 352 Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(tokensPath)). 353 DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) { 354 var resp *http.Response 355 r := io.NopCloser(bytes.NewReader([]byte(`{"token": "xxx", "name": "testToken"}`))) 356 resp = &http.Response{ 357 StatusCode: http.StatusCreated, 358 Body: r, 359 Request: &http.Request{Method: http.MethodPost}, 360 } 361 return resp, nil 362 }) 363 364 // Expect an HTTP request to fetch the token from Rancher 365 expectHTTPLoginRequests(httpMock) 366 return httpMock 367 } 368 369 func generateClientObject(objs ...runtime.Object) client.WithWatch { 370 user := unstructured.Unstructured{} 371 user.SetUnstructuredContent(map[string]interface{}{UserUsernameAttribute: constants.ArgoCDClusterRancherUsername}) 372 user.SetGroupVersionKind(schema.GroupVersionKind{ 373 Group: APIGroupRancherManagement, 374 Version: APIGroupVersionRancherManagement, 375 Kind: UserKind, 376 }) 377 378 totalObjects := []runtime.Object{ 379 &corev1.Secret{ 380 ObjectMeta: metav1.ObjectMeta{ 381 Name: constants.ArgoCDClusterRancherSecretName, 382 Namespace: constants.VerrazzanoMultiClusterNamespace, 383 }, 384 Data: map[string][]byte{ 385 "password": []byte("foobar"), 386 }, 387 }, 388 &corev1.Secret{ 389 ObjectMeta: metav1.ObjectMeta{ 390 Namespace: "cattle-system", 391 Name: "rancher-admin-secret", 392 }, 393 Data: map[string][]byte{ 394 "password": []byte(""), 395 }, 396 }, 397 &networkv1.Ingress{ 398 ObjectMeta: metav1.ObjectMeta{ 399 Namespace: rancherNamespace, 400 Name: rancherIngressName, 401 }, 402 Spec: networkv1.IngressSpec{ 403 Rules: []networkv1.IngressRule{ 404 { 405 Host: "test-rancher.com", 406 }, 407 }, 408 }, 409 }, 410 user.DeepCopyObject(), 411 } 412 totalObjects = append(totalObjects, objs...) 413 return fake.NewClientBuilder().WithRuntimeObjects(totalObjects...).Build() 414 } 415 416 // TestUpdateArgoCDClusterRoleBindingTemplate tests the update of cluster role for 'vz-argocd-reg' user 417 // GIVEN a call to update argocd cluster role binding 418 // 419 // THEN the template binding is created/updated via API with no error 420 func TestUpdateArgoCDClusterRoleBindingTemplate(t *testing.T) { 421 a := assert.New(t) 422 savedRancherHTTPClient := rancherutil.RancherHTTPClient 423 defer func() { 424 rancherutil.RancherHTTPClient = savedRancherHTTPClient 425 }() 426 427 savedRetry := rancherutil.DefaultRetry 428 defer func() { 429 rancherutil.DefaultRetry = savedRetry 430 }() 431 rancherutil.DefaultRetry = wait.Backoff{ 432 Steps: 1, 433 Duration: 1 * time.Millisecond, 434 Factor: 1.0, 435 Jitter: 0.1, 436 } 437 438 mocker := gomock.NewController(t) 439 httpMock := mocks.NewMockRequestSender(mocker) 440 httpMock = expectHTTPLoginRequests(httpMock) 441 httpMock = expectHTTPClusterRoleTemplateUpdateRequests(httpMock) 442 rancherutil.RancherHTTPClient = httpMock 443 444 vmcID := &v1alpha1.VerrazzanoManagedCluster{} 445 446 clusterID := "testID" 447 vmcID.Status.RancherRegistration.ClusterID = clusterID 448 449 clusterUserData := &unstructured.Unstructured{} 450 clusterUserData.SetGroupVersionKind(schema.GroupVersionKind{ 451 Group: APIGroupRancherManagement, 452 Version: APIGroupVersionRancherManagement, 453 Kind: UserKind, 454 }) 455 clusterUserData.SetName(constants.ArgoCDClusterRancherUsername) 456 data := clusterUserData.UnstructuredContent() 457 data[UserUsernameAttribute] = constants.ArgoCDClusterRancherUsername 458 459 tests := []struct { 460 name string 461 vmc *v1alpha1.VerrazzanoManagedCluster 462 user *unstructured.Unstructured 463 }{ 464 { 465 name: "test vmc with cluster id", 466 vmc: vmcID, 467 user: clusterUserData, 468 }, 469 } 470 for _, tt := range tests { 471 t.Run(tt.name, func(t *testing.T) { 472 cli := generateClientObject(clusterUserData) 473 474 r := &VerrazzanoManagedClusterReconciler{ 475 Client: cli, 476 log: vzlog.DefaultLogger(), 477 } 478 rc, err := rancherutil.NewAdminRancherConfig(cli, rancherutil.RancherIngressServiceHost(), vzlog.DefaultLogger()) 479 assert.NoError(t, err) 480 481 err = r.updateArgoCDClusterRoleBindingTemplate(rc, tt.vmc) 482 a.NoError(err) 483 }) 484 } 485 } 486 487 // TestMutateArgoCDSecretThatExistingLabelDoesNotGetRemovedandClusterSecretLabelIsAdded tests the update of the ArgoCD Cluster Secret for a user when an existing label is present, but the cluster label is not present 488 // GIVEN a call to update the ArgoCD Cluster Secret when the secret has a user provided label, but does not have the ArgoCD provided cluster label 489 // 490 // THEN the ArgoCD cluster secret is created/updated via API with no error and the existing label remains, but the ArgoCD cluster label is added 491 func TestMutateArgoCDClusterSecretThatExistingLabelDoesNotGetRemovedandClusterSecretLabelIsAdded(t *testing.T) { 492 // clear any cached user auth tokens when the test completes 493 defer rancherutil.DeleteStoredTokens() 494 495 cli := generateClientObject() 496 log := vzlog.DefaultLogger() 497 498 savedRancherHTTPClient := rancherutil.RancherHTTPClient 499 defer func() { 500 rancherutil.RancherHTTPClient = savedRancherHTTPClient 501 }() 502 503 savedRetry := rancherutil.DefaultRetry 504 defer func() { 505 rancherutil.DefaultRetry = savedRetry 506 }() 507 rancherutil.DefaultRetry = wait.Backoff{ 508 Steps: 1, 509 Duration: 1 * time.Millisecond, 510 Factor: 1.0, 511 Jitter: 0.1, 512 } 513 514 vmc := &v1alpha1.VerrazzanoManagedCluster{ 515 ObjectMeta: metav1.ObjectMeta{ 516 Namespace: constants.VerrazzanoMultiClusterNamespace, 517 Name: "cluster", 518 }, 519 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 520 RancherRegistration: v1alpha1.RancherRegistration{ 521 ClusterID: clusterID, 522 }, 523 }, 524 } 525 r := &VerrazzanoManagedClusterReconciler{ 526 Client: cli, 527 log: vzlog.DefaultLogger(), 528 } 529 530 secret := &corev1.Secret{ 531 ObjectMeta: metav1.ObjectMeta{ 532 Name: "demo" + "-" + clusterSecretName, 533 Namespace: constants.ArgoCDNamespace, 534 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339), expiresAtTimestamp: time.Now().Format(time.RFC3339)}, 535 Labels: map[string]string{"testlabel": "shouldnotbedeleted"}, 536 }, 537 Data: map[string][]byte{ 538 "password": []byte("foobar"), 539 }, 540 } 541 542 mocker := gomock.NewController(t) 543 httpMock := mocks.NewMockRequestSender(mocker) 544 httpMock = expectHTTPRequests(httpMock) 545 rancherutil.RancherHTTPClient = httpMock 546 547 caData := []byte("ca") 548 549 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 550 assert.NoError(t, err) 551 552 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 553 assert.NoError(t, err) 554 assert.Equal(t, secret.Labels, map[string]string{"testlabel": "shouldnotbedeleted", "argocd.argoproj.io/secret-type": "cluster"}) 555 } 556 557 // TestMutateArgoCDClusterSecretThatClusterSecretLabelIsAdded tests the update of the ArgoCD Cluster Secret for a user when there are no labels present in the cluster secret 558 // GIVEN a call to update the ArgoCD Cluster Secret when the secret does not have the ArgoCD provided cluster label/a label at all 559 // 560 // THEN the ArgoCD cluster secret is created/updated via API with no error and the ArgoCD cluster label is added 561 func TestMutateArgoCDClusterSecretThatClusterSecretLabelIsAdded(t *testing.T) { 562 // clear any cached user auth tokens when the test completes 563 defer rancherutil.DeleteStoredTokens() 564 565 cli := generateClientObject() 566 log := vzlog.DefaultLogger() 567 568 savedRancherHTTPClient := rancherutil.RancherHTTPClient 569 defer func() { 570 rancherutil.RancherHTTPClient = savedRancherHTTPClient 571 }() 572 573 savedRetry := rancherutil.DefaultRetry 574 defer func() { 575 rancherutil.DefaultRetry = savedRetry 576 }() 577 rancherutil.DefaultRetry = wait.Backoff{ 578 Steps: 1, 579 Duration: 1 * time.Millisecond, 580 Factor: 1.0, 581 Jitter: 0.1, 582 } 583 584 vmc := &v1alpha1.VerrazzanoManagedCluster{ 585 ObjectMeta: metav1.ObjectMeta{ 586 Namespace: constants.VerrazzanoMultiClusterNamespace, 587 Name: "cluster", 588 }, 589 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 590 RancherRegistration: v1alpha1.RancherRegistration{ 591 ClusterID: clusterID, 592 }, 593 }, 594 } 595 r := &VerrazzanoManagedClusterReconciler{ 596 Client: cli, 597 log: vzlog.DefaultLogger(), 598 } 599 600 secret := &corev1.Secret{ 601 ObjectMeta: metav1.ObjectMeta{ 602 Name: "demo" + "-" + clusterSecretName, 603 Namespace: constants.ArgoCDNamespace, 604 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339), expiresAtTimestamp: time.Now().Format(time.RFC3339)}, 605 }, 606 Data: map[string][]byte{ 607 "password": []byte("foobar"), 608 }, 609 } 610 611 mocker := gomock.NewController(t) 612 httpMock := mocks.NewMockRequestSender(mocker) 613 httpMock = expectHTTPRequests(httpMock) 614 rancherutil.RancherHTTPClient = httpMock 615 616 caData := []byte("ca") 617 618 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 619 assert.NoError(t, err) 620 621 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 622 assert.NoError(t, err) 623 assert.Equal(t, secret.Labels, map[string]string{"argocd.argoproj.io/secret-type": "cluster"}) 624 } 625 626 // TestMutateArgoCDClusterSecretThatExistingLabelRemainsAndClusterSecretLabelRemains tests the update of the ArgoCD Cluster Secret for a user when there is the user-provided labels and the ArgoCD cluster label 627 // GIVEN a call to update the ArgoCD Cluster Secret when the secret has both a user-provided label and an ArgoCD Cluster label 628 // 629 // THEN the ArgoCD cluster secret is created/updated via API with no error and both labels should remain 630 func TestMutateArgoCDClusterSecretThatExistingLabelRemainsAndClusterSecretLabelRemains(t *testing.T) { 631 // clear any cached user auth tokens when the test completes 632 defer rancherutil.DeleteStoredTokens() 633 634 cli := generateClientObject() 635 log := vzlog.DefaultLogger() 636 637 savedRancherHTTPClient := rancherutil.RancherHTTPClient 638 defer func() { 639 rancherutil.RancherHTTPClient = savedRancherHTTPClient 640 }() 641 642 savedRetry := rancherutil.DefaultRetry 643 defer func() { 644 rancherutil.DefaultRetry = savedRetry 645 }() 646 rancherutil.DefaultRetry = wait.Backoff{ 647 Steps: 1, 648 Duration: 1 * time.Millisecond, 649 Factor: 1.0, 650 Jitter: 0.1, 651 } 652 653 vmc := &v1alpha1.VerrazzanoManagedCluster{ 654 ObjectMeta: metav1.ObjectMeta{ 655 Namespace: constants.VerrazzanoMultiClusterNamespace, 656 Name: "cluster", 657 }, 658 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 659 RancherRegistration: v1alpha1.RancherRegistration{ 660 ClusterID: clusterID, 661 }, 662 }, 663 } 664 r := &VerrazzanoManagedClusterReconciler{ 665 Client: cli, 666 log: vzlog.DefaultLogger(), 667 } 668 669 secret := &corev1.Secret{ 670 ObjectMeta: metav1.ObjectMeta{ 671 Name: "demo" + "-" + clusterSecretName, 672 Namespace: constants.ArgoCDNamespace, 673 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339), expiresAtTimestamp: time.Now().Format(time.RFC3339)}, 674 Labels: map[string]string{"testlabel": "shouldnotbedeleted", "argocd.argoproj.io/secret-type": "cluster"}, 675 }, 676 Data: map[string][]byte{ 677 "password": []byte("foobar"), 678 }, 679 } 680 681 mocker := gomock.NewController(t) 682 httpMock := mocks.NewMockRequestSender(mocker) 683 httpMock = expectHTTPRequests(httpMock) 684 rancherutil.RancherHTTPClient = httpMock 685 686 caData := []byte("ca") 687 688 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 689 assert.NoError(t, err) 690 691 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 692 assert.NoError(t, err) 693 assert.Equal(t, secret.Labels, map[string]string{"testlabel": "shouldnotbedeleted", "argocd.argoproj.io/secret-type": "cluster"}) 694 } 695 696 // TestMutateArgoCDClusterSecretThatClusterSecretLabelRemains tests the update of the ArgoCD Cluster Secret for a user when there is the ArgoCD cluster label 697 // GIVEN a call to update the ArgoCD Cluster Secret when the secret has an ArgoCD Cluster label 698 // 699 // THEN the ArgoCD cluster secret is created/updated via API with no error and the ArgoCD Cluster label should remain 700 func TestMutateArgoCDClusterSecretThatClusterSecretLabelRemains(t *testing.T) { 701 // clear any cached user auth tokens when the test completes 702 defer rancherutil.DeleteStoredTokens() 703 704 cli := generateClientObject() 705 log := vzlog.DefaultLogger() 706 707 savedRancherHTTPClient := rancherutil.RancherHTTPClient 708 defer func() { 709 rancherutil.RancherHTTPClient = savedRancherHTTPClient 710 }() 711 712 savedRetry := rancherutil.DefaultRetry 713 defer func() { 714 rancherutil.DefaultRetry = savedRetry 715 }() 716 rancherutil.DefaultRetry = wait.Backoff{ 717 Steps: 1, 718 Duration: 1 * time.Millisecond, 719 Factor: 1.0, 720 Jitter: 0.1, 721 } 722 723 vmc := &v1alpha1.VerrazzanoManagedCluster{ 724 ObjectMeta: metav1.ObjectMeta{ 725 Namespace: constants.VerrazzanoMultiClusterNamespace, 726 Name: "cluster", 727 }, 728 Status: v1alpha1.VerrazzanoManagedClusterStatus{ 729 RancherRegistration: v1alpha1.RancherRegistration{ 730 ClusterID: clusterID, 731 }, 732 }, 733 } 734 r := &VerrazzanoManagedClusterReconciler{ 735 Client: cli, 736 log: vzlog.DefaultLogger(), 737 } 738 739 secret := &corev1.Secret{ 740 ObjectMeta: metav1.ObjectMeta{ 741 Name: "demo" + "-" + clusterSecretName, 742 Namespace: constants.ArgoCDNamespace, 743 Annotations: map[string]string{createTimestamp: time.Now().Add(-10 * time.Hour).Format(time.RFC3339), expiresAtTimestamp: time.Now().Format(time.RFC3339)}, 744 Labels: map[string]string{"argocd.argoproj.io/secret-type": "cluster"}, 745 }, 746 Data: map[string][]byte{ 747 "password": []byte("foobar"), 748 }, 749 } 750 751 mocker := gomock.NewController(t) 752 httpMock := mocks.NewMockRequestSender(mocker) 753 httpMock = expectHTTPRequests(httpMock) 754 rancherutil.RancherHTTPClient = httpMock 755 756 caData := []byte("ca") 757 758 rc, err := rancherutil.NewRancherConfigForUser(cli, constants.ArgoCDClusterRancherUsername, "foobar", rancherutil.RancherIngressServiceHost(), log) 759 assert.NoError(t, err) 760 761 err = r.mutateArgoCDClusterSecret(secret, rc, vmc.Name, clusterID, rancherURL, caData) 762 assert.NoError(t, err) 763 assert.Equal(t, secret.Labels, map[string]string{"argocd.argoproj.io/secret-type": "cluster"}) 764 }