github.com/verrazzano/verrazzano@v1.7.0/cluster-operator/controllers/quickcreate/ociocne/ociocne_controller_test.go (about)

     1  // Copyright (c) 2022, 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 ociocne
     5  
     6  import (
     7  	"context"
     8  	_ "embed"
     9  	"fmt"
    10  	"github.com/stretchr/testify/assert"
    11  	vmcv1alpha1 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1"
    12  	"github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller"
    13  	"github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci"
    14  	ocifake "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci/fake"
    15  	corev1 "k8s.io/api/core/v1"
    16  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    17  	"k8s.io/apimachinery/pkg/runtime"
    18  	"k8s.io/apimachinery/pkg/types"
    19  	"os"
    20  	"sigs.k8s.io/cluster-api/api/v1beta1"
    21  	ctrl "sigs.k8s.io/controller-runtime"
    22  	clipkg "sigs.k8s.io/controller-runtime/pkg/client"
    23  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    24  	"sigs.k8s.io/yaml"
    25  	"testing"
    26  )
    27  
    28  var (
    29  	scheme *runtime.Scheme
    30  	//go:embed testdata/base.yaml
    31  	testBase []byte
    32  	//go:embed testdata/existing-vcn-patch.yaml
    33  	testExistingVCNPatch []byte
    34  	//go:embed testdata/new-vcn-patch.yaml
    35  	testNewVCNPatch []byte
    36  	//go:embed testdata/completed-patch.yaml
    37  	testCompletedPatch []byte
    38  	//go:embed testdata/new-vcn-private-registry.yaml
    39  	testNewVCNPrivateRegistryPatch []byte
    40  	testOCNEVersions               = "../controller/ocne/testdata/ocne-versions.yaml"
    41  	testLoader                     = &ocifake.CredentialsLoaderImpl{
    42  		Credentials: &oci.Credentials{
    43  			Region:  "",
    44  			Tenancy: "a",
    45  			User:    "b",
    46  			PrivateKey: `abc
    47  def
    48  ghi
    49  `,
    50  			Fingerprint:          "d",
    51  			Passphrase:           "e",
    52  			UseInstancePrincipal: "false",
    53  		},
    54  	}
    55  	testOCIClientGetter = func(creds *oci.Credentials) (oci.Client, error) {
    56  		return &ocifake.ClientImpl{
    57  			AvailabilityDomains: []oci.AvailabilityDomain{
    58  				{
    59  					Name: "x",
    60  					FaultDomains: []oci.FaultDomain{
    61  						{Name: "y"},
    62  					},
    63  				},
    64  			},
    65  		}, nil
    66  	}
    67  	privateRegistrySecret = &corev1.Secret{
    68  		ObjectMeta: metav1.ObjectMeta{
    69  			Name:      testRegistrySecretName,
    70  			Namespace: testNamespace,
    71  		},
    72  		Data: map[string][]byte{
    73  			".dockerconfigjson": []byte("foo"),
    74  		},
    75  		Type: corev1.SecretTypeDockerConfigJson,
    76  	}
    77  )
    78  
    79  const (
    80  	testNamespace          = "test"
    81  	testName               = testNamespace
    82  	testRegistrySecretName = "registry"
    83  )
    84  
    85  func init() {
    86  	scheme = runtime.NewScheme()
    87  	_ = corev1.AddToScheme(scheme)
    88  	_ = vmcv1alpha1.AddToScheme(scheme)
    89  	_ = v1beta1.AddToScheme(scheme)
    90  }
    91  
    92  func testCreateCR(patch []byte) (*vmcv1alpha1.OCNEOCIQuickCreate, error) {
    93  	baseCR := &vmcv1alpha1.OCNEOCIQuickCreate{}
    94  	patchCR := &vmcv1alpha1.OCNEOCIQuickCreate{}
    95  	if err := yaml.Unmarshal(testBase, baseCR); err != nil {
    96  		return nil, err
    97  	}
    98  	if err := yaml.Unmarshal(patch, patchCR); err != nil {
    99  		return nil, err
   100  	}
   101  	baseCR.Spec = patchCR.Spec
   102  	baseCR.Status = patchCR.Status
   103  	return baseCR, nil
   104  }
   105  
   106  func testOCNEConfigMap() *corev1.ConfigMap {
   107  	cm := &corev1.ConfigMap{}
   108  	b, _ := os.ReadFile(testOCNEVersions)
   109  	_ = yaml.Unmarshal(b, cm)
   110  	return cm
   111  }
   112  
   113  func testReconciler(cli clipkg.Client) *ClusterReconciler {
   114  	return &ClusterReconciler{
   115  		Base: &controller.Base{
   116  			Client: cli,
   117  		},
   118  		Scheme:            scheme,
   119  		CredentialsLoader: testLoader,
   120  		OCIClientGetter:   testOCIClientGetter,
   121  	}
   122  }
   123  
   124  func getTestCR(cli clipkg.Client) (*vmcv1alpha1.OCNEOCIQuickCreate, error) {
   125  	ctx := context.TODO()
   126  	q := &vmcv1alpha1.OCNEOCIQuickCreate{}
   127  	err := cli.Get(ctx, types.NamespacedName{
   128  		Namespace: testNamespace,
   129  		Name:      testName,
   130  	}, q)
   131  
   132  	return q, err
   133  }
   134  
   135  func TestReconcile(t *testing.T) {
   136  	existingVCNCR, err := testCreateCR(testExistingVCNPatch)
   137  	assert.NoError(t, err)
   138  	completedCR, err := testCreateCR(testCompletedPatch)
   139  	assert.NoError(t, err)
   140  	noFinalizerCR := existingVCNCR.DeepCopy()
   141  	noFinalizerCR.Finalizers = nil
   142  	provisioningCR, err := testCreateCR(testNewVCNPatch)
   143  	assert.NoError(t, err)
   144  	privateRegistryCR, err := testCreateCR(testNewVCNPrivateRegistryPatch)
   145  	assert.NoError(t, err)
   146  	notFoundReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).Build())
   147  	quickCreateReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(existingVCNCR, testOCNEConfigMap()).Build())
   148  	completedReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(completedCR, testOCNEConfigMap()).Build())
   149  	noFinalizerReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(noFinalizerCR, testOCNEConfigMap()).Build())
   150  	provisioningReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(provisioningCR, testOCNEConfigMap()).Build())
   151  	privateRegistryReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(privateRegistrySecret, privateRegistryCR, testOCNEConfigMap()).Build())
   152  	var tests = []struct {
   153  		name        string
   154  		reconciler  *ClusterReconciler
   155  		assertsFunc func(t *testing.T)
   156  	}{
   157  		{
   158  			"nothing to do when resource not found",
   159  			notFoundReconciler,
   160  			func(t *testing.T) {},
   161  		},
   162  		{
   163  			"when quick creating, a CAPI cluster is applied",
   164  			quickCreateReconciler,
   165  			func(t *testing.T) {
   166  				ctx := context.TODO()
   167  				assert.NoError(t, quickCreateReconciler.Client.Get(ctx, types.NamespacedName{
   168  					Namespace: testNamespace,
   169  					Name:      testName,
   170  				}, &v1beta1.Cluster{}))
   171  			},
   172  		},
   173  		{
   174  			"completed CRs are deleted",
   175  			completedReconciler,
   176  			func(t *testing.T) {
   177  				q, err := getTestCR(completedReconciler.Client)
   178  				assert.NoError(t, err)
   179  				assert.False(t, q.GetDeletionTimestamp().IsZero())
   180  			},
   181  		},
   182  		{
   183  			"finalizers are added if not present",
   184  			noFinalizerReconciler,
   185  			func(t *testing.T) {
   186  				q, _ := getTestCR(noFinalizerReconciler.Client)
   187  				assert.NotNil(t, q)
   188  				assert.NotNil(t, q.Finalizers)
   189  				assert.Equal(t, finalizerKey, q.Finalizers[0])
   190  			},
   191  		},
   192  		{
   193  			"provisoning CR creates addon resources",
   194  			provisioningReconciler,
   195  			func(t *testing.T) {
   196  				err := provisioningReconciler.Client.Get(context.TODO(), types.NamespacedName{
   197  					Name:      fmt.Sprintf("%s-csi", testName),
   198  					Namespace: testNamespace,
   199  				}, &corev1.Secret{})
   200  				assert.NoError(t, err)
   201  			},
   202  		},
   203  		{
   204  			"private registry secret is created when using private registry credentials",
   205  			privateRegistryReconciler,
   206  			func(t *testing.T) {
   207  				err := privateRegistryReconciler.Client.Get(context.TODO(), types.NamespacedName{
   208  					Name:      fmt.Sprintf("%s-image-pull-secret", testName),
   209  					Namespace: testNamespace,
   210  				}, &corev1.Secret{})
   211  				assert.NoError(t, err)
   212  			},
   213  		},
   214  	}
   215  
   216  	for _, tt := range tests {
   217  		t.Run(tt.name, func(t *testing.T) {
   218  			_, err := tt.reconciler.Reconcile(context.TODO(), ctrl.Request{
   219  				NamespacedName: types.NamespacedName{
   220  					Namespace: testNamespace,
   221  					Name:      testName,
   222  				},
   223  			})
   224  			assert.NoError(t, err)
   225  			tt.assertsFunc(t)
   226  		})
   227  	}
   228  }