github.com/cilium/cilium@v1.16.2/operator/pkg/gateway-api/gateway_reconcile_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package gateway_api 5 6 import ( 7 "context" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 corev1 "k8s.io/api/core/v1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 ctrl "sigs.k8s.io/controller-runtime" 15 "sigs.k8s.io/controller-runtime/pkg/client" 16 "sigs.k8s.io/controller-runtime/pkg/client/fake" 17 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" 18 gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" 19 20 "github.com/cilium/cilium/operator/pkg/model" 21 "github.com/cilium/cilium/operator/pkg/model/translation" 22 gatewayApiTranslation "github.com/cilium/cilium/operator/pkg/model/translation/gateway-api" 23 ) 24 25 var gwFixture = []client.Object{ 26 // Valid Gateway class 27 &gatewayv1.GatewayClass{ 28 ObjectMeta: metav1.ObjectMeta{ 29 Name: "cilium", 30 }, 31 Spec: gatewayv1.GatewayClassSpec{ 32 ControllerName: "io.cilium/gateway-controller", 33 }, 34 }, 35 36 // Service for valid HTTPRoute 37 &corev1.Service{ 38 ObjectMeta: metav1.ObjectMeta{ 39 Name: "dummy-backend", 40 Namespace: "default", 41 }, 42 }, 43 &corev1.Service{ 44 ObjectMeta: metav1.ObjectMeta{ 45 Name: "cilium-gateway-valid-gateway", 46 Namespace: "another-namespace", 47 Annotations: map[string]string{ 48 "pre-existing-annotation": "true", 49 }, 50 }, 51 Status: corev1.ServiceStatus{ 52 LoadBalancer: corev1.LoadBalancerStatus{ 53 Ingress: []corev1.LoadBalancerIngress{ 54 { 55 IP: "10.10.10.11", 56 Ports: []corev1.PortStatus{ 57 { 58 Port: 80, 59 Protocol: "TCP", 60 }, 61 }, 62 }, 63 }, 64 }, 65 }, 66 }, 67 &corev1.Service{ 68 ObjectMeta: metav1.ObjectMeta{ 69 Name: "cilium-gateway-valid-gateway", 70 Namespace: "default", 71 Annotations: map[string]string{ 72 "pre-existing-annotation": "true", 73 }, 74 }, 75 Status: corev1.ServiceStatus{ 76 LoadBalancer: corev1.LoadBalancerStatus{ 77 Ingress: []corev1.LoadBalancerIngress{ 78 { 79 IP: "10.10.10.10", 80 Ports: []corev1.PortStatus{ 81 { 82 Port: 80, 83 Protocol: "TCP", 84 }, 85 }, 86 }, 87 }, 88 }, 89 }, 90 }, 91 &corev1.Service{ 92 ObjectMeta: metav1.ObjectMeta{ 93 Name: "cilium-gateway-test-long-long-long-long-long-long-lo-8tfth549c6", 94 Namespace: "long-name-test", 95 Annotations: map[string]string{ 96 "pre-existing-annotation": "true", 97 }, 98 }, 99 }, 100 101 // Service in another namespace 102 &corev1.Service{ 103 ObjectMeta: metav1.ObjectMeta{ 104 Name: "dummy-backend", 105 Namespace: "another-namespace", 106 }, 107 }, 108 109 // Valid HTTPRoute 110 &gatewayv1.HTTPRoute{ 111 ObjectMeta: metav1.ObjectMeta{ 112 Name: "http-route", 113 Namespace: "default", 114 }, 115 Spec: gatewayv1.HTTPRouteSpec{ 116 CommonRouteSpec: gatewayv1.CommonRouteSpec{ 117 ParentRefs: []gatewayv1.ParentReference{ 118 { 119 Name: "valid-gateway", 120 }, 121 }, 122 }, 123 Rules: []gatewayv1.HTTPRouteRule{ 124 { 125 BackendRefs: []gatewayv1.HTTPBackendRef{ 126 { 127 BackendRef: gatewayv1.BackendRef{ 128 BackendObjectReference: gatewayv1.BackendObjectReference{ 129 Name: "dummy-backend", 130 Port: model.AddressOf[gatewayv1.PortNumber](80), 131 }, 132 }, 133 }, 134 }, 135 }, 136 }, 137 }, 138 Status: gatewayv1.HTTPRouteStatus{ 139 RouteStatus: gatewayv1.RouteStatus{ 140 Parents: []gatewayv1.RouteParentStatus{ 141 { 142 ParentRef: gatewayv1.ParentReference{ 143 Name: "valid-gateway", 144 }, 145 ControllerName: "io.cilium/gateway-controller", 146 Conditions: []metav1.Condition{ 147 { 148 Type: "Accepted", 149 Status: "True", 150 }, 151 }, 152 }, 153 }, 154 }, 155 }, 156 }, 157 158 // Valid TLSRoute 159 &gatewayv1alpha2.TLSRoute{ 160 ObjectMeta: metav1.ObjectMeta{ 161 Name: "tls-route", 162 Namespace: "default", 163 }, 164 Spec: gatewayv1alpha2.TLSRouteSpec{ 165 CommonRouteSpec: gatewayv1.CommonRouteSpec{ 166 ParentRefs: []gatewayv1.ParentReference{ 167 { 168 Name: "valid-tlsroute-gateway", 169 }, 170 }, 171 }, 172 Hostnames: []gatewayv1alpha2.Hostname{ 173 "sni.cilium.rocks", 174 }, 175 Rules: []gatewayv1alpha2.TLSRouteRule{ 176 { 177 BackendRefs: []gatewayv1.BackendRef{ 178 { 179 BackendObjectReference: gatewayv1.BackendObjectReference{ 180 Name: "dummy-backend", 181 Port: model.AddressOf[gatewayv1.PortNumber](443), 182 }, 183 }, 184 }, 185 }, 186 }, 187 }, 188 Status: gatewayv1alpha2.TLSRouteStatus{ 189 RouteStatus: gatewayv1.RouteStatus{ 190 Parents: []gatewayv1.RouteParentStatus{ 191 { 192 ParentRef: gatewayv1.ParentReference{ 193 Name: "valid-tlsroute-gateway", 194 }, 195 ControllerName: "io.cilium/gateway-controller", 196 Conditions: []metav1.Condition{ 197 { 198 Type: "Accepted", 199 Status: "True", 200 }, 201 }, 202 }, 203 }, 204 }, 205 }, 206 }, 207 208 // Valid gateway 209 &gatewayv1.Gateway{ 210 TypeMeta: metav1.TypeMeta{ 211 Kind: "Gateway", 212 APIVersion: gatewayv1.GroupName, 213 }, 214 ObjectMeta: metav1.ObjectMeta{ 215 Name: "valid-gateway", 216 Namespace: "default", 217 }, 218 Spec: gatewayv1.GatewaySpec{ 219 GatewayClassName: "cilium", 220 Listeners: []gatewayv1.Listener{ 221 { 222 Name: "http", 223 Port: 80, 224 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.io"), 225 Protocol: "HTTP", 226 }, 227 }, 228 }, 229 }, 230 // Valid gateway 231 &gatewayv1.Gateway{ 232 TypeMeta: metav1.TypeMeta{ 233 Kind: "Gateway", 234 APIVersion: gatewayv1.GroupName, 235 }, 236 ObjectMeta: metav1.ObjectMeta{ 237 Name: "test-long-long-long-long-long-long-long-long-long-long-long-long-name", 238 Namespace: "long-name-test", 239 }, 240 Spec: gatewayv1.GatewaySpec{ 241 GatewayClassName: "cilium", 242 Listeners: []gatewayv1.Listener{ 243 { 244 Name: "http", 245 Port: 80, 246 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.io"), 247 Protocol: "HTTP", 248 }, 249 }, 250 }, 251 }, 252 // gateway with non-existent gateway class 253 &gatewayv1.Gateway{ 254 TypeMeta: metav1.TypeMeta{ 255 Kind: "Gateway", 256 APIVersion: gatewayv1.GroupName, 257 }, 258 ObjectMeta: metav1.ObjectMeta{ 259 Name: "gateway-with-non-existent-gateway-class", 260 Namespace: "default", 261 }, 262 Spec: gatewayv1.GatewaySpec{ 263 GatewayClassName: "non-existent-gateway-class", 264 Listeners: []gatewayv1.Listener{ 265 { 266 Name: "http", 267 Port: 80, 268 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.io"), 269 Protocol: "HTTP", 270 }, 271 }, 272 }, 273 }, 274 275 /// Valid TLSRoute gateway 276 &gatewayv1.Gateway{ 277 TypeMeta: metav1.TypeMeta{ 278 Kind: "Gateway", 279 APIVersion: gatewayv1.GroupName, 280 }, 281 ObjectMeta: metav1.ObjectMeta{ 282 Name: "valid-tlsroute-gateway", 283 Namespace: "default", 284 }, 285 Spec: gatewayv1.GatewaySpec{ 286 GatewayClassName: "cilium", 287 Listeners: []gatewayv1.Listener{ 288 { 289 Name: "tls", 290 Port: 443, 291 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.rocks"), 292 Protocol: "TLS", 293 }, 294 }, 295 }, 296 }, 297 } 298 299 func Test_gatewayReconciler_Reconcile(t *testing.T) { 300 c := fake.NewClientBuilder(). 301 WithScheme(testScheme()). 302 WithObjects(gwFixture...). 303 WithStatusSubresource(&gatewayv1.Gateway{}). 304 Build() 305 306 cecTranslator := translation.NewCECTranslator("", false, false, true, 60, false, nil, false, false, 0) 307 gatewayAPITranslator := gatewayApiTranslation.NewTranslator(cecTranslator, false, string(corev1.ServiceExternalTrafficPolicyCluster)) 308 309 r := &gatewayReconciler{ 310 Client: c, 311 translator: gatewayAPITranslator, 312 } 313 314 t.Run("non-existent gateway", func(t *testing.T) { 315 result, err := r.Reconcile(context.Background(), ctrl.Request{ 316 NamespacedName: client.ObjectKey{ 317 Namespace: "default", 318 Name: "non-existent-gateway", 319 }, 320 }) 321 322 require.NoError(t, err) 323 require.Equal(t, ctrl.Result{}, result) 324 }) 325 326 t.Run("non-existent gateway class", func(t *testing.T) { 327 key := client.ObjectKey{ 328 Namespace: "default", 329 Name: "gateway-with-non-existent-gateway-class", 330 } 331 result, err := r.Reconcile(context.Background(), ctrl.Request{ 332 NamespacedName: key, 333 }) 334 335 require.NoError(t, err) 336 require.Equal(t, ctrl.Result{}, result) 337 }) 338 339 t.Run("valid http gateway", func(t *testing.T) { 340 key := client.ObjectKey{ 341 Namespace: "default", 342 Name: "valid-gateway", 343 } 344 result, err := r.Reconcile(context.Background(), ctrl.Request{NamespacedName: key}) 345 346 // First reconcile should wait for LB status before writing addresses into Ingress status 347 require.NoError(t, err) 348 require.Equal(t, ctrl.Result{}, result) 349 350 gw := &gatewayv1.Gateway{} 351 err = c.Get(context.Background(), key, gw) 352 require.NoError(t, err) 353 354 // Check that the gateway status has been updated 355 err = c.Get(context.Background(), key, gw) 356 require.NoError(t, err) 357 358 require.Len(t, gw.Status.Conditions, 2) 359 require.Equal(t, "Accepted", gw.Status.Conditions[0].Type) 360 require.Equal(t, "True", string(gw.Status.Conditions[0].Status)) 361 require.Equal(t, "Gateway successfully scheduled", gw.Status.Conditions[0].Message) 362 require.Equal(t, "Programmed", gw.Status.Conditions[1].Type) 363 require.Equal(t, "True", string(gw.Status.Conditions[1].Status)) 364 require.Equal(t, "Gateway successfully reconciled", gw.Status.Conditions[1].Message) 365 366 require.Len(t, gw.Status.Addresses, 1) 367 require.Equal(t, "IPAddress", string(*gw.Status.Addresses[0].Type)) 368 require.Equal(t, "10.10.10.10", gw.Status.Addresses[0].Value) 369 370 require.Len(t, gw.Status.Listeners, 1) 371 require.Equal(t, "http", string(gw.Status.Listeners[0].Name)) 372 require.Len(t, gw.Status.Listeners[0].Conditions, 3) 373 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Type) 374 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[0].Status)) 375 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Reason) 376 require.Equal(t, "Listener Programmed", gw.Status.Listeners[0].Conditions[0].Message) 377 require.Equal(t, "Accepted", gw.Status.Listeners[0].Conditions[1].Type) 378 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[1].Status)) 379 require.Equal(t, "ResolvedRefs", gw.Status.Listeners[0].Conditions[2].Type) 380 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[2].Status)) 381 }) 382 383 t.Run("valid http gateway - long name", func(t *testing.T) { 384 key := client.ObjectKey{ 385 Namespace: "long-name-test", 386 Name: "test-long-long-long-long-long-long-long-long-long-long-long-long-name", 387 } 388 result, err := r.Reconcile(context.Background(), ctrl.Request{NamespacedName: key}) 389 390 // First reconcile should wait for LB status before writing addresses into Ingress status 391 require.NoError(t, err) 392 require.Equal(t, ctrl.Result{}, result) 393 394 gw := &gatewayv1.Gateway{} 395 err = c.Get(context.Background(), key, gw) 396 require.NoError(t, err) 397 require.Empty(t, gw.Status.Addresses) 398 399 // Simulate LB service update 400 lb := &corev1.Service{} 401 err = c.Get(context.Background(), client.ObjectKey{Namespace: "long-name-test", Name: "cilium-gateway-test-long-long-long-long-long-long-lo-8tfth549c6"}, lb) 402 require.NoError(t, err) 403 require.Equal(t, corev1.ServiceTypeLoadBalancer, lb.Spec.Type) 404 require.Equal(t, "test-long-long-long-long-long-long-long-long-long-lo-4bftbgh5ht", lb.Labels["io.cilium.gateway/owning-gateway"]) 405 require.Equal(t, "true", lb.Annotations["pre-existing-annotation"]) 406 407 // Update LB status 408 lb.Status.LoadBalancer.Ingress = []corev1.LoadBalancerIngress{ 409 { 410 IP: "10.10.10.20", 411 Ports: []corev1.PortStatus{ 412 { 413 Port: 80, 414 Protocol: "TCP", 415 }, 416 }, 417 }, 418 } 419 err = c.Status().Update(context.Background(), lb) 420 require.NoError(t, err) 421 422 // Perform second reconciliation 423 result, err = r.Reconcile(context.Background(), ctrl.Request{NamespacedName: key}) 424 require.NoError(t, err) 425 require.Equal(t, ctrl.Result{}, result) 426 427 // Check that the gateway status has been updated 428 err = c.Get(context.Background(), key, gw) 429 require.NoError(t, err) 430 431 require.Len(t, gw.Status.Conditions, 2) 432 require.Equal(t, "Accepted", gw.Status.Conditions[0].Type) 433 require.Equal(t, "True", string(gw.Status.Conditions[0].Status)) 434 require.Equal(t, "Gateway successfully scheduled", gw.Status.Conditions[0].Message) 435 require.Equal(t, "Programmed", gw.Status.Conditions[1].Type) 436 require.Equal(t, "True", string(gw.Status.Conditions[1].Status)) 437 require.Equal(t, "Gateway successfully reconciled", gw.Status.Conditions[1].Message) 438 439 require.Len(t, gw.Status.Addresses, 1) 440 require.Equal(t, "IPAddress", string(*gw.Status.Addresses[0].Type)) 441 require.Equal(t, "10.10.10.20", gw.Status.Addresses[0].Value) 442 443 require.Len(t, gw.Status.Listeners, 1) 444 require.Equal(t, "http", string(gw.Status.Listeners[0].Name)) 445 require.Len(t, gw.Status.Listeners[0].Conditions, 3) 446 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Type) 447 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[0].Status)) 448 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Reason) 449 require.Equal(t, "Listener Programmed", gw.Status.Listeners[0].Conditions[0].Message) 450 require.Equal(t, "Accepted", gw.Status.Listeners[0].Conditions[1].Type) 451 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[1].Status)) 452 require.Equal(t, "ResolvedRefs", gw.Status.Listeners[0].Conditions[2].Type) 453 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[2].Status)) 454 }) 455 456 t.Run("valid tls gateway", func(t *testing.T) { 457 key := client.ObjectKey{ 458 Namespace: "default", 459 Name: "valid-tlsroute-gateway", 460 } 461 result, err := r.Reconcile(context.Background(), ctrl.Request{NamespacedName: key}) 462 463 // First reconcile should wait for LB status before writing addresses into Ingress status 464 require.NoError(t, err) 465 require.Equal(t, ctrl.Result{}, result) 466 467 gw := &gatewayv1.Gateway{} 468 err = c.Get(context.Background(), key, gw) 469 require.NoError(t, err) 470 require.Empty(t, gw.Status.Addresses) 471 472 // Simulate LB service update 473 lb := &corev1.Service{} 474 err = c.Get(context.Background(), client.ObjectKey{Namespace: "default", Name: "cilium-gateway-valid-tlsroute-gateway"}, lb) 475 require.NoError(t, err) 476 require.Equal(t, corev1.ServiceTypeLoadBalancer, lb.Spec.Type) 477 require.Equal(t, "valid-tlsroute-gateway", lb.Labels["io.cilium.gateway/owning-gateway"]) 478 479 // Update LB status 480 lb.Status.LoadBalancer.Ingress = []corev1.LoadBalancerIngress{ 481 { 482 IP: "10.10.10.11", 483 Ports: []corev1.PortStatus{ 484 { 485 Port: 443, 486 Protocol: "TCP", 487 }, 488 }, 489 }, 490 } 491 err = c.Status().Update(context.Background(), lb) 492 require.NoError(t, err) 493 494 // Perform second reconciliation 495 result, err = r.Reconcile(context.Background(), ctrl.Request{NamespacedName: key}) 496 require.NoError(t, err) 497 require.Equal(t, ctrl.Result{}, result) 498 499 // Check that the gateway status has been updated 500 err = c.Get(context.Background(), key, gw) 501 require.NoError(t, err) 502 503 require.Len(t, gw.Status.Conditions, 2) 504 require.Equal(t, "Accepted", gw.Status.Conditions[0].Type) 505 require.Equal(t, "True", string(gw.Status.Conditions[0].Status)) 506 require.Equal(t, "Gateway successfully scheduled", gw.Status.Conditions[0].Message) 507 require.Equal(t, "Programmed", gw.Status.Conditions[1].Type) 508 require.Equal(t, "True", string(gw.Status.Conditions[1].Status)) 509 require.Equal(t, "Gateway successfully reconciled", gw.Status.Conditions[1].Message) 510 511 require.Len(t, gw.Status.Addresses, 1) 512 require.Equal(t, "IPAddress", string(*gw.Status.Addresses[0].Type)) 513 require.Equal(t, "10.10.10.11", gw.Status.Addresses[0].Value) 514 515 require.Len(t, gw.Status.Listeners, 1) 516 require.Equal(t, "tls", string(gw.Status.Listeners[0].Name)) 517 require.Len(t, gw.Status.Listeners[0].Conditions, 3) 518 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Type) 519 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[0].Status)) 520 require.Equal(t, "Programmed", gw.Status.Listeners[0].Conditions[0].Reason) 521 require.Equal(t, "Listener Programmed", gw.Status.Listeners[0].Conditions[0].Message) 522 require.Equal(t, "Accepted", gw.Status.Listeners[0].Conditions[1].Type) 523 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[1].Status)) 524 require.Equal(t, "ResolvedRefs", gw.Status.Listeners[0].Conditions[2].Type) 525 require.Equal(t, "True", string(gw.Status.Listeners[0].Conditions[2].Status)) 526 }) 527 } 528 529 func Test_isValidPemFormat(t *testing.T) { 530 cert := []byte(`-----BEGIN CERTIFICATE----- 531 MIIENDCCApygAwIBAgIRAKD/BLFBfwKIZ0WGrHtTH6gwDQYJKoZIhvcNAQELBQAw 532 dzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSYwJAYDVQQLDB10YW1t 533 YWNoQGZlZG9yYS5sYW4gKFRhbSBNYWNoKTEtMCsGA1UEAwwkbWtjZXJ0IHRhbW1h 534 Y2hAZmVkb3JhLmxhbiAoVGFtIE1hY2gpMB4XDTIzMDIyMTExMDg0M1oXDTI1MDUy 535 MTEyMDg0M1owUTEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmlj 536 YXRlMSYwJAYDVQQLDB10YW1tYWNoQGZlZG9yYS5sYW4gKFRhbSBNYWNoKTCCASIw 537 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMIZy+0JRVjqpWgeq2dP+1oliO4A 538 CcZnMg4tSqPalhDQL6Mf68HYLfizyJIpRzMJ905rYd0AcmXmu/g0Eo8ykHxFDz5T 539 sePs2XQng8MN4azsRmm1l4f74ovawQzQcb822QP1CS6ILZ3VtwNjRh2nAwthYBMo 540 CkngDGeQ8Gl0tjHLFnBdTdSwQRmE2jtDBcAgyEGpq+6ReYt+/47nNn7dCftsVqhE 541 BYr9XH3itefHmsbfj7zWFbptdko7q9lMHwnBd+0hd40MmJIXMZrOGGFZjawJDBqS 542 sBq2Q3l6XQz8X7P/GA8Dn8h4w3rppmiaN7LOmGXeki3xX2wqnM+0s6aZYZsCAwEA 543 AaNhMF8wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1Ud 544 IwQYMBaAFGQ2DB06CdQFQBsYPye0NBwErUNEMBcGA1UdEQQQMA6CDHVuaXR0ZXN0 545 LmNvbTANBgkqhkiG9w0BAQsFAAOCAYEArtHdKWXR6aELpfal17biabCPvIF9j6nw 546 uDzcdMYQLrXm8M+NHe8x3dpI7u3lltO+dzLng+nVKQOR3alQACSmRD9c7ie8eT5d 547 7zKOTk6keY195I1wVV4jbNLbNWa9y4RJQRTvBLAvAP9NVtUw2Q/w/ErUTqSyz+ob 548 dwnt4gYCw6dGnluLxlfF34DB9KflvVNSnkyMB/gsB4A3r1GPOIo0Gyf74ig3FWrS 549 wHYKnBbtZfYO0JV0LCoPyHe8g0XajZe8DCbP/E6SmlTNAmJESVjigTTcIBAkFI+n 550 toBAdxfhjKUGaClOHS29cpaiynjSayGm4RkHkx7mcAua9lWPf7pSa3mCcFb+wFr3 551 ABkHDPJH2acfaUK1vgKTgOwcG/6KA820/PraoSihLaPK/A7eg77r1EeYpt0Neppb 552 XjvUp3YmVlIMZXPzrjOsastoDSrsygj5jdVtm4Pslv9nPhzDrBjlZpEJScW4Jlb+ 553 6wtd7p03UDBSKfTbVROVAe5mvJvA0hoS 554 -----END CERTIFICATE----- 555 `) 556 key := []byte(`-----BEGIN PRIVATE KEY----- 557 MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDCGcvtCUVY6qVo 558 HqtnT/taJYjuAAnGZzIOLUqj2pYQ0C+jH+vB2C34s8iSKUczCfdOa2HdAHJl5rv4 559 NBKPMpB8RQ8+U7Hj7Nl0J4PDDeGs7EZptZeH++KL2sEM0HG/NtkD9QkuiC2d1bcD 560 Y0YdpwMLYWATKApJ4AxnkPBpdLYxyxZwXU3UsEEZhNo7QwXAIMhBqavukXmLfv+O 561 5zZ+3Qn7bFaoRAWK/Vx94rXnx5rG34+81hW6bXZKO6vZTB8JwXftIXeNDJiSFzGa 562 zhhhWY2sCQwakrAatkN5el0M/F+z/xgPA5/IeMN66aZomjeyzphl3pIt8V9sKpzP 563 tLOmmWGbAgMBAAECggEAEjASoMJ2og9Ssn/1NbgT6G2N+Cc+wz2WPifWT6ZC2452 564 eEWcdMyJ+jz2dWOyzUCI0OtU/z10esH1KRvQBWUKjup1tDRpfd8KvUyalyNs2yRE 565 sNEYQuDCaLJ11nqNvgooqatDUf3msFx/Sqz5u/uTWHSmaQUeea+p2eaF8IvEKsQf 566 6QNklkeHsv+GVPv+iibfbXXne6I5aV35Rc4Q08zRCgYX/BN1AYXV6ho4RC9dZVGP 567 JUkSLzRadegok/EONKkrqLZOFJVb2wtFq85gJ01lODM/gj7GqM59M/wk55CaQIRD 568 9x5H4X4rpM2rhmiNLkIN0tGLKO8X31up7hTx9bvJcQKBgQD51MLWYYUPz/umvSrN 569 QOT9UhEHI/bxtCbWQthW3L1qrVT7DB8Jko/6/xYlXhl7nwVwJz24jJf9vuxWbBpL 570 HZRf0QsDO2/O4rqhKDov/GMUCx2shzc+J7k+T93KNVANYa05guqMeB8n30HProkF 571 LgihVFF20k9Z6SibUvgTMpF1EwKBgQDG5MBgc8oFXmlr/7pHKizC4F3eDAXUxVHM 572 WCIbSwMyzOXKqDcdXNDz8cQrjhKa2rD1fKhE0oRR+QvHz8IPC+0MsT7Q6QsIHYj5 573 CXubHr0s5k8PJAp+Lk2EdHePZQM/I/vj/gSwxnJ9Qs64FWZ25K9zYnNNsiojQel7 574 WVmI9IVaWQKBgD3BYggsQwANoV8uE455JCGaT6s8MKa+qXr9Owz9s7TS89a6wFFV 575 cVHSDF9gS1xLisSWbqNX3ZpTv4f9YOKAhVTKD7bU0maJlSiREREbikJCHSuwoO80 576 Uo4cn+6EDy2/n1pACkp+xvTMMzBrLGOjZW67sQd2JTdMc0Ux1TCpp1sRAoGAaEVI 577 rchGYyYp8pqw19o+eTQTQfPforqHta+GwfRDiwBsgCBMNLKSQTHAfG0RR+na1/gw 578 Z1ROVoNQL8K1pBnGft71ZaSnSeviAV19Vcd5ue5MCE4GyjwQG57Lh3uXhiShS9fC 579 McL4Br9djJh7jV06ti0o8dSzzqQhea9QB0LaHpECgYApc8oBoiK69s0wXyI4+Phx 580 ScBJ0XqDBYFkxyXr8Y5pEarEaqCtl1OPPMOiQRDWoxRR+FwA/0laSfh5xw0U3b+q 581 iZ2XpkrbQp034rC0UR6p+Km1Sv9AVCACAjrcQ3NZaf8bDOWqvpla7Auq0oG8i6UX 582 hEKCKf/N3gE1oMrTxVzUDQ== 583 -----END PRIVATE KEY----- 584 `) 585 keyAndCert := append(key, cert...) 586 type args struct { 587 b []byte 588 } 589 tests := []struct { 590 name string 591 args args 592 want bool 593 }{ 594 { 595 name: "valid cert pem", 596 args: args{ 597 b: cert, 598 }, 599 want: true, 600 }, 601 { 602 name: "value key pem", 603 args: args{ 604 b: key, 605 }, 606 want: true, 607 }, 608 { 609 name: "multiple valid pem blocks", 610 args: args{ 611 b: keyAndCert, 612 }, 613 want: true, 614 }, 615 { 616 name: "invalid first block", 617 args: args{ 618 b: append([]byte("invalid block"), key...), 619 }, 620 want: false, 621 }, 622 { 623 name: "invalid subsequent block", 624 args: args{ 625 b: append(keyAndCert, []byte("invalid block")...), 626 }, 627 want: false, 628 }, 629 { 630 name: "invalid pem", 631 args: args{ 632 b: []byte("invalid pem"), 633 }, 634 want: false, 635 }, 636 } 637 for _, tt := range tests { 638 t.Run(tt.name, func(t *testing.T) { 639 assert.Equalf(t, tt.want, isValidPemFormat(tt.args.b), "isValidPemFormat(%v)", tt.args.b) 640 }) 641 } 642 } 643 644 func Test_sectionNameMatched(t *testing.T) { 645 httpListener := &gatewayv1.Listener{ 646 Name: "http", 647 Port: 80, 648 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.io"), 649 Protocol: "HTTP", 650 } 651 httpNoMatchListener := &gatewayv1.Listener{ 652 Name: "http-no-match", 653 Port: 8080, 654 Hostname: model.AddressOf[gatewayv1.Hostname]("*.cilium.io"), 655 Protocol: "HTTP", 656 } 657 gw := &gatewayv1.Gateway{ 658 TypeMeta: metav1.TypeMeta{ 659 Kind: "Gateway", 660 APIVersion: gatewayv1.GroupName, 661 }, 662 ObjectMeta: metav1.ObjectMeta{ 663 Name: "valid-gateway", 664 Namespace: "default", 665 }, 666 Spec: gatewayv1.GatewaySpec{ 667 GatewayClassName: "cilium", 668 Listeners: []gatewayv1.Listener{ 669 *httpListener, 670 *httpNoMatchListener, 671 }, 672 }, 673 } 674 type args struct { 675 routeNamespace string 676 listener *gatewayv1.Listener 677 refs []gatewayv1.ParentReference 678 } 679 tests := []struct { 680 name string 681 args args 682 want bool 683 }{ 684 { 685 name: "Matching Section name", 686 args: args{ 687 listener: httpListener, 688 refs: []gatewayv1.ParentReference{ 689 { 690 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 691 Name: "valid-gateway", 692 SectionName: (*gatewayv1.SectionName)(model.AddressOf("http")), 693 }, 694 }, 695 }, 696 want: true, 697 }, 698 { 699 name: "Not matching Section name", 700 args: args{ 701 listener: httpNoMatchListener, 702 refs: []gatewayv1.ParentReference{ 703 { 704 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 705 Name: "valid-gateway", 706 SectionName: (*gatewayv1.SectionName)(model.AddressOf("http")), 707 }, 708 }, 709 }, 710 want: false, 711 }, 712 { 713 name: "Matching Port number", 714 args: args{ 715 listener: httpListener, 716 refs: []gatewayv1.ParentReference{ 717 { 718 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 719 Name: "valid-gateway", 720 Port: (*gatewayv1.PortNumber)(model.AddressOf[int32](80)), 721 }, 722 }, 723 }, 724 want: true, 725 }, 726 { 727 name: "No matching Port number", 728 args: args{ 729 listener: httpNoMatchListener, 730 refs: []gatewayv1.ParentReference{ 731 { 732 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 733 Name: "valid-gateway", 734 Port: (*gatewayv1.PortNumber)(model.AddressOf[int32](80)), 735 }, 736 }, 737 }, 738 want: false, 739 }, 740 { 741 name: "Matching both Section name and Port number", 742 args: args{ 743 listener: httpListener, 744 refs: []gatewayv1.ParentReference{ 745 { 746 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 747 Name: "valid-gateway", 748 SectionName: (*gatewayv1.SectionName)(model.AddressOf("http")), 749 Port: (*gatewayv1.PortNumber)(model.AddressOf[int32](80)), 750 }, 751 }, 752 }, 753 want: true, 754 }, 755 { 756 name: "Matching any listener (httpListener)", 757 args: args{ 758 listener: httpListener, 759 refs: []gatewayv1.ParentReference{ 760 { 761 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 762 Name: "valid-gateway", 763 }, 764 }, 765 }, 766 want: true, 767 }, 768 { 769 name: "Matching any listener (httpNoMatchListener)", 770 args: args{ 771 listener: httpNoMatchListener, 772 refs: []gatewayv1.ParentReference{ 773 { 774 Kind: (*gatewayv1.Kind)(model.AddressOf("Gateway")), 775 Name: "valid-gateway", 776 }, 777 }, 778 }, 779 want: true, 780 }, 781 } 782 for _, tt := range tests { 783 t.Run(tt.name, func(t *testing.T) { 784 assert.Equalf(t, tt.want, parentRefMatched(gw, tt.args.listener, "default", tt.args.refs), "parentRefMatched(%v, %v, %v, %v)", gw, tt.args.listener, tt.args.routeNamespace, tt.args.refs) 785 }) 786 } 787 }