From e9d677f8cbdd86541dde8fb15608f9de978d7b74 Mon Sep 17 00:00:00 2001 From: Will Da Silva Date: Wed, 9 Oct 2024 10:26:04 -0400 Subject: [PATCH] Support http and https appProtocol for Kubernetes Service --- .../kubernetes/gateway/fixtures/services.yml | 3 +++ pkg/provider/kubernetes/gateway/grpcroute.go | 27 ++++++++++++++++--- pkg/provider/kubernetes/gateway/httproute.go | 22 +++++++-------- pkg/provider/kubernetes/gateway/kubernetes.go | 12 ++++++--- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/pkg/provider/kubernetes/gateway/fixtures/services.yml b/pkg/provider/kubernetes/gateway/fixtures/services.yml index d2872a0d7..65376431b 100644 --- a/pkg/provider/kubernetes/gateway/fixtures/services.yml +++ b/pkg/provider/kubernetes/gateway/fixtures/services.yml @@ -96,6 +96,7 @@ spec: - name: web protocol: TCP port: 8080 + appProtocol: http targetPort: web selector: app: containous @@ -131,6 +132,8 @@ metadata: spec: ports: - name: websecure + protocol: TCP + appProtocol: https port: 443 targetPort: websecure selector: diff --git a/pkg/provider/kubernetes/gateway/grpcroute.go b/pkg/provider/kubernetes/gateway/grpcroute.go index 8f8fac13c..021a3909c 100644 --- a/pkg/provider/kubernetes/gateway/grpcroute.go +++ b/pkg/provider/kubernetes/gateway/grpcroute.go @@ -2,6 +2,7 @@ package gateway import ( "context" + "errors" "fmt" "net" "strconv" @@ -337,14 +338,15 @@ func (p *Provider) loadGRPCServers(namespace string, route *gatev1.GRPCRoute, ba } } - if svcPort.AppProtocol != nil && *svcPort.AppProtocol != appProtocolH2C { + protocol, err := getGRPCServiceProtocol(svcPort) + if err != nil { return nil, &metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), Status: metav1.ConditionFalse, ObservedGeneration: route.Generation, LastTransitionTime: metav1.Now(), Reason: string(gatev1.RouteReasonUnsupportedProtocol), - Message: fmt.Sprintf("Cannot load GRPCBackendRef %s/%s: only kubernetes.io/h2c appProtocol is supported", namespace, backendRef.Name), + Message: fmt.Sprintf("Cannot load GRPCBackendRef %s/%s: only \"kubernetes.io/h2c\" and \"https\" appProtocol is supported", namespace, backendRef.Name), } } @@ -353,7 +355,7 @@ func (p *Provider) loadGRPCServers(namespace string, route *gatev1.GRPCRoute, ba for _, ba := range backendAddresses { lb.Servers = append(lb.Servers, dynamic.Server{ - URL: fmt.Sprintf("h2c://%s", net.JoinHostPort(ba.IP, strconv.Itoa(int(ba.Port)))), + URL: fmt.Sprintf("%s://%s", protocol, net.JoinHostPort(ba.IP, strconv.Itoa(int(ba.Port)))), }) } return lb, nil @@ -408,3 +410,22 @@ func buildGRPCHeaderRules(headers []gatev1.GRPCHeaderMatch) []string { return rules } + +func getGRPCServiceProtocol(portSpec corev1.ServicePort) (string, error) { + if portSpec.Protocol != corev1.ProtocolTCP { + return "", errors.New("only TCP protocol is supported") + } + + if portSpec.AppProtocol == nil { + return schemeH2C, nil + } + + switch ap := *portSpec.AppProtocol; ap { + case appProtocolH2C: + return schemeH2C, nil + case appProtocolHTTPS: + return schemeHTTPS, nil + default: + return "", fmt.Errorf("unsupported application protocol %s", ap) + } +} diff --git a/pkg/provider/kubernetes/gateway/httproute.go b/pkg/provider/kubernetes/gateway/httproute.go index cda154240..a45d007e9 100644 --- a/pkg/provider/kubernetes/gateway/httproute.go +++ b/pkg/provider/kubernetes/gateway/httproute.go @@ -468,7 +468,7 @@ func (p *Provider) loadHTTPServers(namespace string, route *gatev1.HTTPRoute, ba } } - protocol, err := getProtocol(svcPort) + protocol, err := getHTTPServiceProtocol(svcPort) if err != nil { return nil, corev1.ServicePort{}, &metav1.Condition{ Type: string(gatev1.RouteConditionResolvedRefs), @@ -721,7 +721,7 @@ func createRequestRedirect(filter *gatev1.HTTPRequestRedirectFilter, pathMatch g var port *string filterScheme := ptr.Deref(filter.Scheme, "") - if filterScheme == "http" || filterScheme == "https" { + if filterScheme == schemeHTTP || filterScheme == schemeHTTPS { port = ptr.To("") } if filter.Port != nil { @@ -783,26 +783,26 @@ func createURLRewrite(filter *gatev1.HTTPURLRewriteFilter, pathMatch gatev1.HTTP }, nil } -func getProtocol(portSpec corev1.ServicePort) (string, error) { +func getHTTPServiceProtocol(portSpec corev1.ServicePort) (string, error) { if portSpec.Protocol != corev1.ProtocolTCP { return "", errors.New("only TCP protocol is supported") } if portSpec.AppProtocol == nil { - protocol := "http" - if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, "https") { - protocol = "https" + protocol := schemeHTTP + if portSpec.Port == 443 || strings.HasPrefix(portSpec.Name, schemeHTTPS) { + protocol = schemeHTTPS } return protocol, nil } switch ap := *portSpec.AppProtocol; ap { case appProtocolH2C: - return "h2c", nil - case appProtocolWS: - return "http", nil - case appProtocolWSS: - return "https", nil + return schemeH2C, nil + case appProtocolHTTP, appProtocolWS: + return schemeHTTP, nil + case appProtocolHTTPS, appProtocolWSS: + return schemeHTTPS, nil default: return "", fmt.Errorf("unsupported application protocol %s", ap) } diff --git a/pkg/provider/kubernetes/gateway/kubernetes.go b/pkg/provider/kubernetes/gateway/kubernetes.go index 1a4356757..1f31045ca 100644 --- a/pkg/provider/kubernetes/gateway/kubernetes.go +++ b/pkg/provider/kubernetes/gateway/kubernetes.go @@ -50,9 +50,15 @@ const ( kindTLSRoute = "TLSRoute" kindService = "Service" - appProtocolH2C = "kubernetes.io/h2c" - appProtocolWS = "kubernetes.io/ws" - appProtocolWSS = "kubernetes.io/wss" + appProtocolHTTP = "http" + appProtocolHTTPS = "https" + appProtocolH2C = "kubernetes.io/h2c" + appProtocolWS = "kubernetes.io/ws" + appProtocolWSS = "kubernetes.io/wss" + + schemeHTTP = "http" + schemeHTTPS = "https" + schemeH2C = "h2c" ) // Provider holds configurations of the provider.