github.com/verrazzano/verrazzano@v1.7.0/platform-operator/internal/vzconfig/ingress_test.go (about) 1 // Copyright (c) 2020, 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 package vzconfig 4 5 import ( 6 "github.com/verrazzano/verrazzano/pkg/nginxutil" 7 "testing" 8 9 "github.com/verrazzano/verrazzano/pkg/test/ip" 10 11 vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 12 vpoconst "github.com/verrazzano/verrazzano/platform-operator/constants" 13 14 "github.com/stretchr/testify/assert" 15 corev1 "k8s.io/api/core/v1" 16 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 17 k8scheme "k8s.io/client-go/kubernetes/scheme" 18 "sigs.k8s.io/controller-runtime/pkg/client/fake" 19 ) 20 21 const testDomain = "mydomain.com" 22 23 // Test_getServiceTypeLoadBalancer tests the GetServiceType function 24 // GIVEN a call to GetServiceType 25 // 26 // WHEN the Ingress specifies a LoadBalancer type 27 // THEN the LoadBalancer type is returned with no error 28 func Test_getServiceTypeLoadBalancer(t *testing.T) { 29 vz := &vzapi.Verrazzano{ 30 Spec: vzapi.VerrazzanoSpec{ 31 EnvironmentName: "myenv", 32 Components: vzapi.ComponentSpec{ 33 Ingress: &vzapi.IngressNginxComponent{ 34 Type: vzapi.LoadBalancer, 35 }, 36 }, 37 }, 38 } 39 40 svcType, err := GetIngressServiceType(vz) 41 assert.NoError(t, err) 42 assert.Equal(t, vzapi.LoadBalancer, svcType) 43 } 44 45 // Test_getServiceTypeNodePort tests the GetServiceType function 46 // GIVEN a call to GetServiceType 47 // 48 // WHEN the Ingress specifies a NodePort type 49 // THEN the NodePort type is returned with no error 50 func Test_getServiceTypeNodePort(t *testing.T) { 51 vz := &vzapi.Verrazzano{ 52 Spec: vzapi.VerrazzanoSpec{ 53 EnvironmentName: "myenv", 54 Components: vzapi.ComponentSpec{ 55 Ingress: &vzapi.IngressNginxComponent{ 56 Type: vzapi.NodePort, 57 }, 58 }, 59 }, 60 } 61 62 svcType, err := GetIngressServiceType(vz) 63 assert.NoError(t, err) 64 assert.Equal(t, vzapi.NodePort, svcType) 65 } 66 67 // Test_getServiceTypeInvalidType tests the GetServiceType function 68 // GIVEN a call to GetServiceType 69 // 70 // WHEN the Ingress specifies invalid service type 71 // THEN an empty string and an error are returned 72 func Test_getServiceTypeInvalidType(t *testing.T) { 73 vz := &vzapi.Verrazzano{ 74 Spec: vzapi.VerrazzanoSpec{ 75 EnvironmentName: "myenv", 76 Components: vzapi.ComponentSpec{ 77 Ingress: &vzapi.IngressNginxComponent{ 78 Type: "somethingbad", 79 }, 80 }, 81 }, 82 } 83 84 svcType, err := GetIngressServiceType(vz) 85 assert.Error(t, err) 86 assert.Equal(t, vzapi.IngressType(""), svcType) 87 } 88 89 // TestGetIngressServiceNotFound tests the GetIngressIP function 90 // GIVEN a call to GetIngressIP 91 // 92 // WHEN the VZ config Ingress is a LB type and no service is found 93 // THEN an error is returned 94 func TestGetIngressServiceNotFound(t *testing.T) { 95 vz := &vzapi.Verrazzano{ 96 Spec: vzapi.VerrazzanoSpec{ 97 Components: vzapi.ComponentSpec{ 98 Ingress: &vzapi.IngressNginxComponent{ 99 Type: vzapi.LoadBalancer, 100 }, 101 }, 102 }, 103 } 104 fakeClient := fake.NewClientBuilder().WithScheme(k8scheme.Scheme).Build() 105 _, err := GetIngressIP(fakeClient, vz) 106 assert.Error(t, err) 107 } 108 109 func TestGetIngressIP(t *testing.T) { 110 testExternalIP := ip.RandomIP() 111 testLoadBalancerIP := ip.RandomIP() 112 tests := []struct { 113 name string 114 serviceType vzapi.IngressType 115 lbIP string 116 externalIP string 117 want string 118 wantErr bool 119 }{ 120 { 121 name: "lb no address found", 122 serviceType: vzapi.LoadBalancer, 123 wantErr: true, 124 }, 125 { 126 name: "lb with both lb and external ip", 127 serviceType: vzapi.LoadBalancer, 128 lbIP: testLoadBalancerIP, 129 externalIP: testExternalIP, 130 want: testExternalIP, 131 }, 132 { 133 name: "lb with lb ip", 134 serviceType: vzapi.LoadBalancer, 135 lbIP: testLoadBalancerIP, 136 want: testLoadBalancerIP, 137 }, 138 { 139 name: "lb with external ip", 140 serviceType: vzapi.LoadBalancer, 141 externalIP: testExternalIP, 142 want: testExternalIP, 143 }, 144 { 145 name: "nodeport without external ip", 146 serviceType: vzapi.NodePort, 147 wantErr: true, 148 }, 149 { 150 name: "nodeport with external ip", 151 serviceType: vzapi.NodePort, 152 externalIP: testExternalIP, 153 want: testExternalIP, 154 }, 155 } 156 for _, tt := range tests { 157 t.Run(tt.name, func(t *testing.T) { 158 vz := &vzapi.Verrazzano{ 159 Spec: vzapi.VerrazzanoSpec{ 160 Components: vzapi.ComponentSpec{ 161 Ingress: &vzapi.IngressNginxComponent{ 162 Type: tt.serviceType, 163 }, 164 }, 165 }, 166 } 167 svc := &corev1.Service{ 168 ObjectMeta: metav1.ObjectMeta{ 169 Namespace: nginxutil.IngressNGINXNamespace(), 170 Name: vpoconst.NGINXControllerServiceName, 171 }, 172 } 173 if len(tt.externalIP) > 0 { 174 svc.Spec = corev1.ServiceSpec{ 175 ExternalIPs: []string{tt.externalIP}, 176 } 177 } 178 if len(tt.lbIP) > 0 { 179 svc.Status = corev1.ServiceStatus{ 180 LoadBalancer: corev1.LoadBalancerStatus{ 181 Ingress: []corev1.LoadBalancerIngress{ 182 {IP: tt.lbIP}, 183 }, 184 }, 185 } 186 } 187 fakeClient := fake.NewClientBuilder().WithScheme(k8scheme.Scheme).WithObjects(svc).Build() 188 got, err := GetIngressIP(fakeClient, vz) 189 if (err != nil) != tt.wantErr { 190 t.Errorf("GetIngressIP() error = %v, wantErr %v", err, tt.wantErr) 191 return 192 } 193 if got != tt.want { 194 t.Errorf("GetIngressIP() got = %v, want %v", got, tt.want) 195 } 196 }) 197 } 198 } 199 200 func TestGetDNSSuffix(t *testing.T) { 201 const testWildCardSuffix = "xip.io" 202 testExternalIP := ip.RandomIP() 203 testLoadBalancerIP := ip.RandomIP() 204 tests := []struct { 205 name string 206 serviceType vzapi.IngressType 207 dnsOCIZone string 208 dnsExternalSuffix string 209 dnsWildCardSuffix string 210 lbIP string 211 externalIP string 212 want string 213 wantErr bool 214 }{ 215 { 216 name: "lb with oci dns", 217 serviceType: vzapi.LoadBalancer, 218 dnsOCIZone: testDomain, 219 want: testDomain, 220 }, 221 { 222 name: "lb with external dns", 223 serviceType: vzapi.LoadBalancer, 224 dnsExternalSuffix: testDomain, 225 want: testDomain, 226 }, 227 { 228 name: "lb with external dns and external ip", 229 serviceType: vzapi.LoadBalancer, 230 dnsExternalSuffix: testDomain, 231 externalIP: testExternalIP, 232 want: testDomain, 233 }, 234 { 235 name: "lb with wildcard dns and lb ip", 236 serviceType: vzapi.LoadBalancer, 237 dnsWildCardSuffix: testWildCardSuffix, 238 lbIP: testLoadBalancerIP, 239 want: testLoadBalancerIP + "." + testWildCardSuffix, 240 }, 241 { 242 name: "lb with wildcard dns and external ip", 243 serviceType: vzapi.LoadBalancer, 244 dnsWildCardSuffix: testWildCardSuffix, 245 externalIP: testExternalIP, 246 want: testExternalIP + "." + testWildCardSuffix, 247 }, 248 { 249 name: "lb with wildcard dns and both external and lb ip", 250 serviceType: vzapi.LoadBalancer, 251 dnsWildCardSuffix: testWildCardSuffix, 252 lbIP: testLoadBalancerIP, 253 externalIP: testExternalIP, 254 want: testExternalIP + "." + testWildCardSuffix, 255 }, 256 { 257 name: "lb with external ip", 258 serviceType: vzapi.LoadBalancer, 259 externalIP: testExternalIP, 260 want: testExternalIP + "." + defaultWildcardDomain, 261 }, 262 { 263 name: "lb with lb ip", 264 serviceType: vzapi.LoadBalancer, 265 lbIP: testLoadBalancerIP, 266 want: testLoadBalancerIP + "." + defaultWildcardDomain, 267 }, 268 { 269 name: "lb with both external and lb ip", 270 serviceType: vzapi.LoadBalancer, 271 lbIP: testLoadBalancerIP, 272 externalIP: testExternalIP, 273 want: testExternalIP + "." + defaultWildcardDomain, 274 }, 275 { 276 name: "lb no address found", 277 serviceType: vzapi.LoadBalancer, 278 wantErr: true, 279 }, 280 { 281 name: "nodeport without external ip", 282 serviceType: vzapi.NodePort, 283 wantErr: true, 284 }, 285 { 286 name: "nodeport with external ip", 287 serviceType: vzapi.NodePort, 288 externalIP: testExternalIP, 289 want: testExternalIP + "." + defaultWildcardDomain, 290 }, 291 { 292 name: "nodeport with external dns and external ip", 293 serviceType: vzapi.NodePort, 294 dnsExternalSuffix: testDomain, 295 externalIP: testExternalIP, 296 want: testDomain, 297 }, 298 } 299 for _, tt := range tests { 300 t.Run(tt.name, func(t *testing.T) { 301 vz := &vzapi.Verrazzano{ 302 Spec: vzapi.VerrazzanoSpec{ 303 Components: vzapi.ComponentSpec{ 304 Ingress: &vzapi.IngressNginxComponent{ 305 Type: tt.serviceType, 306 }, 307 }, 308 }, 309 } 310 if len(tt.dnsOCIZone) > 0 { 311 vz.Spec.Components.DNS = &vzapi.DNSComponent{ 312 OCI: &vzapi.OCI{ 313 DNSZoneName: testDomain, 314 }, 315 } 316 } else if len(tt.dnsExternalSuffix) > 0 { 317 vz.Spec.Components.DNS = &vzapi.DNSComponent{ 318 External: &vzapi.External{ 319 Suffix: tt.dnsExternalSuffix, 320 }, 321 } 322 } else if len(tt.dnsWildCardSuffix) > 0 { 323 vz.Spec.Components.DNS = &vzapi.DNSComponent{ 324 Wildcard: &vzapi.Wildcard{ 325 Domain: tt.dnsWildCardSuffix, 326 }, 327 } 328 } 329 svc := &corev1.Service{ 330 ObjectMeta: metav1.ObjectMeta{ 331 Namespace: nginxutil.IngressNGINXNamespace(), 332 Name: vpoconst.NGINXControllerServiceName, 333 }, 334 } 335 if len(tt.externalIP) > 0 { 336 svc.Spec = corev1.ServiceSpec{ 337 ExternalIPs: []string{tt.externalIP}, 338 } 339 } 340 if len(tt.lbIP) > 0 { 341 svc.Status = corev1.ServiceStatus{ 342 LoadBalancer: corev1.LoadBalancerStatus{ 343 Ingress: []corev1.LoadBalancerIngress{ 344 {IP: tt.lbIP}, 345 }, 346 }, 347 } 348 } 349 fakeClient := fake.NewClientBuilder().WithScheme(k8scheme.Scheme).WithObjects(svc).Build() 350 got, err := GetDNSSuffix(fakeClient, vz) 351 if (err != nil) != tt.wantErr { 352 t.Errorf("GetDNSSuffix() error = %v, wantErr %v", err, tt.wantErr) 353 return 354 } 355 if got != tt.want { 356 t.Errorf("GetDNSSuffix() got = %v, want %v", got, tt.want) 357 } 358 }) 359 } 360 } 361 362 // TestGetEnvName tests the GetEnvName function 363 // GIVEN a call to GetEnvName 364 // 365 // WHEN the VZ config specifies an env name 366 // THEN the configured env name is returned 367 func TestGetEnvName(t *testing.T) { 368 vz := &vzapi.Verrazzano{ 369 Spec: vzapi.VerrazzanoSpec{ 370 EnvironmentName: "myenv", 371 }, 372 } 373 assert.Equal(t, "myenv", GetEnvName(vz)) 374 } 375 376 // TestGetEnvNameDefault tests the GetEnvName function 377 // GIVEN a call to GetEnvName 378 // 379 // WHEN the VZ config does not explicitly configure an EnvironmentName 380 // THEN then "default" is returned 381 func TestGetEnvNameDefault(t *testing.T) { 382 vz := &vzapi.Verrazzano{} 383 assert.Equal(t, "default", GetEnvName(vz)) 384 } 385 386 // TestBuildDNSDomainDefaultEnv tests the BuildDNSDomain function 387 // GIVEN a call to BuildDNSDomain 388 // 389 // WHEN the VZ config specifies no env name 390 // THEN the domain name is correctly returned 391 func TestBuildDNSDomainDefaultEnv(t *testing.T) { 392 vz := &vzapi.Verrazzano{ 393 Spec: vzapi.VerrazzanoSpec{ 394 Components: vzapi.ComponentSpec{ 395 DNS: &vzapi.DNSComponent{ 396 OCI: &vzapi.OCI{ 397 DNSZoneName: testDomain, 398 }, 399 }, 400 }, 401 }, 402 } 403 domain, err := BuildDNSDomain(fake.NewClientBuilder().WithScheme(k8scheme.Scheme).Build(), vz) 404 assert.NoError(t, err) 405 assert.Equal(t, "default."+testDomain, domain) 406 } 407 408 // TestBuildDNSDomainCustomEnv tests the BuildDNSDomain function 409 // GIVEN a call to BuildDNSDomain 410 // 411 // WHEN the VZ config specifies a custom env name 412 // THEN the domain name is correctly returned 413 func TestBuildDNSDomainCustomEnv(t *testing.T) { 414 vz := &vzapi.Verrazzano{ 415 Spec: vzapi.VerrazzanoSpec{ 416 EnvironmentName: "myenv", 417 Components: vzapi.ComponentSpec{ 418 DNS: &vzapi.DNSComponent{ 419 OCI: &vzapi.OCI{ 420 DNSZoneName: testDomain, 421 }, 422 }, 423 }, 424 }, 425 } 426 domain, err := BuildDNSDomain(fake.NewClientBuilder().WithScheme(k8scheme.Scheme).Build(), vz) 427 assert.NoError(t, err) 428 assert.Equal(t, "myenv."+testDomain, domain) 429 } 430 431 // TestFindVolumeTemplate Test the FindVolumeTemplate utility function 432 // GIVEN a call to FindVolumeTemplate 433 // WHEN valid or invalid arguments are given 434 // THEN true and the found template are is returned if found, nil/false otherwise 435 func TestFindVolumeTemplate(t *testing.T) { 436 437 specTemplateList := []vzapi.VolumeClaimSpecTemplate{ 438 { 439 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 440 Spec: corev1.PersistentVolumeClaimSpec{ 441 VolumeName: "defVolume", 442 }, 443 }, 444 { 445 ObjectMeta: metav1.ObjectMeta{Name: "template1"}, 446 Spec: corev1.PersistentVolumeClaimSpec{ 447 VolumeName: "temp1Volume", 448 }, 449 }, 450 { 451 ObjectMeta: metav1.ObjectMeta{Name: "template2"}, 452 Spec: corev1.PersistentVolumeClaimSpec{ 453 VolumeName: "temp2Volume", 454 }, 455 }, 456 } 457 458 vz := vzapi.Verrazzano{ 459 Spec: vzapi.VerrazzanoSpec{ 460 VolumeClaimSpecTemplates: specTemplateList, 461 }, 462 } 463 // Test boundary conditions 464 invalidName, found := FindVolumeTemplate("blah", &vz) 465 assert.Nil(t, invalidName) 466 assert.False(t, found) 467 emptyName, found2 := FindVolumeTemplate("", &vz) 468 assert.Nil(t, emptyName) 469 assert.False(t, found2) 470 nilList, found3 := FindVolumeTemplate("default", nil) 471 assert.Nil(t, nilList) 472 assert.False(t, found3) 473 emptyList, found4 := FindVolumeTemplate("default", &vzapi.Verrazzano{ 474 Spec: vzapi.VerrazzanoSpec{ 475 VolumeClaimSpecTemplates: []vzapi.VolumeClaimSpecTemplate{}, 476 }, 477 }) 478 assert.Nil(t, emptyList) 479 assert.False(t, found4) 480 481 // Test normal behavior 482 defTemplate, found := FindVolumeTemplate("default", &vz) 483 assert.True(t, found) 484 assert.Equal(t, "defVolume", defTemplate.VolumeName) 485 temp1, found := FindVolumeTemplate("template1", &vz) 486 assert.True(t, found) 487 assert.Equal(t, "temp1Volume", temp1.VolumeName) 488 temp2, found := FindVolumeTemplate("template2", &vz) 489 assert.True(t, found) 490 assert.Equal(t, "temp2Volume", temp2.VolumeName) 491 } 492 493 // TestGetIngressClassName Tests the GetIngressClassName utility function 494 // GIVEN a call to GetIngressClassName 495 // WHEN a Verrazzano resource with an ingress class name specified is given 496 // THEN the ingress class name specified in the Verrazzano resource is returned 497 func TestGetIngressClassName(t *testing.T) { 498 assert.Equal(t, defaultIngressClassName, GetIngressClassName(&vzapi.Verrazzano{})) 499 ingressClassName := "foobar" 500 assert.Equal(t, ingressClassName, GetIngressClassName(&vzapi.Verrazzano{ 501 Spec: vzapi.VerrazzanoSpec{ 502 Components: vzapi.ComponentSpec{ 503 Ingress: &vzapi.IngressNginxComponent{ 504 IngressClassName: &ingressClassName, 505 }, 506 }, 507 }, 508 })) 509 }