github.com/verrazzano/verrazzano@v1.7.0/cluster-operator/controllers/capi/capi_cluster_controller_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 capi 5 6 import ( 7 "context" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1" 12 "github.com/verrazzano/verrazzano/cluster-operator/internal/capi" 13 "github.com/verrazzano/verrazzano/pkg/constants" 14 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/common" 15 "go.uber.org/zap" 16 appsv1 "k8s.io/api/apps/v1" 17 v1 "k8s.io/api/core/v1" 18 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 19 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 20 "k8s.io/apimachinery/pkg/runtime" 21 "k8s.io/apimachinery/pkg/types" 22 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 23 ctrl "sigs.k8s.io/controller-runtime" 24 "sigs.k8s.io/controller-runtime/pkg/client" 25 "sigs.k8s.io/controller-runtime/pkg/client/fake" 26 ) 27 28 const ( 29 clusterName = "capi1" 30 ) 31 32 // GIVEN a CAPI cluster resource is created 33 // WHEN the reconciler runs 34 // THEN a rancher registration and associated artifacts are created 35 func TestClusterRancherRegistration(t *testing.T) { 36 asserts := assert.New(t) 37 38 rancherDeployment := &appsv1.Deployment{ 39 ObjectMeta: metav1.ObjectMeta{ 40 Name: common.RancherName, 41 Namespace: common.CattleSystem, 42 }, 43 Status: appsv1.DeploymentStatus{ 44 Replicas: 1, 45 ReadyReplicas: 1, 46 }, 47 } 48 ep := &v1.Endpoints{ 49 ObjectMeta: metav1.ObjectMeta{ 50 Name: "kubernetes", 51 Namespace: "default", 52 }, 53 Subsets: []v1.EndpointSubset{{Addresses: []v1.EndpointAddress{{IP: "1.2.3.4"}}}}, 54 } 55 56 fakeClient := fake.NewClientBuilder().WithScheme(newScheme()).WithObjects(newCAPICluster(clusterName), rancherDeployment, ep).Build() 57 reconciler := newCAPIClusterReconciler(fakeClient) 58 request := newRequest(clusterName) 59 60 SetClusterRancherRegistrationFunction(func(ctx context.Context, r *RancherRegistration, cluster *unstructured.Unstructured) (ctrl.Result, error) { 61 persistClusterStatus(ctx, reconciler.Client, cluster, reconciler.Log, "capi1Id", registrationInitiated) 62 return ctrl.Result{}, nil 63 }) 64 defer SetDefaultClusterRancherRegistrationFunction() 65 66 SetVerrazzanoReconcileFunction(func(ctx context.Context, cluster *unstructured.Unstructured, r *CAPIClusterReconciler) (ctrl.Result, error) { 67 return ctrl.Result{}, nil 68 }) 69 defer SetDefaultVerrazzanoReconcileFunction() 70 71 _, err := reconciler.Reconcile(context.TODO(), request) 72 asserts.NoError(err) 73 74 clusterRegistrationSecret := &v1.Secret{} 75 err = fakeClient.Get(context.TODO(), types.NamespacedName{Name: clusterName + clusterStatusSuffix, Namespace: constants.VerrazzanoCAPINamespace}, clusterRegistrationSecret) 76 asserts.NoError(err) 77 asserts.Equal(registrationInitiated, string(clusterRegistrationSecret.Data[clusterRegistrationStatusKey])) 78 cluster := &unstructured.Unstructured{} 79 cluster.SetGroupVersionKind(capi.GVKCAPICluster) 80 err = fakeClient.Get(context.TODO(), types.NamespacedName{Name: clusterName}, cluster) 81 asserts.NoError(err) 82 asserts.Equal(finalizerName, cluster.GetFinalizers()[0]) 83 } 84 85 // GIVEN a CAPI cluster resource is deleted 86 // WHEN the reconciler runs 87 // THEN a rancher registration and associated artifacts are removed 88 func TestClusterUnregistration(t *testing.T) { 89 asserts := assert.New(t) 90 91 rancherDeployment := &appsv1.Deployment{ 92 ObjectMeta: metav1.ObjectMeta{ 93 Name: common.RancherName, 94 Namespace: common.CattleSystem, 95 }, 96 Status: appsv1.DeploymentStatus{ 97 Replicas: 1, 98 ReadyReplicas: 1, 99 }, 100 } 101 102 clusterRegistrationSecret := &v1.Secret{ 103 ObjectMeta: metav1.ObjectMeta{ 104 Name: clusterName + clusterStatusSuffix, 105 Namespace: constants.VerrazzanoCAPINamespace, 106 }, 107 Data: map[string][]byte{clusterIDKey: []byte("capi1Id"), clusterRegistrationStatusKey: []byte(registrationInitiated)}, 108 } 109 110 cluster := newCAPICluster(clusterName) 111 now := metav1.Now() 112 cluster.SetDeletionTimestamp(&now) 113 cluster.SetFinalizers([]string{finalizerName}) 114 115 fakeClient := fake.NewClientBuilder().WithScheme(newScheme()).WithObjects(cluster, rancherDeployment, clusterRegistrationSecret).Build() 116 reconciler := newCAPIClusterReconciler(fakeClient) 117 request := newRequest(clusterName) 118 119 SetClusterRancherUnregistrationFunction(func(ctx context.Context, r *RancherRegistration, cluster *unstructured.Unstructured) error { 120 return nil 121 }) 122 defer SetDefaultClusterRancherUnregistrationFunction() 123 124 _, err := reconciler.Reconcile(context.TODO(), request) 125 asserts.NoError(err) 126 127 remainingSecret := &v1.Secret{} 128 asserts.Error(fakeClient.Get(context.TODO(), types.NamespacedName{Name: clusterName + clusterStatusSuffix, Namespace: constants.VerrazzanoCAPINamespace}, remainingSecret)) 129 deletedCluster := &unstructured.Unstructured{} 130 deletedCluster.SetGroupVersionKind(capi.GVKCAPICluster) 131 asserts.Error(fakeClient.Get(context.TODO(), types.NamespacedName{Name: clusterName}, deletedCluster)) 132 } 133 134 func newScheme() *runtime.Scheme { 135 scheme := runtime.NewScheme() 136 clientgoscheme.AddToScheme(scheme) 137 v1alpha1.AddToScheme(scheme) 138 139 return scheme 140 } 141 142 func newCAPICluster(name string) *unstructured.Unstructured { 143 cluster := &unstructured.Unstructured{} 144 cluster.SetGroupVersionKind(capi.GVKCAPICluster) 145 cluster.SetName(name) 146 return cluster 147 } 148 149 func newCAPIClusterReconciler(c client.Client) CAPIClusterReconciler { 150 rancherRegistrar := &RancherRegistration{ 151 Client: c, 152 Log: zap.S(), 153 } 154 verrazzanoRegistrar := &VerrazzanoRegistration{ 155 Client: c, 156 Log: zap.S(), 157 } 158 return CAPIClusterReconciler{ 159 Client: c, 160 Scheme: newScheme(), 161 Log: zap.S(), 162 RancherEnabled: true, 163 RancherRegistrar: rancherRegistrar, 164 VerrazzanoRegistrar: verrazzanoRegistrar, 165 } 166 } 167 168 func newRequest(name string) ctrl.Request { 169 return ctrl.Request{ 170 NamespacedName: types.NamespacedName{ 171 Name: name, 172 }, 173 } 174 }