github.com/verrazzano/verrazzano@v1.7.1/cluster-operator/controllers/quickcreate/oke/oke_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 oke 5 6 import ( 7 "context" 8 _ "embed" 9 "github.com/stretchr/testify/assert" 10 vmcv1alpha1 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1" 11 "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller" 12 "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci" 13 ocifake "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci/fake" 14 corev1 "k8s.io/api/core/v1" 15 "k8s.io/apimachinery/pkg/runtime" 16 "k8s.io/apimachinery/pkg/types" 17 "sigs.k8s.io/cluster-api/api/v1beta1" 18 ctrl "sigs.k8s.io/controller-runtime" 19 clipkg "sigs.k8s.io/controller-runtime/pkg/client" 20 "sigs.k8s.io/controller-runtime/pkg/client/fake" 21 "sigs.k8s.io/yaml" 22 "testing" 23 ) 24 25 const ( 26 testNamespace = "test" 27 testName = testNamespace 28 ) 29 30 var ( 31 scheme *runtime.Scheme 32 //go:embed testdata/base.yaml 33 testBase []byte 34 //go:embed testdata/completed-patch.yaml 35 testCompleted []byte 36 //go:embed testdata/existing-vcn-patch.yaml 37 testExistingVCN []byte 38 //go:embed testdata/new-vcn-native-patch.yaml 39 testNewVCN []byte 40 //go:embed testdata/existing-vcn-provisioning.yaml 41 testProvisioning []byte 42 testLoader = &ocifake.CredentialsLoaderImpl{ 43 Credentials: &oci.Credentials{}, 44 } 45 testOCIClientGetter = func(_ *oci.Credentials) (oci.Client, error) { 46 return &ocifake.ClientImpl{ 47 AvailabilityDomains: []oci.AvailabilityDomain{ 48 { 49 Name: "x", 50 FaultDomains: []oci.FaultDomain{ 51 {Name: "y"}, 52 }, 53 }, 54 }, 55 }, nil 56 } 57 ) 58 59 func init() { 60 scheme = runtime.NewScheme() 61 _ = corev1.AddToScheme(scheme) 62 _ = vmcv1alpha1.AddToScheme(scheme) 63 _ = v1beta1.AddToScheme(scheme) 64 } 65 66 func TestReconcile(t *testing.T) { 67 existingVCNCR, err := testCreateCR(testExistingVCN) 68 assert.NoError(t, err) 69 completedCR, err := testCreateCR(testCompleted) 70 assert.NoError(t, err) 71 newVCNCR, err := testCreateCR(testNewVCN) 72 assert.NoError(t, err) 73 provisioningCR, err := testCreateCR(testProvisioning) 74 assert.NoError(t, err) 75 76 notFoundReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).Build()) 77 existingVCNReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(existingVCNCR).Build()) 78 completedReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(completedCR).Build()) 79 newVCNReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(newVCNCR).Build()) 80 provisioningReconciler := testReconciler(fake.NewClientBuilder().WithScheme(scheme).WithObjects(provisioningCR).Build()) 81 82 var tests = []struct { 83 name string 84 reconciler *ClusterReconciler 85 assertsFunc func(t *testing.T) 86 }{ 87 { 88 "no error when resource not found", 89 notFoundReconciler, 90 func(t *testing.T) {}, 91 }, 92 { 93 "create a cluster when using an existing VCN", 94 existingVCNReconciler, 95 func(t *testing.T) { 96 ctx := context.TODO() 97 assert.NoError(t, existingVCNReconciler.Client.Get(ctx, types.NamespacedName{ 98 Namespace: testNamespace, 99 Name: testName, 100 }, &v1beta1.Cluster{})) 101 }, 102 }, 103 { 104 "completed CRs are deleted", 105 completedReconciler, 106 func(t *testing.T) { 107 q, err := getTestCR(completedReconciler.Client) 108 assert.NoError(t, err) 109 assert.False(t, q.GetDeletionTimestamp().IsZero()) 110 }, 111 }, 112 { 113 "create a cluster when creating a new VCN", 114 newVCNReconciler, 115 func(t *testing.T) { 116 ctx := context.TODO() 117 assert.NoError(t, newVCNReconciler.Client.Get(ctx, types.NamespacedName{ 118 Namespace: testNamespace, 119 Name: testName, 120 }, &v1beta1.Cluster{})) 121 }, 122 }, 123 { 124 "quick create moves to completed when reconciling provisioning", 125 provisioningReconciler, 126 func(t *testing.T) { 127 q, err := getTestCR(completedReconciler.Client) 128 assert.NoError(t, err) 129 assert.Equal(t, vmcv1alpha1.QuickCreatePhaseComplete, q.Status.Phase) 130 }, 131 }, 132 } 133 134 for _, tt := range tests { 135 t.Run(tt.name, func(t *testing.T) { 136 _, err := tt.reconciler.Reconcile(context.TODO(), ctrl.Request{ 137 NamespacedName: types.NamespacedName{ 138 Namespace: testNamespace, 139 Name: testName, 140 }, 141 }) 142 assert.NoError(t, err) 143 tt.assertsFunc(t) 144 }) 145 } 146 } 147 148 func testCreateCR(patch []byte) (*vmcv1alpha1.OKEQuickCreate, error) { 149 baseCR := &vmcv1alpha1.OKEQuickCreate{} 150 patchCR := &vmcv1alpha1.OKEQuickCreate{} 151 if err := yaml.Unmarshal(testBase, baseCR); err != nil { 152 return nil, err 153 } 154 if err := yaml.Unmarshal(patch, patchCR); err != nil { 155 return nil, err 156 } 157 baseCR.Spec = patchCR.Spec 158 baseCR.Status = patchCR.Status 159 return baseCR, nil 160 } 161 162 func testReconciler(cli clipkg.Client) *ClusterReconciler { 163 return &ClusterReconciler{ 164 Base: &controller.Base{ 165 Client: cli, 166 }, 167 Scheme: scheme, 168 CredentialsLoader: testLoader, 169 OCIClientGetter: testOCIClientGetter, 170 } 171 } 172 173 func getTestCR(cli clipkg.Client) (*vmcv1alpha1.OKEQuickCreate, error) { 174 ctx := context.TODO() 175 q := &vmcv1alpha1.OKEQuickCreate{} 176 err := cli.Get(ctx, types.NamespacedName{ 177 Namespace: testNamespace, 178 Name: testName, 179 }, q) 180 181 return q, err 182 }