sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/client/cluster/cert_manager_test.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cluster 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 "time" 24 25 . "github.com/onsi/gomega" 26 admissionregistration "k8s.io/api/admissionregistration/v1" 27 appsv1 "k8s.io/api/apps/v1" 28 corev1 "k8s.io/api/core/v1" 29 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 30 apierrors "k8s.io/apimachinery/pkg/api/errors" 31 "k8s.io/apimachinery/pkg/api/meta" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 34 "k8s.io/apimachinery/pkg/util/wait" 35 "sigs.k8s.io/controller-runtime/pkg/client" 36 37 clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" 38 "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" 39 "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" 40 "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/scheme" 41 "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test" 42 utilyaml "sigs.k8s.io/cluster-api/util/yaml" 43 ) 44 45 var certManagerDeploymentYaml = []byte("apiVersion: apps/v1\n" + 46 "kind: Deployment\n" + 47 "metadata:\n" + 48 " name: cert-manager\n" + 49 "spec:\n" + 50 " template:\n" + 51 " spec:\n" + 52 " containers:\n" + 53 " - name: manager\n" + 54 " image: quay.io/jetstack/cert-manager:v1.1.0\n") 55 56 var certManagerNamespaceYaml = []byte("apiVersion: v1\n" + 57 "kind: Namespace\n" + 58 "metadata:\n" + 59 " name: cert-manager\n") 60 61 func Test_getManifestObjs(t *testing.T) { 62 g := NewWithT(t) 63 64 defaultConfigClient, err := config.New(context.Background(), "", config.InjectReader(test.NewFakeReader().WithImageMeta(config.CertManagerImageComponent, "bar-repository.io", ""))) 65 g.Expect(err).ToNot(HaveOccurred()) 66 67 type fields struct { 68 configClient config.Client 69 repository repository.Repository 70 } 71 tests := []struct { 72 name string 73 fields fields 74 wantErr bool 75 }{ 76 { 77 name: "successfully gets the cert-manager components", 78 fields: fields{ 79 configClient: defaultConfigClient, 80 repository: repository.NewMemoryRepository(). 81 WithPaths("root", "components.yaml"). 82 WithDefaultVersion(config.CertManagerDefaultVersion). 83 WithFile(config.CertManagerDefaultVersion, "components.yaml", utilyaml.JoinYaml(certManagerNamespaceYaml, certManagerDeploymentYaml)), 84 }, 85 wantErr: false, 86 }, 87 { 88 name: "fails if the file does not exists", 89 fields: fields{ 90 configClient: defaultConfigClient, 91 repository: repository.NewMemoryRepository(). 92 WithPaths("root", "components.yaml"). 93 WithDefaultVersion("v1.0.0"), 94 }, 95 wantErr: true, 96 }, 97 { 98 name: "fails if the file does not exists for the desired version", 99 fields: fields{ 100 configClient: defaultConfigClient, 101 repository: repository.NewMemoryRepository(). 102 WithPaths("root", "components.yaml"). 103 WithDefaultVersion("v99.0.0"). 104 WithFile("v99.0.0", "components.yaml", utilyaml.JoinYaml(certManagerNamespaceYaml, certManagerDeploymentYaml)), 105 }, 106 wantErr: true, 107 }, 108 { 109 name: "successfully gets the cert-manager components for a custom release", 110 fields: fields{ 111 configClient: func() config.Client { 112 configClient, err := config.New(context.Background(), "", config.InjectReader(test.NewFakeReader().WithImageMeta(config.CertManagerImageComponent, "bar-repository.io", "").WithCertManager("", "v1.0.0", ""))) 113 g.Expect(err).ToNot(HaveOccurred()) 114 return configClient 115 }(), 116 repository: repository.NewMemoryRepository(). 117 WithPaths("root", "components.yaml"). 118 WithDefaultVersion(config.CertManagerDefaultVersion). 119 WithFile(config.CertManagerDefaultVersion, "components.yaml", utilyaml.JoinYaml(certManagerNamespaceYaml, certManagerDeploymentYaml)), 120 }, 121 wantErr: false, 122 }, 123 } 124 for _, tt := range tests { 125 t.Run(tt.name, func(t *testing.T) { 126 g := NewWithT(t) 127 128 ctx := context.Background() 129 130 cm := &certManagerClient{ 131 configClient: defaultConfigClient, 132 repositoryClientFactory: func(ctx context.Context, provider config.Provider, configClient config.Client, _ ...repository.Option) (repository.Client, error) { 133 return repository.New(ctx, provider, configClient, repository.InjectRepository(tt.fields.repository)) 134 }, 135 } 136 137 certManagerConfig, err := cm.configClient.CertManager().Get() 138 g.Expect(err).ToNot(HaveOccurred()) 139 140 got, err := cm.getManifestObjs(ctx, certManagerConfig) 141 if tt.wantErr { 142 g.Expect(err).To(HaveOccurred()) 143 return 144 } 145 g.Expect(err).ToNot(HaveOccurred()) 146 147 for i := range got { 148 o := &got[i] 149 // Assert Get adds clusterctl labels. 150 g.Expect(o.GetLabels()).To(HaveKey(clusterctlv1.ClusterctlLabel)) 151 g.Expect(o.GetLabels()).To(HaveKey(clusterctlv1.ClusterctlCoreLabel)) 152 g.Expect(o.GetLabels()[clusterctlv1.ClusterctlCoreLabel]).To(Equal(clusterctlv1.ClusterctlCoreLabelCertManagerValue)) 153 154 // Assert Get adds clusterctl annotations. 155 g.Expect(o.GetAnnotations()).To(HaveKey(clusterctlv1.CertManagerVersionAnnotation)) 156 g.Expect(o.GetAnnotations()[clusterctlv1.CertManagerVersionAnnotation]).To(Equal(certManagerConfig.Version())) 157 158 // Assert Get fixes images. 159 if o.GetKind() == "Deployment" { 160 // Convert Unstructured into a typed object 161 d := &appsv1.Deployment{} 162 g.Expect(scheme.Scheme.Convert(o, d, nil)).To(Succeed()) 163 g.Expect(d.Spec.Template.Spec.Containers[0].Image).To(Equal("bar-repository.io/cert-manager:v1.1.0")) 164 } 165 } 166 }) 167 } 168 } 169 170 func Test_GetTimeout(t *testing.T) { 171 pollImmediateWaiter := func(context.Context, time.Duration, time.Duration, wait.ConditionWithContextFunc) error { 172 return nil 173 } 174 175 tests := []struct { 176 name string 177 config *fakeConfigClient 178 want time.Duration 179 }{ 180 { 181 name: "no custom value set for timeout", 182 config: newFakeConfig(), 183 want: 10 * time.Minute, 184 }, 185 { 186 name: "a custom value of timeout is set", 187 config: newFakeConfig().WithCertManager("", "", "5m"), 188 want: 5 * time.Minute, 189 }, 190 { 191 name: "invalid custom value of timeout is set", 192 config: newFakeConfig().WithCertManager("", "", "foo"), 193 want: 10 * time.Minute, 194 }, 195 } 196 for _, tt := range tests { 197 t.Run(tt.name, func(t *testing.T) { 198 g := NewWithT(t) 199 200 cm := newCertManagerClient(tt.config, nil, nil, pollImmediateWaiter) 201 202 tm := cm.getWaitTimeout() 203 204 g.Expect(tm).To(Equal(tt.want)) 205 }) 206 } 207 } 208 209 func Test_shouldUpgrade(t *testing.T) { 210 type args struct { 211 objs []unstructured.Unstructured 212 } 213 tests := []struct { 214 name string 215 configVersion string 216 args args 217 wantFromVersion string 218 wantToVersion string 219 want bool 220 wantErr bool 221 }{ 222 { 223 name: "Version is not defined (e.g. cluster created with clusterctl < v0.3.9), should upgrade", 224 args: args{ 225 objs: []unstructured.Unstructured{ 226 { 227 Object: map[string]interface{}{}, 228 }, 229 }, 230 }, 231 wantFromVersion: "v0.11.0", 232 wantToVersion: config.CertManagerDefaultVersion, 233 want: true, 234 wantErr: false, 235 }, 236 { 237 name: "Version is equal, should not upgrade", 238 args: args{ 239 objs: []unstructured.Unstructured{ 240 { 241 Object: map[string]interface{}{ 242 "metadata": map[string]interface{}{ 243 "annotations": map[string]interface{}{ 244 clusterctlv1.CertManagerVersionAnnotation: config.CertManagerDefaultVersion, 245 }, 246 }, 247 }, 248 }, 249 }, 250 }, 251 wantFromVersion: config.CertManagerDefaultVersion, 252 wantToVersion: config.CertManagerDefaultVersion, 253 want: false, 254 wantErr: false, 255 }, 256 { 257 name: "Version is equal but current version has no build metadata, should upgrade", 258 configVersion: "v1.5.3+h4fd4", 259 args: args{ 260 objs: []unstructured.Unstructured{ 261 { 262 Object: map[string]interface{}{ 263 "metadata": map[string]interface{}{ 264 "annotations": map[string]interface{}{ 265 clusterctlv1.CertManagerVersionAnnotation: "v1.5.3", 266 }, 267 }, 268 }, 269 }, 270 }, 271 }, 272 wantFromVersion: "v1.5.3", 273 wantToVersion: "v1.5.3+h4fd4", 274 want: true, 275 wantErr: false, 276 }, 277 { 278 name: "Version is equal but different build metadata with hash, should upgrade", 279 configVersion: "v1.5.3+h4fd4", 280 args: args{ 281 objs: []unstructured.Unstructured{ 282 { 283 Object: map[string]interface{}{ 284 "metadata": map[string]interface{}{ 285 "annotations": map[string]interface{}{ 286 clusterctlv1.CertManagerVersionAnnotation: "v1.5.3+h4fd5", 287 }, 288 }, 289 }, 290 }, 291 }, 292 }, 293 wantFromVersion: "v1.5.3+h4fd5", 294 wantToVersion: "v1.5.3+h4fd4", 295 want: true, 296 wantErr: false, 297 }, 298 { 299 name: "Version is equal and same build metadata with hash, should not upgrade", 300 configVersion: "v1.5.3+h4fd5", 301 args: args{ 302 objs: []unstructured.Unstructured{ 303 { 304 Object: map[string]interface{}{ 305 "metadata": map[string]interface{}{ 306 "annotations": map[string]interface{}{ 307 clusterctlv1.CertManagerVersionAnnotation: "v1.5.3+h4fd5", 308 }, 309 }, 310 }, 311 }, 312 }, 313 }, 314 wantFromVersion: "v1.5.3+h4fd5", 315 wantToVersion: "v1.5.3+h4fd5", 316 want: false, 317 wantErr: false, 318 }, 319 { 320 name: "Version is equal but older numbered build metadata, should not upgrade", 321 configVersion: "v1.5.3+build.1", 322 args: args{ 323 objs: []unstructured.Unstructured{ 324 { 325 Object: map[string]interface{}{ 326 "metadata": map[string]interface{}{ 327 "annotations": map[string]interface{}{ 328 clusterctlv1.CertManagerVersionAnnotation: "v1.5.3+build.2", 329 }, 330 }, 331 }, 332 }, 333 }, 334 }, 335 wantFromVersion: "v1.5.3+build.2", 336 wantToVersion: "v1.5.3+build.1", 337 want: false, 338 wantErr: false, 339 }, 340 { 341 name: "Version is equal but newer numbered build metadata, should upgrade", 342 configVersion: "v1.5.3+build.3", 343 args: args{ 344 objs: []unstructured.Unstructured{ 345 { 346 Object: map[string]interface{}{ 347 "metadata": map[string]interface{}{ 348 "annotations": map[string]interface{}{ 349 clusterctlv1.CertManagerVersionAnnotation: "v1.5.3+build.2", 350 }, 351 }, 352 }, 353 }, 354 }, 355 }, 356 wantFromVersion: "v1.5.3+build.2", 357 wantToVersion: "v1.5.3+build.3", 358 want: true, 359 wantErr: false, 360 }, 361 { 362 name: "Version is older, should upgrade", 363 args: args{ 364 objs: []unstructured.Unstructured{ 365 { 366 Object: map[string]interface{}{ 367 "metadata": map[string]interface{}{ 368 "annotations": map[string]interface{}{ 369 clusterctlv1.CertManagerVersionAnnotation: "v0.11.0", 370 }, 371 }, 372 }, 373 }, 374 }, 375 }, 376 wantFromVersion: "v0.11.0", 377 wantToVersion: config.CertManagerDefaultVersion, 378 want: true, 379 wantErr: false, 380 }, 381 { 382 name: "Version is newer, should not upgrade", 383 args: args{ 384 objs: []unstructured.Unstructured{ 385 { 386 Object: map[string]interface{}{ 387 "metadata": map[string]interface{}{ 388 "annotations": map[string]interface{}{ 389 clusterctlv1.CertManagerVersionAnnotation: "v100.0.0", 390 }, 391 }, 392 }, 393 }, 394 }, 395 }, 396 wantFromVersion: "v100.0.0", 397 wantToVersion: config.CertManagerDefaultVersion, 398 want: false, 399 wantErr: false, 400 }, 401 { 402 name: "Endpoint are ignored", 403 args: args{ 404 objs: []unstructured.Unstructured{ 405 { 406 Object: map[string]interface{}{ 407 "kind": "Endpoints", 408 "metadata": map[string]interface{}{ 409 "annotations": map[string]interface{}{ 410 clusterctlv1.CertManagerVersionAnnotation: config.CertManagerDefaultVersion, 411 }, 412 }, 413 }, 414 }, 415 }, 416 }, 417 wantFromVersion: "", 418 wantToVersion: config.CertManagerDefaultVersion, 419 want: false, 420 wantErr: false, 421 }, 422 } 423 for _, tt := range tests { 424 t.Run(tt.name, func(t *testing.T) { 425 g := NewWithT(t) 426 427 proxy := test.NewFakeProxy() 428 fakeConfigClient := newFakeConfig().WithCertManager("", tt.configVersion, "") 429 pollImmediateWaiter := func(context.Context, time.Duration, time.Duration, wait.ConditionWithContextFunc) error { 430 return nil 431 } 432 cm := newCertManagerClient(fakeConfigClient, nil, proxy, pollImmediateWaiter) 433 434 fromVersion, toVersion, got, err := cm.shouldUpgrade(tt.args.objs) 435 if tt.wantErr { 436 g.Expect(err).To(HaveOccurred()) 437 return 438 } 439 g.Expect(err).ToNot(HaveOccurred()) 440 441 g.Expect(got).To(Equal(tt.want)) 442 g.Expect(fromVersion).To(Equal(tt.wantFromVersion)) 443 g.Expect(toVersion).To(Equal(tt.wantToVersion)) 444 }) 445 } 446 } 447 448 func Test_certManagerClient_deleteObjs(t *testing.T) { 449 type fields struct { 450 objs []client.Object 451 } 452 tests := []struct { 453 name string 454 fields fields 455 want []string // Define the list of "Kind, Namespace/Name" that should still exist after delete 456 wantErr bool 457 }{ 458 { 459 name: "CRD should not be deleted", 460 fields: fields{ 461 objs: []client.Object{ 462 &apiextensionsv1.CustomResourceDefinition{ 463 TypeMeta: metav1.TypeMeta{ 464 Kind: "CustomResourceDefinition", 465 APIVersion: apiextensionsv1.SchemeGroupVersion.String(), 466 }, 467 ObjectMeta: metav1.ObjectMeta{ 468 Name: "foo", 469 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 470 }, 471 }, 472 }, 473 }, 474 want: []string{"CustomResourceDefinition, /foo"}, 475 wantErr: false, 476 }, 477 { 478 name: "Namespace should not be deleted", 479 fields: fields{ 480 objs: []client.Object{ 481 &corev1.Namespace{ 482 TypeMeta: metav1.TypeMeta{ 483 Kind: "Namespace", 484 APIVersion: corev1.SchemeGroupVersion.String(), 485 }, 486 ObjectMeta: metav1.ObjectMeta{ 487 Name: "foo", 488 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 489 }, 490 }, 491 }, 492 }, 493 want: []string{"Namespace, /foo"}, 494 wantErr: false, 495 }, 496 { 497 name: "MutatingWebhookConfiguration should not be deleted", 498 fields: fields{ 499 objs: []client.Object{ 500 &admissionregistration.MutatingWebhookConfiguration{ 501 TypeMeta: metav1.TypeMeta{ 502 Kind: "MutatingWebhookConfiguration", 503 APIVersion: admissionregistration.SchemeGroupVersion.String(), 504 }, 505 ObjectMeta: metav1.ObjectMeta{ 506 Name: "foo", 507 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 508 }, 509 }, 510 }, 511 }, 512 want: []string{"MutatingWebhookConfiguration, /foo"}, 513 wantErr: false, 514 }, 515 { 516 name: "ValidatingWebhookConfiguration should not be deleted", 517 fields: fields{ 518 objs: []client.Object{ 519 &admissionregistration.ValidatingWebhookConfiguration{ 520 TypeMeta: metav1.TypeMeta{ 521 Kind: "ValidatingWebhookConfiguration", 522 APIVersion: admissionregistration.SchemeGroupVersion.String(), 523 }, 524 ObjectMeta: metav1.ObjectMeta{ 525 Name: "foo", 526 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 527 }, 528 }, 529 }, 530 }, 531 want: []string{"ValidatingWebhookConfiguration, /foo"}, 532 wantErr: false, 533 }, 534 { 535 name: "Other resources should be deleted", 536 fields: fields{ 537 objs: []client.Object{ 538 &corev1.ServiceAccount{ 539 TypeMeta: metav1.TypeMeta{ 540 Kind: "ServiceAccount", 541 APIVersion: corev1.SchemeGroupVersion.String(), 542 }, 543 ObjectMeta: metav1.ObjectMeta{ 544 Name: "foo", 545 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 546 }, 547 }, 548 &appsv1.Deployment{ 549 TypeMeta: metav1.TypeMeta{ 550 Kind: "Deployment", 551 APIVersion: appsv1.SchemeGroupVersion.String(), 552 }, 553 ObjectMeta: metav1.ObjectMeta{ 554 Name: "bar", 555 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 556 }, 557 }, 558 }, 559 }, 560 want: nil, 561 wantErr: false, 562 }, 563 } 564 for _, tt := range tests { 565 t.Run(tt.name, func(t *testing.T) { 566 g := NewWithT(t) 567 568 ctx := context.Background() 569 570 proxy := test.NewFakeProxy().WithObjs(tt.fields.objs...) 571 cm := &certManagerClient{ 572 pollImmediateWaiter: fakePollImmediateWaiter, 573 proxy: proxy, 574 } 575 576 objBefore, err := proxy.ListResources(ctx, map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}) 577 g.Expect(err).ToNot(HaveOccurred()) 578 579 err = cm.deleteObjs(ctx, objBefore) 580 if tt.wantErr { 581 g.Expect(err).To(HaveOccurred()) 582 return 583 } 584 g.Expect(err).ToNot(HaveOccurred()) 585 586 for _, obj := range tt.fields.objs { 587 accessor, err := meta.Accessor(obj) 588 g.Expect(err).ToNot(HaveOccurred()) 589 590 objShouldStillExist := false 591 for _, want := range tt.want { 592 if fmt.Sprintf("%s, %s/%s", obj.GetObjectKind().GroupVersionKind().Kind, accessor.GetNamespace(), accessor.GetName()) == want { 593 objShouldStillExist = true 594 } 595 } 596 597 cl, err := proxy.NewClient(ctx) 598 g.Expect(err).ToNot(HaveOccurred()) 599 600 err = cl.Get(context.Background(), client.ObjectKeyFromObject(obj), obj) 601 switch objShouldStillExist { 602 case true: 603 g.Expect(err).ToNot(HaveOccurred()) 604 case false: 605 g.Expect(apierrors.IsNotFound(err)).To(BeTrue()) 606 } 607 } 608 }) 609 } 610 } 611 612 func Test_certManagerClient_PlanUpgrade(t *testing.T) { 613 tests := []struct { 614 name string 615 objs []client.Object 616 expectErr bool 617 expectedPlan CertManagerUpgradePlan 618 }{ 619 { 620 name: "returns the upgrade plan for cert-manager if v0.11.0 is installed", 621 // Cert-manager deployment without annotation, this must be from 622 // v0.11.0 623 objs: []client.Object{ 624 &appsv1.Deployment{ 625 TypeMeta: metav1.TypeMeta{ 626 Kind: "Deployment", 627 APIVersion: appsv1.SchemeGroupVersion.String(), 628 }, 629 ObjectMeta: metav1.ObjectMeta{ 630 Name: "cert-manager", 631 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 632 }, 633 }, 634 }, 635 expectErr: false, 636 expectedPlan: CertManagerUpgradePlan{ 637 From: "v0.11.0", 638 To: config.CertManagerDefaultVersion, 639 ShouldUpgrade: true, 640 }, 641 }, 642 { 643 name: "returns the upgrade plan for cert-manager if an older version is installed", 644 objs: []client.Object{ 645 &appsv1.Deployment{ 646 TypeMeta: metav1.TypeMeta{ 647 Kind: "Deployment", 648 APIVersion: appsv1.SchemeGroupVersion.String(), 649 }, 650 ObjectMeta: metav1.ObjectMeta{ 651 Name: "cert-manager", 652 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 653 Annotations: map[string]string{clusterctlv1.CertManagerVersionAnnotation: "v0.10.2"}, 654 }, 655 }, 656 }, 657 expectErr: false, 658 expectedPlan: CertManagerUpgradePlan{ 659 From: "v0.10.2", 660 To: config.CertManagerDefaultVersion, 661 ShouldUpgrade: true, 662 }, 663 }, 664 { 665 name: "returns plan if shouldn't upgrade", 666 objs: []client.Object{ 667 &appsv1.Deployment{ 668 TypeMeta: metav1.TypeMeta{ 669 Kind: "Deployment", 670 APIVersion: appsv1.SchemeGroupVersion.String(), 671 }, 672 ObjectMeta: metav1.ObjectMeta{ 673 Name: "cert-manager", 674 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 675 Annotations: map[string]string{clusterctlv1.CertManagerVersionAnnotation: config.CertManagerDefaultVersion}, 676 }, 677 }, 678 }, 679 expectErr: false, 680 expectedPlan: CertManagerUpgradePlan{ 681 From: config.CertManagerDefaultVersion, 682 To: config.CertManagerDefaultVersion, 683 ShouldUpgrade: false, 684 }, 685 }, 686 { 687 name: "returns empty plan and error if cannot parse semver", 688 objs: []client.Object{ 689 &appsv1.Deployment{ 690 TypeMeta: metav1.TypeMeta{ 691 Kind: "Deployment", 692 APIVersion: appsv1.SchemeGroupVersion.String(), 693 }, 694 ObjectMeta: metav1.ObjectMeta{ 695 Name: "cert-manager", 696 Labels: map[string]string{clusterctlv1.ClusterctlCoreLabel: clusterctlv1.ClusterctlCoreLabelCertManagerValue}, 697 Annotations: map[string]string{clusterctlv1.CertManagerVersionAnnotation: "bad-sem-ver"}, 698 }, 699 }, 700 }, 701 expectErr: true, 702 expectedPlan: CertManagerUpgradePlan{ 703 From: "", 704 To: "", 705 ShouldUpgrade: false, 706 }, 707 }, 708 } 709 710 for _, tt := range tests { 711 t.Run(tt.name, func(t *testing.T) { 712 g := NewWithT(t) 713 714 ctx := context.Background() 715 716 proxy := test.NewFakeProxy().WithObjs(tt.objs...) 717 fakeConfigClient := newFakeConfig() 718 pollImmediateWaiter := func(context.Context, time.Duration, time.Duration, wait.ConditionWithContextFunc) error { 719 return nil 720 } 721 cm := newCertManagerClient(fakeConfigClient, nil, proxy, pollImmediateWaiter) 722 723 actualPlan, err := cm.PlanUpgrade(ctx) 724 if tt.expectErr { 725 g.Expect(err).To(HaveOccurred()) 726 g.Expect(actualPlan).To(BeComparableTo(CertManagerUpgradePlan{})) 727 return 728 } 729 g.Expect(err).ToNot(HaveOccurred()) 730 g.Expect(actualPlan).To(Equal(tt.expectedPlan)) 731 }) 732 } 733 } 734 735 func Test_certManagerClient_EnsureLatestVersion(t *testing.T) { 736 type fields struct { 737 proxy Proxy 738 } 739 tests := []struct { 740 name string 741 fields fields 742 wantErr bool 743 }{ 744 { 745 name: "", 746 fields: fields{ 747 proxy: test.NewFakeProxy().WithObjs( 748 &corev1.Namespace{ 749 ObjectMeta: metav1.ObjectMeta{ 750 Labels: map[string]string{}, 751 }, 752 }, 753 ), 754 }, 755 wantErr: false, 756 }, 757 } 758 for _, tt := range tests { 759 t.Run(tt.name, func(t *testing.T) { 760 g := NewWithT(t) 761 762 cm := &certManagerClient{ 763 proxy: tt.fields.proxy, 764 } 765 766 err := cm.EnsureLatestVersion(context.Background()) 767 if tt.wantErr { 768 g.Expect(err).To(HaveOccurred()) 769 return 770 } 771 g.Expect(err).ToNot(HaveOccurred()) 772 }) 773 } 774 } 775 776 func newFakeConfig() *fakeConfigClient { 777 fakeReader := test.NewFakeReader() 778 779 client, _ := config.New(context.Background(), "fake-config", config.InjectReader(fakeReader)) 780 return &fakeConfigClient{ 781 fakeReader: fakeReader, 782 internalclient: client, 783 } 784 } 785 786 type fakeConfigClient struct { 787 fakeReader *test.FakeReader 788 internalclient config.Client 789 } 790 791 var _ config.Client = &fakeConfigClient{} 792 793 func (f fakeConfigClient) CertManager() config.CertManagerClient { 794 return f.internalclient.CertManager() 795 } 796 797 func (f fakeConfigClient) Providers() config.ProvidersClient { 798 return f.internalclient.Providers() 799 } 800 801 func (f fakeConfigClient) Variables() config.VariablesClient { 802 return f.internalclient.Variables() 803 } 804 805 func (f fakeConfigClient) ImageMeta() config.ImageMetaClient { 806 return f.internalclient.ImageMeta() 807 } 808 809 func (f *fakeConfigClient) WithVar(key, value string) *fakeConfigClient { 810 f.fakeReader.WithVar(key, value) 811 return f 812 } 813 814 func (f *fakeConfigClient) WithProvider(provider config.Provider) *fakeConfigClient { 815 f.fakeReader.WithProvider(provider.Name(), provider.Type(), provider.URL()) 816 return f 817 } 818 819 func (f *fakeConfigClient) WithCertManager(url, version, timeout string) *fakeConfigClient { 820 f.fakeReader.WithCertManager(url, version, timeout) 821 return f 822 }