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  }