Filter ingress class resources by name
Co-authored-by: SantoDE <manuel.zapf@traefik.io>
This commit is contained in:
parent
438eec720a
commit
e658712d53
15 changed files with 364 additions and 6 deletions
|
@ -616,7 +616,7 @@ Kubernetes certificate authority file path (not needed for in-cluster client).
|
||||||
Kubernetes server endpoint (required for external cluster client).
|
Kubernetes server endpoint (required for external cluster client).
|
||||||
|
|
||||||
`--providers.kubernetesingress.ingressclass`:
|
`--providers.kubernetesingress.ingressclass`:
|
||||||
Value of kubernetes.io/ingress.class annotation to watch for.
|
Value of kubernetes.io/ingress.class annotation or IngressClass name to watch for.
|
||||||
|
|
||||||
`--providers.kubernetesingress.ingressendpoint.hostname`:
|
`--providers.kubernetesingress.ingressendpoint.hostname`:
|
||||||
Hostname used for Kubernetes Ingress endpoints.
|
Hostname used for Kubernetes Ingress endpoints.
|
||||||
|
|
|
@ -616,7 +616,7 @@ Kubernetes certificate authority file path (not needed for in-cluster client).
|
||||||
Kubernetes server endpoint (required for external cluster client).
|
Kubernetes server endpoint (required for external cluster client).
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_INGRESSCLASS`:
|
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_INGRESSCLASS`:
|
||||||
Value of kubernetes.io/ingress.class annotation to watch for.
|
Value of kubernetes.io/ingress.class annotation or IngressClass name to watch for.
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_INGRESSENDPOINT_HOSTNAME`:
|
`TRAEFIK_PROVIDERS_KUBERNETESINGRESS_INGRESSENDPOINT_HOSTNAME`:
|
||||||
Hostname used for Kubernetes Ingress endpoints.
|
Hostname used for Kubernetes Ingress endpoints.
|
||||||
|
|
70
integration/fixtures/k8s/08-ingressclass.yml
Normal file
70
integration/fixtures/k8s/08-ingressclass.yml
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-keep
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: "whoami-keep-route"
|
||||||
|
spec:
|
||||||
|
ingressClassName: "traefik-keep"
|
||||||
|
rules:
|
||||||
|
- host: "whoami.test.keep"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: "/keep"
|
||||||
|
backend:
|
||||||
|
serviceName: "whoami"
|
||||||
|
servicePort: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-drop
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: "whoami-drop-route"
|
||||||
|
spec:
|
||||||
|
ingressClassName: "traefik-drop"
|
||||||
|
rules:
|
||||||
|
- host: "whoami.test.drop"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: "/drop"
|
||||||
|
backend:
|
||||||
|
serviceName: "whoami"
|
||||||
|
servicePort: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-not-ingress-controller
|
||||||
|
spec:
|
||||||
|
controller: not.tr43phic.io/ingress-controller
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: "whoami-drop-ingress"
|
||||||
|
spec:
|
||||||
|
ingressClassName: "traefik-not-ingress-controller"
|
||||||
|
rules:
|
||||||
|
- host: "whoami.test.not.ingress"
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: "/ingress"
|
||||||
|
backend:
|
||||||
|
serviceName: "whoami"
|
||||||
|
servicePort: 80
|
16
integration/fixtures/k8s_ingressclass.toml
Normal file
16
integration/fixtures/k8s_ingressclass.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[global]
|
||||||
|
checkNewVersion = false
|
||||||
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
|
[log]
|
||||||
|
level = "DEBUG"
|
||||||
|
|
||||||
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.web]
|
||||||
|
address = ":8000"
|
||||||
|
|
||||||
|
[providers.kubernetesIngress]
|
||||||
|
ingressClass = "traefik-keep"
|
|
@ -119,6 +119,17 @@ func (s *K8sSuite) TestGatewayConfiguration(c *check.C) {
|
||||||
testConfiguration(c, "testdata/rawdata-gateway.json", "8080")
|
testConfiguration(c, "testdata/rawdata-gateway.json", "8080")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *K8sSuite) TestIngressclass(c *check.C) {
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile("fixtures/k8s_ingressclass.toml"))
|
||||||
|
defer display(c)
|
||||||
|
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer s.killCmd(cmd)
|
||||||
|
|
||||||
|
testConfiguration(c, "testdata/rawdata-ingressclass.json", "8080")
|
||||||
|
}
|
||||||
|
|
||||||
func testConfiguration(c *check.C, path, apiPort string) {
|
func testConfiguration(c *check.C, path, apiPort string) {
|
||||||
err := try.GetRequest("http://127.0.0.1:"+apiPort+"/api/entrypoints", 20*time.Second, try.BodyContains(`"name":"web"`))
|
err := try.GetRequest("http://127.0.0.1:"+apiPort+"/api/entrypoints", 20*time.Second, try.BodyContains(`"name":"web"`))
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
server:
|
server:
|
||||||
image: rancher/k3s:v1.17.2-k3s1
|
image: rancher/k3s:v1.18.15-k3s1
|
||||||
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log
|
command: server --disable-agent --no-deploy coredns --no-deploy servicelb --no-deploy traefik --no-deploy local-storage --no-deploy metrics-server --log /output/k3s.log
|
||||||
environment:
|
environment:
|
||||||
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
- K3S_CLUSTER_SECRET=somethingtotallyrandom
|
||||||
|
@ -12,7 +12,7 @@ server:
|
||||||
- 6443:6443
|
- 6443:6443
|
||||||
|
|
||||||
node:
|
node:
|
||||||
image: rancher/k3s:v1.17.2-k3s1
|
image: rancher/k3s:v1.18.15-k3s1
|
||||||
privileged: true
|
privileged: true
|
||||||
links:
|
links:
|
||||||
- server
|
- server
|
||||||
|
|
44
integration/testdata/rawdata-ingress.json
vendored
44
integration/testdata/rawdata-ingress.json
vendored
|
@ -49,6 +49,28 @@
|
||||||
"using": [
|
"using": [
|
||||||
"web"
|
"web"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"whoami-drop-route-default-whoami-test-drop-drop@kubernetes": {
|
||||||
|
"entryPoints": [
|
||||||
|
"web"
|
||||||
|
],
|
||||||
|
"service": "default-whoami-80",
|
||||||
|
"rule": "Host(`whoami.test.drop`) \u0026\u0026 PathPrefix(`/drop`)",
|
||||||
|
"status": "enabled",
|
||||||
|
"using": [
|
||||||
|
"web"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"whoami-keep-route-default-whoami-test-keep-keep@kubernetes": {
|
||||||
|
"entryPoints": [
|
||||||
|
"web"
|
||||||
|
],
|
||||||
|
"service": "default-whoami-80",
|
||||||
|
"rule": "Host(`whoami.test.keep`) \u0026\u0026 PathPrefix(`/keep`)",
|
||||||
|
"status": "enabled",
|
||||||
|
"using": [
|
||||||
|
"web"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"middlewares": {
|
"middlewares": {
|
||||||
|
@ -89,6 +111,28 @@
|
||||||
"dashboard@internal"
|
"dashboard@internal"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"default-whoami-80@kubernetes": {
|
||||||
|
"loadBalancer": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "XXXX"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "XXXX"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"passHostHeader": true
|
||||||
|
},
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"whoami-drop-route-default-whoami-test-drop-drop@kubernetes",
|
||||||
|
"whoami-keep-route-default-whoami-test-keep-keep@kubernetes"
|
||||||
|
],
|
||||||
|
"serverStatus": {
|
||||||
|
"http://XXXX": "UP",
|
||||||
|
"http://XXXX": "UP"
|
||||||
|
}
|
||||||
|
},
|
||||||
"default-whoami-http@kubernetes": {
|
"default-whoami-http@kubernetes": {
|
||||||
"loadBalancer": {
|
"loadBalancer": {
|
||||||
"servers": [
|
"servers": [
|
||||||
|
|
106
integration/testdata/rawdata-ingressclass.json
vendored
Normal file
106
integration/testdata/rawdata-ingressclass.json
vendored
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
{
|
||||||
|
"routers": {
|
||||||
|
"api@internal": {
|
||||||
|
"entryPoints": [
|
||||||
|
"traefik"
|
||||||
|
],
|
||||||
|
"service": "api@internal",
|
||||||
|
"rule": "PathPrefix(`/api`)",
|
||||||
|
"priority": 2147483646,
|
||||||
|
"status": "enabled",
|
||||||
|
"using": [
|
||||||
|
"traefik"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dashboard@internal": {
|
||||||
|
"entryPoints": [
|
||||||
|
"traefik"
|
||||||
|
],
|
||||||
|
"middlewares": [
|
||||||
|
"dashboard_redirect@internal",
|
||||||
|
"dashboard_stripprefix@internal"
|
||||||
|
],
|
||||||
|
"service": "dashboard@internal",
|
||||||
|
"rule": "PathPrefix(`/`)",
|
||||||
|
"priority": 2147483645,
|
||||||
|
"status": "enabled",
|
||||||
|
"using": [
|
||||||
|
"traefik"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"whoami-keep-route-default-whoami-test-keep-keep@kubernetes": {
|
||||||
|
"entryPoints": [
|
||||||
|
"web"
|
||||||
|
],
|
||||||
|
"service": "default-whoami-80",
|
||||||
|
"rule": "Host(`whoami.test.keep`) \u0026\u0026 PathPrefix(`/keep`)",
|
||||||
|
"status": "enabled",
|
||||||
|
"using": [
|
||||||
|
"web"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"middlewares": {
|
||||||
|
"dashboard_redirect@internal": {
|
||||||
|
"redirectRegex": {
|
||||||
|
"regex": "^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$",
|
||||||
|
"replacement": "${1}/dashboard/",
|
||||||
|
"permanent": true
|
||||||
|
},
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"dashboard@internal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dashboard_stripprefix@internal": {
|
||||||
|
"stripPrefix": {
|
||||||
|
"prefixes": [
|
||||||
|
"/dashboard/",
|
||||||
|
"/dashboard"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"dashboard@internal"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"api@internal": {
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"api@internal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dashboard@internal": {
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"dashboard@internal"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default-whoami-80@kubernetes": {
|
||||||
|
"loadBalancer": {
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://10.42.0.4:80"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://10.42.0.5:80"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"passHostHeader": true
|
||||||
|
},
|
||||||
|
"status": "enabled",
|
||||||
|
"usedBy": [
|
||||||
|
"whoami-keep-route-default-whoami-test-keep-keep@kubernetes"
|
||||||
|
],
|
||||||
|
"serverStatus": {
|
||||||
|
"http://10.42.0.4:80": "UP",
|
||||||
|
"http://10.42.0.5:80": "UP"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"noop@internal": {
|
||||||
|
"status": "enabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -476,3 +476,16 @@ func supportsIngressClass(serverVersion *version.Version) bool {
|
||||||
|
|
||||||
return ingressClassVersion.LessThanOrEqual(serverVersion)
|
return ingressClassVersion.LessThanOrEqual(serverVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filterIngressClassByName return a slice containing ingressclasses with the correct name.
|
||||||
|
func filterIngressClassByName(ingressClassName string, ics []*networkingv1beta1.IngressClass) []*networkingv1beta1.IngressClass {
|
||||||
|
var ingressClasses []*networkingv1beta1.IngressClass
|
||||||
|
|
||||||
|
for _, ic := range ics {
|
||||||
|
if ic.Name == ingressClassName {
|
||||||
|
ingressClasses = append(ingressClasses, ic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingressClasses
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
kind: Endpoints
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
subsets:
|
||||||
|
- addresses:
|
||||||
|
- ip: 10.10.0.1
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
|
@ -0,0 +1,30 @@
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik-lb
|
||||||
|
rules:
|
||||||
|
- http:
|
||||||
|
paths:
|
||||||
|
- path: /bar
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: Ingress
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: ""
|
||||||
|
namespace: testing
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik-lb2
|
||||||
|
rules:
|
||||||
|
- http:
|
||||||
|
paths:
|
||||||
|
- path: /foo
|
||||||
|
backend:
|
||||||
|
serviceName: service1
|
||||||
|
servicePort: 80
|
|
@ -0,0 +1,14 @@
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-lb2
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
kind: IngressClass
|
||||||
|
metadata:
|
||||||
|
name: traefik-lb
|
||||||
|
spec:
|
||||||
|
controller: traefik.io/ingress-controller
|
|
@ -0,0 +1,10 @@
|
||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: service1
|
||||||
|
namespace: testing
|
||||||
|
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
clusterIP: 10.0.0.1
|
|
@ -42,7 +42,7 @@ type Provider struct {
|
||||||
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
|
CertAuthFilePath string `description:"Kubernetes certificate authority file path (not needed for in-cluster client)." json:"certAuthFilePath,omitempty" toml:"certAuthFilePath,omitempty" yaml:"certAuthFilePath,omitempty"`
|
||||||
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
|
Namespaces []string `description:"Kubernetes namespaces." json:"namespaces,omitempty" toml:"namespaces,omitempty" yaml:"namespaces,omitempty" export:"true"`
|
||||||
LabelSelector string `description:"Kubernetes Ingress label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
|
LabelSelector string `description:"Kubernetes Ingress label selector to use." json:"labelSelector,omitempty" toml:"labelSelector,omitempty" yaml:"labelSelector,omitempty" export:"true"`
|
||||||
IngressClass string `description:"Value of kubernetes.io/ingress.class annotation to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"`
|
IngressClass string `description:"Value of kubernetes.io/ingress.class annotation or IngressClass name to watch for." json:"ingressClass,omitempty" toml:"ingressClass,omitempty" yaml:"ingressClass,omitempty" export:"true"`
|
||||||
IngressEndpoint *EndpointIngress `description:"Kubernetes Ingress Endpoint." json:"ingressEndpoint,omitempty" toml:"ingressEndpoint,omitempty" yaml:"ingressEndpoint,omitempty" export:"true"`
|
IngressEndpoint *EndpointIngress `description:"Kubernetes Ingress Endpoint." json:"ingressEndpoint,omitempty" toml:"ingressEndpoint,omitempty" yaml:"ingressEndpoint,omitempty" export:"true"`
|
||||||
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
|
ThrottleDuration ptypes.Duration `description:"Ingress refresh throttle duration" json:"throttleDuration,omitempty" toml:"throttleDuration,omitempty" yaml:"throttleDuration,omitempty" export:"true"`
|
||||||
lastConfiguration safe.Safe
|
lastConfiguration safe.Safe
|
||||||
|
@ -198,8 +198,12 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
||||||
log.FromContext(ctx).Warnf("Failed to list ingress classes: %v", err)
|
log.FromContext(ctx).Warnf("Failed to list ingress classes: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.IngressClass != "" {
|
||||||
|
ingressClasses = filterIngressClassByName(p.IngressClass, ics)
|
||||||
|
} else {
|
||||||
ingressClasses = ics
|
ingressClasses = ics
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ingresses := client.GetIngresses()
|
ingresses := client.GetIngresses()
|
||||||
|
|
||||||
|
|
|
@ -1273,6 +1273,35 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "v18 Ingress with ingressClasses filter",
|
||||||
|
serverVersion: "v1.18",
|
||||||
|
ingressClass: "traefik-lb2",
|
||||||
|
expected: &dynamic.Configuration{
|
||||||
|
TCP: &dynamic.TCPConfiguration{},
|
||||||
|
HTTP: &dynamic.HTTPConfiguration{
|
||||||
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
|
Routers: map[string]*dynamic.Router{
|
||||||
|
"testing-foo": {
|
||||||
|
Rule: "PathPrefix(`/foo`)",
|
||||||
|
Service: "testing-service1-80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Services: map[string]*dynamic.Service{
|
||||||
|
"testing-service1-80": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
PassHostHeader: Bool(true),
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
|
Loading…
Reference in a new issue