From 638a93835a8a0ce7de28975da07ea59ff0bd2045 Mon Sep 17 00:00:00 2001 From: Marcos Nery Date: Wed, 25 Aug 2021 21:45:23 -0300 Subject: [PATCH] Improving e2e tests for non-service backends #7544 (#7545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adding test cases for backend with nil service Signed-off-by: Marcos Co-authored-by: Renato Araujo Co-authored-by: André Goretti Co-authored-by: Kalebe Lopes * Add e2e test for backend nil service and add nil safeguard (#7344) Co-authored-by: Renato Araujo Co-authored-by: André Goretti Co-authored-by: Kalebe Lopes * changing portuguese names to english in order to maintain the pattern * updating boilerplate header * adding second test case to also test valid path Co-authored-by: Ricardo Katz * Updating boilerplate * fixing boilerplate Signed-off-by: MarcosN Co-authored-by: André Goretti Co-authored-by: Gabriel Albino * Improving template test for cases where a nil backend service is included Signed-off-by: MarcosN Co-authored-by: André Goretti Co-authored-by: Gabriel Albino Co-authored-by: Renato Araujo Co-authored-by: André Goretti Co-authored-by: Kalebe Lopes Co-authored-by: Ricardo Katz Co-authored-by: Gabriel Albino --- .../ingress/controller/template/template.go | 4 + .../controller/template/template_test.go | 100 +++++++++++++++++ .../e2e/servicebackend/service_nil_backend.go | 106 ++++++++++++++++++ 3 files changed, 210 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 3f7e4af50..b06f5a216 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -1018,6 +1018,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 4a64a0962..14291dbf2 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -1203,6 +1203,106 @@ 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", + }, + }, + }, + "valid ingress definition with name demo in namespace something and path /ok with both a nil service and a valid one": { + &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, + }, + }, + { + Path: "/oksvc", + PathType: &pathPrefix, + Backend: networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: "b-svc", + Port: networking.ServiceBackendPort{ + Name: "b-svc-80", + }, + }, + }, + }, + }, + }, + }, + }, + {}, + }, + }, + }, + }, + "foo.bar", + "/oksvc", + &ingressInformation{ + Namespace: "something", + Rule: "demo", + Annotations: map[string]string{ + "ingress.annotation": "ok", + }, + Service: "b-svc", + ServicePort: "b-svc-80", + }, + }, } 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 000000000..864f94fbe --- /dev/null +++ b/test/e2e/servicebackend/service_nil_backend.go @@ -0,0 +1,106 @@ +/* +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: "mytest", + 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, + }, + }, + }, + }, + }, + }, + }, + }, + } +}