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 }