From e2136676d8eb230943a1261d000e27a0fc1192f6 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Tue, 24 Aug 2021 20:03:19 -0300 Subject: [PATCH] Add e2e test for backend nil service and add nil safeguard (#7344) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Renato Araujo Co-authored-by: André Goretti Co-authored-by: Kalebe Lopes --- .../ingress/controller/template/template.go | 4 + .../controller/template/template_test.go | 43 ++++++++ .../e2e/servicebackend/service_nil_backend.go | 103 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 test/e2e/servicebackend/service_nil_backend.go diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 2a0f92206a..f51b9ada87 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -1015,6 +1015,10 @@ func getIngressInformation(i, h, p interface{}) *ingressInformation { continue } + if rPath.Backend.Service == nil { + continue + } + if info.Service != "" && rPath.Backend.Service.Name == "" { // empty rule. Only contains a Path and PathType return info diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go index 0ffa2bc1a9..9673714c21 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -1140,6 +1140,49 @@ func TestGetIngressInformation(t *testing.T) { ServicePort: "b-svc-80", }, }, + "valid ingress definition with name demo in namespace something and path /ok with a nil backend service": { + &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: "/ok", + PathType: &pathPrefix, + Backend: networking.IngressBackend{ + Service: nil, + }, + }, + }, + }, + }, + }, + {}, + }, + }, + }, + }, + "foo.bar", + "/ok", + &ingressInformation{ + Namespace: "something", + Rule: "demo", + Annotations: map[string]string{ + "ingress.annotation": "ok", + }, + }, + }, } for title, testCase := range testcases { diff --git a/test/e2e/servicebackend/service_nil_backend.go b/test/e2e/servicebackend/service_nil_backend.go new file mode 100644 index 0000000000..305beec1b5 --- /dev/null +++ b/test/e2e/servicebackend/service_nil_backend.go @@ -0,0 +1,103 @@ +/* +Copyright 2021 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 servicebackend + +import ( + "net/http" + "strings" + + "github.com/onsi/ginkgo" + corev1 "k8s.io/api/core/v1" + networking "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/ingress-nginx/test/e2e/framework" +) + +var _ = framework.IngressNginxDescribe("[Service] Nil Service Backend", func() { + f := framework.NewDefaultFramework("service-nil-backend") + + ginkgo.BeforeEach(func() { + f.NewEchoDeployment() + }) + + ginkgo.It("should return 404 when backend service is nil", func() { + ginkgo.By("setting an ingress with a nil backend") + validHost := "valid.svc.com" + invalidHost := "nilbackend.svc.com" + + ing := framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, + framework.EchoService, 80, nil) + + bi := buildIngressWithNonServiceBackend(invalidHost, f.Namespace, "/") + + f.EnsureIngress(bi) + f.EnsureIngress(ing) + + f.WaitForNginxConfiguration(func(cfg string) bool { + return strings.Contains(cfg, "server_name nilbackend.svc.com") && + strings.Contains(cfg, "server_name valid.svc.com") + }) + + f.HTTPTestClient(). + GET("/"). + WithHeader("Host", validHost). + Expect(). + Status(http.StatusOK) + + f.HTTPTestClient(). + GET("/"). + WithHeader("Host", invalidHost). + Expect(). + Status(http.StatusNotFound) + + }) +}) + +func buildIngressWithNonServiceBackend(host, namespace, path string) *networking.Ingress { + apiGroup := "otherobj.testingress.com" + obj := corev1.TypedLocalObjectReference{ + Kind: "Anything", + Name: "meutest", + APIGroup: &apiGroup, + } + + return &networking.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: host, + Namespace: namespace, + }, + Spec: networking.IngressSpec{ + IngressClassName: framework.GetIngressClassName(namespace), + Rules: []networking.IngressRule{ + { + Host: host, + IngressRuleValue: networking.IngressRuleValue{ + HTTP: &networking.HTTPIngressRuleValue{ + Paths: []networking.HTTPIngressPath{ + { + Path: path, + PathType: &pathtype, + Backend: networking.IngressBackend{ + Resource: &obj, + }, + }, + }, + }, + }, + }, + }, + }, + } +}