kubernetes ingress rewrite-target implementation
* Adding support for `ingress.kubernetes.io/rewrite-target` We create a rule using the `PathPrefixStrip` to trim out the bit in the rewrite rule.
This commit is contained in:
parent
dbf6161fa1
commit
41dd124a4b
2 changed files with 83 additions and 13 deletions
|
@ -29,11 +29,13 @@ var _ provider.Provider = (*Provider)(nil)
|
|||
const (
|
||||
annotationFrontendRuleType = "traefik.frontend.rule.type"
|
||||
ruleTypePathPrefix = "PathPrefix"
|
||||
ruleTypeReplacePath = "ReplacePath"
|
||||
|
||||
annotationKubernetesIngressClass = "kubernetes.io/ingress.class"
|
||||
annotationKubernetesAuthRealm = "ingress.kubernetes.io/auth-realm"
|
||||
annotationKubernetesAuthType = "ingress.kubernetes.io/auth-type"
|
||||
annotationKubernetesAuthSecret = "ingress.kubernetes.io/auth-secret"
|
||||
annotationKubernetesRewriteTarget = "ingress.kubernetes.io/rewrite-target"
|
||||
annotationKubernetesWhitelistSourceRange = "ingress.kubernetes.io/whitelist-source-range"
|
||||
)
|
||||
|
||||
|
@ -153,6 +155,7 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
|||
log.Warn("Error in ingress: HTTP is nil")
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pa := range r.HTTP.Paths {
|
||||
if _, exists := templateObjects.Backends[r.Host+pa.Path]; !exists {
|
||||
templateObjects.Backends[r.Host+pa.Path] = &types.Backend{
|
||||
|
@ -213,14 +216,10 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
|||
}
|
||||
}
|
||||
|
||||
if len(pa.Path) > 0 {
|
||||
ruleType := i.Annotations[annotationFrontendRuleType]
|
||||
if ruleType == "" {
|
||||
ruleType = ruleTypePathPrefix
|
||||
}
|
||||
|
||||
rule := getRuleForPath(pa, i)
|
||||
if rule != "" {
|
||||
templateObjects.Frontends[r.Host+pa.Path].Routes[pa.Path] = types.Route{
|
||||
Rule: ruleType + ":" + pa.Path,
|
||||
Rule: rule,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,9 +240,11 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
|||
Expression: expression,
|
||||
}
|
||||
}
|
||||
|
||||
if service.Annotations["traefik.backend.loadbalancer.method"] == "drr" {
|
||||
templateObjects.Backends[r.Host+pa.Path].LoadBalancer.Method = "drr"
|
||||
}
|
||||
|
||||
if service.Annotations["traefik.backend.loadbalancer.sticky"] == "true" {
|
||||
templateObjects.Backends[r.Host+pa.Path].LoadBalancer.Sticky = true
|
||||
}
|
||||
|
@ -254,6 +255,7 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
|||
if port.Port == 443 {
|
||||
protocol = "https"
|
||||
}
|
||||
|
||||
if service.Spec.Type == "ExternalName" {
|
||||
url := protocol + "://" + service.Spec.ExternalName
|
||||
name := url
|
||||
|
@ -302,6 +304,25 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
|
|||
return &templateObjects, nil
|
||||
}
|
||||
|
||||
func getRuleForPath(pa v1beta1.HTTPIngressPath, i *v1beta1.Ingress) string {
|
||||
if len(pa.Path) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
ruleType := i.Annotations[annotationFrontendRuleType]
|
||||
if ruleType == "" {
|
||||
ruleType = ruleTypePathPrefix
|
||||
}
|
||||
|
||||
rule := ruleType + ":" + pa.Path
|
||||
|
||||
if rewriteTarget := i.Annotations[annotationKubernetesRewriteTarget]; rewriteTarget != "" {
|
||||
rule = ruleTypeReplacePath + ":" + rewriteTarget
|
||||
}
|
||||
|
||||
return rule
|
||||
}
|
||||
|
||||
func handleBasicAuthConfig(i *v1beta1.Ingress, k8sClient Client) ([]string, error) {
|
||||
authType, exists := i.Annotations[annotationKubernetesAuthType]
|
||||
if !exists {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/containous/traefik/types"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
||||
"k8s.io/client-go/pkg/util/intstr"
|
||||
|
@ -1555,6 +1556,33 @@ func TestIngressAnnotations(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "testing",
|
||||
Annotations: map[string]string{
|
||||
"ingress.kubernetes.io/rewrite-target": "/",
|
||||
},
|
||||
},
|
||||
Spec: v1beta1.IngressSpec{
|
||||
Rules: []v1beta1.IngressRule{
|
||||
{
|
||||
Host: "rewrite",
|
||||
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||
Paths: []v1beta1.HTTPIngressPath{
|
||||
{
|
||||
Path: "/api",
|
||||
Backend: v1beta1.IngressBackend{
|
||||
ServiceName: "service1",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
services := []*v1.Service{
|
||||
|
@ -1659,6 +1687,19 @@ func TestIngressAnnotations(t *testing.T) {
|
|||
Method: "wrr",
|
||||
},
|
||||
},
|
||||
"rewrite/api": {
|
||||
Servers: map[string]types.Server{
|
||||
"http://example.com": {
|
||||
URL: "http://example.com",
|
||||
Weight: 1,
|
||||
},
|
||||
},
|
||||
CircuitBreaker: nil,
|
||||
LoadBalancer: &types.LoadBalancer{
|
||||
Sticky: false,
|
||||
Method: "wrr",
|
||||
},
|
||||
},
|
||||
},
|
||||
Frontends: map[string]*types.Frontend{
|
||||
"foo/bar": {
|
||||
|
@ -1718,15 +1759,23 @@ func TestIngressAnnotations(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"rewrite/api": {
|
||||
Backend: "rewrite/api",
|
||||
PassHostHeader: true,
|
||||
Routes: map[string]types.Route{
|
||||
"/api": {
|
||||
Rule: "ReplacePath:/",
|
||||
},
|
||||
"rewrite": {
|
||||
Rule: "Host:rewrite",
|
||||
},
|
||||
},
|
||||
Priority: len("/api"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actualJSON, _ := json.Marshal(actual)
|
||||
expectedJSON, _ := json.Marshal(expected)
|
||||
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("expected %+v, got %+v", string(expectedJSON), string(actualJSON))
|
||||
}
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestInvalidPassHostHeaderValue(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue