From 8c34a2d4377ebc6e02498337ac19de74559d8fc0 Mon Sep 17 00:00:00 2001 From: Christian Groschupp Date: Wed, 15 Mar 2023 15:19:56 +0100 Subject: [PATCH] add tests Signed-off-by: Christian Groschupp --- internal/ingress/annotations/annotations.go | 2 +- .../ingress/annotations/annotations_test.go | 48 +++++++- .../ingress/annotations/customheaders/main.go | 2 +- .../annotations/customheaders/main_test.go | 103 ++++++++++++++++++ 4 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 internal/ingress/annotations/customheaders/main_test.go diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go index 88c248078..0bb2ac7b8 100644 --- a/internal/ingress/annotations/annotations.go +++ b/internal/ingress/annotations/annotations.go @@ -135,7 +135,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor { "Canary": canary.NewParser(cfg), "CertificateAuth": authtls.NewParser(cfg), "ClientBodyBufferSize": clientbodybuffersize.NewParser(cfg), - "ClientHeaders": customheaders.NewParser(cfg), + "CustomHeaders": customheaders.NewParser(cfg), "ConfigurationSnippet": snippet.NewParser(cfg), "Connection": connection.NewParser(cfg), "CorsConfig": cors.NewParser(cfg), diff --git a/internal/ingress/annotations/annotations_test.go b/internal/ingress/annotations/annotations_test.go index 0f4f8f7d7..b1a50401c 100644 --- a/internal/ingress/annotations/annotations_test.go +++ b/internal/ingress/annotations/annotations_test.go @@ -43,12 +43,14 @@ var ( annotationAffinityCookieName = parser.GetAnnotationWithPrefix("session-cookie-name") annotationUpstreamHashBy = parser.GetAnnotationWithPrefix("upstream-hash-by") annotationCustomHTTPErrors = parser.GetAnnotationWithPrefix("custom-http-errors") + annotationCustomHeaders = parser.GetAnnotationWithPrefix("custom-headers") ) type mockCfg struct { resolver.Mock - MockSecrets map[string]*apiv1.Secret - MockServices map[string]*apiv1.Service + MockSecrets map[string]*apiv1.Secret + MockServices map[string]*apiv1.Service + MockConfigMaps map[string]*apiv1.ConfigMap } func (m mockCfg) GetDefaultBackend() defaults.Backend { @@ -63,6 +65,10 @@ func (m mockCfg) GetService(name string) (*apiv1.Service, error) { return m.MockServices[name], nil } +func (m mockCfg) GetConfigMap(name string) (*apiv1.ConfigMap, error) { + return m.MockConfigMaps[name], nil +} + func (m mockCfg) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error) { secret, err := m.GetSecret(name) if err != nil { @@ -317,3 +323,41 @@ func TestCustomHTTPErrors(t *testing.T) { } } } + +func TestCustomResponseHeaders(t *testing.T) { + mockObj := mockCfg{} + mockObj.MockConfigMaps = map[string]*apiv1.ConfigMap{} + mockObj.MockConfigMaps["custom-headers"] = &apiv1.ConfigMap{Data: map[string]string{"Content-Type": "application/json"}} + mockObj.MockConfigMaps["empty-custom-headers"] = &apiv1.ConfigMap{Data: map[string]string{}} + + ec := NewAnnotationExtractor(mockObj) + ing := buildIngress() + + fooAnns := []struct { + annotations map[string]string + headers map[string]string + }{ + {map[string]string{annotationCustomHeaders: "custom-headers"}, map[string]string{"Content-Type": "application/json"}}, + {map[string]string{annotationCustomHeaders: "empty-custom-headers"}, map[string]string{}}, + {nil, map[string]string{}}, + } + + for _, foo := range fooAnns { + ing.SetAnnotations(foo.annotations) + r := ec.Extract(ing).CustomHeaders.Headers + + // Check that expected headers were created + for i := range foo.headers { + if r[i] != foo.headers[i] { + t.Errorf("Returned %v but expected %v", r, foo.headers) + } + } + + // Check that no unexpected headers were created + for i := range r { + if r[i] != foo.headers[i] { + t.Errorf("Returned %v but expected %v", r, foo.headers) + } + } + } +} diff --git a/internal/ingress/annotations/customheaders/main.go b/internal/ingress/annotations/customheaders/main.go index 08efbd6aa..267eb7ebe 100644 --- a/internal/ingress/annotations/customheaders/main.go +++ b/internal/ingress/annotations/customheaders/main.go @@ -40,7 +40,7 @@ var ( // ValidHeader checks is the provided string satisfies the header's name regex func ValidHeader(header string) bool { - return headerRegexp.Match([]byte(header)) + return headerRegexp.MatchString(header) } type customHeaders struct { diff --git a/internal/ingress/annotations/customheaders/main_test.go b/internal/ingress/annotations/customheaders/main_test.go new file mode 100644 index 000000000..52a1b9115 --- /dev/null +++ b/internal/ingress/annotations/customheaders/main_test.go @@ -0,0 +1,103 @@ +/* +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 customheaders + +import ( + "reflect" + "testing" + + api "k8s.io/api/core/v1" + networking "k8s.io/api/networking/v1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/resolver" +) + +func buildIngress() *networking.Ingress { + return &networking.Ingress{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "foo", + Namespace: api.NamespaceDefault, + }, + Spec: networking.IngressSpec{ + DefaultBackend: &networking.IngressBackend{ + Service: &networking.IngressServiceBackend{ + Name: "default-backend", + Port: networking.ServiceBackendPort{ + Number: 80, + }, + }, + }, + }, + } +} + +func TestCustomHeadersParseInvalidAnnotations(t *testing.T) { + ing := buildIngress() + configMapResolver := &resolver.Mock{ + ConfigMaps: map[string]*api.ConfigMap{}, + } + + _, err := NewParser(configMapResolver).Parse(ing) + if err != nil { + t.Errorf("expected error parsing ingress with custom-response-headers") + } + + data := map[string]string{} + data[parser.GetAnnotationWithPrefix("custom-headers")] = "custom-headers-configmap" + ing.SetAnnotations(data) + i, err := NewParser(&resolver.Mock{}).Parse(ing) + if err == nil { + t.Errorf("expected error parsing ingress with custom-response-headers") + } + if i != nil { + t.Errorf("expected %v but got %v", nil, i) + } +} + +func TestCustomHeadersParseAnnotations(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[parser.GetAnnotationWithPrefix("custom-headers")] = "custom-headers-configmap" + ing.SetAnnotations(data) + + configMapResolver := &resolver.Mock{ + ConfigMaps: map[string]*api.ConfigMap{}, + } + + configMapResolver.ConfigMaps["custom-headers-configmap"] = &api.ConfigMap{Data: map[string]string{"Content-Type": "application/json", "Access-Control-Max-Age": "600"}} + + i, err := NewParser(configMapResolver).Parse(ing) + if err != nil { + t.Errorf("unexpected error parsing ingress with custom-response-headers") + } + val, ok := i.(*Config) + if !ok { + t.Errorf("expected a *Config type") + } + + expected_response_headers := map[string]string{} + expected_response_headers["Content-Type"] = "application/json" + expected_response_headers["Access-Control-Max-Age"] = "600" + + c := &Config{expected_response_headers} + + if !reflect.DeepEqual(c, val) { + t.Errorf("expected %v but got %v", c, val) + } +}