Merge pull request #5324 from aledbf/exact
Add support for PathTypeExact
This commit is contained in:
commit
a51bc3e8ac
8 changed files with 221 additions and 51 deletions
|
@ -527,6 +527,12 @@ func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*in
|
||||||
addLoc := true
|
addLoc := true
|
||||||
for _, loc := range server.Locations {
|
for _, loc := range server.Locations {
|
||||||
if loc.Path == nginxPath {
|
if loc.Path == nginxPath {
|
||||||
|
// Same paths but different types are allowed
|
||||||
|
// (same type means overlap in the path definition)
|
||||||
|
if *loc.PathType != *path.PathType {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
addLoc = false
|
addLoc = false
|
||||||
|
|
||||||
if !loc.IsDefBackend {
|
if !loc.IsDefBackend {
|
||||||
|
@ -543,6 +549,7 @@ func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*in
|
||||||
loc.Port = ups.Port
|
loc.Port = ups.Port
|
||||||
loc.Service = ups.Service
|
loc.Service = ups.Service
|
||||||
loc.Ingress = ing
|
loc.Ingress = ing
|
||||||
|
|
||||||
locationApplyAnnotations(loc, anns)
|
locationApplyAnnotations(loc, anns)
|
||||||
|
|
||||||
if loc.Redirect.FromToWWW {
|
if loc.Redirect.FromToWWW {
|
||||||
|
@ -556,9 +563,9 @@ func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*in
|
||||||
if addLoc {
|
if addLoc {
|
||||||
klog.V(3).Infof("Adding location %q for server %q with upstream %q (Ingress %q)",
|
klog.V(3).Infof("Adding location %q for server %q with upstream %q (Ingress %q)",
|
||||||
nginxPath, server.Hostname, ups.Name, ingKey)
|
nginxPath, server.Hostname, ups.Name, ingKey)
|
||||||
|
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
Path: nginxPath,
|
Path: nginxPath,
|
||||||
|
PathType: path.PathType,
|
||||||
Backend: ups.Name,
|
Backend: ups.Name,
|
||||||
IsDefBackend: false,
|
IsDefBackend: false,
|
||||||
Service: ups.Service,
|
Service: ups.Service,
|
||||||
|
@ -953,12 +960,14 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize default server and root location
|
// initialize default server and root location
|
||||||
|
pathTypePrefix := networking.PathTypePrefix
|
||||||
servers[defServerName] = &ingress.Server{
|
servers[defServerName] = &ingress.Server{
|
||||||
Hostname: defServerName,
|
Hostname: defServerName,
|
||||||
SSLCert: n.getDefaultSSLCertificate(),
|
SSLCert: n.getDefaultSSLCertificate(),
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: rootLocation,
|
Path: rootLocation,
|
||||||
|
PathType: &pathTypePrefix,
|
||||||
IsDefBackend: true,
|
IsDefBackend: true,
|
||||||
Backend: du.Name,
|
Backend: du.Name,
|
||||||
Proxy: ngxProxy,
|
Proxy: ngxProxy,
|
||||||
|
@ -1025,8 +1034,10 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pathTypePrefix := networking.PathTypePrefix
|
||||||
loc := &ingress.Location{
|
loc := &ingress.Location{
|
||||||
Path: rootLocation,
|
Path: rootLocation,
|
||||||
|
PathType: &pathTypePrefix,
|
||||||
IsDefBackend: true,
|
IsDefBackend: true,
|
||||||
Backend: un,
|
Backend: un,
|
||||||
Service: &apiv1.Service{},
|
Service: &apiv1.Service{},
|
||||||
|
@ -1311,7 +1322,7 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if canMergeBackend(priUps, altUps) && loc.Path == path.Path {
|
if canMergeBackend(priUps, altUps) && loc.Path == path.Path && *loc.PathType == *path.PathType {
|
||||||
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
||||||
priUps.Name, altUps.Name)
|
priUps.Name, altUps.Name)
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,8 @@ func TestCheckIngress(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pathPrefix = networking.PathTypePrefix
|
||||||
|
|
||||||
func TestMergeAlternativeBackends(t *testing.T) {
|
func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
ingress *ingress.Ingress
|
ingress *ingress.Ingress
|
||||||
|
@ -279,7 +281,8 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-canary",
|
ServiceName: "http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -314,8 +317,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "example.com",
|
Hostname: "example.com",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -339,8 +343,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "example.com",
|
Hostname: "example.com",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -360,7 +365,8 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "foo-http-svc-canary",
|
ServiceName: "foo-http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -379,7 +385,8 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-canary",
|
ServiceName: "http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -426,8 +433,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "foo.bar",
|
Hostname: "foo.bar",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-foo-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-foo-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -435,8 +443,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "example.com",
|
Hostname: "example.com",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -472,8 +481,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "example.com",
|
Hostname: "example.com",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -493,7 +503,8 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-canary",
|
ServiceName: "http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -557,8 +568,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "_",
|
Hostname: "_",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -582,8 +594,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "_",
|
Hostname: "_",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "example-http-svc-80",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "example-http-svc-80",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -623,8 +636,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "_",
|
Hostname: "_",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "upstream-default-backend",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "upstream-default-backend",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -635,8 +649,9 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
||||||
Hostname: "_",
|
Hostname: "_",
|
||||||
Locations: []*ingress.Location{
|
Locations: []*ingress.Location{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
Backend: "upstream-default-backend",
|
PathType: &pathPrefix,
|
||||||
|
Backend: "upstream-default-backend",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -943,7 +958,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-canary",
|
ServiceName: "http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1002,7 +1018,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc",
|
ServiceName: "http-svc",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1038,7 +1055,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/",
|
Path: "/",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-canary",
|
ServiceName: "http-svc-canary",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1106,7 +1124,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/a",
|
Path: "/a",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-1",
|
ServiceName: "http-svc-1",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1142,7 +1161,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/a",
|
Path: "/a",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-2",
|
ServiceName: "http-svc-2",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1178,7 +1198,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/b",
|
Path: "/b",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-2",
|
ServiceName: "http-svc-2",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1214,7 +1235,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/b",
|
Path: "/b",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-1",
|
ServiceName: "http-svc-1",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1250,7 +1272,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/c",
|
Path: "/c",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-1",
|
ServiceName: "http-svc-1",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1286,7 +1309,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/c",
|
Path: "/c",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "http-svc-2",
|
ServiceName: "http-svc-2",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1370,7 +1394,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/path1",
|
Path: "/path1",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "path1-svc",
|
ServiceName: "path1-svc",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1409,7 +1434,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/path2",
|
Path: "/path2",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "path2-svc",
|
ServiceName: "path2-svc",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1473,7 +1499,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/path1",
|
Path: "/path1",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "path1-svc",
|
ServiceName: "path1-svc",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
@ -1512,7 +1539,8 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
Paths: []networking.HTTPIngressPath{
|
Paths: []networking.HTTPIngressPath{
|
||||||
{
|
{
|
||||||
Path: "/path2",
|
Path: "/path2",
|
||||||
|
PathType: &pathPrefix,
|
||||||
Backend: networking.IngressBackend{
|
Backend: networking.IngressBackend{
|
||||||
ServiceName: "path2-svc",
|
ServiceName: "path2-svc",
|
||||||
ServicePort: intstr.IntOrString{
|
ServicePort: intstr.IntOrString{
|
||||||
|
|
|
@ -26,8 +26,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog"
|
|
||||||
|
|
||||||
"github.com/eapache/channels"
|
"github.com/eapache/channels"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||||
|
@ -36,6 +34,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
k8sruntime "k8s.io/apimachinery/pkg/runtime"
|
k8sruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
@ -43,6 +42,7 @@ import (
|
||||||
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
|
"k8s.io/klog"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/internal/file"
|
"k8s.io/ingress-nginx/internal/file"
|
||||||
"k8s.io/ingress-nginx/internal/ingress"
|
"k8s.io/ingress-nginx/internal/ingress"
|
||||||
|
@ -639,6 +639,9 @@ func isCatchAllIngress(spec networkingv1beta1.IngressSpec) bool {
|
||||||
return spec.Backend != nil && len(spec.Rules) == 0
|
return spec.Backend != nil && len(spec.Rules) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default path type is Prefix to not break existing definitions
|
||||||
|
var defaultPathType = networkingv1beta1.PathTypePrefix
|
||||||
|
|
||||||
// syncIngress parses ingress annotations converting the value of the
|
// syncIngress parses ingress annotations converting the value of the
|
||||||
// annotation to a go struct
|
// annotation to a go struct
|
||||||
func (s *k8sStore) syncIngress(ing *networkingv1beta1.Ingress) {
|
func (s *k8sStore) syncIngress(ing *networkingv1beta1.Ingress) {
|
||||||
|
@ -659,6 +662,17 @@ func (s *k8sStore) syncIngress(ing *networkingv1beta1.Ingress) {
|
||||||
if path.Path == "" {
|
if path.Path == "" {
|
||||||
copyIng.Spec.Rules[ri].HTTP.Paths[pi].Path = "/"
|
copyIng.Spec.Rules[ri].HTTP.Paths[pi].Path = "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if path.PathType == nil {
|
||||||
|
copyIng.Spec.Rules[ri].HTTP.Paths[pi].PathType = &defaultPathType
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathType ImplementationSpecific is not supported.
|
||||||
|
// Set type to PathTypePrefix.
|
||||||
|
if *path.PathType == networkingv1beta1.PathTypeImplementationSpecific {
|
||||||
|
copyIng.Spec.Rules[ri].HTTP.Paths[pi].PathType = &defaultPathType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,8 +939,8 @@ func (s k8sStore) GetRunningControllerPodsCount() int {
|
||||||
var runtimeScheme = k8sruntime.NewScheme()
|
var runtimeScheme = k8sruntime.NewScheme()
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
extensionsv1beta1.AddToScheme(runtimeScheme)
|
utilruntime.Must(extensionsv1beta1.AddToScheme(runtimeScheme))
|
||||||
networkingv1beta1.AddToScheme(runtimeScheme)
|
utilruntime.Must(networkingv1beta1.AddToScheme(runtimeScheme))
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromExtensions(old *extensionsv1beta1.Ingress) (*networkingv1beta1.Ingress, error) {
|
func fromExtensions(old *extensionsv1beta1.Ingress) (*networkingv1beta1.Ingress, error) {
|
||||||
|
@ -961,9 +975,6 @@ func toIngress(obj interface{}) (*networkingv1beta1.Ingress, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default path type is Prefix to not break existing definitions
|
|
||||||
var defaultPathType = networkingv1beta1.PathTypePrefix
|
|
||||||
|
|
||||||
func setDefaultPathTypeIfEmpty(ing *networkingv1beta1.Ingress) {
|
func setDefaultPathTypeIfEmpty(ing *networkingv1beta1.Ingress) {
|
||||||
for _, rule := range ing.Spec.Rules {
|
for _, rule := range ing.Spec.Rules {
|
||||||
if rule.IngressRuleValue.HTTP == nil {
|
if rule.IngressRuleValue.HTTP == nil {
|
||||||
|
|
|
@ -39,6 +39,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
networkingv1beta1 "k8s.io/api/networking/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
|
|
||||||
|
@ -402,6 +403,11 @@ func buildLocation(input interface{}, enforceRegex bool) string {
|
||||||
if enforceRegex {
|
if enforceRegex {
|
||||||
return fmt.Sprintf(`~* "^%s"`, path)
|
return fmt.Sprintf(`~* "^%s"`, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if location.PathType != nil && *location.PathType == networkingv1beta1.PathTypeExact {
|
||||||
|
return fmt.Sprintf(`= %s`, path)
|
||||||
|
}
|
||||||
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,8 @@ type Location struct {
|
||||||
// a '/'. If unspecified, the path defaults to a catch all sending
|
// a '/'. If unspecified, the path defaults to a catch all sending
|
||||||
// traffic to the backend.
|
// traffic to the backend.
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
// PathType represents the type of path referred to by a HTTPIngressPath.
|
||||||
|
PathType *networking.PathType `json:"pathType"`
|
||||||
// IsDefBackend indicates if service specified in the Ingress
|
// IsDefBackend indicates if service specified in the Ingress
|
||||||
// contains active endpoints or not. Returning true means the location
|
// contains active endpoints or not. Returning true means the location
|
||||||
// uses the default backend.
|
// uses the default backend.
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
|
|
||||||
// required
|
// required
|
||||||
|
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
|
@ -34,6 +35,7 @@ import (
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/dbg"
|
_ "k8s.io/ingress-nginx/test/e2e/dbg"
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/defaultbackend"
|
_ "k8s.io/ingress-nginx/test/e2e/defaultbackend"
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/gracefulshutdown"
|
_ "k8s.io/ingress-nginx/test/e2e/gracefulshutdown"
|
||||||
|
_ "k8s.io/ingress-nginx/test/e2e/ingress"
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/leaks"
|
_ "k8s.io/ingress-nginx/test/e2e/leaks"
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/loadbalance"
|
_ "k8s.io/ingress-nginx/test/e2e/loadbalance"
|
||||||
_ "k8s.io/ingress-nginx/test/e2e/lua"
|
_ "k8s.io/ingress-nginx/test/e2e/lua"
|
||||||
|
|
|
@ -61,13 +61,6 @@ func Failf(format string, args ...interface{}) {
|
||||||
ginkgo.Fail(nowStamp()+": "+msg, 1)
|
ginkgo.Fail(nowStamp()+": "+msg, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skipf logs to the INFO logs and skips the test.
|
|
||||||
func Skipf(format string, args ...interface{}) {
|
|
||||||
msg := fmt.Sprintf(format, args...)
|
|
||||||
log("INFO", msg)
|
|
||||||
ginkgo.Skip(nowStamp() + ": " + msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RestclientConfig deserializes the contents of a kubeconfig file into a Config object.
|
// RestclientConfig deserializes the contents of a kubeconfig file into a Config object.
|
||||||
func RestclientConfig(config, context string) (*api.Config, error) {
|
func RestclientConfig(config, context string) (*api.Config, error) {
|
||||||
Logf(">>> config: %s\n", config)
|
Logf(">>> config: %s\n", config)
|
||||||
|
|
117
test/e2e/ingress/pathtype_exact.go
Normal file
117
test/e2e/ingress/pathtype_exact.go
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
Copyright 2019 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ingress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
networkingv1beta1 "k8s.io/api/networking/v1beta1"
|
||||||
|
|
||||||
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
|
||||||
|
f := framework.NewDefaultFramework("exact")
|
||||||
|
|
||||||
|
ginkgo.BeforeEach(func() {
|
||||||
|
f.NewEchoDeployment()
|
||||||
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should choose exact location for /exact", func() {
|
||||||
|
if !f.IsIngressV1Ready {
|
||||||
|
ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
|
||||||
|
}
|
||||||
|
|
||||||
|
host := "exact.path"
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";`,
|
||||||
|
}
|
||||||
|
|
||||||
|
var exactPathType = networkingv1beta1.PathTypeExact
|
||||||
|
ing := framework.NewSingleIngress("exact", "/exact", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||||
|
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
annotations = map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";`,
|
||||||
|
}
|
||||||
|
|
||||||
|
ing = framework.NewSingleIngress("exact-sufix", "/exact", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, host) &&
|
||||||
|
strings.Contains(server, "location = /exact") &&
|
||||||
|
strings.Contains(server, "location /exact")
|
||||||
|
})
|
||||||
|
|
||||||
|
body := f.HTTPTestClient().
|
||||||
|
GET("/exact").
|
||||||
|
WithHeader("Host", host).
|
||||||
|
Expect().
|
||||||
|
Status(http.StatusOK).
|
||||||
|
Body().
|
||||||
|
Raw()
|
||||||
|
|
||||||
|
assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||||
|
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact")
|
||||||
|
|
||||||
|
body = f.HTTPTestClient().
|
||||||
|
GET("/exact/sufix").
|
||||||
|
WithHeader("Host", host).
|
||||||
|
Expect().
|
||||||
|
Status(http.StatusOK).
|
||||||
|
Body().
|
||||||
|
Raw()
|
||||||
|
|
||||||
|
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||||
|
|
||||||
|
annotations = map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/configuration-snippet": `
|
||||||
|
more_set_input_headers "pathType: prefix";
|
||||||
|
more_set_input_headers "duplicated: true";
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
ing = framework.NewSingleIngress("duplicated-prefix", "/exact", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, host) &&
|
||||||
|
strings.Contains(server, "location = /exact") &&
|
||||||
|
strings.Contains(server, "location /exact")
|
||||||
|
})
|
||||||
|
|
||||||
|
body = f.HTTPTestClient().
|
||||||
|
GET("/exact/sufix").
|
||||||
|
WithHeader("Host", host).
|
||||||
|
Expect().
|
||||||
|
Status(http.StatusOK).
|
||||||
|
Body().
|
||||||
|
Raw()
|
||||||
|
|
||||||
|
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||||
|
assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=exact")
|
||||||
|
assert.NotContains(ginkgo.GinkgoT(), body, "duplicated=true")
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue