From 09b489a614920678a510a955f17d5c5cd8ec04bd Mon Sep 17 00:00:00 2001 From: Manuel Zapf Date: Tue, 31 Jul 2018 17:12:03 +0200 Subject: [PATCH] Add possibility to set a protocol --- docs/configuration/backends/kubernetes.md | 3 +- provider/kubernetes/annotations.go | 1 + provider/kubernetes/kubernetes.go | 12 +++ provider/kubernetes/kubernetes_test.go | 95 +++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) diff --git a/docs/configuration/backends/kubernetes.md b/docs/configuration/backends/kubernetes.md index b574942d1..32fa18971 100644 --- a/docs/configuration/backends/kubernetes.md +++ b/docs/configuration/backends/kubernetes.md @@ -159,7 +159,8 @@ The following general annotations are applicable on the Ingress object: | `traefik.ingress.kubernetes.io/whitelist-source-range: "1.2.3.0/24, fe80::/16"` | A comma-separated list of IP ranges permitted for access (6). | | `ingress.kubernetes.io/whitelist-x-forwarded-for: "true"` | Use `X-Forwarded-For` header as valid source of IP for the white list. | | `traefik.ingress.kubernetes.io/app-root: "/index.html"` | Redirects all requests for `/` to the defined path. (4) | -| `traefik.ingress.kubernetes.io/service-weights: ` | Set ingress backend weights specified as percentage or decimal numbers in YAML. (5) | +| `traefik.ingress.kubernetes.io/service-weights: ` | Set ingress backend weights specified as percentage or decimal numbers in YAML. (5) +| `ingress.kubernetes.io/protocol: ` | Set the protocol Traefik will use to communicate with pods. <1> `traefik.ingress.kubernetes.io/error-pages` example: diff --git a/provider/kubernetes/annotations.go b/provider/kubernetes/annotations.go index 4b716e395..e85211b2f 100644 --- a/provider/kubernetes/annotations.go +++ b/provider/kubernetes/annotations.go @@ -63,6 +63,7 @@ const ( annotationKubernetesPublicKey = "ingress.kubernetes.io/public-key" annotationKubernetesReferrerPolicy = "ingress.kubernetes.io/referrer-policy" annotationKubernetesIsDevelopment = "ingress.kubernetes.io/is-development" + annotationKubernetesProtocol = "ingress.kubernetes.io/protocol" ) // TODO [breaking] remove label support diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index 628e4ac44..d7a4a3109 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -43,6 +43,8 @@ const ( traefikDefaultIngressClass = "traefik" defaultBackendName = "global-default-backend" defaultFrontendName = "global-default-frontend" + allowedProtocolHTTPS = "https" + allowedProtocolH2C = "h2c" ) // IngressEndpoint holds the endpoint information for the Kubernetes provider @@ -312,6 +314,16 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error) protocol = "https" } + protocol = getStringValue(i.Annotations, annotationKubernetesProtocol, protocol) + switch protocol { + case allowedProtocolHTTPS: + case allowedProtocolH2C: + case label.DefaultProtocol: + default: + log.Errorf("Invalid protocol %s/%s specified for Ingress %s - skipping", annotationKubernetesProtocol, i.Namespace, i.Name) + continue + } + if service.Spec.Type == "ExternalName" { url := protocol + "://" + service.Spec.ExternalName if port.Port != 443 && port.Port != 80 { diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index 83d2d3e18..52d8c0e15 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -1224,6 +1224,41 @@ rateset: iPaths(onePath(iPath("/customheaders"), iBackend("service1", intstr.FromInt(80))))), ), ), + buildIngress( + iNamespace("testing"), + iAnnotation(annotationKubernetesProtocol, "h2c"), + iRules( + iRule( + iHost("protocol"), + iPaths(onePath(iPath("/valid"), iBackend("service1", intstr.FromInt(80))))), + ), + ), + buildIngress( + iNamespace("testing"), + iAnnotation(annotationKubernetesProtocol, "foobar"), + iRules( + iRule( + iHost("protocol"), + iPaths(onePath(iPath("/notvalid"), iBackend("service1", intstr.FromInt(80))))), + ), + ), + buildIngress( + iNamespace("testing"), + iAnnotation(annotationKubernetesProtocol, "http"), + iRules( + iRule( + iHost("protocol"), + iPaths(onePath(iPath("/missmatch"), iBackend("serviceHTTPS", intstr.FromInt(443))))), + ), + ), + buildIngress( + iNamespace("testing"), + iRules( + iRule( + iHost("protocol"), + iPaths(onePath(iPath("/noAnnotation"), iBackend("serviceHTTPS", intstr.FromInt(443))))), + ), + ), } services := []*corev1.Service{ @@ -1245,6 +1280,16 @@ rateset: clusterIP("10.0.0.2"), sPorts(sPort(802, ""))), ), + buildService( + sName("serviceHTTPS"), + sNamespace("testing"), + sUID("2"), + sSpec( + clusterIP("10.0.0.3"), + sType("ExternalName"), + sExternalName("example.com"), + sPorts(sPort(443, "https"))), + ), } secrets := []*corev1.Secret{ @@ -1352,6 +1397,28 @@ rateset: servers(), lbMethod("wrr"), ), + backend("protocol/valid", + servers( + server("h2c://example.com", weight(1)), + server("h2c://example.com", weight(1))), + lbMethod("wrr"), + ), + backend("protocol/notvalid", + servers(), + lbMethod("wrr"), + ), + backend("protocol/missmatch", + servers( + server("http://example.com", weight(1)), + server("http://example.com", weight(1))), + lbMethod("wrr"), + ), + backend("protocol/noAnnotation", + servers( + server("https://example.com", weight(1)), + server("https://example.com", weight(1))), + lbMethod("wrr"), + ), ), frontends( frontend("foo/bar", @@ -1483,6 +1550,34 @@ rateset: route("root", "Host:root"), ), ), + frontend("protocol/valid", + passHostHeader(), + routes( + route("/valid", "PathPrefix:/valid"), + route("protocol", "Host:protocol"), + ), + ), + frontend("protocol/notvalid", + passHostHeader(), + routes( + route("/notvalid", "PathPrefix:/notvalid"), + route("protocol", "Host:protocol"), + ), + ), + frontend("protocol/missmatch", + passHostHeader(), + routes( + route("/missmatch", "PathPrefix:/missmatch"), + route("protocol", "Host:protocol"), + ), + ), + frontend("protocol/noAnnotation", + passHostHeader(), + routes( + route("/noAnnotation", "PathPrefix:/noAnnotation"), + route("protocol", "Host:protocol"), + ), + ), ), )