@@ -25,6 +25,7 @@ import (
25
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
26
"k8s.io/apimachinery/pkg/runtime"
27
27
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
28
+ "k8s.io/utils/pointer"
28
29
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
29
30
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
30
31
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -462,6 +463,181 @@ func TestNewGenericProviderList(t *testing.T) {
462
463
}
463
464
}
464
465
466
+ func TestProviderSpecChanges (t * testing.T ) {
467
+ testCases := []struct {
468
+ name string
469
+ spec operatorv1.ProviderSpec
470
+ updatedSpec operatorv1.ProviderSpec
471
+ expectError bool
472
+ }{
473
+ {
474
+ name : "same spec, hash annotation doesn't change" ,
475
+ spec : operatorv1.ProviderSpec {
476
+ Version : testCurrentVersion ,
477
+ FetchConfig : & operatorv1.FetchConfiguration {
478
+ Selector : & metav1.LabelSelector {
479
+ MatchLabels : map [string ]string {
480
+ "test" : "dummy-config" ,
481
+ },
482
+ },
483
+ },
484
+ },
485
+ updatedSpec : operatorv1.ProviderSpec {
486
+ Version : testCurrentVersion ,
487
+ FetchConfig : & operatorv1.FetchConfiguration {
488
+ Selector : & metav1.LabelSelector {
489
+ MatchLabels : map [string ]string {
490
+ "test" : "dummy-config" ,
491
+ },
492
+ },
493
+ },
494
+ },
495
+ },
496
+ {
497
+ name : "add more replicas, hash annotation is updated" ,
498
+ spec : operatorv1.ProviderSpec {
499
+ Version : testCurrentVersion ,
500
+ FetchConfig : & operatorv1.FetchConfiguration {
501
+ Selector : & metav1.LabelSelector {
502
+ MatchLabels : map [string ]string {
503
+ "test" : "dummy-config" ,
504
+ },
505
+ },
506
+ },
507
+ },
508
+ updatedSpec : operatorv1.ProviderSpec {
509
+ Version : testCurrentVersion ,
510
+ Deployment : & operatorv1.DeploymentSpec {
511
+ Replicas : pointer .Int (2 ),
512
+ },
513
+ FetchConfig : & operatorv1.FetchConfiguration {
514
+ Selector : & metav1.LabelSelector {
515
+ MatchLabels : map [string ]string {
516
+ "test" : "dummy-config" ,
517
+ },
518
+ },
519
+ },
520
+ },
521
+ },
522
+ {
523
+ name : "upgrade to a non-existent version, hash annotation is empty" ,
524
+ expectError : true ,
525
+ spec : operatorv1.ProviderSpec {
526
+ Version : testCurrentVersion ,
527
+ FetchConfig : & operatorv1.FetchConfiguration {
528
+ Selector : & metav1.LabelSelector {
529
+ MatchLabels : map [string ]string {
530
+ "test" : "dummy-config" ,
531
+ },
532
+ },
533
+ },
534
+ },
535
+ updatedSpec : operatorv1.ProviderSpec {
536
+ Version : "10000.0.0-NONEXISTENT" ,
537
+ Deployment : & operatorv1.DeploymentSpec {
538
+ Replicas : pointer .Int (2 ),
539
+ },
540
+ FetchConfig : & operatorv1.FetchConfiguration {
541
+ Selector : & metav1.LabelSelector {
542
+ MatchLabels : map [string ]string {
543
+ "test" : "dummy-config" ,
544
+ },
545
+ },
546
+ },
547
+ },
548
+ },
549
+ }
550
+
551
+ for _ , tc := range testCases {
552
+ t .Run (tc .name , func (t * testing.T ) {
553
+ g := NewWithT (t )
554
+
555
+ specHash , err := calculateHash (tc .spec )
556
+ g .Expect (err ).ToNot (HaveOccurred ())
557
+
558
+ updatedSpecHash , err := calculateHash (tc .spec )
559
+ g .Expect (err ).ToNot (HaveOccurred ())
560
+
561
+ provider := & genericprovider.CoreProviderWrapper {
562
+ CoreProvider : & operatorv1.CoreProvider {
563
+ ObjectMeta : metav1.ObjectMeta {
564
+ Name : "cluster-api" ,
565
+ },
566
+ Spec : operatorv1.CoreProviderSpec {
567
+ ProviderSpec : tc .spec ,
568
+ },
569
+ },
570
+ }
571
+
572
+ namespace := "test-provider-spec-changes"
573
+
574
+ t .Log ("Ensure namespace exists" , namespace )
575
+ g .Expect (env .EnsureNamespaceExists (ctx , namespace )).To (Succeed ())
576
+
577
+ g .Expect (env .CreateAndWait (ctx , dummyConfigMap (namespace , testCurrentVersion ))).To (Succeed ())
578
+
579
+ provider .SetNamespace (namespace )
580
+ t .Log ("creating test provider" , provider .GetName ())
581
+ g .Expect (env .CreateAndWait (ctx , provider .GetObject ())).To (Succeed ())
582
+
583
+ g .Eventually (generateExpectedResultChecker (provider , specHash , corev1 .ConditionTrue ), timeout ).Should (BeEquivalentTo (true ))
584
+
585
+ // Change provider spec
586
+ provider .SetSpec (tc .updatedSpec )
587
+
588
+ // Set a label to ensure that provider was changed
589
+ labels := provider .GetLabels ()
590
+ if labels == nil {
591
+ labels = map [string ]string {}
592
+ }
593
+ labels ["my-label" ] = "some-value"
594
+ provider .SetLabels (labels )
595
+
596
+ g .Expect (env .Client .Update (ctx , provider .GetObject ())).To (Succeed ())
597
+
598
+ if ! tc .expectError {
599
+ g .Eventually (generateExpectedResultChecker (provider , updatedSpecHash , corev1 .ConditionTrue ), timeout ).Should (BeEquivalentTo (true ))
600
+ } else {
601
+ g .Eventually (generateExpectedResultChecker (provider , "" , corev1 .ConditionFalse ), timeout ).Should (BeEquivalentTo (true ))
602
+ }
603
+
604
+ // Clean up
605
+ objs := []client.Object {provider .GetObject ()}
606
+ objs = append (objs , & corev1.ConfigMap {
607
+ ObjectMeta : metav1.ObjectMeta {
608
+ Name : testCurrentVersion ,
609
+ Namespace : namespace ,
610
+ },
611
+ })
612
+
613
+ g .Expect (env .CleanupAndWait (ctx , objs ... )).To (Succeed ())
614
+ })
615
+ }
616
+ }
617
+
618
+ func generateExpectedResultChecker (provider * genericprovider.CoreProviderWrapper , specHash string , condStatus corev1.ConditionStatus ) func () bool {
619
+ return func () bool {
620
+ if err := env .Get (ctx , client .ObjectKeyFromObject (provider .GetObject ()), provider .GetObject ()); err != nil {
621
+ return false
622
+ }
623
+
624
+ // In case of error we don't want the spec annotation to be updated
625
+ if provider .GetAnnotations ()[appliedSpecHashAnnotation ] != specHash {
626
+ return false
627
+ }
628
+
629
+ for _ , cond := range provider .GetStatus ().Conditions {
630
+ if cond .Type == operatorv1 .ProviderInstalledCondition {
631
+ if cond .Status == condStatus {
632
+ return true
633
+ }
634
+ }
635
+ }
636
+
637
+ return false
638
+ }
639
+ }
640
+
465
641
func setupScheme () * runtime.Scheme {
466
642
scheme := runtime .NewScheme ()
467
643
utilruntime .Must (corev1 .AddToScheme (scheme ))
0 commit comments