diff --git a/pkg/i2gw/intermediate/provider_gce.go b/pkg/i2gw/intermediate/provider_gce.go index 4cfa94ad..f53f397f 100644 --- a/pkg/i2gw/intermediate/provider_gce.go +++ b/pkg/i2gw/intermediate/provider_gce.go @@ -27,6 +27,7 @@ type GceHTTPRouteIR struct{} type GceServiceIR struct { SessionAffinity *SessionAffinityConfig SecurityPolicy *SecurityPolicyConfig + HealthCheck *HealthCheckConfig } type SessionAffinityConfig struct { AffinityType string @@ -35,6 +36,15 @@ type SessionAffinityConfig struct { type SecurityPolicyConfig struct { Name string } +type HealthCheckConfig struct { + CheckIntervalSec *int64 + TimeoutSec *int64 + HealthyThreshold *int64 + UnhealthyThreshold *int64 + Type *string + Port *int64 + RequestPath *string +} func mergeGceGatewayIR(current, existing *GceGatewayIR) *GceGatewayIR { // If either GceGatewayIR is nil, return the other one as the merged result. diff --git a/pkg/i2gw/providers/gce/extensions/input_extensions.go b/pkg/i2gw/providers/gce/extensions/input_extensions.go index 6dabe62b..413a9849 100644 --- a/pkg/i2gw/providers/gce/extensions/input_extensions.go +++ b/pkg/i2gw/providers/gce/extensions/input_extensions.go @@ -20,17 +20,24 @@ import ( "fmt" "github.com/kubernetes-sigs/ingress2gateway/pkg/i2gw/intermediate" + "k8s.io/apimachinery/pkg/util/sets" backendconfigv1 "k8s.io/ingress-gce/pkg/apis/backendconfig/v1" frontendconfigv1beta1 "k8s.io/ingress-gce/pkg/apis/frontendconfig/v1beta1" ) +var supportedHcProtocol = sets.NewString("HTTP", "HTTPS", "HTTP2") + func ValidateBeConfig(beConfig *backendconfigv1.BackendConfig) error { if beConfig.Spec.SessionAffinity != nil { if err := validateSessionAffinity(beConfig); err != nil { return err } } - + if beConfig.Spec.HealthCheck != nil { + if err := validateHealthCheck(beConfig); err != nil { + return err + } + } return nil } @@ -41,6 +48,18 @@ func validateSessionAffinity(beConfig *backendconfigv1.BackendConfig) error { return nil } +func validateHealthCheck(beConfig *backendconfigv1.BackendConfig) error { + hcType := beConfig.Spec.HealthCheck.Type + if hcType == nil { + return fmt.Errorf("HealthCheck Protocol type is not specified") + } + + if !supportedHcProtocol.Has(*hcType) { + return fmt.Errorf("Protocol %q is not valid, must be one of %v", *hcType, supportedHcProtocol) + } + return nil +} + func BuildIRSessionAffinityConfig(beConfig *backendconfigv1.BackendConfig) *intermediate.SessionAffinityConfig { return &intermediate.SessionAffinityConfig{ AffinityType: beConfig.Spec.SessionAffinity.AffinityType, @@ -59,3 +78,15 @@ func BuildIRSslPolicyConfig(feConfig *frontendconfigv1beta1.FrontendConfig) *int Name: *feConfig.Spec.SslPolicy, } } + +func BuildIRHealthCheckConfig(beConfig *backendconfigv1.BackendConfig) *intermediate.HealthCheckConfig { + return &intermediate.HealthCheckConfig{ + CheckIntervalSec: beConfig.Spec.HealthCheck.CheckIntervalSec, + TimeoutSec: beConfig.Spec.HealthCheck.TimeoutSec, + HealthyThreshold: beConfig.Spec.HealthCheck.HealthyThreshold, + UnhealthyThreshold: beConfig.Spec.HealthCheck.UnhealthyThreshold, + Type: beConfig.Spec.HealthCheck.Type, + Port: beConfig.Spec.HealthCheck.Port, + RequestPath: beConfig.Spec.HealthCheck.RequestPath, + } +} diff --git a/pkg/i2gw/providers/gce/extensions/output_extensions.go b/pkg/i2gw/providers/gce/extensions/output_extensions.go index 5962e000..6291b61a 100644 --- a/pkg/i2gw/providers/gce/extensions/output_extensions.go +++ b/pkg/i2gw/providers/gce/extensions/output_extensions.go @@ -40,3 +40,52 @@ func BuildGCPBackendPolicySecurityPolicyConfig(serviceIR intermediate.ProviderSp func BuildGCPGatewayPolicySecurityPolicyConfig(gatewayIR intermediate.ProviderSpecificGatewayIR) string { return gatewayIR.Gce.SslPolicy.Name } + +func BuildHealthCheckPolicyConfig(serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.HealthCheckPolicyConfig { + hcConfig := gkegatewayv1.HealthCheckPolicyConfig{ + CheckIntervalSec: serviceIR.Gce.HealthCheck.CheckIntervalSec, + TimeoutSec: serviceIR.Gce.HealthCheck.TimeoutSec, + HealthyThreshold: serviceIR.Gce.HealthCheck.HealthyThreshold, + UnhealthyThreshold: serviceIR.Gce.HealthCheck.UnhealthyThreshold, + } + commonHc := gkegatewayv1.CommonHealthCheck{ + Port: serviceIR.Gce.HealthCheck.Port, + } + commonHTTPHc := gkegatewayv1.CommonHTTPHealthCheck{ + RequestPath: serviceIR.Gce.HealthCheck.RequestPath, + } + + switch *serviceIR.Gce.HealthCheck.Type { + case "HTTP": + hcConfig.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTP, + HTTP: &gkegatewayv1.HTTPHealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + + case "HTTPS": + hcConfig.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTPS, + HTTPS: &gkegatewayv1.HTTPSHealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + + case "HTTP2": + hcConfig.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTP2, + HTTP2: &gkegatewayv1.HTTP2HealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + + default: + return nil + } + + return &hcConfig +} diff --git a/pkg/i2gw/providers/gce/gateway_converter.go b/pkg/i2gw/providers/gce/gateway_converter.go index e7f3f86a..fce436cc 100644 --- a/pkg/i2gw/providers/gce/gateway_converter.go +++ b/pkg/i2gw/providers/gce/gateway_converter.go @@ -94,15 +94,24 @@ func addGatewayPolicyIfConfigured(gatewayNamespacedName types.NamespacedName, ga func buildGceServiceExtensions(ir intermediate.IR, gatewayResources *i2gw.GatewayResources) { for svcKey, serviceIR := range ir.Services { bePolicy := addGCPBackendPolicyIfConfigured(svcKey, serviceIR) - if bePolicy == nil { - continue + if bePolicy != nil { + obj, err := i2gw.CastToUnstructured(bePolicy) + if err != nil { + notify(notifications.ErrorNotification, "Failed to cast GCPBackendPolicy to unstructured", bePolicy) + continue + } + gatewayResources.GatewayExtensions = append(gatewayResources.GatewayExtensions, *obj) } - obj, err := i2gw.CastToUnstructured(bePolicy) - if err != nil { - notify(notifications.ErrorNotification, "Failed to cast GCPBackendPolicy to unstructured", bePolicy) - continue + + hcPolicy := addHealthCheckPolicyIfConfigured(svcKey, serviceIR) + if hcPolicy != nil { + obj, err := i2gw.CastToUnstructured(hcPolicy) + if err != nil { + notify(notifications.ErrorNotification, "Failed to cast HealthCheckPolicy to unstructured", hcPolicy) + continue + } + gatewayResources.GatewayExtensions = append(gatewayResources.GatewayExtensions, *obj) } - gatewayResources.GatewayExtensions = append(gatewayResources.GatewayExtensions, *obj) } } @@ -110,6 +119,11 @@ func addGCPBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, if serviceIR.Gce == nil { return nil } + // If there is no specification related to GCPBackendPolicy feature, return nil. + if serviceIR.Gce.SessionAffinity == nil && serviceIR.Gce.SecurityPolicy == nil { + return nil + } + gcpBackendPolicy := gkegatewayv1.GCPBackendPolicy{ ObjectMeta: metav1.ObjectMeta{ Namespace: serviceNamespacedName.Namespace, @@ -135,3 +149,30 @@ func addGCPBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, return &gcpBackendPolicy } + +func addHealthCheckPolicyIfConfigured(serviceNamespacedName types.NamespacedName, serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.HealthCheckPolicy { + if serviceIR.Gce == nil { + return nil + } + // If there is no specification related to HealthCheckPolicy feature, return nil. + if serviceIR.Gce.HealthCheck == nil { + return nil + } + + healthCheckPolicy := gkegatewayv1.HealthCheckPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: serviceNamespacedName.Namespace, + Name: serviceNamespacedName.Name, + }, + Spec: gkegatewayv1.HealthCheckPolicySpec{ + Default: extensions.BuildHealthCheckPolicyConfig(serviceIR), + TargetRef: gatewayv1alpha2.NamespacedPolicyTargetReference{ + Group: "", + Kind: "Service", + Name: gatewayv1.ObjectName(serviceNamespacedName.Name), + }, + }, + } + healthCheckPolicy.SetGroupVersionKind(HealthCheckPolicyGVK) + return &healthCheckPolicy +} diff --git a/pkg/i2gw/providers/gce/gateway_converter_test.go b/pkg/i2gw/providers/gce/gateway_converter_test.go index 4f17b542..3e695a6e 100644 --- a/pkg/i2gw/providers/gce/gateway_converter_test.go +++ b/pkg/i2gw/providers/gce/gateway_converter_test.go @@ -345,6 +345,132 @@ func Test_irToGateway(t *testing.T) { }, expectedErrors: field.ErrorList{}, }, + { + name: "ingress with a Backend Config specifying custom HTTP health check", + ir: intermediate.IR{ + Gateways: map[types.NamespacedName]intermediate.GatewayContext{ + {Namespace: testNamespace, Name: testGatewayName}: { + Gateway: testGateway, + }, + }, + HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{ + {Namespace: testNamespace, Name: testHTTPRouteName}: { + HTTPRoute: testHTTPRoute, + }, + }, + Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{ + {Namespace: testNamespace, Name: testServiceName}: { + Gce: &intermediate.GceServiceIR{ + HealthCheck: &intermediate.HealthCheckConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + Type: common.PtrTo(protocolHTTP), + Port: common.PtrTo(testPort), + RequestPath: common.PtrTo(testRequestPath), + }, + }, + }, + }, + }, + expectedGatewayResources: i2gw.GatewayResources{ + Gateways: map[types.NamespacedName]gatewayv1.Gateway{ + {Namespace: testNamespace, Name: testGatewayName}: testGateway, + }, + HTTPRoutes: map[types.NamespacedName]gatewayv1.HTTPRoute{ + {Namespace: testNamespace, Name: testHTTPRouteName}: testHTTPRoute, + }, + GatewayExtensions: []unstructured.Unstructured{ + getTestHealthCheckPolicyUnstrctured(testNamespace, testServiceName, protocolHTTP), + }, + }, + expectedErrors: field.ErrorList{}, + }, + { + name: "ingress with a Backend Config specifying custom HTTPS health check", + ir: intermediate.IR{ + Gateways: map[types.NamespacedName]intermediate.GatewayContext{ + {Namespace: testNamespace, Name: testGatewayName}: { + Gateway: testGateway, + }, + }, + HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{ + {Namespace: testNamespace, Name: testHTTPRouteName}: { + HTTPRoute: testHTTPRoute, + }, + }, + Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{ + {Namespace: testNamespace, Name: testServiceName}: { + Gce: &intermediate.GceServiceIR{ + HealthCheck: &intermediate.HealthCheckConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + Type: common.PtrTo(protocolHTTPS), + Port: common.PtrTo(testPort), + RequestPath: common.PtrTo(testRequestPath), + }, + }, + }, + }, + }, + expectedGatewayResources: i2gw.GatewayResources{ + Gateways: map[types.NamespacedName]gatewayv1.Gateway{ + {Namespace: testNamespace, Name: testGatewayName}: testGateway, + }, + HTTPRoutes: map[types.NamespacedName]gatewayv1.HTTPRoute{ + {Namespace: testNamespace, Name: testHTTPRouteName}: testHTTPRoute, + }, + GatewayExtensions: []unstructured.Unstructured{ + getTestHealthCheckPolicyUnstrctured(testNamespace, testServiceName, protocolHTTPS), + }, + }, + expectedErrors: field.ErrorList{}, + }, + { + name: "ingress with a Backend Config specifying custom HTTP2 health check", + ir: intermediate.IR{ + Gateways: map[types.NamespacedName]intermediate.GatewayContext{ + {Namespace: testNamespace, Name: testGatewayName}: { + Gateway: testGateway, + }, + }, + HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{ + {Namespace: testNamespace, Name: testHTTPRouteName}: { + HTTPRoute: testHTTPRoute, + }, + }, + Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{ + {Namespace: testNamespace, Name: testServiceName}: { + Gce: &intermediate.GceServiceIR{ + HealthCheck: &intermediate.HealthCheckConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + Type: common.PtrTo(protocolHTTP2), + Port: common.PtrTo(testPort), + RequestPath: common.PtrTo(testRequestPath), + }, + }, + }, + }, + }, + expectedGatewayResources: i2gw.GatewayResources{ + Gateways: map[types.NamespacedName]gatewayv1.Gateway{ + {Namespace: testNamespace, Name: testGatewayName}: testGateway, + }, + HTTPRoutes: map[types.NamespacedName]gatewayv1.HTTPRoute{ + {Namespace: testNamespace, Name: testHTTPRouteName}: testHTTPRoute, + }, + GatewayExtensions: []unstructured.Unstructured{ + getTestHealthCheckPolicyUnstrctured(testNamespace, testServiceName, protocolHTTP2), + }, + }, + expectedErrors: field.ErrorList{}, + }, } for _, tc := range testCases { @@ -412,3 +538,71 @@ func Test_irToGateway(t *testing.T) { }) } } + +// getTestHealthCheckPolicyUnstrctured returns the template HealthCheckPolicy +// based on the protocol and the service it attaches to. +func getTestHealthCheckPolicyUnstrctured(serviceNamespace, serviceName, protocol string) unstructured.Unstructured { + commonHc := gkegatewayv1.CommonHealthCheck{ + Port: common.PtrTo(testPort), + } + commonHTTPHc := gkegatewayv1.CommonHTTPHealthCheck{ + RequestPath: common.PtrTo(testRequestPath), + } + + hcPolicy := gkegatewayv1.HealthCheckPolicy{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "networking.gke.io/v1", + Kind: "HealthCheckPolicy", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: serviceNamespace, + Name: serviceName, // Converted Health Check Policy will share the name of the service it attaches to. + }, + Spec: gkegatewayv1.HealthCheckPolicySpec{ + Default: &gkegatewayv1.HealthCheckPolicyConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + }, + TargetRef: v1alpha2.NamespacedPolicyTargetReference{ + Group: "", + Kind: "Service", + Name: gatewayv1.ObjectName(serviceName), + }, + }, + } + if protocol == protocolHTTP { + hcPolicy.Spec.Default.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTP, + HTTP: &gkegatewayv1.HTTPHealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + } else if protocol == protocolHTTPS { + hcPolicy.Spec.Default.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTPS, + HTTPS: &gkegatewayv1.HTTPSHealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + } else if protocol == protocolHTTP2 { + hcPolicy.Spec.Default.Config = &gkegatewayv1.HealthCheck{ + Type: gkegatewayv1.HTTP2, + HTTP2: &gkegatewayv1.HTTP2HealthCheck{ + CommonHealthCheck: commonHc, + CommonHTTPHealthCheck: commonHTTPHc, + }, + } + } else { + return unstructured.Unstructured{} + } + hcPolicyUnstructured, err := i2gw.CastToUnstructured(&hcPolicy) + if err != nil { + return unstructured.Unstructured{} + } + + return *hcPolicyUnstructured +} diff --git a/pkg/i2gw/providers/gce/ir_converter.go b/pkg/i2gw/providers/gce/ir_converter.go index b3b03d53..d1c1179b 100644 --- a/pkg/i2gw/providers/gce/ir_converter.go +++ b/pkg/i2gw/providers/gce/ir_converter.go @@ -266,6 +266,9 @@ func beConfigToGceServiceIR(beConfig *backendconfigv1.BackendConfig) intermediat if beConfig.Spec.SecurityPolicy != nil { gceServiceIR.SecurityPolicy = extensions.BuildIRSecurityPolicyConfig(beConfig) } + if beConfig.Spec.HealthCheck != nil { + gceServiceIR.HealthCheck = extensions.BuildIRHealthCheckConfig(beConfig) + } return gceServiceIR } diff --git a/pkg/i2gw/providers/gce/ir_converter_test.go b/pkg/i2gw/providers/gce/ir_converter_test.go index 9b06a608..6ba7fc41 100644 --- a/pkg/i2gw/providers/gce/ir_converter_test.go +++ b/pkg/i2gw/providers/gce/ir_converter_test.go @@ -56,6 +56,15 @@ const ( testSecurityPolicy = "test-security-policy" testCookieTTLSec = int64(10) testSslPolicy = "test-ssl-policy" + testCheckIntervalSec = int64(5) + testTimeoutSec = int64(10) + testHealthyThreshold = int64(2) + testUnhealthyThreshold = int64(3) + protocolHTTP = "HTTP" + protocolHTTPS = "HTTPS" + protocolHTTP2 = "HTTP2" + testPort = int64(8081) + testRequestPath = "/foo" ) func Test_convertToIR(t *testing.T) { @@ -467,7 +476,7 @@ func Test_convertToIR(t *testing.T) { }, } storage.BackendConfigs = map[types.NamespacedName]*backendconfigv1.BackendConfig{ - {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(testNamespace, testBackendConfigName, beConfigSpec), + {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(beConfigSpec), } }, expectedIR: intermediate.IR{ @@ -552,7 +561,7 @@ func Test_convertToIR(t *testing.T) { }, } storage.BackendConfigs = map[types.NamespacedName]*backendconfigv1.BackendConfig{ - {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(testNamespace, testBackendConfigName, beConfigSpec), + {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(beConfigSpec), } }, expectedIR: intermediate.IR{ @@ -637,7 +646,7 @@ func Test_convertToIR(t *testing.T) { }, } storage.BackendConfigs = map[types.NamespacedName]*backendconfigv1.BackendConfig{ - {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(testNamespace, testBackendConfigName, beConfigSpec), + {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(beConfigSpec), } }, expectedIR: intermediate.IR{ @@ -706,6 +715,102 @@ func Test_convertToIR(t *testing.T) { }, expectedErrors: field.ErrorList{}, }, + { + name: "ingress with a Backend Config specifying custom HTTP Health Check", + modify: func(storage *storage) { + testService := storage.Services[types.NamespacedName{Namespace: testNamespace, Name: testServiceName}] + testService.Annotations = map[string]string{ + backendConfigKey: `{"default":"test-backendconfig"}`, + } + storage.Services[types.NamespacedName{Namespace: testNamespace, Name: testServiceName}] = testService + + beConfigSpec := backendconfigv1.BackendConfigSpec{ + HealthCheck: &backendconfigv1.HealthCheckConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + Type: common.PtrTo(protocolHTTP), + Port: common.PtrTo(testPort), + RequestPath: common.PtrTo(testRequestPath), + }, + } + storage.BackendConfigs = map[types.NamespacedName]*backendconfigv1.BackendConfig{ + {Namespace: testNamespace, Name: testBackendConfigName}: getTestBackendConfig(beConfigSpec), + } + }, + expectedIR: intermediate.IR{ + Gateways: map[types.NamespacedName]intermediate.GatewayContext{ + {Namespace: testNamespace, Name: gceIngressClass}: { + Gateway: gatewayv1.Gateway{ + ObjectMeta: metav1.ObjectMeta{Name: gceIngressClass, Namespace: testNamespace}, + Spec: gatewayv1.GatewaySpec{ + GatewayClassName: gceL7GlobalExternalManagedGatewayClass, + Listeners: []gatewayv1.Listener{{ + Name: "test-mydomain-com-http", + Port: 80, + Protocol: gatewayv1.HTTPProtocolType, + Hostname: common.PtrTo(gatewayv1.Hostname(testHost)), + }}, + }, + }, + }, + }, + HTTPRoutes: map[types.NamespacedName]intermediate.HTTPRouteContext{ + {Namespace: testNamespace, Name: fmt.Sprintf("%s-test-mydomain-com", testIngressName)}: { + HTTPRoute: gatewayv1.HTTPRoute{ + ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("%s-test-mydomain-com", testIngressName), Namespace: testNamespace}, + Spec: gatewayv1.HTTPRouteSpec{ + CommonRouteSpec: gatewayv1.CommonRouteSpec{ + ParentRefs: []gatewayv1.ParentReference{{ + Name: gceIngressClass, + }}, + }, + Hostnames: []gatewayv1.Hostname{gatewayv1.Hostname(testHost)}, + Rules: []gatewayv1.HTTPRouteRule{ + { + Matches: []gatewayv1.HTTPRouteMatch{ + { + Path: &gatewayv1.HTTPPathMatch{ + Type: common.PtrTo(gPathPrefix), + Value: common.PtrTo("/"), + }, + }, + }, + BackendRefs: []gatewayv1.HTTPBackendRef{ + { + BackendRef: gatewayv1.BackendRef{ + BackendObjectReference: gatewayv1.BackendObjectReference{ + Name: gatewayv1.ObjectName(testServiceName), + Port: common.PtrTo(gatewayv1.PortNumber(80)), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Services: map[types.NamespacedName]intermediate.ProviderSpecificServiceIR{ + {Namespace: testNamespace, Name: testServiceName}: { + Gce: &intermediate.GceServiceIR{ + HealthCheck: &intermediate.HealthCheckConfig{ + CheckIntervalSec: common.PtrTo(testCheckIntervalSec), + TimeoutSec: common.PtrTo(testTimeoutSec), + HealthyThreshold: common.PtrTo(testHealthyThreshold), + UnhealthyThreshold: common.PtrTo(testUnhealthyThreshold), + Type: common.PtrTo(protocolHTTP), + Port: common.PtrTo(testPort), + RequestPath: common.PtrTo(testRequestPath), + }, + }, + }, + }, + }, + expectedErrors: field.ErrorList{}, + }, { name: "ingress with a Frontend Config specifying Ssl Policy", modify: func(storage *storage) { @@ -894,11 +999,11 @@ func getTestIngress(namespace, name, serviceName string) *networkingv1.Ingress { } } -func getTestBackendConfig(namespace, name string, spec backendconfigv1.BackendConfigSpec) *backendconfigv1.BackendConfig { +func getTestBackendConfig(spec backendconfigv1.BackendConfigSpec) *backendconfigv1.BackendConfig { return &backendconfigv1.BackendConfig{ ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, + Namespace: testNamespace, + Name: testBackendConfigName, }, Spec: spec, } diff --git a/pkg/i2gw/providers/gce/types.go b/pkg/i2gw/providers/gce/types.go index b47fd9e8..1eed0b7d 100644 --- a/pkg/i2gw/providers/gce/types.go +++ b/pkg/i2gw/providers/gce/types.go @@ -41,4 +41,10 @@ var ( Version: "v1", Kind: "GCPGatewayPolicy", } + + HealthCheckPolicyGVK = schema.GroupVersionKind{ + Group: "networking.gke.io", + Version: "v1", + Kind: "HealthCheckPolicy", + } )