Add new ingressClass support to ingress provider

* add new ingressClass

* add doc

* lint

* adjust behavior to look for a class with a specific controller

* remove looking strange test ingressclass

* return nil rather than en empty object

* change documentation

* apply @kevinpollet suggestion

* change order of processIngress to be correct and adjust tests

* review: clean.

* review: clean.

* Fix for review

Co-authored-by: Manuel Zapf <manuel@containo.us>
Co-authored-by: Fernandez Ludovic <ludovic@containo.us>
Co-authored-by: Michael <michael.matur@gmail.com>
This commit is contained in:
Daniel Tomcej 2020-07-15 10:18:03 -07:00 committed by GitHub
parent 1ef93fead7
commit cb6ec507e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 265 additions and 22 deletions

View file

@ -21,14 +21,16 @@ import (
"github.com/mitchellh/hashstructure"
corev1 "k8s.io/api/core/v1"
"k8s.io/api/networking/v1beta1"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/intstr"
)
const (
annotationKubernetesIngressClass = "kubernetes.io/ingress.class"
traefikDefaultIngressClass = "traefik"
defaultPathMatcher = "PathPrefix"
annotationKubernetesIngressClass = "kubernetes.io/ingress.class"
traefikDefaultIngressClass = "traefik"
traefikDefaultIngressClassController = "traefik.io/ingress-controller"
defaultPathMatcher = "PathPrefix"
)
// Provider holds configurations of the provider.
@ -181,13 +183,36 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
TCP: &dynamic.TCPConfiguration{},
}
major, minor, err := client.GetServerVersion()
if err != nil {
log.FromContext(ctx).Errorf("Failed to get server version: %v", err)
return conf
}
var ingressClass *networkingv1beta1.IngressClass
if major >= 1 && minor >= 18 {
ic, err := client.GetIngressClass()
if err != nil {
log.FromContext(ctx).Errorf("Failed to find an ingress class: %v", err)
return conf
}
if ic == nil {
log.FromContext(ctx).Errorf("No ingress class for the traefik-controller in the cluster")
return conf
}
ingressClass = ic
}
ingresses := client.GetIngresses()
certConfigs := make(map[string]*tls.CertAndStores)
for _, ingress := range ingresses {
ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace))
if !shouldProcessIngress(p.IngressClass, ingress.Annotations[annotationKubernetesIngressClass]) {
if !p.shouldProcessIngress(p.IngressClass, ingress, ingressClass) {
continue
}
@ -273,7 +298,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
}
func (p *Provider) updateIngressStatus(ing *v1beta1.Ingress, k8sClient Client) error {
// Only process if an EndpointIngress has been configured
// Only process if an EndpointIngress has been configured.
if p.IngressEndpoint == nil {
return nil
}
@ -311,6 +336,12 @@ func (p *Provider) updateIngressStatus(ing *v1beta1.Ingress, k8sClient Client) e
return k8sClient.UpdateIngressStatus(ing, service.Status.LoadBalancer.Ingress[0].IP, service.Status.LoadBalancer.Ingress[0].Hostname)
}
func (p *Provider) shouldProcessIngress(providerIngressClass string, ingress *networkingv1beta1.Ingress, ingressClass *networkingv1beta1.IngressClass) bool {
return ingressClass != nil && ingress.Spec.IngressClassName != nil && ingressClass.ObjectMeta.Name == *ingress.Spec.IngressClassName ||
providerIngressClass == ingress.Annotations[annotationKubernetesIngressClass] ||
len(providerIngressClass) == 0 && ingress.Annotations[annotationKubernetesIngressClass] == traefikDefaultIngressClass
}
func buildHostRule(host string) string {
if strings.HasPrefix(host, "*.") {
return "HostRegexp(`" + strings.Replace(host, "*.", "{subdomain:[a-zA-Z0-9-]+}.", 1) + "`)"
@ -319,11 +350,6 @@ func buildHostRule(host string) string {
return "Host(`" + host + "`)"
}
func shouldProcessIngress(ingressClass, ingressClassAnnotation string) bool {
return ingressClass == ingressClassAnnotation ||
(len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass)
}
func getCertificates(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error {
for _, t := range ingress.Spec.TLS {
if t.SecretName == "" {
@ -552,7 +578,8 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s
if throttleDuration == 0 {
return nil
}
// Create a buffered channel to hold the pending event (if we're delaying processing the event due to throttling)
// Create a buffered channel to hold the pending event (if we're delaying processing the event due to throttling).
eventsChanBuffered := make(chan interface{}, 1)
// Run a goroutine that reads events from eventChan and does a
@ -571,7 +598,7 @@ func throttleEvents(ctx context.Context, throttleDuration time.Duration, pool *s
// We already have an event in eventsChanBuffered, so we'll
// do a refresh as soon as our throttle allows us to. It's fine
// to drop the event and keep whatever's in the buffer -- we
// don't do different things for different events
// don't do different things for different events.
log.FromContext(ctx).Debugf("Dropping event kind %T due to throttling", nextEvent)
}
}