Avoid flapping of multiple Ingress definitions

This commit is contained in:
Rene Treffer 2018-10-05 18:36:03 +02:00 committed by Traefiker Bot
parent a9deeb321b
commit 157580c232
3 changed files with 163 additions and 23 deletions

View file

@ -258,7 +258,10 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
continue
}
if _, exists := templateObjects.Frontends[baseName]; !exists {
var frontend *types.Frontend
if fe, exists := templateObjects.Frontends[baseName]; exists {
frontend = fe
} else {
auth, err := getAuthConfig(i, k8sClient)
if err != nil {
log.Errorf("Failed to retrieve auth configuration for ingress %s/%s: %s", i.Namespace, i.Name, err)
@ -269,7 +272,7 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
passTLSCert := getBoolValue(i.Annotations, annotationKubernetesPassTLSCert, p.EnablePassTLSCert)
entryPoints := getSliceStringValue(i.Annotations, annotationKubernetesFrontendEntryPoints)
templateObjects.Frontends[baseName] = &types.Frontend{
frontend = &types.Frontend{
Backend: baseName,
PassHostHeader: passHostHeader,
PassTLSCert: passTLSCert,
@ -285,26 +288,6 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
}
}
if len(r.Host) > 0 {
if _, exists := templateObjects.Frontends[baseName].Routes[r.Host]; !exists {
templateObjects.Frontends[baseName].Routes[r.Host] = types.Route{
Rule: getRuleForHost(r.Host),
}
}
}
rule, err := getRuleForPath(pa, i)
if err != nil {
log.Errorf("Failed to get rule for ingress %s/%s: %s", i.Namespace, i.Name, err)
delete(templateObjects.Frontends, baseName)
continue
}
if rule != "" {
templateObjects.Frontends[baseName].Routes[pa.Path] = types.Route{
Rule: rule,
}
}
service, exists, err := k8sClient.GetService(i.Namespace, pa.Backend.ServiceName)
if err != nil {
log.Errorf("Error while retrieving service information from k8s API %s/%s: %v", i.Namespace, pa.Backend.ServiceName, err)
@ -313,10 +296,30 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error)
if !exists {
log.Errorf("Service not found for %s/%s", i.Namespace, pa.Backend.ServiceName)
delete(templateObjects.Frontends, baseName)
continue
}
rule, err := getRuleForPath(pa, i)
if err != nil {
log.Errorf("Failed to get rule for ingress %s/%s: %s", i.Namespace, i.Name, err)
continue
}
if rule != "" {
frontend.Routes[pa.Path] = types.Route{
Rule: rule,
}
}
if len(r.Host) > 0 {
if _, exists := frontend.Routes[r.Host]; !exists {
frontend.Routes[r.Host] = types.Route{
Rule: getRuleForHost(r.Host),
}
}
}
templateObjects.Frontends[baseName] = frontend
templateObjects.Backends[baseName].CircuitBreaker = getCircuitBreaker(service)
templateObjects.Backends[baseName].LoadBalancer = getLoadBalancer(service)
templateObjects.Backends[baseName].MaxConn = getMaxConn(service)

View file

@ -1571,6 +1571,14 @@ rateset:
route("root", "Host:root"),
),
),
frontend("root2/",
passHostHeader(),
redirectRegex("root2/$", "root2/root2"),
routes(
route("/", "PathPrefix:/;ReplacePathRegex: ^/(.*) /abc$1"),
route("root2", "Host:root2"),
),
),
frontend("root/root1",
passHostHeader(),
routes(
@ -3476,3 +3484,93 @@ func TestTemplateBreakingIngresssValues(t *testing.T) {
assert.Equal(t, expected, actual)
}
func TestDivergingIngressDefinitions(t *testing.T) {
ingresses := []*extensionsv1beta1.Ingress{
buildIngress(
iNamespace("testing"),
iRules(
iRule(
iHost("host-a"),
iPaths(
onePath(iBackend("service1", intstr.FromString("80"))),
)),
),
),
buildIngress(
iNamespace("testing"),
iRules(
iRule(
iHost("host-a"),
iPaths(
onePath(iBackend("missing", intstr.FromString("80"))),
)),
),
),
}
services := []*corev1.Service{
buildService(
sName("service1"),
sNamespace("testing"),
sUID("1"),
sSpec(
clusterIP("10.0.0.1"),
sPorts(sPort(80, "http")),
),
),
}
endpoints := []*corev1.Endpoints{
buildEndpoint(
eNamespace("testing"),
eName("service1"),
eUID("1"),
subset(
eAddresses(
eAddress("10.10.0.1"),
),
ePorts(ePort(80, "http")),
),
subset(
eAddresses(
eAddress("10.10.0.2"),
),
ePorts(ePort(80, "http")),
),
),
}
watchChan := make(chan interface{})
client := clientMock{
ingresses: ingresses,
services: services,
endpoints: endpoints,
watchChan: watchChan,
}
provider := Provider{}
actual, err := provider.loadIngresses(client)
require.NoError(t, err, "error loading ingresses")
expected := buildConfiguration(
backends(
backend("host-a",
servers(
server("http://10.10.0.1:80", weight(1)),
server("http://10.10.0.2:80", weight(1)),
),
lbMethod("wrr"),
),
),
frontends(
frontend("host-a",
passHostHeader(),
routes(
route("host-a", "Host:host-a")),
),
),
)
assert.Equal(t, expected, actual, "error merging multiple backends")
}