Fix panic on multiple ingress mess up upstream is primary or not
This commit is contained in:
parent
8740c1b661
commit
435377f47f
2 changed files with 286 additions and 9 deletions
|
@ -1227,9 +1227,16 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
merged := false
|
merged := false
|
||||||
|
altEqualsPri := false
|
||||||
|
|
||||||
for _, loc := range servers[defServerName].Locations {
|
for _, loc := range servers[defServerName].Locations {
|
||||||
priUps := upstreams[loc.Backend]
|
priUps := upstreams[loc.Backend]
|
||||||
|
altEqualsPri = altUps.Name == priUps.Name
|
||||||
|
if altEqualsPri {
|
||||||
|
klog.Warningf("alternative upstream %s in Ingress %s/%s is primary upstream in Other Ingress for location %s%s!",
|
||||||
|
altUps.Name, ing.Namespace, ing.Name, servers[defServerName].Hostname, loc.Path)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if canMergeBackend(priUps, altUps) {
|
if canMergeBackend(priUps, altUps) {
|
||||||
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
||||||
|
@ -1239,7 +1246,7 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !merged {
|
if !altEqualsPri && !merged {
|
||||||
klog.Warningf("unable to find real backend for alternative backend %v. Deleting.", altUps.Name)
|
klog.Warningf("unable to find real backend for alternative backend %v. Deleting.", altUps.Name)
|
||||||
delete(upstreams, altUps.Name)
|
delete(upstreams, altUps.Name)
|
||||||
}
|
}
|
||||||
|
@ -1258,6 +1265,7 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
}
|
}
|
||||||
|
|
||||||
merged := false
|
merged := false
|
||||||
|
altEqualsPri := false
|
||||||
|
|
||||||
server, ok := servers[rule.Host]
|
server, ok := servers[rule.Host]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -1271,6 +1279,12 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
// find matching paths
|
// find matching paths
|
||||||
for _, loc := range server.Locations {
|
for _, loc := range server.Locations {
|
||||||
priUps := upstreams[loc.Backend]
|
priUps := upstreams[loc.Backend]
|
||||||
|
altEqualsPri = altUps.Name == priUps.Name
|
||||||
|
if altEqualsPri {
|
||||||
|
klog.Warningf("alternative upstream %s in Ingress %s/%s is primary upstream in Other Ingress for location %s%s!",
|
||||||
|
altUps.Name, ing.Namespace, ing.Name, server.Hostname, loc.Path)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if canMergeBackend(priUps, altUps) && loc.Path == path.Path {
|
if canMergeBackend(priUps, altUps) && loc.Path == path.Path {
|
||||||
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
klog.V(2).Infof("matching backend %v found for alternative backend %v",
|
||||||
|
@ -1280,7 +1294,7 @@ func mergeAlternativeBackends(ing *ingress.Ingress, upstreams map[string]*ingres
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !merged {
|
if !altEqualsPri && !merged {
|
||||||
klog.Warningf("unable to find real backend for alternative backend %v. Deleting.", altUps.Name)
|
klog.Warningf("unable to find real backend for alternative backend %v. Deleting.", altUps.Name)
|
||||||
delete(upstreams, altUps.Name)
|
delete(upstreams, altUps.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -818,7 +818,7 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Ingresses []*ingress.Ingress
|
Ingresses []*ingress.Ingress
|
||||||
Validate func(servers []*ingress.Server)
|
Validate func(upstreams []*ingress.Backend, servers []*ingress.Server)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Ingresses: []*ingress.Ingress{
|
Ingresses: []*ingress.Ingress{
|
||||||
|
@ -843,7 +843,7 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Validate: func(servers []*ingress.Server) {
|
Validate: func(upstreams []*ingress.Backend, servers []*ingress.Server) {
|
||||||
if len(servers) != 1 {
|
if len(servers) != 1 {
|
||||||
t.Errorf("servers count should be 1, got %d", len(servers))
|
t.Errorf("servers count should be 1, got %d", len(servers))
|
||||||
return
|
return
|
||||||
|
@ -905,7 +905,7 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Validate: func(servers []*ingress.Server) {
|
Validate: func(upstreams []*ingress.Backend, servers []*ingress.Server) {
|
||||||
if len(servers) != 1 {
|
if len(servers) != 1 {
|
||||||
t.Errorf("servers count should be 1, got %d", len(servers))
|
t.Errorf("servers count should be 1, got %d", len(servers))
|
||||||
return
|
return
|
||||||
|
@ -962,7 +962,7 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Validate: func(servers []*ingress.Server) {
|
Validate: func(upstreams []*ingress.Backend, servers []*ingress.Server) {
|
||||||
if len(servers) != 1 {
|
if len(servers) != 1 {
|
||||||
t.Errorf("servers count should be 1, got %d", len(servers))
|
t.Errorf("servers count should be 1, got %d", len(servers))
|
||||||
return
|
return
|
||||||
|
@ -1056,7 +1056,7 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Validate: func(servers []*ingress.Server) {
|
Validate: func(upstreams []*ingress.Backend, servers []*ingress.Server) {
|
||||||
if len(servers) != 2 {
|
if len(servers) != 2 {
|
||||||
t.Errorf("servers count should be 2, got %d", len(servers))
|
t.Errorf("servers count should be 2, got %d", len(servers))
|
||||||
return
|
return
|
||||||
|
@ -1084,11 +1084,274 @@ func TestGetBackendServers(t *testing.T) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Ingresses: []*ingress.Ingress{
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-a",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/a",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-1",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-a-canary",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/a",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-2",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-b",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/b",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-2",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-b-canary",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/b",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-1",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-c",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/c",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-1",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Ingress: networking.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "example-c-canary",
|
||||||
|
Namespace: "example",
|
||||||
|
},
|
||||||
|
Spec: networking.IngressSpec{
|
||||||
|
Rules: []networking.IngressRule{
|
||||||
|
{
|
||||||
|
Host: "example.com",
|
||||||
|
IngressRuleValue: networking.IngressRuleValue{
|
||||||
|
HTTP: &networking.HTTPIngressRuleValue{
|
||||||
|
Paths: []networking.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/c",
|
||||||
|
Backend: networking.IngressBackend{
|
||||||
|
ServiceName: "http-svc-2",
|
||||||
|
ServicePort: intstr.IntOrString{
|
||||||
|
Type: intstr.Int,
|
||||||
|
IntVal: 80,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ParsedAnnotations: &annotations.Ingress{
|
||||||
|
Canary: canary.Config{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Validate: func(upstreams []*ingress.Backend, servers []*ingress.Server) {
|
||||||
|
if len(servers) != 2 {
|
||||||
|
t.Errorf("servers count should be 2, got %d", len(servers))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s := servers[0]
|
||||||
|
if s.Hostname != "_" {
|
||||||
|
t.Errorf("server hostname should be '_', got '%s'", s.Hostname)
|
||||||
|
}
|
||||||
|
if !s.Locations[0].IsDefBackend {
|
||||||
|
t.Errorf("server location 0 should be default backend")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Locations[0].Backend != defUpstreamName {
|
||||||
|
t.Errorf("location backend should be '%s', got '%s'", defUpstreamName, s.Locations[0].Backend)
|
||||||
|
}
|
||||||
|
|
||||||
|
s = servers[1]
|
||||||
|
if s.Hostname != "example.com" {
|
||||||
|
t.Errorf("server hostname should be 'example.com', got '%s'", s.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Locations[0].Backend != "example-http-svc-1-80" || s.Locations[1].Backend != "example-http-svc-1-80" || s.Locations[2].Backend != "example-http-svc-1-80" {
|
||||||
|
t.Errorf("all location backend should be 'example-http-svc-1-80'")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(upstreams) != 3 {
|
||||||
|
t.Errorf("upstreams count should be 3, got %d", len(upstreams))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if upstreams[0].Name != "example-http-svc-1-80" {
|
||||||
|
t.Errorf("example-http-svc-1-80 should be frist upstream, got %s", upstreams[0].Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if upstreams[0].NoServer {
|
||||||
|
t.Errorf("'example-http-svc-1-80' should be primary upstream, got as alternative upstream")
|
||||||
|
}
|
||||||
|
if len(upstreams[0].AlternativeBackends) != 1 || upstreams[0].AlternativeBackends[0] != "example-http-svc-2-80" {
|
||||||
|
t.Errorf("example-http-svc-2-80 should be alternative upstream for 'example-http-svc-1-80'")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
_, servers := ctl.getBackendServers(testCase.Ingresses)
|
upstreams, servers := ctl.getBackendServers(testCase.Ingresses)
|
||||||
testCase.Validate(servers)
|
testCase.Validate(upstreams, servers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue