Fix incorrect service name being set

Fix: https://github.com/kubernetes/ingress-nginx/issues/10210

This handles the case where multiple rules have identical paths, but
differing types.
This commit is contained in:
Adrian Moisey 2024-04-21 15:01:48 +02:00
parent 29513e8564
commit 422e9c4c4e
No known key found for this signature in database
GPG key ID: 41AE4AE32747C7CF
3 changed files with 80 additions and 3 deletions

View file

@ -37,6 +37,7 @@ import (
text_template "text/template" text_template "text/template"
networkingv1 "k8s.io/api/networking/v1" networkingv1 "k8s.io/api/networking/v1"
v1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2" "k8s.io/klog/v2"
@ -1051,7 +1052,7 @@ func (info *ingressInformation) Equal(other *ingressInformation) bool {
return true return true
} }
func getIngressInformation(i, h, p interface{}) *ingressInformation { func getIngressInformation(i, h, p, t interface{}) *ingressInformation {
ing, ok := i.(*ingress.Ingress) ing, ok := i.(*ingress.Ingress)
if !ok { if !ok {
klog.Errorf("expected an '*ingress.Ingress' type but %T was returned", i) klog.Errorf("expected an '*ingress.Ingress' type but %T was returned", i)
@ -1070,6 +1071,11 @@ func getIngressInformation(i, h, p interface{}) *ingressInformation {
return &ingressInformation{} return &ingressInformation{}
} }
ingressPathType, ok := t.(*v1.PathType)
if !ok {
klog.Errorf("expected a '*v1.PathType' type but %T was returned", t)
}
if ing == nil { if ing == nil {
return &ingressInformation{} return &ingressInformation{}
} }
@ -1118,6 +1124,10 @@ func getIngressInformation(i, h, p interface{}) *ingressInformation {
continue continue
} }
if *ingressPathType != *rPath.PathType {
continue
}
if rPath.Backend.Service == nil { if rPath.Backend.Service == nil {
continue continue
} }

View file

@ -55,6 +55,7 @@ func init() {
var ( var (
pathPrefix networking.PathType = networking.PathTypePrefix pathPrefix networking.PathType = networking.PathTypePrefix
pathExact networking.PathType = networking.PathTypeExact
// TODO: add tests for SSLPassthrough // TODO: add tests for SSLPassthrough
tmplFuncTestcases = map[string]struct { tmplFuncTestcases = map[string]struct {
@ -1154,18 +1155,21 @@ func TestGetIngressInformation(t *testing.T) {
Ingress interface{} Ingress interface{}
Host string Host string
Path interface{} Path interface{}
PathType interface{}
Expected *ingressInformation Expected *ingressInformation
}{ }{
"wrong ingress type": { "wrong ingress type": {
"wrongtype", "wrongtype",
"host1", "host1",
"/ok", "/ok",
"",
&ingressInformation{}, &ingressInformation{},
}, },
"wrong path type": { "wrong path type": {
&ingress.Ingress{}, &ingress.Ingress{},
"host1", "host1",
10, 10,
"",
&ingressInformation{}, &ingressInformation{},
}, },
"valid ingress definition with name validIng in namespace default using a service with name a-svc port number 8080": { "valid ingress definition with name validIng in namespace default using a service with name a-svc port number 8080": {
@ -1192,6 +1196,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"host1", "host1",
"", "",
"",
&ingressInformation{ &ingressInformation{
Namespace: "default", Namespace: "default",
Rule: "validIng", Rule: "validIng",
@ -1227,6 +1232,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"host1", "host1",
"", "",
"",
&ingressInformation{ &ingressInformation{
Namespace: "default", Namespace: "default",
Rule: "validIng", Rule: "validIng",
@ -1259,6 +1265,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"host1", "host1",
"", "",
"",
&ingressInformation{ &ingressInformation{
Namespace: "default", Namespace: "default",
Rule: "validIng", Rule: "validIng",
@ -1309,6 +1316,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"foo.bar", "foo.bar",
"/ok", "/ok",
&pathPrefix,
&ingressInformation{ &ingressInformation{
Namespace: "something", Namespace: "something",
Rule: "demo", Rule: "demo",
@ -1359,6 +1367,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"foo.bar", "foo.bar",
"/ok", "/ok",
&pathPrefix,
&ingressInformation{ &ingressInformation{
Namespace: "something", Namespace: "something",
Rule: "demo", Rule: "demo",
@ -1404,6 +1413,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"foo.bar", "foo.bar",
"/ok", "/ok",
&pathPrefix,
&ingressInformation{ &ingressInformation{
Namespace: "something", Namespace: "something",
Rule: "demo", Rule: "demo",
@ -1459,6 +1469,7 @@ func TestGetIngressInformation(t *testing.T) {
}, },
"foo.bar", "foo.bar",
"/oksvc", "/oksvc",
&pathPrefix,
&ingressInformation{ &ingressInformation{
Namespace: "something", Namespace: "something",
Rule: "demo", Rule: "demo",
@ -1469,10 +1480,66 @@ func TestGetIngressInformation(t *testing.T) {
ServicePort: "b-svc-80", ServicePort: "b-svc-80",
}, },
}, },
"valid ingress definition with name demo in namespace something and two path / with Prefix and Exact": {
&ingress.Ingress{
Ingress: networking.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "demo",
Namespace: "something",
Annotations: map[string]string{
"ingress.annotation": "ok",
},
},
Spec: networking.IngressSpec{
Rules: []networking.IngressRule{
{
Host: "foo.bar",
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
PathType: &pathPrefix,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: "a-svc",
},
},
},
{
Path: "/",
PathType: &pathExact,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: "b-svc",
},
},
},
},
},
},
},
},
},
},
},
"foo.bar",
"/",
&pathExact,
&ingressInformation{
Path: "/",
Namespace: "something",
Rule: "demo",
Annotations: map[string]string{
"ingress.annotation": "ok",
},
Service: "b-svc",
},
},
} }
for title, testCase := range testcases { for title, testCase := range testcases {
info := getIngressInformation(testCase.Ingress, testCase.Host, testCase.Path) info := getIngressInformation(testCase.Ingress, testCase.Host, testCase.Path, testCase.PathType)
if !info.Equal(testCase.Expected) { if !info.Equal(testCase.Expected) {
t.Fatalf("%s: expected '%v' but returned %v", title, testCase.Expected, info) t.Fatalf("%s: expected '%v' but returned %v", title, testCase.Expected, info)

View file

@ -1110,7 +1110,7 @@ stream {
{{ end }} {{ end }}
location {{ $path }} { location {{ $path }} {
{{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} {{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath $location.PathType) }}
set $namespace {{ $ing.Namespace | quote}}; set $namespace {{ $ing.Namespace | quote}};
set $ingress_name {{ $ing.Rule | quote }}; set $ingress_name {{ $ing.Rule | quote }};
set $service_name {{ $ing.Service | quote }}; set $service_name {{ $ing.Service | quote }};