Skip to content

Commit

Permalink
Add translation for GKE Custom health check (#194)
Browse files Browse the repository at this point in the history
* Convert custom health check into IR

* Add custom HealthCheck conversion.

* Compare protocol with set
  • Loading branch information
sawsa307 authored Sep 30, 2024
1 parent 3ec528d commit 574be1b
Show file tree
Hide file tree
Showing 8 changed files with 453 additions and 14 deletions.
10 changes: 10 additions & 0 deletions pkg/i2gw/intermediate/provider_gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type GceHTTPRouteIR struct{}
type GceServiceIR struct {
SessionAffinity *SessionAffinityConfig
SecurityPolicy *SecurityPolicyConfig
HealthCheck *HealthCheckConfig
}
type SessionAffinityConfig struct {
AffinityType string
Expand All @@ -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.
Expand Down
33 changes: 32 additions & 1 deletion pkg/i2gw/providers/gce/extensions/input_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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,
Expand All @@ -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,
}
}
49 changes: 49 additions & 0 deletions pkg/i2gw/providers/gce/extensions/output_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
55 changes: 48 additions & 7 deletions pkg/i2gw/providers/gce/gateway_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,22 +94,36 @@ 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)
}
}

func addGCPBackendPolicyIfConfigured(serviceNamespacedName types.NamespacedName, serviceIR intermediate.ProviderSpecificServiceIR) *gkegatewayv1.GCPBackendPolicy {
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,
Expand All @@ -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
}
Loading

0 comments on commit 574be1b

Please sign in to comment.