github.com/verrazzano/verrazzano@v1.7.1/cluster-operator/apis/clusters/v1alpha1/common_webhook_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 v1alpha1 5 6 import ( 7 "context" 8 "github.com/oracle/oci-go-sdk/v53/core" 9 "github.com/stretchr/testify/assert" 10 "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci" 11 ocifake "github.com/verrazzano/verrazzano/cluster-operator/controllers/quickcreate/controller/oci/fake" 12 vzerror "github.com/verrazzano/verrazzano/cluster-operator/internal/errors" 13 corev1 "k8s.io/api/core/v1" 14 "k8s.io/client-go/kubernetes/scheme" 15 "os" 16 clipkg "sigs.k8s.io/controller-runtime/pkg/client" 17 "sigs.k8s.io/controller-runtime/pkg/client/fake" 18 "sigs.k8s.io/yaml" 19 "testing" 20 ) 21 22 func testValidationContextWithOCIClient(cli clipkg.Client, ociClient oci.Client) *validationContext { 23 return &validationContext{ 24 Ctx: context.TODO(), 25 Cli: cli, 26 OCIClientGetter: func(creds *oci.Credentials) (oci.Client, error) { 27 return ociClient, nil 28 }, 29 CredentialsLoader: &ocifake.CredentialsLoaderImpl{ 30 Credentials: &oci.Credentials{}, 31 }, 32 Errors: &vzerror.ErrorAggregator{}, 33 } 34 } 35 36 func testValidationContext(cli clipkg.Client) *validationContext { 37 return testValidationContextWithOCIClient(cli, nil) 38 } 39 40 func testOCNEConfigMap() (*corev1.ConfigMap, error) { 41 d, err := os.ReadFile("../../../controllers/quickcreate/controller/ocne/testdata/ocne-versions.yaml") 42 if err != nil { 43 return nil, err 44 } 45 cm := &corev1.ConfigMap{} 46 if err := yaml.Unmarshal(d, cm); err != nil { 47 return nil, err 48 } 49 return cm, nil 50 } 51 52 func TestAddOCINodeErrors(t *testing.T) { 53 var ( 54 flexShape = "VM.Standard.E4.Flex" 55 nonFlexShape = "BM.Standard.E5" 56 one = 1 57 fifty = 50 58 ) 59 var tests = []struct { 60 name string 61 node OCINode 62 hasError bool 63 }{ 64 { 65 "no error when ocpus/memory are not provided for a flex shape", 66 OCINode{ 67 Shape: &flexShape, 68 OCPUs: &one, 69 MemoryGbs: &one, 70 BootVolumeGbs: &fifty, 71 Replicas: &one, 72 }, 73 false, 74 }, 75 { 76 "no error when ocpus/memory are provided for a flex shape", 77 OCINode{ 78 Shape: &flexShape, 79 OCPUs: &one, 80 MemoryGbs: &one, 81 BootVolumeGbs: &fifty, 82 Replicas: &one, 83 }, 84 false, 85 }, 86 { 87 "error when providing ocpus without flex shape", 88 OCINode{ 89 Shape: &nonFlexShape, 90 OCPUs: &one, 91 BootVolumeGbs: &fifty, 92 Replicas: &one, 93 }, 94 true, 95 }, 96 { 97 "error when providing memory without flex shape", 98 OCINode{ 99 Shape: &nonFlexShape, 100 MemoryGbs: &one, 101 BootVolumeGbs: &fifty, 102 Replicas: &one, 103 }, 104 true, 105 }, 106 } 107 108 for _, tt := range tests { 109 t.Run(tt.name, func(t *testing.T) { 110 ctx := testValidationContext(nil) 111 addOCINodeErrors(ctx, tt.node, "") 112 assert.Equal(t, tt.hasError, ctx.Errors.HasError()) 113 }) 114 } 115 } 116 117 func TestAddOCINetworkErrors(t *testing.T) { 118 var ( 119 vcnID = "my-vcn" 120 subnetID = "my-subnet" 121 lbSubnet = Subnet{ 122 Role: SubnetRoleServiceLB, 123 ID: subnetID, 124 } 125 workerSubnet = Subnet{ 126 Role: SubnetRoleWorker, 127 ID: subnetID, 128 } 129 cpSubnet = Subnet{ 130 Role: SubnetRoleControlPlane, 131 ID: subnetID, 132 } 133 cpeSubnet = Subnet{ 134 Role: SubnetRoleControlPlaneEndpoint, 135 ID: subnetID, 136 } 137 subnets = []Subnet{ 138 workerSubnet, 139 lbSubnet, 140 cpSubnet, 141 cpeSubnet, 142 } 143 ) 144 ociClient := &ocifake.ClientImpl{ 145 VCN: &core.Vcn{ 146 Id: &vcnID, 147 }, 148 } 149 var tests = []struct { 150 name string 151 network *Network 152 hasError bool 153 }{ 154 { 155 "no error when using creating a VCN without existing VCN/subnet ids", 156 &Network{ 157 CreateVCN: true, 158 }, 159 false, 160 }, 161 { 162 "error when creating a VCN, but a VCN id is supplied", 163 &Network{ 164 CreateVCN: true, 165 VCN: vcnID, 166 }, 167 true, 168 }, 169 { 170 "error when creating a VCN, but subnets are supplied", 171 &Network{ 172 CreateVCN: true, 173 Subnets: subnets, 174 }, 175 true, 176 }, 177 { 178 "error when using an existing a VCN, and not enough subnets are supplied", 179 &Network{ 180 CreateVCN: false, 181 VCN: vcnID, 182 Subnets: []Subnet{workerSubnet}, 183 }, 184 true, 185 }, 186 { 187 "no error when using an existing vcn and subnets", 188 &Network{ 189 CreateVCN: false, 190 VCN: vcnID, 191 Subnets: subnets, 192 }, 193 false, 194 }, 195 { 196 "error when vcn is not found", 197 &Network{ 198 CreateVCN: false, 199 VCN: "unknown", 200 Subnets: subnets, 201 }, 202 true, 203 }, 204 } 205 206 for _, tt := range tests { 207 t.Run(tt.name, func(t *testing.T) { 208 ctx := testValidationContext(nil) 209 addOCINetworkErrors(ctx, ociClient, tt.network, 4, "") 210 assert.Equal(t, tt.hasError, ctx.Errors.HasError()) 211 }) 212 } 213 } 214 215 func TestAddOCNEErrors(t *testing.T) { 216 ocneConfigMap, err := testOCNEConfigMap() 217 assert.NoError(t, err) 218 ocneVersion := "1.7" 219 cliWithCM := fake.NewClientBuilder().WithObjects(ocneConfigMap).WithScheme(scheme.Scheme).Build() 220 var tests = []struct { 221 name string 222 ocneVersion string 223 224 cli clipkg.Client 225 hasError bool 226 }{ 227 {"no errors when using valid OCNE version and configmap is present", 228 ocneVersion, 229 230 cliWithCM, 231 false, 232 }, 233 {"error when using invalid OCNE version", 234 "boom", 235 236 cliWithCM, 237 true, 238 }, 239 {"error when OCNE Versions are not presnet", 240 ocneVersion, 241 242 fake.NewClientBuilder().WithScheme(scheme.Scheme).Build(), 243 true, 244 }, 245 } 246 247 for _, tt := range tests { 248 t.Run(tt.name, func(t *testing.T) { 249 ctx := testValidationContext(tt.cli) 250 addOCNEErrors(ctx, OCNE{ 251 Version: tt.ocneVersion, 252 }, "") 253 assert.Equal(t, tt.hasError, ctx.Errors.HasError()) 254 }) 255 } 256 } 257 258 func TestAddProxyErrors(t *testing.T) { 259 var tests = []struct { 260 name string 261 proxy *Proxy 262 hasError bool 263 }{ 264 { 265 "no error when proxy is nil", 266 nil, 267 false, 268 }, 269 { 270 "no error when proxy has valid urls", 271 &Proxy{ 272 HTTPProxy: "http://foo.com", 273 HTTPSProxy: "https://foo.com", 274 NoProxy: "", 275 }, 276 false, 277 }, 278 { 279 "error when proxy has invalid urls", 280 &Proxy{ 281 HTTPProxy: "x", 282 }, 283 true, 284 }, 285 } 286 for _, tt := range tests { 287 t.Run(tt.name, func(t *testing.T) { 288 ctx := testValidationContext(nil) 289 addProxyErrors(ctx, tt.proxy, "") 290 assert.Equal(t, tt.hasError, ctx.Errors.HasError()) 291 }) 292 } 293 } 294 295 func TestAddPrivateRegistryErrors(t *testing.T) { 296 var tests = []struct { 297 name string 298 privateRegistry *PrivateRegistry 299 hasError bool 300 }{ 301 { 302 "no error when private registry is nil", 303 nil, 304 false, 305 }, 306 { 307 "no error when private registry has valid urls", 308 &PrivateRegistry{ 309 URL: "http://my-registry.com:80", 310 }, 311 false, 312 }, 313 { 314 "error when private registry has invalid urls", 315 &PrivateRegistry{ 316 URL: "x", 317 }, 318 true, 319 }, 320 } 321 for _, tt := range tests { 322 t.Run(tt.name, func(t *testing.T) { 323 ctx := testValidationContext(nil) 324 addPrivateRegistryErrors(ctx, tt.privateRegistry, "") 325 assert.Equal(t, tt.hasError, ctx.Errors.HasError()) 326 }) 327 } 328 }