Merge branch 'kubernetes:main' into main

This commit is contained in:
Nicholas Orlowsky 2024-05-18 02:10:37 +02:00 committed by GitHub
commit 9e79a36020
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
664 changed files with 19886 additions and 10226 deletions

View file

@ -47,7 +47,7 @@ http {
listen_ports = { ssl_proxy = "442", https = "443" },
hsts = true,
hsts_max_age = 15724800,
hsts_max_age = 31536000,
hsts_include_subdomains = true,
hsts_preload = false,
})

View file

@ -65,7 +65,7 @@ lua_shared_dict ocsp_response_cache 5M;
listen_ports = { ssl_proxy = "442", https = "443" },
hsts = true,
hsts_max_age = 15724800,
hsts_max_age = 31536000,
hsts_include_subdomains = true,
hsts_preload = false,
})

View file

@ -25,7 +25,7 @@
"gzipTypes": "application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/javascript text/plain text/x-component",
"hsts": true,
"hstsIncludeSubdomains": true,
"hstsMaxAge": "15724800",
"hstsMaxAge": "31536000",
"keepAlive": 75,
"mapHashBucketSize": 64,
"maxWorkerConnections": 16384,

View file

@ -1,13 +1,12 @@
ARG E2E_BASE_IMAGE
FROM ${E2E_BASE_IMAGE} AS BASE
FROM alpine:3.18.0
FROM alpine:3.19.1
RUN apk update \
&& apk upgrade && apk add -U --no-cache \
ca-certificates \
bash \
curl \
tzdata \
libc6-compat \
openssl

View file

@ -1,6 +1,6 @@
DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
E2E_BASE_IMAGE ?= "registry.k8s.io/ingress-nginx/e2e-test-runner:v20230623-d50c7193b@sha256:e5c68dc56934c273850bfb75c0348a2819756669baf59fcdce9e16771537b247"
E2E_BASE_IMAGE ?= "registry.k8s.io/ingress-nginx/e2e-test-runner:v20240404-436df3e4@sha256:6bcba53b14d396177414e01f20e9111f1c009ac3b476a9b7668bb98d12bd5e85"
image:
echo "..entered Makefile in /test/e2e-image"

View file

@ -0,0 +1,34 @@
# TODO: remove the need to use fullnameOverride
fullnameOverride: nginx-ingress
controller:
image:
repository: ingress-controller/controller
chroot: true
tag: 1.0.0-dev
digest:
digestChroot:
scope:
# Necessary to allow the ingress controller to get the topology information from the nodes
enabled: false
config:
worker-processes: "1"
readinessProbe:
initialDelaySeconds: 3
periodSeconds: 1
livenessProbe:
initialDelaySeconds: 3
periodSeconds: 1
service:
type: NodePort
extraArgs:
# e2e tests do not require information about ingress status
update-status: "false"
terminationGracePeriodSeconds: 1
admissionWebhooks:
enabled: false
disableLeaderElection: true
rbac:
create: true
scope: false

View file

@ -0,0 +1,38 @@
# TODO: remove the need to use fullnameOverride
fullnameOverride: nginx-ingress
controller:
image:
repository: ingress-controller/controller
chroot: true
tag: 1.0.0-dev
digest:
digestChroot:
containerPort:
http: "1080"
https: "1443"
extraArgs:
http-port: "1080"
https-port: "1443"
# e2e tests do not require information about ingress status
update-status: "false"
scope:
enabled: true
config:
worker-processes: "1"
service:
type: NodePort
admissionWebhooks:
enabled: true
certificate: "/usr/local/certificates/cert"
key: "/usr/local/certificates/key"
defaultBackend:
enabled: false
rbac:
create: true
scope: true

View file

@ -1 +1 @@
registry.k8s.io/ingress-nginx/e2e-test-httpbun:v20230505-v0.0.1
registry.k8s.io/ingress-nginx/e2e-test-httpbun:v20231011-8b53cabe0

View file

@ -34,6 +34,8 @@ import (
networking "k8s.io/api/networking/v1"
)
const admissionTestHost = "admission-test"
var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller", func() {
f := framework.NewDefaultFramework("admission")
@ -43,7 +45,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("reject ingress with global-rate-limit annotations when memcached is not configured", func() {
host := "admission-test"
host := admissionTestHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/global-rate-limit": "100",
@ -70,7 +72,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should not allow overlaps of host and paths without canary annotations", func() {
host := "admission-test"
host := admissionTestHost
firstIngress := framework.NewSingleIngress("first-ingress", "/", host, f.Namespace, framework.EchoService, 80, nil)
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
@ -87,7 +89,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should allow overlaps of host and paths with canary annotation", func() {
host := "admission-test"
host := admissionTestHost
firstIngress := framework.NewSingleIngress("first-ingress", "/", host, f.Namespace, framework.EchoService, 80, nil)
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
@ -125,7 +127,16 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should return an error if there is an error validating the ingress definition", func() {
host := "admission-test"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := admissionTestHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/configuration-snippet": "something invalid",
@ -136,7 +147,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should return an error if there is an invalid value in some annotation", func() {
host := "admission-test"
host := admissionTestHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/connection-proxy-header": "a;}",
@ -150,7 +161,7 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should return an error if there is a forbidden value in some annotation", func() {
host := "admission-test"
host := admissionTestHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/connection-proxy-header": "set_by_lua",
@ -195,7 +206,6 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
validPath := framework.NewSingleIngress("second-ingress", "/bloblo", host, f.Namespace, framework.EchoService, 80, nil)
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), validPath, metav1.CreateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "creating an ingress with valid path should not return an error")
})
ginkgo.It("should not return an error if the Ingress V1 definition is valid with Ingress Class", func() {
@ -231,6 +241,15 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should return an error if the Ingress V1 definition contains invalid annotations", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
out, err := createIngress(f.Namespace, invalidV1Ingress)
assert.Empty(ginkgo.GinkgoT(), out)
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
@ -242,6 +261,14 @@ var _ = framework.IngressNginxDescribeSerial("[Admission] admission controller",
})
ginkgo.It("should not return an error for an invalid Ingress when it has unknown class", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
out, err := createIngress(f.Namespace, invalidV1IngressWithOtherClass)
assert.Equal(ginkgo.GinkgoT(), "ingress.networking.k8s.io/extensions-invalid-other created\n", out)
assert.Nil(ginkgo.GinkgoT(), err, "creating an invalid ingress with unknown class using kubectl")
@ -346,7 +373,7 @@ func createIngress(namespace, ingressDefinition string) (string, error) {
execOut bytes.Buffer
execErr bytes.Buffer
)
//nolint:gosec // Ignore G204 error
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v --warnings-as-errors=false apply --namespace %s -f -", framework.KubectlPath, namespace))
cmd.Stdin = strings.NewReader(ingressDefinition)
cmd.Stdout = &execOut

View file

@ -32,6 +32,14 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
affinityAnnotation = "cookie"
cookieName = "SERVERID"
enableAnnotation = "true"
disableAnnotation = "false"
defaultHost = "foo.com"
)
var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
f := framework.NewDefaultFramework("affinity")
@ -42,8 +50,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should set sticky cookie SERVERID", func() {
host := "sticky.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -64,8 +72,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should change cookie name on ingress definition change", func() {
host := "change.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -80,7 +88,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
WithHeader("Host", host).
Expect().
Status(http.StatusOK).
Header("Set-Cookie").Contains("SERVERID")
Header("Set-Cookie").Contains(cookieName)
ing.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "OTHERCOOKIENAME"
@ -99,8 +107,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should set the path to /something on the generated cookie", func() {
host := "path.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
ing := framework.NewSingleIngress(host, "/something", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -122,8 +130,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
pathtype := networking.PathTypePrefix
host := "morethanonerule.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
f.EnsureIngress(&networking.Ingress{
ObjectMeta: metav1.ObjectMeta{
@ -194,7 +202,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should set cookie with expires", func() {
host := "cookieexpires.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "ExpiresCookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-expires"] = "172800"
annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "259200"
@ -211,7 +219,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
assert.Nil(ginkgo.GinkgoT(), err, "loading GMT location")
assert.NotNil(ginkgo.GinkgoT(), local, "expected a location but none returned")
duration, _ := time.ParseDuration("48h")
duration, err := time.ParseDuration("48h")
assert.Nil(ginkgo.GinkgoT(), err, "parsing duration")
expected := time.Now().In(local).Add(duration).Format("Mon, 02-Jan-06 15:04")
f.HTTPTestClient().
@ -225,7 +234,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should set cookie with domain", func() {
host := "cookiedomain.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "DomainCookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-domain"] = "foo.bar"
@ -248,7 +257,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should not set cookie without domain annotation", func() {
host := "cookienodomain.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "NoDomainCookie"
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
@ -270,9 +279,9 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should work with use-regex annotation and session-cookie-path", func() {
host := "useregex.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/use-regex"] = "true"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/use-regex"] = enableAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-path"] = "/foo/bar"
ing := framework.NewSingleIngress(host, "/foo/.*", host, f.Namespace, framework.EchoService, 80, annotations)
@ -294,9 +303,9 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should warn user when use-regex is true and session-cookie-path is not set", func() {
host := "useregexwarn.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/use-regex"] = "true"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/use-regex"] = enableAnnotation
ing := framework.NewSingleIngress(host, "/foo/.*", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -321,7 +330,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
host := "separate.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
ing1 := framework.NewSingleIngress("ingress1", "/foo/bar", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing1)
@ -351,8 +360,8 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ginkgo.It("should set sticky cookie without host", func() {
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
ing := framework.NewSingleIngress("default-no-host", "/", "", f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -370,12 +379,12 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
})
ginkgo.It("should work with server-alias annotation", func() {
host := "foo.com"
host := defaultHost
alias1 := "a1.foo.com"
alias2 := "a2.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/server-alias"] = fmt.Sprintf("%s,%s", alias1, alias2)
ing := framework.NewSingleIngress(host, "/bar", host, f.Namespace, framework.EchoService, 80, annotations)
@ -383,7 +392,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
f.WaitForNginxServer(host,
func(server string) bool {
//server alias sort by sort.Strings(), see: internal/ingress/annotations/alias/main.go:60
// server alias sort by sort.Strings(), see: internal/ingress/annotations/alias/main.go:60
return strings.Contains(server, fmt.Sprintf("server_name %s %s %s ;", host, alias1, alias2))
})
@ -410,11 +419,11 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
})
ginkgo.It("should set secure in cookie with provided true annotation on http", func() {
host := "foo.com"
host := defaultHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = "true"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = enableAnnotation
ing := framework.NewSingleIngress(host, "/bar", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -433,11 +442,11 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
})
ginkgo.It("should not set secure in cookie with provided false annotation on http", func() {
host := "foo.com"
host := defaultHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = "false"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = disableAnnotation
ing := framework.NewSingleIngress(host, "/bar", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -456,11 +465,11 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
})
ginkgo.It("should set secure in cookie with provided false annotation on https", func() {
host := "foo.com"
host := defaultHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "SERVERID"
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = "false"
annotations["nginx.ingress.kubernetes.io/affinity"] = affinityAnnotation
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = cookieName
annotations["nginx.ingress.kubernetes.io/session-cookie-secure"] = disableAnnotation
f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, framework.EchoService, 80, annotations))
@ -470,6 +479,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
strings.Contains(server, "listen 443")
})
//nolint:gosec // Ignore the gosec error in testing
f.HTTPTestClientWithTLSConfig(&tls.Config{ServerName: host, InsecureSkipVerify: true}).
GET("/").
WithURL(f.GetURL(framework.HTTPS)).

View file

@ -28,6 +28,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const sslRedirectValue = "false"
var _ = framework.DescribeAnnotation("affinitymode", func() {
f := framework.NewDefaultFramework("affinity")
@ -45,7 +47,7 @@ var _ = framework.DescribeAnnotation("affinitymode", func() {
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "hello-cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-expires"] = "172800"
annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "172800"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = sslRedirectValue
annotations["nginx.ingress.kubernetes.io/affinity-mode"] = "balanced"
annotations["nginx.ingress.kubernetes.io/session-cookie-hash"] = "sha1"
@ -78,7 +80,7 @@ var _ = framework.DescribeAnnotation("affinitymode", func() {
annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "hello-cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-expires"] = "172800"
annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "172800"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = sslRedirectValue
annotations["nginx.ingress.kubernetes.io/affinity-mode"] = "persistent"
annotations["nginx.ingress.kubernetes.io/session-cookie-hash"] = "sha1"
@ -106,7 +108,7 @@ var _ = framework.DescribeAnnotation("affinitymode", func() {
// Send new requests and add new backends. Check which backend responded to the sent request
cookies := getCookiesFromHeader(response.Header("Set-Cookie").Raw())
for sendRequestNumber := 0; sendRequestNumber < 10; sendRequestNumber++ {
replicas = replicas + 1
replicas++
err := framework.UpdateDeployment(f.KubeClientSet, f.Namespace, deploymentName, replicas, nil)
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()

View file

@ -26,6 +26,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const fooHost = "foo"
var _ = framework.DescribeAnnotation("server-alias", func() {
f := framework.NewDefaultFramework("alias")
@ -34,7 +36,7 @@ var _ = framework.DescribeAnnotation("server-alias", func() {
})
ginkgo.It("should return status code 200 for host 'foo' and 404 for 'bar'", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -60,7 +62,7 @@ var _ = framework.DescribeAnnotation("server-alias", func() {
})
ginkgo.It("should return status code 200 for host 'foo' and 'bar'", func() {
host := "foo"
host := fooHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/server-alias": "bar",
}
@ -73,7 +75,7 @@ var _ = framework.DescribeAnnotation("server-alias", func() {
return strings.Contains(server, fmt.Sprintf("server_name %v", host))
})
hosts := []string{"foo", "bar"}
hosts := []string{fooHost, "bar"}
for _, host := range hosts {
f.HTTPTestClient().
GET("/").
@ -85,7 +87,7 @@ var _ = framework.DescribeAnnotation("server-alias", func() {
})
ginkgo.It("should return status code 200 for hosts defined in two ingresses, different path with one alias", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleIngress("app-a", "/app-a", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -101,7 +103,7 @@ var _ = framework.DescribeAnnotation("server-alias", func() {
return strings.Contains(server, fmt.Sprintf("server_name %v bar", host))
})
hosts := []string{"foo", "bar"}
hosts := []string{fooHost, "bar"}
for _, host := range hosts {
f.HTTPTestClient().
GET("/app-a").

View file

@ -36,6 +36,12 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
differentHost = "different"
authHost = "auth"
authURL = "http://foo.bar.baz:5000/path"
)
var _ = framework.DescribeAnnotation("auth-*", func() {
f := framework.NewDefaultFramework("auth", framework.WithHTTPBunEnabled())
@ -44,7 +50,7 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 200 when no authentication is configured", func() {
host := "auth"
host := authHost
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -63,7 +69,7 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 503 when authentication is configured with an invalid secret", func() {
host := "auth"
host := authHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
"nginx.ingress.kubernetes.io/auth-secret": "something",
@ -87,9 +93,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 401 when authentication is configured but Authorization header is not configured", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.Namespace))
s := f.EnsureSecret(buildSecret(fooHost, "bar", "test", f.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -114,9 +120,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 401 when authentication is configured and Authorization header is sent with invalid credentials", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.Namespace))
s := f.EnsureSecret(buildSecret(fooHost, "bar", "test", f.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -142,9 +148,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 401 and cors headers when authentication and cors is configured but Authorization header is not configured", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.Namespace))
s := f.EnsureSecret(buildSecret(fooHost, "bar", "test", f.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -170,9 +176,9 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It("should return status code 200 when authentication is configured and Authorization header is sent", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(buildSecret("foo", "bar", "test", f.Namespace))
s := f.EnsureSecret(buildSecret(fooHost, "bar", "test", f.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -191,15 +197,15 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithBasicAuth("foo", "bar").
WithBasicAuth(fooHost, "bar").
Expect().
Status(http.StatusOK)
})
ginkgo.It("should return status code 200 when authentication is configured with a map and Authorization header is sent", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(buildMapSecret("foo", "bar", "test", f.Namespace))
s := f.EnsureSecret(buildMapSecret(fooHost, "bar", "test", f.Namespace))
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
@ -219,13 +225,13 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithBasicAuth("foo", "bar").
WithBasicAuth(fooHost, "bar").
Expect().
Status(http.StatusOK)
})
ginkgo.It("should return status code 401 when authentication is configured with invalid content and Authorization header is sent", func() {
host := "auth"
host := authHost
s := f.EnsureSecret(
&corev1.Secret{
@ -258,19 +264,27 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithBasicAuth("foo", "bar").
WithBasicAuth(fooHost, "bar").
Expect().
Status(http.StatusUnauthorized)
})
ginkgo.It(`should set snippet "proxy_set_header My-Custom-Header 42;" when external auth is configured`, func() {
host := "auth"
host := authHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-url": "http://foo.bar/basic-auth/user/password",
"nginx.ingress.kubernetes.io/auth-snippet": `
proxy_set_header My-Custom-Header 42;`,
}
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -282,7 +296,16 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It(`should not set snippet "proxy_set_header My-Custom-Header 42;" when external auth is not configured`, func() {
host := "auth"
host := authHost
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-snippet": `
@ -299,7 +322,7 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It(`should set "proxy_set_header 'My-Custom-Header' '42';" when auth-headers are set`, func() {
host := "auth"
host := authHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-url": "http://foo.bar/basic-auth/user/password",
@ -320,11 +343,11 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
})
ginkgo.It(`should set cache_key when external auth cache is configured`, func() {
host := "auth"
host := authHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-url": "http://foo.bar/basic-auth/user/password",
"nginx.ingress.kubernetes.io/auth-cache-key": "foo",
"nginx.ingress.kubernetes.io/auth-cache-key": fooHost,
"nginx.ingress.kubernetes.io/auth-cache-duration": "200 202 401 30m",
}
@ -337,7 +360,6 @@ var _ = framework.DescribeAnnotation("auth-*", func() {
func(server string) bool {
return cacheRegex.MatchString(server) &&
strings.Contains(server, `proxy_cache_valid 200 202 401 30m;`)
})
})
@ -403,9 +425,9 @@ http {
f.EnsureIngress(ing2)
f.WaitForNginxServer(host, func(server string) bool {
//nolint:goconst //server_name is a constant
return strings.Contains(server, "server_name "+host)
})
})
ginkgo.It("user retains cookie by default", func() {
@ -431,7 +453,7 @@ http {
})
ginkgo.It("user with annotated ingress retains cookie if upstream returns error status code", func() {
annotations["nginx.ingress.kubernetes.io/auth-always-set-cookie"] = "true"
annotations["nginx.ingress.kubernetes.io/auth-always-set-cookie"] = enableAnnotation
f.UpdateIngress(ing1)
f.UpdateIngress(ing2)
@ -451,7 +473,7 @@ http {
})
ginkgo.Context("when external authentication is configured", func() {
host := "auth"
host := authHost
var annotations map[string]string
var ing *networking.Ingress
@ -495,7 +517,7 @@ http {
annotations["nginx.ingress.kubernetes.io/auth-realm"] = "test auth"
f.UpdateIngress(ing)
anotherHost := "different"
anotherHost := differentHost
anotherAnnotations := map[string]string{}
anotherIng := framework.NewSingleIngress(anotherHost, "/", anotherHost, f.Namespace, framework.EchoService, 80, anotherAnnotations)
@ -544,12 +566,12 @@ http {
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
annotations["nginx.ingress.kubernetes.io/auth-url"] = "http://foo.bar.baz:5000/path"
annotations["nginx.ingress.kubernetes.io/auth-url"] = authURL
f.UpdateIngress(ing)
f.WaitForNginxServer("",
func(server string) bool {
return strings.Contains(server, "http://foo.bar.baz:5000/path") &&
return strings.Contains(server, authURL) &&
!strings.Contains(server, `upstream auth-external-auth`)
})
})
@ -582,19 +604,19 @@ http {
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
annotations["nginx.ingress.kubernetes.io/auth-url"] = "http://foo.bar.baz:5000/path"
annotations["nginx.ingress.kubernetes.io/auth-url"] = authURL
annotations["nginx.ingress.kubernetes.io/auth-keepalive"] = "-1"
f.UpdateIngress(ing)
f.WaitForNginxServer("",
func(server string) bool {
return strings.Contains(server, "http://foo.bar.baz:5000/path") &&
return strings.Contains(server, authURL) &&
!strings.Contains(server, `upstream auth-external-auth`)
})
})
ginkgo.It(`should not create additional upstream block when auth-keepalive is set with HTTP/2`, func() {
annotations["nginx.ingress.kubernetes.io/auth-url"] = "http://foo.bar.baz:5000/path"
annotations["nginx.ingress.kubernetes.io/auth-url"] = authURL
annotations["nginx.ingress.kubernetes.io/auth-keepalive"] = "123"
annotations["nginx.ingress.kubernetes.io/auth-keepalive-requests"] = "456"
annotations["nginx.ingress.kubernetes.io/auth-keepalive-timeout"] = "789"
@ -602,7 +624,7 @@ http {
f.WaitForNginxServer("",
func(server string) bool {
return strings.Contains(server, "http://foo.bar.baz:5000/path") &&
return strings.Contains(server, authURL) &&
!strings.Contains(server, `upstream auth-external-auth`)
})
})
@ -628,10 +650,49 @@ http {
strings.Contains(server, `keepalive_timeout 789s;`)
})
})
ginkgo.It(`should disable set_all_vars when auth-keepalive-share-vars is not set`, func() {
f.UpdateNginxConfigMapData("use-http2", "false")
defer func() {
f.UpdateNginxConfigMapData("use-http2", "true")
}()
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
annotations["nginx.ingress.kubernetes.io/auth-keepalive"] = "10"
f.UpdateIngress(ing)
f.WaitForNginxServer("",
func(server string) bool {
return strings.Contains(server, `upstream auth-external-auth`) &&
strings.Contains(server, `keepalive 10;`) &&
strings.Contains(server, `share_all_vars = false`)
})
})
ginkgo.It(`should enable set_all_vars when auth-keepalive-share-vars is true`, func() {
f.UpdateNginxConfigMapData("use-http2", "false")
defer func() {
f.UpdateNginxConfigMapData("use-http2", "true")
}()
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
annotations["nginx.ingress.kubernetes.io/auth-keepalive"] = "10"
annotations["nginx.ingress.kubernetes.io/auth-keepalive-share-vars"] = enableAnnotation
f.UpdateIngress(ing)
f.WaitForNginxServer("",
func(server string) bool {
return strings.Contains(server, `upstream auth-external-auth`) &&
strings.Contains(server, `keepalive 10;`) &&
strings.Contains(server, `share_all_vars = true`)
})
})
})
ginkgo.Context("when external authentication is configured with a custom redirect param", func() {
host := "auth"
host := authHost
var annotations map[string]string
var ing *networking.Ingress
@ -676,7 +737,7 @@ http {
annotations["nginx.ingress.kubernetes.io/auth-realm"] = "test auth"
f.UpdateIngress(ing)
anotherHost := "different"
anotherHost := differentHost
anotherAnnotations := map[string]string{}
anotherIng := framework.NewSingleIngress(anotherHost, "/", anotherHost, f.Namespace, framework.EchoService, 80, anotherAnnotations)
@ -696,8 +757,8 @@ http {
})
ginkgo.Context("when external authentication with caching is configured", func() {
thisHost := "auth"
thatHost := "different"
thisHost := authHost
thatHost := differentHost
fooPath := "/foo"
barPath := "/bar"
@ -819,7 +880,7 @@ http {
})
ginkgo.Context("with invalid auth-url should deny whole location", func() {
host := "auth"
host := authHost
var annotations map[string]string
var ing *networking.Ingress
@ -859,7 +920,6 @@ http {
// Auth error
func buildSecret(username, password, name, namespace string) *corev1.Secret {
//out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput()
out, err := bcrypt.GenerateFromPassword([]byte(password), 14)
encpass := fmt.Sprintf("%v:%s\n", username, out)
assert.Nil(ginkgo.GinkgoT(), err)
@ -878,7 +938,6 @@ func buildSecret(username, password, name, namespace string) *corev1.Secret {
}
func buildMapSecret(username, password, name, namespace string) *corev1.Secret {
//out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput()
out, err := bcrypt.GenerateFromPassword([]byte(password), 14)
assert.Nil(ginkgo.GinkgoT(), err)
@ -889,7 +948,7 @@ func buildMapSecret(username, password, name, namespace string) *corev1.Secret {
DeletionGracePeriodSeconds: framework.NewInt64(1),
},
Data: map[string][]byte{
username: []byte(out),
username: out,
},
Type: corev1.SecretTypeOpaque,
}

View file

@ -26,6 +26,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const authTLSFooHost = "authtls.foo.com"
var _ = framework.DescribeAnnotation("auth-tls-*", func() {
f := framework.NewDefaultFramework("authtls")
@ -34,7 +36,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should set sslClientCertificate, sslVerifyClient and sslVerifyDepth with auth-tls-secret", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -82,7 +84,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should set valid auth-tls-secret, sslVerify to off, and sslVerifyDepth to 2", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
_, err := framework.CreateIngressMASecret(
@ -112,7 +114,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should 302 redirect to error page instead of 400 when auth-tls-error-page is set", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
errorPath := "/error"
@ -159,7 +161,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should pass URL-encoded certificate to upstream", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -204,7 +206,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should validate auth-tls-verify-client", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -260,11 +262,10 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should return 403 using auth-tls-match-cn with no matching CN from client", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -293,7 +294,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should return 200 using auth-tls-match-cn with matching CN from client", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -322,7 +323,7 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
ginkgo.It("should return 200 using auth-tls-match-cn where atleast one of the regex options matches CN from client", func() {
host := "authtls.foo.com"
host := authTLSFooHost
nameSpace := f.Namespace
clientConfig, err := framework.CreateIngressMASecret(
@ -351,7 +352,8 @@ var _ = framework.DescribeAnnotation("auth-tls-*", func() {
})
})
func assertSslClientCertificateConfig(f *framework.Framework, host string, verifyClient string, verifyDepth string) {
//nolint:unparam // Ignore the invariant param: host
func assertSslClientCertificateConfig(f *framework.Framework, host, verifyClient, verifyDepth string) {
sslClientCertDirective := fmt.Sprintf("ssl_client_certificate /etc/ingress-controller/ssl/%s-%s.pem;", f.Namespace, host)
sslVerify := fmt.Sprintf("ssl_verify_client %s;", verifyClient)
sslVerifyDepth := fmt.Sprintf("ssl_verify_depth %s;", verifyDepth)

View file

@ -24,6 +24,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const backendProtocolHost = "backendprotocol.foo.com"
var _ = framework.DescribeAnnotation("backend-protocol", func() {
f := framework.NewDefaultFramework("backendprotocol")
@ -32,7 +34,7 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
})
ginkgo.It("should set backend protocol to https:// and use proxy_pass", func() {
host := "backendprotocol.foo.com"
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
}
@ -46,8 +48,23 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
})
})
ginkgo.It("should set backend protocol to https:// and use proxy_pass with lowercase annotation", func() {
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "https",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass https://upstream_balancer;")
})
})
ginkgo.It("should set backend protocol to $scheme:// and use proxy_pass", func() {
host := "backendprotocol.foo.com"
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "AUTO_HTTP",
}
@ -62,7 +79,7 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
})
ginkgo.It("should set backend protocol to grpc:// and use grpc_pass", func() {
host := "backendprotocol.foo.com"
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
}
@ -77,7 +94,7 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
})
ginkgo.It("should set backend protocol to grpcs:// and use grpc_pass", func() {
host := "backendprotocol.foo.com"
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "GRPCS",
}
@ -92,7 +109,7 @@ var _ = framework.DescribeAnnotation("backend-protocol", func() {
})
ginkgo.It("should set backend protocol to '' and use fastcgi_pass", func() {
host := "backendprotocol.foo.com"
host := backendProtocolHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
}

View file

@ -43,7 +43,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canary is created", func() {
ginkgo.It("should response with a 200 status from the mainline upstream when requests are made to the mainline ingress", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -87,7 +87,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should return 404 status for requests to the canary if no matching ingress is found", func() {
host := "foo"
host := fooHost
canaryAnnotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
@ -118,7 +118,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
TODO: This test needs improvements made to the e2e framework so that deployment updates work in order to successfully run
It("should return the correct status codes when endpoints are unavailable", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
ing := framework.NewSingleIngress(host, "/info", host, f.Namespace, framework.HTTPBunService, 80, annotations)
@ -172,7 +172,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
*/
ginkgo.It("should route requests to the correct upstream if mainline ingress is created before the canary ingress", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -230,7 +230,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests to the correct upstream if mainline ingress is created after the canary ingress", func() {
host := "foo"
host := fooHost
canaryAnnotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
@ -287,7 +287,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests to the correct upstream if the mainline ingress is modified", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -321,7 +321,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
canaryAnnotations))
modAnnotations := map[string]string{
"foo": "bar",
fooHost: "bar",
}
f.UpdateIngress(framework.NewSingleIngress(
@ -361,7 +361,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests to the correct upstream if the canary ingress is modified", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -443,7 +443,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by header with no value", func() {
ginkgo.It("should route requests to the correct upstream", func() {
host := "foo"
host := fooHost
f.EnsureIngress(framework.NewSingleIngress(
host,
@ -511,7 +511,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by header with value", func() {
ginkgo.It("should route requests to the correct upstream", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -592,7 +592,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by header with value and pattern", func() {
ginkgo.It("should route requests to the correct upstream", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -645,7 +645,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
Body().Contains(framework.HTTPBunService).NotContains(canaryService)
})
ginkgo.It("should route requests to the correct upstream", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -690,7 +690,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
Body().Contains(framework.HTTPBunService).NotContains(canaryService)
})
ginkgo.It("should routes to mainline upstream when the given Regex causes error", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -739,7 +739,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by header with value and cookie", func() {
ginkgo.It("should route requests to the correct upstream", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -788,7 +788,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by cookie", func() {
ginkgo.It("respects always and never values", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -860,7 +860,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("when canaried by weight", func() {
ginkgo.It("should route requests only to mainline if canary weight is 0", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -908,7 +908,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests only to canary if canary weight is 100", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -950,7 +950,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests only to canary if canary weight is equal to canary weight total", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -993,7 +993,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests split between mainline and canary if canary weight is 50", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -1029,7 +1029,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should route requests split between mainline and canary if canary weight is 100 and weight total is 200", func() {
host := "foo"
host := fooHost
annotations := map[string]string{}
f.EnsureIngress(framework.NewSingleIngress(
@ -1068,7 +1068,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.Context("Single canary Ingress", func() {
ginkgo.It("should not use canary as a catch-all server", func() {
host := "foo"
host := fooHost
canaryIngName := fmt.Sprintf("%v-canary", host)
annotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
@ -1102,7 +1102,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("should not use canary with domain as a server", func() {
host := "foo"
host := fooHost
canaryIngName := fmt.Sprintf("%v-canary", host)
annotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
@ -1136,7 +1136,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.It("does not crash when canary ingress has multiple paths to the same non-matching backend", func() {
host := "foo"
host := fooHost
canaryIngName := fmt.Sprintf("%v-canary", host)
annotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
@ -1168,7 +1168,7 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
})
ginkgo.Context("canary affinity behavior", func() {
host := "foo"
host := fooHost
affinityCookieName := "aff"
canaryIngName := fmt.Sprintf("%v-canary", host)
@ -1370,7 +1370,6 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
TestMainlineCanaryDistribution(f, host)
})
})
})
// This method assumes canary weight being configured at 50%.
@ -1407,12 +1406,12 @@ func TestMainlineCanaryDistribution(f *framework.Framework, host string) {
assert.GreaterOrEqual(
ginkgo.GinkgoT(),
int(replicaRequestCount[keys[0].String()]),
replicaRequestCount[keys[0].String()],
requestsNumberToTest,
)
assert.GreaterOrEqual(
ginkgo.GinkgoT(),
int(replicaRequestCount[keys[1].String()]),
replicaRequestCount[keys[1].String()],
requestsNumberToTest,
)
}

View file

@ -25,6 +25,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const clientBodyBufferSizeHost = "client-body-buffer-size.com"
var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
f := framework.NewDefaultFramework("clientbodybuffersize")
@ -33,7 +35,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should set client_body_buffer_size to 1000", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1000"
annotations := make(map[string]string)
@ -55,7 +57,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should set client_body_buffer_size to 1K", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1K"
annotations := make(map[string]string)
@ -77,7 +79,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should set client_body_buffer_size to 1k", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1k"
annotations := make(map[string]string)
@ -99,7 +101,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should set client_body_buffer_size to 1m", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1m"
annotations := make(map[string]string)
@ -121,7 +123,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should set client_body_buffer_size to 1M", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1M"
annotations := make(map[string]string)
@ -143,7 +145,7 @@ var _ = framework.DescribeAnnotation("client-body-buffer-size", func() {
})
ginkgo.It("should not set client_body_buffer_size to invalid 1b", func() {
host := "client-body-buffer-size.com"
host := clientBodyBufferSizeHost
clientBodyBufferSize := "1b"
annotations := make(map[string]string)

View file

@ -25,6 +25,11 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
originHost = "http://origin.com:8080"
corsHost = "cors.foo.com"
)
var _ = framework.DescribeAnnotation("cors-*", func() {
f := framework.NewDefaultFramework("cors")
@ -33,7 +38,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should enable cors", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
}
@ -60,7 +65,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should set cors methods to only allow POST, GET", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-methods": "POST, GET",
@ -76,7 +81,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should set cors max-age", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-max-age": "200",
@ -92,7 +97,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should disable cors allow credentials", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-credentials": "false",
@ -108,7 +113,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow origin for cors", func() {
host := "cors.foo.com"
host := corsHost
origin := "https://origin.cors.com:8080"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -135,7 +140,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow headers for cors", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-headers": "DNT, User-Agent",
@ -151,7 +156,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should expose headers for cors", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-expose-headers": "X-CustomResponseHeader, X-CustomSecondHeader",
@ -167,7 +172,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow - single origin for multiple cors values", func() {
host := "cors.foo.com"
host := corsHost
origin := "https://origin.cors.com:8080"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -194,7 +199,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not allow - single origin for multiple cors values", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://no.origin.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -214,7 +219,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow correct origins - single origin for multiple cors values", func() {
host := "cors.foo.com"
host := corsHost
badOrigin := "origin.cors.com:8080"
origin1 := "https://origin2.cors.com"
origin2 := "https://origin.com"
@ -265,7 +270,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not break functionality", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "*",
@ -289,7 +294,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not break functionality - without `*`", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
}
@ -312,7 +317,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not break functionality with extra domain", func() {
host := "cors.foo.com"
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "*, foo.bar.com",
@ -336,7 +341,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not match", func() {
host := "cors.foo.com"
host := corsHost
origin := "https://fooxbar.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -356,8 +361,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow - single origin with required port", func() {
host := "cors.foo.com"
origin := "http://origin.com:8080"
host := corsHost
origin := originHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "http://origin.cors.com:8080, http://origin.com:8080",
@ -384,8 +389,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not allow - single origin with port and origin without port", func() {
host := "cors.foo.com"
origin := "http://origin.com:8080"
host := corsHost
origin := originHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "https://origin2.cors.com, http://origin.com",
@ -403,7 +408,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not allow - single origin without port and origin with required port", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://origin.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -423,7 +428,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow - matching origin with wildcard origin (2 subdomains)", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://foo.origin.cors.com"
origin2 := "http://bar-foo.origin.cors.com"
annotations := map[string]string{
@ -466,7 +471,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not allow - unmatching origin with wildcard origin (2 subdomains)", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://bar.foo.origin.cors.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -486,7 +491,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow - matching origin+port with wildcard origin", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://abc.origin.com:8080"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -513,7 +518,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should not allow - portless origin with wildcard origin", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://abc.origin.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -533,8 +538,8 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow correct origins - missing subdomain + origin with wildcard origin and correct origin", func() {
host := "cors.foo.com"
badOrigin := "http://origin.com:8080"
host := corsHost
badOrigin := originHost
origin := "http://bar.origin.com:8080"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
@ -569,7 +574,7 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
})
ginkgo.It("should allow - missing origins (should allow all origins)", func() {
host := "cors.foo.com"
host := corsHost
origin := "http://origin.com"
origin2 := "http://book.origin.com"
origin3 := "test.origin.com"
@ -627,4 +632,41 @@ var _ = framework.DescribeAnnotation("cors-*", func() {
Status(http.StatusOK).Headers().
ValueEqual("Access-Control-Allow-Origin", []string{"*"})
})
ginkgo.It("should allow correct origin but not others - cors allow origin annotations contain trailing comma", func() {
host := corsHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-cors": "true",
"nginx.ingress.kubernetes.io/cors-allow-origin": "https://origin-123.cors.com:8080, ,https://origin-321.cors.com:8080,",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
origin1 := "https://origin-123.cors.com:8080"
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("Origin", origin1).
Expect().
Headers().ContainsKey("Access-Control-Allow-Origin")
origin2 := "https://origin-321.cors.com:8080"
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("Origin", origin2).
Expect().
Status(http.StatusOK).Headers().
ValueEqual("Access-Control-Allow-Origin", []string{origin2})
origin3 := "https://unknown.cors.com:8080"
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("Origin", origin3).
Expect().
Headers().
NotContainsKey("Access-Control-Allow-Origin")
})
})

View file

@ -0,0 +1,110 @@
/*
Copyright 2023 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 annotations
import (
"fmt"
"net/http"
"strings"
"github.com/onsi/ginkgo/v2"
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
customHeaderHost = "custom-headers"
)
var _ = framework.DescribeAnnotation("custom-headers-*", func() {
f := framework.NewDefaultFramework("custom-headers")
ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
})
ginkgo.It("should return status code 200 when no custom-headers is configured", func() {
ing := framework.NewSingleIngress(customHeaderHost, "/", customHeaderHost, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(customHeaderHost,
func(server string) bool {
return strings.Contains(server, "server_name custom-headers")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", customHeaderHost).
Expect().
Status(http.StatusOK).
Body().Contains(fmt.Sprintf("host=%v", customHeaderHost))
})
ginkgo.It("should return status code 503 when custom-headers is configured with an invalid secret", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers",
}
ing := framework.NewSingleIngress(customHeaderHost, "/", customHeaderHost, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(customHeaderHost,
func(server string) bool {
return strings.Contains(server, "server_name custom-headers")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", customHeaderHost).
Expect().
Status(http.StatusServiceUnavailable).
Body().Contains("503 Service Temporarily Unavailable")
})
ginkgo.It(`should set "more_set_headers 'My-Custom-Header' '42';" when custom-headers are set`, func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/custom-headers": f.Namespace + "/custom-headers",
}
f.CreateConfigMap("custom-headers", map[string]string{
"My-Custom-Header": "42",
"My-Custom-Header-Dollar": "$remote_addr",
})
f.UpdateNginxConfigMapData("global-allowed-response-headers", "My-Custom-Header,My-Custom-Header-Dollar")
ing := framework.NewSingleIngress(customHeaderHost, "/", customHeaderHost, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(customHeaderHost,
func(server string) bool {
return strings.Contains(server, `more_set_headers "My-Custom-Header: 42";`)
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", customHeaderHost).
Expect().
Status(http.StatusOK).
Header("My-Custom-Header").Contains("42")
f.HTTPTestClient().
GET("/").
WithHeader("Host", customHeaderHost).
Expect().
Status(http.StatusOK).
Header("My-Custom-Header-Dollar").Contains("$remote_addr")
})
})

View file

@ -27,7 +27,7 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
func errorBlockName(upstreamName string, errorCode string) string {
func errorBlockName(upstreamName, errorCode string) string {
return fmt.Sprintf("@custom_%s_%s", upstreamName, errorCode)
}

View file

@ -48,18 +48,18 @@ var _ = framework.DescribeAnnotation("default-backend", func() {
return strings.Contains(server, fmt.Sprintf("server_name %v", host))
})
requestId := "something-unique"
requestID := "something-unique"
f.HTTPTestClient().
GET("/alma/armud").
WithHeader("Host", host).
WithHeader("x-request-id", requestId).
WithHeader("x-request-id", requestID).
Expect().
Status(http.StatusOK).
Body().Contains("x-code=503").
Contains(fmt.Sprintf("x-ingress-name=%s", host)).
Contains("x-service-name=invalid").
Contains(fmt.Sprintf("x-request-id=%s", requestId))
Contains(fmt.Sprintf("x-request-id=%s", requestID))
})
})
})

View file

@ -0,0 +1,100 @@
/*
Copyright 2023 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 annotations
import (
"fmt"
"net/http"
"strings"
networking "k8s.io/api/networking/v1"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeAnnotation("disable-proxy-intercept-errors", func() {
f := framework.NewDefaultFramework("disable-proxy-intercept-errors")
ginkgo.BeforeEach(func() {
f.NewHttpbunDeployment()
f.NewEchoDeployment()
})
ginkgo.It("configures Nginx correctly", func() {
host := "pie.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/custom-http-errors": "404",
"nginx.ingress.kubernetes.io/disable-proxy-intercept-errors": "true",
"nginx.ingress.kubernetes.io/default-backend": framework.EchoService,
}
ingHTTPBunService := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, annotations)
f.EnsureIngress(ingHTTPBunService)
var serverConfig string
f.WaitForNginxServer(host, func(sc string) bool {
serverConfig = sc
return strings.Contains(serverConfig, fmt.Sprintf("server_name %s", host))
})
ginkgo.By("turning off proxy_intercept_errors directive")
assert.NotContains(ginkgo.GinkgoT(), serverConfig, "proxy_intercept_errors on;")
// the plan for client side testing
// create ingress where we disable intercept for code 404 - that error should get to the client
// the same ingress should intercept any other error (>300 and not 404) where we will get intercepted error
ginkgo.By("client test to check response - with intercept disabled")
requestID := "proxy_intercept_errors"
f.HTTPTestClient().
GET("/status/404").
WithHeader("Host", host).
WithHeader("x-request-id", requestID).
Expect().
Status(http.StatusNotFound).
Body().Empty()
ginkgo.By("client test to check response - with intercept enabled")
err := framework.UpdateIngress(f.KubeClientSet, f.Namespace, host, func(ingress *networking.Ingress) error {
ingress.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/disable-proxy-intercept-errors"] = "false"
return nil
})
assert.Nil(ginkgo.GinkgoT(), err)
f.WaitForNginxServer(host, func(sc string) bool {
if serverConfig != sc {
serverConfig = sc
return true
}
return false
})
f.HTTPTestClient().
GET("/status/404").
WithHeader("Host", host).
WithHeader("x-request-id", requestID).
Expect().
Status(http.StatusOK).
Body().Contains("x-code=404").
Contains(fmt.Sprintf("x-ingress-name=%s", host)).
Contains(fmt.Sprintf("x-service-name=%s", framework.HTTPBunService)).
Contains(fmt.Sprintf("x-request-id=%s", requestID))
})
})

View file

@ -75,14 +75,14 @@ var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() {
Namespace: f.Namespace,
},
Data: map[string]string{
"SCRIPT_FILENAME": "/home/www/scripts/php$fastcgi_script_name",
"SCRIPT_FILENAME": "$fastcgi_script_name",
"REDIRECT_STATUS": "200",
},
}
f.EnsureConfigMap(configuration)
host := "fastcgi-params-configmap"
host := "fastcgi-params-configmap" //#nosec G101
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
@ -94,7 +94,7 @@ var _ = framework.DescribeAnnotation("backend-protocol - FastCGI", func() {
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "fastcgi_param SCRIPT_FILENAME \"/home/www/scripts/php$fastcgi_script_name\";") &&
return strings.Contains(server, "fastcgi_param SCRIPT_FILENAME \"$fastcgi_script_name\";") &&
strings.Contains(server, "fastcgi_param REDIRECT_STATUS \"200\";")
})
})

View file

@ -62,6 +62,15 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() {
})
ginkgo.It("should redirect from www HTTPS to HTTPS", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
ginkgo.By("setting up server for redirect from www")
fromHost := fmt.Sprintf("%s.nip.io", f.GetNginxIP())
@ -90,7 +99,7 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() {
ginkgo.By("sending request to www should redirect to domain")
f.HTTPTestClientWithTLSConfig(&tls.Config{
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
ServerName: toHost,
}).
GET("/").
@ -102,7 +111,7 @@ var _ = framework.DescribeAnnotation("from-to-www-redirect", func() {
ginkgo.By("sending request to domain should not redirect to www")
f.HTTPTestClientWithTLSConfig(&tls.Config{
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
ServerName: fromHost,
}).
GET("/").

View file

@ -47,7 +47,7 @@ var _ = framework.DescribeAnnotation("annotation-global-rate-limit", func() {
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
ing = f.EnsureIngress(ing)
namespace := strings.Replace(string(ing.UID), "-", "", -1)
namespace := strings.ReplaceAll(string(ing.UID), "-", "")
serverConfig := ""
f.WaitForNginxServer(host, func(server string) bool {

View file

@ -17,12 +17,11 @@ limitations under the License.
package annotations
import (
"context"
"crypto/tls"
"fmt"
"strings"
"context"
pb "github.com/moul/pb/grpcbin/go-grpc"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
@ -36,6 +35,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const echoHost = "echo"
var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
f := framework.NewDefaultFramework("grpc", framework.WithHTTPBunEnabled())
@ -67,7 +68,7 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
ginkgo.It("should return OK for service with backend protocol GRPC", func() {
f.NewGRPCBinDeployment()
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -102,14 +103,16 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
return strings.Contains(server, "grpc_pass grpc://upstream_balancer;")
})
conn, _ := grpc.Dial(f.GetNginxIP()+":443",
//nolint:goconst //string interpolation
conn, err := grpc.Dial(f.GetNginxIP()+":443",
grpc.WithTransportCredentials(
credentials.NewTLS(&tls.Config{
ServerName: "echo",
InsecureSkipVerify: true,
ServerName: echoHost,
InsecureSkipVerify: true, //nolint:gosec // Ignore certificate validation in testing
}),
),
)
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
defer conn.Close()
client := pb.NewGRPCBinClient(conn)
@ -125,7 +128,7 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
ginkgo.It("authorization metadata should be overwritten by external auth response headers", func() {
f.NewGRPCBinDeployment()
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -162,14 +165,15 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
return strings.Contains(server, "grpc_pass grpc://upstream_balancer;")
})
conn, _ := grpc.Dial(f.GetNginxIP()+":443",
conn, err := grpc.Dial(f.GetNginxIP()+":443",
grpc.WithTransportCredentials(
credentials.NewTLS(&tls.Config{
ServerName: "echo",
InsecureSkipVerify: true,
ServerName: echoHost,
InsecureSkipVerify: true, //nolint:gosec // Ignore certificate validation in testing
}),
),
)
assert.Nil(ginkgo.GinkgoT(), err)
defer conn.Close()
client := pb.NewGRPCBinClient(conn)
@ -180,13 +184,22 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
assert.Nil(ginkgo.GinkgoT(), err)
metadata := res.GetMetadata()
assert.Equal(ginkgo.GinkgoT(), "foo", metadata["authorization"].Values[0])
assert.Equal(ginkgo.GinkgoT(), fooHost, metadata["authorization"].Values[0])
})
ginkgo.It("should return OK for service with backend protocol GRPCS", func() {
f.NewGRPCBinDeployment()
host := "echo"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -226,14 +239,15 @@ var _ = framework.DescribeAnnotation("backend-protocol - GRPC", func() {
return strings.Contains(server, "grpc_pass grpcs://upstream_balancer;")
})
conn, _ := grpc.Dial(f.GetNginxIP()+":443",
conn, err := grpc.Dial(f.GetNginxIP()+":443",
grpc.WithTransportCredentials(
credentials.NewTLS(&tls.Config{
ServerName: "echo",
InsecureSkipVerify: true,
ServerName: echoHost,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
}),
),
)
assert.Nil(ginkgo.GinkgoT(), err)
defer conn.Close()
client := pb.NewGRPCBinClient(conn)

View file

@ -24,19 +24,19 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeAnnotation("whitelist-source-range", func() {
f := framework.NewDefaultFramework("ipwhitelist")
var _ = framework.DescribeAnnotation("allowlist-source-range", func() {
f := framework.NewDefaultFramework("ipallowlist")
ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
})
ginkgo.It("should set valid ip whitelist range", func() {
host := "ipwhitelist.foo.com"
ginkgo.It("should set valid ip allowlist range", func() {
host := "ipallowlist.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/whitelist-source-range": "18.0.0.0/8, 56.0.0.0/8",
"nginx.ingress.kubernetes.io/allowlist-source-range": "18.0.0.0/8, 56.0.0.0/8",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)

View file

@ -25,6 +25,17 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
modSecurityFooHost = "modsecurity.foo.com"
defaultSnippet = `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
)
var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
f := framework.NewDefaultFramework("modsecuritylocation")
@ -33,7 +44,7 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity", func() {
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -51,7 +62,7 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity with transaction ID and OWASP rules", func() {
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -72,7 +83,7 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should disable modsecurity", func() {
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -89,7 +100,16 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity with snippet", func() {
host := "modsecurity.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -109,10 +129,11 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
ginkgo.It("should enable modsecurity without using 'modsecurity on;'", func() {
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true"},
"enable-modsecurity": "true",
},
)
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -131,10 +152,11 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
ginkgo.It("should disable modsecurity using 'modsecurity off;'", func() {
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true"},
"enable-modsecurity": "true",
},
)
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
annotations := map[string]string{
@ -151,16 +173,19 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity with snippet and block requests", func() {
host := "modsecurity.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
snippet := defaultSnippet
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
@ -187,16 +212,19 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity globally and with modsecurity-snippet block requests", func() {
host := "modsecurity.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
snippet := defaultSnippet
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
@ -223,16 +251,21 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity when enable-owasp-modsecurity-crs is set to true", func() {
host := "modsecurity.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
snippet := defaultSnippet
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
@ -243,11 +276,6 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
})
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "SecRuleEngine On")
@ -262,7 +290,7 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity through the config map", func() {
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRequestBodyAccess On
@ -282,12 +310,17 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
f.EnsureIngress(ing)
expectedComment := "SecRuleEngine On"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
"modsecurity-snippet": expectedComment,
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
f.WaitForNginxServer(host,
func(server string) bool {
@ -303,7 +336,7 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should enable modsecurity through the config map but ignore snippet as disabled by admin", func() {
host := "modsecurity.foo.com"
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRequestBodyAccess On
@ -345,7 +378,15 @@ var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
})
ginkgo.It("should disable default modsecurity conf setting when modsecurity-snippet is specified", func() {
host := "modsecurity.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := modSecurityFooHost
nameSpace := f.Namespace
snippet := `SecRuleEngine On

View file

@ -25,6 +25,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const proxyRedirectToHost = "goodbye.com"
var _ = framework.DescribeAnnotation("proxy-*", func() {
f := framework.NewDefaultFramework("proxy")
host := "proxy.foo.com"
@ -38,7 +40,7 @@ var _ = framework.DescribeAnnotation("proxy-*", func() {
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-redirect-from"] = proxyRedirectFrom
annotations["nginx.ingress.kubernetes.io/proxy-redirect-to"] = "goodbye.com"
annotations["nginx.ingress.kubernetes.io/proxy-redirect-to"] = proxyRedirectToHost
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -54,7 +56,7 @@ var _ = framework.DescribeAnnotation("proxy-*", func() {
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-redirect-from"] = proxyRedirectFrom
annotations["nginx.ingress.kubernetes.io/proxy-redirect-to"] = "goodbye.com"
annotations["nginx.ingress.kubernetes.io/proxy-redirect-to"] = proxyRedirectToHost
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -67,7 +69,7 @@ var _ = framework.DescribeAnnotation("proxy-*", func() {
ginkgo.It("should set proxy_redirect to hello.com goodbye.com", func() {
proxyRedirectFrom := "hello.com"
proxyRedirectTo := "goodbye.com"
proxyRedirectTo := proxyRedirectToHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-redirect-from"] = proxyRedirectFrom
@ -244,5 +246,4 @@ var _ = framework.DescribeAnnotation("proxy-*", func() {
return strings.Contains(server, fmt.Sprintf("proxy_http_version %s;", proxyHTTPVersion))
})
})
})

View file

@ -27,6 +27,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const proxySSLHost = "proxyssl.foo.com"
var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
f := framework.NewDefaultFramework("proxyssl")
@ -35,7 +37,7 @@ var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
})
ginkgo.It("should set valid proxy-ssl-secret", func() {
host := "proxyssl.foo.com"
host := proxySSLHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-ssl-secret"] = f.Namespace + "/" + host
@ -62,7 +64,7 @@ var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
})
ginkgo.It("should set valid proxy-ssl-secret, proxy-ssl-verify to on, proxy-ssl-verify-depth to 2, and proxy-ssl-server-name to on", func() {
host := "proxyssl.foo.com"
host := proxySSLHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-ssl-secret"] = f.Namespace + "/" + host
annotations["nginx.ingress.kubernetes.io/proxy-ssl-verify"] = "on"
@ -90,9 +92,9 @@ var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
Expect().
Status(http.StatusOK)
})
//nolint:dupl // Ignore dupl errors for similar test case
ginkgo.It("should set valid proxy-ssl-secret, proxy-ssl-ciphers to HIGH:!AES", func() {
host := "proxyssl.foo.com"
host := proxySSLHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-ssl-secret"] = f.Namespace + "/" + host
annotations["nginx.ingress.kubernetes.io/proxy-ssl-ciphers"] = "HIGH:!AES"
@ -118,9 +120,9 @@ var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
Expect().
Status(http.StatusOK)
})
//nolint:dupl // Ignore dupl errors for similar test case
ginkgo.It("should set valid proxy-ssl-secret, proxy-ssl-protocols", func() {
host := "proxyssl.foo.com"
host := proxySSLHost
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/proxy-ssl-secret"] = f.Namespace + "/" + host
annotations["nginx.ingress.kubernetes.io/proxy-ssl-protocols"] = "TLSv1.2 TLSv1.3"
@ -195,7 +197,6 @@ var _ = framework.DescribeAnnotation("proxy-ssl-*", func() {
strings.Contains(server, "proxy_ssl_certificate_key"))
})
})
})
func assertProxySSL(f *framework.Framework, host, sslName, ciphers, protocols, verify string, depth int, proxySSLServerName string) {

View file

@ -27,6 +27,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const rewriteHost = "rewrite.bar.com"
var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-log", func() {
f := framework.NewDefaultFramework("rewrite")
@ -37,7 +39,7 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
ginkgo.It("should write rewrite logs", func() {
ginkgo.By("setting enable-rewrite-log annotation")
host := "rewrite.bar.com"
host := rewriteHost
annotations := map[string]string{
"nginx.ingress.kubernetes.io/rewrite-target": "/",
"nginx.ingress.kubernetes.io/enable-rewrite-log": "true",
@ -64,7 +66,7 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
})
ginkgo.It("should use correct longest path match", func() {
host := "rewrite.bar.com"
host := rewriteHost
ginkgo.By("creating a regular ingress definition")
ing := framework.NewSingleIngress("kube-lego", "/.well-known/acme/challenge", host, f.Namespace, framework.EchoService, 80, nil)
@ -109,10 +111,10 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
})
ginkgo.It("should use ~* location modifier if regex annotation is present", func() {
host := "rewrite.bar.com"
host := rewriteHost
ginkgo.By("creating a regular ingress definition")
ing := framework.NewSingleIngress("foo", "/foo", host, f.Namespace, framework.EchoService, 80, nil)
ing := framework.NewSingleIngress(fooHost, "/foo", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
@ -156,10 +158,10 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
})
ginkgo.It("should fail to use longest match for documented warning", func() {
host := "rewrite.bar.com"
host := rewriteHost
ginkgo.By("creating a regular ingress definition")
ing := framework.NewSingleIngress("foo", "/foo/bar/bar", host, f.Namespace, framework.EchoService, 80, nil)
ing := framework.NewSingleIngress(fooHost, "/foo/bar/bar", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
ginkgo.By(`creating an ingress definition with the use-regex annotation`)
@ -188,7 +190,7 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
})
ginkgo.It("should allow for custom rewrite parameters", func() {
host := "rewrite.bar.com"
host := rewriteHost
ginkgo.By(`creating an ingress definition with the use-regex annotation`)
annotations := map[string]string{

View file

@ -33,6 +33,15 @@ var _ = framework.DescribeAnnotation("server-snippet", func() {
})
ginkgo.It(`add valid directives to server via server snippet`, func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "serversnippet.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/server-snippet": `
@ -59,6 +68,15 @@ var _ = framework.DescribeAnnotation("server-snippet", func() {
})
ginkgo.It(`drops server snippet if disabled by the administrator`, func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "noserversnippet.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/server-snippet": `
@ -89,6 +107,5 @@ var _ = framework.DescribeAnnotation("server-snippet", func() {
Status(http.StatusOK).Headers().
NotContainsKey("Foo").
NotContainsKey("Xpto")
})
})

View file

@ -25,10 +25,10 @@ import (
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/test/e2e/framework"
"k8s.io/ingress-nginx/internal/nginx"
)
const dbgCmd = "/dbg backends all"
var _ = framework.DescribeAnnotation("service-upstream", func() {
f := framework.NewDefaultFramework("serviceupstream")
host := "serviceupstream"
@ -59,10 +59,9 @@ var _ = framework.DescribeAnnotation("service-upstream", func() {
ginkgo.By("checking if the Service Cluster IP and Port are used")
s := f.GetService(f.Namespace, framework.EchoService)
curlCmd := fmt.Sprintf("curl --fail --silent http://localhost:%v/configuration/backends", nginx.StatusPort)
output, err := f.ExecIngressPod(curlCmd)
output, err := f.ExecIngressPod(dbgCmd)
assert.Nil(ginkgo.GinkgoT(), err)
assert.Contains(ginkgo.GinkgoT(), output, fmt.Sprintf(`{"address":"%s"`, s.Spec.ClusterIP))
assert.Contains(ginkgo.GinkgoT(), output, fmt.Sprintf(`"address": %q`, s.Spec.ClusterIP))
})
})
@ -88,10 +87,9 @@ var _ = framework.DescribeAnnotation("service-upstream", func() {
ginkgo.By("checking if the Service Cluster IP and Port are used")
s := f.GetService(f.Namespace, framework.EchoService)
curlCmd := fmt.Sprintf("curl --fail --silent http://localhost:%v/configuration/backends", nginx.StatusPort)
output, err := f.ExecIngressPod(curlCmd)
output, err := f.ExecIngressPod(dbgCmd)
assert.Nil(ginkgo.GinkgoT(), err)
assert.Contains(ginkgo.GinkgoT(), output, fmt.Sprintf(`{"address":"%s"`, s.Spec.ClusterIP))
assert.Contains(ginkgo.GinkgoT(), output, fmt.Sprintf(`"address": %q`, s.Spec.ClusterIP))
})
})
@ -119,10 +117,9 @@ var _ = framework.DescribeAnnotation("service-upstream", func() {
ginkgo.By("checking if the Service Cluster IP and Port are not used")
s := f.GetService(f.Namespace, framework.EchoService)
curlCmd := fmt.Sprintf("curl --fail --silent http://localhost:%v/configuration/backends", nginx.StatusPort)
output, err := f.ExecIngressPod(curlCmd)
output, err := f.ExecIngressPod(dbgCmd)
assert.Nil(ginkgo.GinkgoT(), err)
assert.NotContains(ginkgo.GinkgoT(), output, fmt.Sprintf(`{"address":"%s"`, s.Spec.ClusterIP))
assert.NotContains(ginkgo.GinkgoT(), output, fmt.Sprintf(`"address": %q`, s.Spec.ClusterIP))
})
})
})

View file

@ -33,6 +33,16 @@ var _ = framework.DescribeAnnotation("configuration-snippet", func() {
ginkgo.It("set snippet more_set_headers in all locations", func() {
host := "configurationsnippet.foo.com"
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
annotations := map[string]string{
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_headers "Foo1: Bar1";`,
}
@ -76,10 +86,6 @@ var _ = framework.DescribeAnnotation("configuration-snippet", func() {
annotations)
f.UpdateNginxConfigMapData("allow-snippet-annotations", "false")
defer func() {
// Return to the original value
f.UpdateNginxConfigMapData("allow-snippet-annotations", "true")
}()
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()

View file

@ -54,4 +54,27 @@ var _ = framework.DescribeAnnotation("ssl-ciphers", func() {
Expect().
Status(http.StatusOK)
})
ginkgo.It("should keep ssl ciphers", func() {
host := "ciphers.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/ssl-ciphers": "ALL:!aNULL:!EXPORT56:RC4+RSA@STRENGTH:+HIGH@SECLEVEL=0:+MEDIUM:+LOW:+SSLv2:+EXP",
"nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers": "true",
}
ing := framework.NewSingleIngress(host, "/something", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "ssl_ciphers ALL:!aNULL:!EXPORT56:RC4+RSA@STRENGTH:+HIGH@SECLEVEL=0:+MEDIUM:+LOW:+SSLv2:+EXP;") &&
strings.Contains(server, "ssl_prefer_server_ciphers on;")
})
f.HTTPTestClient().
GET("/something").
WithURL(f.GetURL(framework.HTTPS)).
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
})
})

View file

@ -39,6 +39,15 @@ var _ = framework.DescribeSetting("stream-snippet", func() {
})
ginkgo.It("should add value of stream-snippet to nginx config", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "foo.com"
snippet := `server {listen 8000; proxy_pass 127.0.0.1:80;}`

View file

@ -39,12 +39,13 @@ func startIngress(f *framework.Framework, annotations map[string]string) map[str
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(framework.Poll, framework.DefaultTimeout, func() (bool, error) {
resp := f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().Raw()
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
return true, nil
@ -55,7 +56,9 @@ func startIngress(f *framework.Framework, annotations map[string]string) map[str
assert.Nil(ginkgo.GinkgoT(), err)
re, _ := regexp.Compile(fmt.Sprintf(`Hostname: %v.*`, framework.EchoService))
re, err := regexp.Compile(fmt.Sprintf(`Hostname: %v.*`, framework.EchoService))
assert.Nil(ginkgo.GinkgoT(), err, "error compiling regex")
podMap := map[string]bool{}
for i := 0; i < 100; i++ {

View file

@ -49,7 +49,7 @@ var _ = framework.IngressNginxDescribe("Debug CLI", func() {
assert.Nil(ginkgo.GinkgoT(), err)
// Should be 2: the default and the echo deployment
numUpstreams := len(strings.Split(strings.Trim(string(output), "\n"), "\n"))
numUpstreams := len(strings.Split(strings.Trim(output, "\n"), "\n"))
assert.Equal(ginkgo.GinkgoT(), numUpstreams, 2)
})
@ -67,7 +67,7 @@ var _ = framework.IngressNginxDescribe("Debug CLI", func() {
output, err := f.ExecIngressPod(cmd)
assert.Nil(ginkgo.GinkgoT(), err)
backends := strings.Split(string(output), "\n")
backends := strings.Split(output, "\n")
assert.Greater(ginkgo.GinkgoT(), len(backends), 0)
getCmd := "/dbg backends get " + backends[0]

View file

@ -49,15 +49,15 @@ var _ = framework.IngressNginxDescribe("[Default Backend]", func() {
{"basic HTTPS POST request without host to path / should return 404", "", framework.HTTPS, "POST", "/", http.StatusNotFound},
{"basic HTTPS POST request without host to path /demo should return 404", "", framework.HTTPS, "POST", "/demo", http.StatusNotFound},
{"basic HTTP GET request to host foo.bar.com and path / should return 404", " foo.bar.com", framework.HTTP, "GET", "/", http.StatusNotFound},
{"basic HTTP GET request to host foo.bar.com and path /demo should return 404", " foo.bar.com", framework.HTTP, "GET", "/demo", http.StatusNotFound},
{"basic HTTPS GET request to host foo.bar.com and path / should return 404", " foo.bar.com", framework.HTTPS, "GET", "/", http.StatusNotFound},
{"basic HTTPS GET request to host foo.bar.com and path /demo should return 404", " foo.bar.com", framework.HTTPS, "GET", "/demo", http.StatusNotFound},
{"basic HTTP GET request to host foo.bar.com and path / should return 404", "foo.bar.com", framework.HTTP, "GET", "/", http.StatusNotFound},
{"basic HTTP GET request to host foo.bar.com and path /demo should return 404", "foo.bar.com", framework.HTTP, "GET", "/demo", http.StatusNotFound},
{"basic HTTPS GET request to host foo.bar.com and path / should return 404", "foo.bar.com", framework.HTTPS, "GET", "/", http.StatusNotFound},
{"basic HTTPS GET request to host foo.bar.com and path /demo should return 404", "foo.bar.com", framework.HTTPS, "GET", "/demo", http.StatusNotFound},
{"basic HTTP POST request to host foo.bar.com and path / should return 404", " foo.bar.com", framework.HTTP, "POST", "/", http.StatusNotFound},
{"basic HTTP POST request to host foo.bar.com and path /demo should return 404", " foo.bar.com", framework.HTTP, "POST", "/demo", http.StatusNotFound},
{"basic HTTPS POST request to host foo.bar.com and path / should return 404", " foo.bar.com", framework.HTTPS, "POST", "/", http.StatusNotFound},
{"basic HTTPS POST request to host foo.bar.com and path /demo should return 404", " foo.bar.com", framework.HTTPS, "POST", "/demo", http.StatusNotFound},
{"basic HTTP POST request to host foo.bar.com and path / should return 404", "foo.bar.com", framework.HTTP, "POST", "/", http.StatusNotFound},
{"basic HTTP POST request to host foo.bar.com and path /demo should return 404", "foo.bar.com", framework.HTTP, "POST", "/demo", http.StatusNotFound},
{"basic HTTPS POST request to host foo.bar.com and path / should return 404", "foo.bar.com", framework.HTTPS, "POST", "/", http.StatusNotFound},
{"basic HTTPS POST request to host foo.bar.com and path /demo should return 404", "foo.bar.com", framework.HTTPS, "POST", "/demo", http.StatusNotFound},
}
framework.Sleep()

View file

@ -0,0 +1,93 @@
/*
Copyright 2024 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 disableleaderelection
import (
"net/http"
"strings"
"github.com/onsi/ginkgo/v2"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("[Disable Leader] Routing works when leader election was disabled", func() {
f := framework.NewDefaultFramework("disableleaderelection")
ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
})
ginkgo.It("should create multiple ingress routings rules when leader election has disabled", func() {
host1 := "leader.election.disabled.com"
host2 := "leader.election.disabled2.com"
ing1 := framework.NewSingleIngress(host1, "/foo", host1, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing1)
ing2 := framework.NewSingleIngress(host2, "/ping", host2, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing2)
f.WaitForNginxServer(host1,
func(server string) bool {
return strings.Contains(server, host1) &&
strings.Contains(server, "location /foo")
})
f.WaitForNginxServer(host2,
func(server string) bool {
return strings.Contains(server, host2) &&
strings.Contains(server, "location /ping")
})
f.HTTPTestClient().
GET("/foo").
WithHeader("Host", host1).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/bar").
WithHeader("Host", host1).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/foo").
WithHeader("Host", host2).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/ping").
WithHeader("Host", host2).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/pong").
WithHeader("Host", host2).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/ping").
WithHeader("Host", host1).
Expect().
Status(http.StatusNotFound)
})
})

View file

@ -35,6 +35,7 @@ import (
_ "k8s.io/ingress-nginx/test/e2e/cgroups"
_ "k8s.io/ingress-nginx/test/e2e/dbg"
_ "k8s.io/ingress-nginx/test/e2e/defaultbackend"
_ "k8s.io/ingress-nginx/test/e2e/disableleaderelection"
_ "k8s.io/ingress-nginx/test/e2e/endpointslices"
_ "k8s.io/ingress-nginx/test/e2e/gracefulshutdown"
_ "k8s.io/ingress-nginx/test/e2e/ingress"
@ -48,6 +49,7 @@ import (
_ "k8s.io/ingress-nginx/test/e2e/settings"
_ "k8s.io/ingress-nginx/test/e2e/settings/modsecurity"
_ "k8s.io/ingress-nginx/test/e2e/settings/ocsp"
_ "k8s.io/ingress-nginx/test/e2e/settings/validations"
_ "k8s.io/ingress-nginx/test/e2e/ssl"
_ "k8s.io/ingress-nginx/test/e2e/status"
_ "k8s.io/ingress-nginx/test/e2e/tcpudp"

View file

@ -26,6 +26,7 @@ func init() {
testing.Init()
framework.RegisterParseFlags()
}
func TestE2E(t *testing.T) {
RunE2ETests(t)
}

View file

@ -36,7 +36,6 @@ var _ = framework.IngressNginxDescribe("[Endpointslices] long service name", fun
})
ginkgo.It("should return 200 when service name has max allowed number of characters 63", func() {
annotations := make(map[string]string)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, name, 80, annotations)
f.EnsureIngress(ing)

View file

@ -28,7 +28,6 @@ import (
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/internal/nginx"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -41,7 +40,6 @@ var _ = framework.IngressNginxDescribeSerial("[TopologyHints] topology aware rou
})
ginkgo.It("should return 200 when service has topology hints", func() {
annotations := make(map[string]string)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
@ -72,8 +70,8 @@ var _ = framework.IngressNginxDescribeSerial("[TopologyHints] topology aware rou
}
}
curlCmd := fmt.Sprintf("curl --fail --silent http://localhost:%v/configuration/backends", nginx.StatusPort)
status, err := f.ExecIngressPod(curlCmd)
dbgCmd := "/dbg backends all"
status, err := f.ExecIngressPod(dbgCmd)
assert.Nil(ginkgo.GinkgoT(), err)
var backends []map[string]interface{}
err = json.Unmarshal([]byte(status), &backends)
@ -86,7 +84,7 @@ var _ = framework.IngressNginxDescribeSerial("[TopologyHints] topology aware rou
}
if gotHints {
//we have 2 replics, if there is just one backend it means that we are routing according slices hints to same zone as controller is
// we have 2 replics, if there is just one backend it means that we are routing according slices hints to same zone as controller is
assert.Equal(ginkgo.GinkgoT(), 1, gotBackends)
} else {
// two replicas should have two endpoints without topology hints

View file

@ -47,10 +47,10 @@ const NIPService = "external-nip"
var HTTPBunImage = os.Getenv("HTTPBUN_IMAGE")
// EchoImage is the default image to be used by the echo service
const EchoImage = "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:4938d1d91a2b7d19454460a8c1b010b89f6ff92d2987fd889ac3e8fc3b70d91a"
const EchoImage = "registry.k8s.io/ingress-nginx/e2e-test-echo@sha256:4938d1d91a2b7d19454460a8c1b010b89f6ff92d2987fd889ac3e8fc3b70d91a" //#nosec G101
// TODO: change all Deployment functions to use these options
// in order to reduce complexity and have a unified API accross the
// in order to reduce complexity and have a unified API across the
// framework
type deploymentOptions struct {
name string
@ -67,11 +67,11 @@ func WithDeploymentNamespace(n string) func(*deploymentOptions) {
}
}
// WithSvcTopologyAnnotations create svc with topology aware hints sets to auto
// WithSvcTopologyAnnotations create svc with topology mode sets to auto
func WithSvcTopologyAnnotations() func(*deploymentOptions) {
return func(o *deploymentOptions) {
o.svcAnnotations = map[string]string{
"service.kubernetes.io/topology-aware-hints": "auto",
corev1.AnnotationTopologyMode: "auto",
}
}
}
@ -213,7 +213,7 @@ func (f *Framework) NewHttpbunDeployment(opts ...func(*deploymentOptions)) strin
80,
int32(options.replicas),
nil, nil,
//Required to get hostname information
// Required to get hostname information
[]corev1.EnvVar{
{
Name: "HTTPBUN_INFO_ENABLED",
@ -317,7 +317,7 @@ func (f *Framework) GetNginxBaseImage() string {
// NGINXDeployment creates a new simple NGINX Deployment using NGINX base image
// and passing the desired configuration
func (f *Framework) NGINXDeployment(name string, cfg string, waitendpoint bool) {
func (f *Framework) NGINXDeployment(name, cfg string, waitendpoint bool) {
cfgMap := map[string]string{
"nginx.conf": cfg,
}
@ -389,7 +389,7 @@ func (f *Framework) NGINXDeployment(name string, cfg string, waitendpoint bool)
}
// NGINXWithConfigDeployment creates an NGINX deployment using a configmap containing the nginx.conf configuration
func (f *Framework) NGINXWithConfigDeployment(name string, cfg string) {
func (f *Framework) NGINXWithConfigDeployment(name, cfg string) {
f.NGINXDeployment(name, cfg, true)
}
@ -487,7 +487,8 @@ func (f *Framework) NewGRPCBinDeployment() {
}
func newDeployment(name, namespace, image string, port int32, replicas int32, command []string, args []string, env []corev1.EnvVar,
volumeMounts []corev1.VolumeMount, volumes []corev1.Volume, setProbe bool) *appsv1.Deployment {
volumeMounts []corev1.VolumeMount, volumes []corev1.Volume, setProbe bool,
) *appsv1.Deployment {
probe := &corev1.Probe{
InitialDelaySeconds: 2,
PeriodSeconds: 1,
@ -559,12 +560,12 @@ func newDeployment(name, namespace, image string, port int32, replicas int32, co
return d
}
func (f *Framework) NewDeployment(name, image string, port int32, replicas int32) {
func (f *Framework) NewDeployment(name, image string, port, replicas int32) {
f.NewDeploymentWithOpts(name, image, port, replicas, nil, nil, nil, nil, nil, true)
}
// NewDeployment creates a new deployment in a particular namespace.
func (f *Framework) NewDeploymentWithOpts(name, image string, port int32, replicas int32, command []string, args []string, env []corev1.EnvVar, volumeMounts []corev1.VolumeMount, volumes []corev1.Volume, setProbe bool) {
func (f *Framework) NewDeploymentWithOpts(name, image string, port, replicas int32, command, args []string, env []corev1.EnvVar, volumeMounts []corev1.VolumeMount, volumes []corev1.Volume, setProbe bool) {
deployment := newDeployment(name, f.Namespace, image, port, replicas, command, args, env, volumeMounts, volumes, setProbe)
f.EnsureDeployment(deployment)
@ -606,7 +607,7 @@ func (f *Framework) DeleteDeployment(name string) error {
})
assert.Nil(ginkgo.GinkgoT(), err, "deleting deployment")
return waitForPodsDeleted(f.KubeClientSet, 2*time.Minute, f.Namespace, metav1.ListOptions{
return waitForPodsDeleted(f.KubeClientSet, 2*time.Minute, f.Namespace, &metav1.ListOptions{
LabelSelector: labelSelectorToString(d.Spec.Selector.MatchLabels),
})
}

View file

@ -66,6 +66,7 @@ func (f *Framework) ExecCommand(pod *corev1.Pod, command string) (string, error)
execErr bytes.Buffer
)
//nolint:gosec // Ignore G204 error
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v exec --namespace %s %s --container controller -- %s", KubectlPath, pod.Namespace, pod.Name, command))
cmd.Stdout = &execOut
cmd.Stderr = &execErr
@ -73,7 +74,6 @@ func (f *Framework) ExecCommand(pod *corev1.Pod, command string) (string, error)
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("could not execute '%s %s': %v", cmd.Path, cmd.Args, err)
}
if execErr.Len() > 0 {
@ -91,6 +91,7 @@ func (f *Framework) NamespaceContent() (string, error) {
execErr bytes.Buffer
)
//nolint:gosec // Ignore G204 error
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%v get pods,services,endpoints,deployments --namespace %s", KubectlPath, f.Namespace))
cmd.Stdout = &execOut
cmd.Stderr = &execErr
@ -98,11 +99,10 @@ func (f *Framework) NamespaceContent() (string, error) {
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("could not execute '%s %s': %v", cmd.Path, cmd.Args, err)
}
eout := strings.TrimSpace(execErr.String())
if len(eout) > 0 {
if eout != "" {
return "", fmt.Errorf("stderr: %v", eout)
}
@ -110,13 +110,18 @@ func (f *Framework) NamespaceContent() (string, error) {
}
// newIngressController deploys a new NGINX Ingress controller in a namespace
func (f *Framework) newIngressController(namespace string, namespaceOverlay string) error {
func (f *Framework) newIngressController(namespace, namespaceOverlay string) error {
// Creates an nginx deployment
isChroot, ok := os.LookupEnv("IS_CHROOT")
if !ok {
isChroot = "false"
}
cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay, isChroot)
enableAnnotationValidations, ok := os.LookupEnv("ENABLE_VALIDATIONS")
if !ok {
enableAnnotationValidations = "false"
}
cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay, isChroot, enableAnnotationValidations)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("unexpected error waiting for ingress controller deployment: %v.\nLogs:\n%v", err, string(out))
@ -125,12 +130,11 @@ func (f *Framework) newIngressController(namespace string, namespaceOverlay stri
return nil
}
var (
proxyRegexp = regexp.MustCompile("Starting to serve on .*:([0-9]+)")
)
var proxyRegexp = regexp.MustCompile(`Starting to serve on .*:(\d+)`)
// KubectlProxy creates a proxy to kubernetes apiserver
func (f *Framework) KubectlProxy(port int) (int, *exec.Cmd, error) {
//nolint:gosec // Ignore G204 error
cmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("%s proxy --accept-hosts=.* --address=0.0.0.0 --port=%d", KubectlPath, port))
stdout, stderr, err := startCmdAndStreamOutput(cmd)
if err != nil {
@ -158,6 +162,7 @@ func (f *Framework) KubectlProxy(port int) (int, *exec.Cmd, error) {
}
func (f *Framework) UninstallChart() error {
//nolint:gosec //Ignore G204 error
cmd := exec.Command("helm", "uninstall", "--namespace", f.Namespace, "nginx-ingress")
_, err := cmd.CombinedOutput()
if err != nil {

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
//nolint:dupl // Ignore dupl errors for similar test case
package framework
import (
@ -75,7 +76,7 @@ func (f *Framework) NewNewFastCGIHelloServerDeploymentWithReplicas(replicas int3
d := f.EnsureDeployment(deployment)
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, metav1.ListOptions{
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, &metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
assert.Nil(ginkgo.GinkgoT(), err, "failed to wait for to become ready")

View file

@ -25,6 +25,7 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework/httpexpect"
"github.com/onsi/ginkgo/v2"
ginkgotypes "github.com/onsi/ginkgo/v2/types"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
@ -49,10 +50,8 @@ const (
HTTPS RequestScheme = "https"
)
var (
// KubectlPath defines the full path of the kubectl binary
KubectlPath = "/usr/local/bin/kubectl"
)
// KubectlPath defines the full path of the kubectl binary
var KubectlPath = "/usr/local/bin/kubectl"
// Framework supports common operations used by e2e tests; it will keep a client & a namespace for you.
type Framework struct {
@ -131,7 +130,6 @@ func (f *Framework) CreateEnvironment() {
f.KubeClientSet, err = kubernetes.NewForConfig(f.KubeConfig)
assert.Nil(ginkgo.GinkgoT(), err, "creating a kubernetes client")
}
f.Namespace, err = CreateKubeNamespace(f.BaseName, f.KubeClientSet)
@ -181,7 +179,7 @@ func (f *Framework) AfterEach() {
assert.Nil(ginkgo.GinkgoT(), err, "deleting IngressClass")
}(f.KubeClientSet, f.IngressClass)
if !ginkgo.CurrentSpecReport().Failed() {
if !ginkgo.CurrentSpecReport().Failed() || ginkgo.CurrentSpecReport().State.Is(ginkgotypes.SpecStateInterrupted) {
return
}
@ -250,9 +248,9 @@ func (f *Framework) GetNginxPodIP() string {
}
// GetURL returns the URL should be used to make a request to NGINX
func (f *Framework) GetURL(scheme RequestScheme) string {
func (f *Framework) GetURL(requestScheme RequestScheme) string {
ip := f.GetNginxIP()
return fmt.Sprintf("%v://%v", scheme, ip)
return fmt.Sprintf("%v://%v", requestScheme, ip)
}
// GetIngressNGINXPod returns the ingress controller running pod
@ -270,6 +268,7 @@ func (f *Framework) updateIngressNGINXPod() error {
// WaitForNginxServer waits until the nginx configuration contains a particular server section.
// `cfg` passed to matcher is normalized by replacing all tabs and spaces with single space.
func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) bool) {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxConditions(name, matcher))
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
Sleep(1 * time.Second)
@ -278,13 +277,15 @@ func (f *Framework) WaitForNginxServer(name string, matcher func(cfg string) boo
// WaitForNginxConfiguration waits until the nginx configuration contains a particular configuration
// `cfg` passed to matcher is normalized by replacing all tabs and spaces with single space.
func (f *Framework) WaitForNginxConfiguration(matcher func(cfg string) bool) {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxConditions("", matcher))
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
Sleep(1 * time.Second)
}
// WaitForNginxCustomConfiguration waits until the nginx configuration given part (from, to) contains a particular configuration
func (f *Framework) WaitForNginxCustomConfiguration(from string, to string, matcher func(cfg string) bool) {
func (f *Framework) WaitForNginxCustomConfiguration(from, to string, matcher func(cfg string) bool) {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(Poll, DefaultTimeout, f.matchNginxCustomConditions(from, to, matcher))
assert.Nil(ginkgo.GinkgoT(), err, "waiting for nginx server condition/s")
}
@ -312,7 +313,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b
return false, nil
}
if klog.V(10).Enabled() && len(o) > 0 {
if klog.V(10).Enabled() && o != "" {
klog.InfoS("NGINX", "configuration", o)
}
@ -325,7 +326,7 @@ func (f *Framework) matchNginxConditions(name string, matcher func(cfg string) b
}
}
func (f *Framework) matchNginxCustomConditions(from string, to string, matcher func(cfg string) bool) wait.ConditionFunc {
func (f *Framework) matchNginxCustomConditions(from, to string, matcher func(cfg string) bool) wait.ConditionFunc {
return func() (bool, error) {
cmd := fmt.Sprintf("cat /etc/nginx/nginx.conf| awk '/%v/,/%v/'", from, to)
@ -334,7 +335,7 @@ func (f *Framework) matchNginxCustomConditions(from string, to string, matcher f
return false, nil
}
if klog.V(10).Enabled() && len(o) > 0 {
if klog.V(10).Enabled() && o != "" {
klog.InfoS("NGINX", "configuration", o)
}
@ -395,7 +396,7 @@ func (f *Framework) CreateConfigMap(name string, data map[string]string) {
}
// UpdateNginxConfigMapData updates single field in ingress-nginx's nginx-ingress-controller map data
func (f *Framework) UpdateNginxConfigMapData(key string, value string) {
func (f *Framework) UpdateNginxConfigMapData(key, value string) {
config, err := f.getConfigMap("nginx-ingress-controller")
assert.Nil(ginkgo.GinkgoT(), err)
assert.NotNil(ginkgo.GinkgoT(), config, "expected a configmap but none returned")
@ -421,6 +422,7 @@ func (f *Framework) WaitForReload(fn func()) {
fn()
count := 0
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(1*time.Second, DefaultTimeout, func() (bool, error) {
reloads := getReloadCount(f.pod, f.Namespace, f.KubeClientSet)
// most of the cases reload the ingress controller
@ -441,8 +443,8 @@ func getReloadCount(pod *v1.Pod, namespace string, client kubernetes.Interface)
assert.Nil(ginkgo.GinkgoT(), err, "obtaining NGINX Pod")
reloadCount := 0
for _, e := range events.Items {
if e.Reason == "RELOAD" && e.Type == v1.EventTypeNormal {
for i := range events.Items {
if events.Items[i].Reason == "RELOAD" && events.Items[i].Type == v1.EventTypeNormal {
reloadCount++
}
}
@ -457,7 +459,7 @@ func (f *Framework) DeleteNGINXPod(grace int64) {
err := f.KubeClientSet.CoreV1().Pods(ns).Delete(context.TODO(), f.pod.GetName(), *metav1.NewDeleteOptions(grace))
assert.Nil(ginkgo.GinkgoT(), err, "deleting ingress nginx pod")
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err = wait.Poll(Poll, DefaultTimeout, func() (bool, error) {
err := f.updateIngressNGINXPod()
if err != nil || f.pod == nil {
@ -487,7 +489,7 @@ func (f *Framework) HTTPTestClientWithTLSConfig(config *tls.Config) *httpexpect.
func (f *Framework) newHTTPTestClient(config *tls.Config, setIngressURL bool) *httpexpect.HTTPRequest {
if config == nil {
config = &tls.Config{
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
}
}
var baseURL string
@ -499,7 +501,7 @@ func (f *Framework) newHTTPTestClient(config *tls.Config, setIngressURL bool) *h
Transport: &http.Transport{
TLSClientConfig: config,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
CheckRedirect: func(_ *http.Request, _ []*http.Request) error {
return http.ErrUseLastResponse
},
}, httpexpect.NewAssertReporter())
@ -507,12 +509,13 @@ func (f *Framework) newHTTPTestClient(config *tls.Config, setIngressURL bool) *h
// WaitForNginxListening waits until NGINX starts accepting connections on a port
func (f *Framework) WaitForNginxListening(port int) {
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, metav1.ListOptions{
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, &metav1.ListOptions{
LabelSelector: "app.kubernetes.io/name=ingress-nginx",
})
assert.Nil(ginkgo.GinkgoT(), err, "waiting for ingress pods to be ready")
podIP := f.GetNginxIP()
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err = wait.Poll(500*time.Millisecond, DefaultTimeout, func() (bool, error) {
hostPort := net.JoinHostPort(podIP, fmt.Sprintf("%v", port))
conn, err := net.Dial("tcp", hostPort)
@ -529,7 +532,7 @@ func (f *Framework) WaitForNginxListening(port int) {
// WaitForPod waits for a specific Pod to be ready, using a label selector
func (f *Framework) WaitForPod(selector string, timeout time.Duration, shouldFail bool) {
err := waitForPodsReady(f.KubeClientSet, timeout, 1, f.Namespace, metav1.ListOptions{
err := waitForPodsReady(f.KubeClientSet, timeout, 1, f.Namespace, &metav1.ListOptions{
LabelSelector: selector,
})
@ -541,7 +544,7 @@ func (f *Framework) WaitForPod(selector string, timeout time.Duration, shouldFai
}
// UpdateDeployment runs the given updateFunc on the deployment and waits for it to be updated
func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name string, replicas int, updateFunc func(d *appsv1.Deployment) error) error {
func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace, name string, replicas int, updateFunc func(d *appsv1.Deployment) error) error {
deployment, err := kubeClientSet.AppsV1().Deployments(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return err
@ -571,7 +574,7 @@ func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name
}
}
err = waitForPodsReady(kubeClientSet, DefaultTimeout, replicas, namespace, metav1.ListOptions{
err = waitForPodsReady(kubeClientSet, DefaultTimeout, replicas, namespace, &metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(deployment.Spec.Template.ObjectMeta.Labels)).String(),
})
if err != nil {
@ -582,6 +585,7 @@ func UpdateDeployment(kubeClientSet kubernetes.Interface, namespace string, name
}
func waitForDeploymentRollout(kubeClientSet kubernetes.Interface, resource *appsv1.Deployment) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, 5*time.Minute, func() (bool, error) {
d, err := kubeClientSet.AppsV1().Deployments(resource.Namespace).Get(context.TODO(), resource.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
@ -605,7 +609,7 @@ func waitForDeploymentRollout(kubeClientSet kubernetes.Interface, resource *apps
}
// UpdateIngress runs the given updateFunc on the ingress
func UpdateIngress(kubeClientSet kubernetes.Interface, namespace string, name string, updateFunc func(d *networking.Ingress) error) error {
func UpdateIngress(kubeClientSet kubernetes.Interface, namespace, name string, updateFunc func(d *networking.Ingress) error) error {
ingress, err := kubeClientSet.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return err

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
//nolint:dupl // Ignore dupl errors for similar test case
package framework
import (
@ -75,7 +76,7 @@ func (f *Framework) NewNewGRPCFortuneTellerDeploymentWithReplicas(replicas int32
d := f.EnsureDeployment(deployment)
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, metav1.ListOptions{
err := waitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, &metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
assert.Nil(ginkgo.GinkgoT(), err, "failed to wait for to become ready")

View file

@ -26,7 +26,7 @@ func (f *Framework) VerifyHealthz(ip string, statusCode int) error {
url := fmt.Sprintf("http://%v:10254/healthz", ip)
client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, url, nil)
req, err := http.NewRequest(http.MethodGet, url, http.NoBody)
if err != nil {
return fmt.Errorf("creating GET request for URL %q failed: %v", url, err)
}

View file

@ -23,7 +23,7 @@ type Match struct {
names map[string]int
}
func makeMatch(chain chain, submatches []string, names []string) *Match {
func makeMatch(chain chain, submatches, names []string) *Match {
if submatches == nil {
submatches = []string{}
}

View file

@ -23,6 +23,8 @@ import (
"github.com/yudai/gojsondiff/formatter"
)
const unavailableMsg = " (unavailable)"
// Object provides methods to inspect attached map[string]interface{} object
// (Go representation of JSON object).
type Object struct {
@ -81,20 +83,21 @@ func diffValues(expected, actual interface{}) string {
var diff gojsondiff.Diff
if ve, ok := expected.(map[string]interface{}); ok {
switch ve := expected.(type) {
case map[string]interface{}:
if va, ok := actual.(map[string]interface{}); ok {
diff = differ.CompareObjects(ve, va)
} else {
return " (unavailable)"
return unavailableMsg
}
} else if ve, ok := expected.([]interface{}); ok {
case []interface{}:
if va, ok := actual.([]interface{}); ok {
diff = differ.CompareArrays(ve, va)
} else {
return " (unavailable)"
return unavailableMsg
}
} else {
return " (unavailable)"
default:
return unavailableMsg
}
config := formatter.AsciiFormatterConfig{
@ -104,7 +107,7 @@ func diffValues(expected, actual interface{}) string {
str, err := f.Format(diff)
if err != nil {
return " (unavailable)"
return unavailableMsg
}
return "--- expected\n+++ actual\n" + str

View file

@ -65,7 +65,7 @@ func (h *HTTPRequest) DoRequest(method, rpath string) *HTTPRequest {
var request *http.Request
uri.Path = path.Join(uri.Path, rpath)
if request, err = http.NewRequest(method, uri.String(), nil); err != nil {
if request, err = http.NewRequest(method, uri.String(), http.NoBody); err != nil {
h.chain.fail(err.Error())
}
@ -93,7 +93,7 @@ func (h *HTTPRequest) ForceResolve(ip string, port uint16) *HTTPRequest {
return h
}
newTransport := oldTransport.Clone()
newTransport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
newTransport.DialContext = func(ctx context.Context, network, _ string) (net.Conn, error) {
return dialer.DialContext(ctx, network, resolveAddr)
}
h.client.Transport = newTransport
@ -110,6 +110,7 @@ func (h *HTTPRequest) Expect() *HTTPResponse {
if err != nil {
h.chain.fail(err.Error())
}
defer response.Body.Close()
h.HTTPResponse.Response = response // set the HTTP response

View file

@ -234,6 +234,7 @@ func (r *HTTPResponse) checkContentType(expectedType string, expectedCharset ...
}
if mediaType != expectedType {
//nolint:goconst //string interpolation
r.chain.fail("\nexpected \"Content-Type\" header with %q media type,"+
"\nbut got %q", expectedType, mediaType)
return false

View file

@ -47,7 +47,7 @@ func (f *Framework) EnsureSecret(secret *core.Secret) *core.Secret {
}
// GetConfigMap gets a ConfigMap object from the given namespace, name and returns it, throws error if it does not exist.
func (f *Framework) GetConfigMap(namespace string, name string) *core.ConfigMap {
func (f *Framework) GetConfigMap(namespace, name string) *core.ConfigMap {
cm, err := f.KubeClientSet.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "getting configmap")
assert.NotNil(ginkgo.GinkgoT(), cm, "expected a configmap but none returned")
@ -73,7 +73,7 @@ func (f *Framework) EnsureConfigMap(configMap *core.ConfigMap) *core.ConfigMap {
}
// GetIngress gets an Ingress object from the given namespace, name and returns it, throws error if it does not exists.
func (f *Framework) GetIngress(namespace string, name string) *networking.Ingress {
func (f *Framework) GetIngress(namespace, name string) *networking.Ingress {
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "getting ingress")
assert.NotNil(ginkgo.GinkgoT(), ing, "expected an ingress but none returned")
@ -114,7 +114,7 @@ func (f *Framework) UpdateIngress(ingress *networking.Ingress) *networking.Ingre
}
// GetService gets a Service object from the given namespace, name and returns it, throws error if it does not exist.
func (f *Framework) GetService(namespace string, name string) *core.Service {
func (f *Framework) GetService(namespace, name string) *core.Service {
s, err := f.KubeClientSet.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "getting service")
assert.NotNil(ginkgo.GinkgoT(), s, "expected a service but none returned")
@ -143,16 +143,21 @@ func (f *Framework) EnsureDeployment(deployment *appsv1.Deployment) *appsv1.Depl
}
// waitForPodsReady waits for a given amount of time until a group of Pods is running in the given namespace.
func waitForPodsReady(kubeClientSet kubernetes.Interface, timeout time.Duration, expectedReplicas int, namespace string, opts metav1.ListOptions) error {
func waitForPodsReady(kubeClientSet kubernetes.Interface, timeout time.Duration, expectedReplicas int, namespace string, opts *metav1.ListOptions) error {
//nolint:staticcheck // TODO: will replace it since wait.PollImmediate is deprecated
return wait.PollImmediate(1*time.Second, timeout, func() (bool, error) {
pl, err := kubeClientSet.CoreV1().Pods(namespace).List(context.TODO(), opts)
pl, err := kubeClientSet.CoreV1().Pods(namespace).List(context.TODO(), *opts)
if err != nil {
return false, nil
}
r := 0
for _, p := range pl.Items {
if isRunning, _ := podRunningReady(&p); isRunning {
for i := range pl.Items {
isRunning, err := podRunningReady(&pl.Items[i])
if err != nil {
Logf("error checking if pod is running : %v", err)
}
if isRunning {
r++
}
}
@ -166,9 +171,10 @@ func waitForPodsReady(kubeClientSet kubernetes.Interface, timeout time.Duration,
}
// waitForPodsDeleted waits for a given amount of time until a group of Pods are deleted in the given namespace.
func waitForPodsDeleted(kubeClientSet kubernetes.Interface, timeout time.Duration, namespace string, opts metav1.ListOptions) error {
func waitForPodsDeleted(kubeClientSet kubernetes.Interface, timeout time.Duration, namespace string, opts *metav1.ListOptions) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, timeout, func() (bool, error) {
pl, err := kubeClientSet.CoreV1().Pods(namespace).List(context.TODO(), opts)
pl, err := kubeClientSet.CoreV1().Pods(namespace).List(context.TODO(), *opts)
if err != nil {
return false, nil
}
@ -186,7 +192,7 @@ func WaitForEndpoints(kubeClientSet kubernetes.Interface, timeout time.Duration,
if expectedEndpoints == 0 {
return nil
}
//nolint:staticcheck // TODO: will replace it since wait.PollImmediate is deprecated
return wait.PollImmediate(Poll, timeout, func() (bool, error) {
endpoint, err := kubeClientSet.CoreV1().Endpoints(ns).Get(context.TODO(), name, metav1.GetOptions{})
if k8sErrors.IsNotFound(err) {
@ -248,6 +254,7 @@ func isPodReady(p *core.Pod) bool {
// getIngressNGINXPod returns the ingress controller running pod
func getIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Pod, error) {
var pod *core.Pod
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(1*time.Second, DefaultTimeout, func() (bool, error) {
l, err := kubeClientSet.CoreV1().Pods(ns).List(context.TODO(), metav1.ListOptions{
LabelSelector: "app.kubernetes.io/name=ingress-nginx",
@ -256,15 +263,16 @@ func getIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Po
return false, nil
}
for _, p := range l.Items {
for i := range l.Items {
p := &l.Items[i]
if strings.HasPrefix(p.GetName(), "nginx-ingress-controller") {
isRunning, err := podRunningReady(&p)
isRunning, err := podRunningReady(p)
if err != nil {
continue
}
if isRunning {
pod = &p
pod = p
return true, nil
}
}
@ -273,6 +281,7 @@ func getIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Po
return false, nil
})
if err != nil {
//nolint:staticcheck // TODO: will replace it since wait.ErrWaitTimeout is deprecated
if err == wait.ErrWaitTimeout {
return nil, fmt.Errorf("timeout waiting at least one ingress-nginx pod running in namespace %v", ns)
}
@ -285,7 +294,7 @@ func getIngressNGINXPod(ns string, kubeClientSet kubernetes.Interface) (*core.Po
func createDeploymentWithRetries(c kubernetes.Interface, namespace string, obj *appsv1.Deployment) error {
if obj == nil {
return fmt.Errorf("Object provided to create is empty")
return fmt.Errorf("object provided to create is empty")
}
createFunc := func() (bool, error) {
_, err := c.AppsV1().Deployments(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
@ -298,7 +307,7 @@ func createDeploymentWithRetries(c kubernetes.Interface, namespace string, obj *
if isRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to create object with non-retriable error: %v", err)
return false, fmt.Errorf("failed to create object with non-retriable error: %v", err)
}
return retryWithExponentialBackOff(createFunc)
@ -306,7 +315,7 @@ func createDeploymentWithRetries(c kubernetes.Interface, namespace string, obj *
func createSecretWithRetries(c kubernetes.Interface, namespace string, obj *core.Secret) error {
if obj == nil {
return fmt.Errorf("Object provided to create is empty")
return fmt.Errorf("object provided to create is empty")
}
createFunc := func() (bool, error) {
_, err := c.CoreV1().Secrets(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
@ -319,14 +328,14 @@ func createSecretWithRetries(c kubernetes.Interface, namespace string, obj *core
if isRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to create object with non-retriable error: %v", err)
return false, fmt.Errorf("failed to create object with non-retriable error: %v", err)
}
return retryWithExponentialBackOff(createFunc)
}
func createServiceWithRetries(c kubernetes.Interface, namespace string, obj *core.Service) error {
if obj == nil {
return fmt.Errorf("Object provided to create is empty")
return fmt.Errorf("object provided to create is empty")
}
createFunc := func() (bool, error) {
_, err := c.CoreV1().Services(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
@ -339,7 +348,7 @@ func createServiceWithRetries(c kubernetes.Interface, namespace string, obj *cor
if isRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to create object with non-retriable error: %v", err)
return false, fmt.Errorf("failed to create object with non-retriable error: %v", err)
}
return retryWithExponentialBackOff(createFunc)
@ -347,7 +356,7 @@ func createServiceWithRetries(c kubernetes.Interface, namespace string, obj *cor
func createIngressWithRetries(c kubernetes.Interface, namespace string, obj *networking.Ingress) error {
if obj == nil {
return fmt.Errorf("Object provided to create is empty")
return fmt.Errorf("object provided to create is empty")
}
createFunc := func() (bool, error) {
_, err := c.NetworkingV1().Ingresses(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
@ -360,7 +369,7 @@ func createIngressWithRetries(c kubernetes.Interface, namespace string, obj *net
if isRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to create object with non-retriable error: %v", err)
return false, fmt.Errorf("failed to create object with non-retriable error: %v", err)
}
return retryWithExponentialBackOff(createFunc)
@ -368,7 +377,7 @@ func createIngressWithRetries(c kubernetes.Interface, namespace string, obj *net
func updateIngressWithRetries(c kubernetes.Interface, namespace string, obj *networking.Ingress) error {
if obj == nil {
return fmt.Errorf("Object provided to create is empty")
return fmt.Errorf("object provided to create is empty")
}
updateFunc := func() (bool, error) {
_, err := c.NetworkingV1().Ingresses(namespace).Update(context.TODO(), obj, metav1.UpdateOptions{})
@ -378,7 +387,7 @@ func updateIngressWithRetries(c kubernetes.Interface, namespace string, obj *net
if isRetryableAPIError(err) {
return false, nil
}
return false, fmt.Errorf("Failed to update object with non-retriable error: %v", err)
return false, fmt.Errorf("failed to update object with non-retriable error: %v", err)
}
return retryWithExponentialBackOff(updateFunc)

View file

@ -29,7 +29,7 @@ func (f *Framework) GetMetric(metricName, ip string) (*dto.MetricFamily, error)
url := fmt.Sprintf("http://%v:10254/metrics", ip)
client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, url, nil)
req, err := http.NewRequest(http.MethodGet, url, http.NoBody)
if err != nil {
return nil, fmt.Errorf("creating GET request for URL %q failed: %v", url, err)
}
@ -44,7 +44,6 @@ func (f *Framework) GetMetric(metricName, ip string) (*dto.MetricFamily, error)
var parser expfmt.TextParser
metrics, err := parser.TextToMetricFamilies(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading text format failed: %v", err)
}

View file

@ -93,8 +93,8 @@ func CreateIngressTLSSecret(client kubernetes.Interface, hosts []string, secretN
// CreateIngressMASecret creates or updates a Secret containing a Mutual Auth
// certificate-chain for the given Ingress and returns a TLS configuration suitable
// for HTTP clients to use against that particular Ingress.
func CreateIngressMASecret(client kubernetes.Interface, host string, secretName, namespace string) (*tls.Config, error) {
if len(host) == 0 {
func CreateIngressMASecret(client kubernetes.Interface, host, secretName, namespace string) (*tls.Config, error) {
if host == "" {
return nil, fmt.Errorf("requires a non-empty host")
}
@ -138,12 +138,13 @@ func CreateIngressMASecret(client kubernetes.Interface, host string, secretName,
return &tls.Config{
ServerName: host,
Certificates: []tls.Certificate{clientPair},
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
}, nil
}
// WaitForTLS waits until the TLS handshake with a given server completes successfully.
func WaitForTLS(url string, tlsConfig *tls.Config) {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err := wait.Poll(Poll, DefaultTimeout, matchTLSServerName(url, tlsConfig))
assert.Nil(ginkgo.GinkgoT(), err, "waiting for TLS configuration in URL %s", url)
}
@ -160,7 +161,6 @@ func generateRSACert(host string, isCA bool, keyOut, certOut io.Writer) error {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate serial number: %s", err)
}
@ -329,7 +329,7 @@ func tlsConfig(serverName string, pemCA []byte) (*tls.Config, error) {
if !rootCAPool.AppendCertsFromPEM(pemCA) {
return nil, fmt.Errorf("error creating CA certificate pool (%s)", serverName)
}
return &tls.Config{
return &tls.Config{ //nolint:gosec // Ignore the gosec error in testing
ServerName: serverName,
RootCAs: rootCAPool,
}, nil

View file

@ -23,7 +23,7 @@ import (
// TestContextType describes the client context to use in communications with the Kubernetes API.
type TestContextType struct {
KubeHost string
//KubeConfig string
// KubeConfig string
KubeContext string
}
@ -33,7 +33,6 @@ var TestContext TestContextType
// registerCommonFlags registers flags common to all e2e test suites.
func registerCommonFlags() {
flag.StringVar(&TestContext.KubeHost, "kubernetes-host", "http://127.0.0.1:8080", "The kubernetes host, or apiserver, to connect to")
//flag.StringVar(&TestContext.KubeConfig, "kubernetes-config", os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to config containing embedded authinfo for kubernetes. Default value is from environment variable "+clientcmd.RecommendedConfigPathEnvVar)
flag.StringVar(&TestContext.KubeContext, "kubernetes-context", "", "config context to use for kubernetes. If unset, will use value from 'current-context'")
}

View file

@ -49,24 +49,24 @@ func nowStamp() string {
return time.Now().Format(time.StampMilli)
}
func log(level string, format string, args ...interface{}) {
func logf(level, format string, args ...interface{}) {
fmt.Fprintf(ginkgo.GinkgoWriter, nowStamp()+": "+level+": "+format+"\n", args...)
}
// Logf logs to the INFO logs.
func Logf(format string, args ...interface{}) {
log("INFO", format, args...)
logf("INFO", format, args...)
}
// Failf logs to the INFO logs and fails the test.
func Failf(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
log("INFO", msg)
logf("INFO", msg)
ginkgo.Fail(nowStamp()+": "+msg, 1)
}
// RestclientConfig deserializes the contents of a kubeconfig file into a Config object.
func RestclientConfig(config, context string) (*api.Config, error) {
func RestclientConfig(config, newContext string) (*api.Config, error) {
Logf(">>> config: %s\n", config)
if config == "" {
return nil, fmt.Errorf("config file must be specified to load client config")
@ -75,9 +75,9 @@ func RestclientConfig(config, context string) (*api.Config, error) {
if err != nil {
return nil, fmt.Errorf("error loading config: %v", err.Error())
}
if context != "" {
Logf(">>> context: %s\n", context)
c.CurrentContext = context
if newContext != "" {
Logf(">>> context: %s\n", newContext)
c.CurrentContext = newContext
}
return c, nil
}
@ -98,6 +98,7 @@ func createNamespace(baseName string, labels map[string]string, c kubernetes.Int
var got *corev1.Namespace
var err error
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
err = wait.Poll(Poll, DefaultTimeout, func() (bool, error) {
got, err = c.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{})
if err != nil {
@ -114,13 +115,11 @@ func createNamespace(baseName string, labels map[string]string, c kubernetes.Int
// CreateKubeNamespace creates a new namespace in the cluster
func CreateKubeNamespace(baseName string, c kubernetes.Interface) (string, error) {
return createNamespace(baseName, nil, c)
}
// CreateKubeNamespaceWithLabel creates a new namespace with given labels in the cluster
func CreateKubeNamespaceWithLabel(baseName string, labels map[string]string, c kubernetes.Interface) (string, error) {
return createNamespace(baseName, labels, c)
}
@ -150,7 +149,7 @@ func CreateIngressClass(namespace string, c kubernetes.Interface) (string, error
},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass %s: %v", icname, err)
return "", fmt.Errorf("unexpected error creating IngressClass %s: %v", icname, err)
}
_, err = c.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
@ -162,7 +161,7 @@ func CreateIngressClass(namespace string, c kubernetes.Interface) (string, error
}},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass ClusterRole %s: %v", icname, err)
return "", fmt.Errorf("unexpected error creating IngressClass ClusterRole %s: %v", icname, err)
}
_, err = c.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
@ -184,7 +183,7 @@ func CreateIngressClass(namespace string, c kubernetes.Interface) (string, error
},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass ClusterRoleBinding %s: %v", icname, err)
return "", fmt.Errorf("unexpected error creating IngressClass ClusterRoleBinding %s: %v", icname, err)
}
return ic.Name, nil
}
@ -200,16 +199,16 @@ func deleteIngressClass(c kubernetes.Interface, ingressclass string) error {
}
err = c.NetworkingV1().IngressClasses().Delete(context.TODO(), ingressclass, deleteOptions)
if err != nil {
return fmt.Errorf("Unexpected error deleting IngressClass %s: %v", ingressclass, err)
return fmt.Errorf("unexpected error deleting IngressClass %s: %v", ingressclass, err)
}
err = c.RbacV1().ClusterRoleBindings().Delete(context.TODO(), ingressclass, deleteOptions)
if err != nil {
return fmt.Errorf("Unexpected error deleting IngressClass ClusterRoleBinding %s: %v", ingressclass, err)
return fmt.Errorf("unexpected error deleting IngressClass ClusterRoleBinding %s: %v", ingressclass, err)
}
err = c.RbacV1().ClusterRoles().Delete(context.TODO(), ingressclass, deleteOptions)
if err != nil {
return fmt.Errorf("Unexpected error deleting IngressClass ClusterRole %s: %v", ingressclass, err)
return fmt.Errorf("unexpected error deleting IngressClass ClusterRole %s: %v", ingressclass, err)
}
return nil
@ -223,6 +222,7 @@ func GetIngressClassName(namespace string) *string {
// WaitForKubeNamespaceNotExist waits until a namespaces is not present in the cluster
func WaitForKubeNamespaceNotExist(c kubernetes.Interface, namespace string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, namespaceNotExist(c, namespace))
}
@ -241,6 +241,7 @@ func namespaceNotExist(c kubernetes.Interface, namespace string) wait.ConditionF
// WaitForNoPodsInNamespace waits until there are no pods running in a namespace
func WaitForNoPodsInNamespace(c kubernetes.Interface, namespace string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, noPodsInNamespace(c, namespace))
}
@ -267,15 +268,17 @@ func WaitForPodRunningInNamespace(c kubernetes.Interface, pod *corev1.Pod) error
if pod.Status.Phase == corev1.PodRunning {
return nil
}
return waitTimeoutForPodRunningInNamespace(c, pod.Name, pod.Namespace, DefaultTimeout)
return waitTimeoutForPodRunningInNamespace(c, pod.Name, pod.Namespace)
}
func waitTimeoutForPodRunningInNamespace(c kubernetes.Interface, podName, namespace string, timeout time.Duration) error {
func waitTimeoutForPodRunningInNamespace(c kubernetes.Interface, podName, namespace string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, podRunning(c, podName, namespace))
}
// WaitForSecretInNamespace waits a default amount of time for the specified secret is present in a particular namespace
func WaitForSecretInNamespace(c kubernetes.Interface, namespace, name string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, secretInNamespace(c, namespace, name))
}
@ -298,6 +301,7 @@ func secretInNamespace(c kubernetes.Interface, namespace, name string) wait.Cond
// WaitForFileInFS waits a default amount of time for the specified file is present in the filesystem
func WaitForFileInFS(file string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, fileInFS(file))
}
@ -322,6 +326,7 @@ func fileInFS(file string) wait.ConditionFunc {
// WaitForNoIngressInNamespace waits until there is no ingress object in a particular namespace
func WaitForNoIngressInNamespace(c kubernetes.Interface, namespace, name string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, noIngressInNamespace(c, namespace, name))
}
@ -344,6 +349,7 @@ func noIngressInNamespace(c kubernetes.Interface, namespace, name string) wait.C
// WaitForIngressInNamespace waits until a particular ingress object exists namespace
func WaitForIngressInNamespace(c kubernetes.Interface, namespace, name string) error {
//nolint:staticcheck // TODO: will replace it since wait.Poll is deprecated
return wait.Poll(Poll, DefaultTimeout, ingressInNamespace(c, namespace, name))
}

View file

@ -33,7 +33,6 @@ var _ = framework.IngressNginxDescribe("[Shutdown] Grace period shutdown", func(
f := framework.NewDefaultFramework("shutdown-grace-period")
ginkgo.It("/healthz should return status code 500 during shutdown grace period", func() {
f.NewSlowEchoDeployment()
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
@ -83,6 +82,5 @@ var _ = framework.IngressNginxDescribe("[Shutdown] Grace period shutdown", func(
for _, err := range <-result {
assert.Nil(ginkgo.GinkgoT(), err)
}
})
})

View file

@ -36,6 +36,15 @@ var _ = framework.IngressNginxDescribe("single ingress - multiple hosts", func()
})
ginkgo.It("should set the correct $service_name NGINX variable", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
annotations := map[string]string{
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "service-name: $service_name";`,
}

View file

@ -35,6 +35,14 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
})
ginkgo.It("should choose exact location for /exact", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "exact.path"
@ -42,7 +50,7 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";`,
}
var exactPathType = networking.PathTypeExact
exactPathType := networking.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)

View file

@ -34,9 +34,17 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefi
f.NewEchoDeployment()
})
var exactPathType = networking.PathTypeExact
exactPathType := networking.PathTypeExact
ginkgo.It("should choose the correct location", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "mixed.path"

View file

@ -68,4 +68,138 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] prefix checks", fun
Expect().
Status(http.StatusOK)
})
ginkgo.It("should test prefix path using simple regex pattern for /id/{int}", func() {
host := "echo.com.br"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/use-regex": `true`,
}
ing := framework.NewSingleIngress(host, "/id/[0-9]+", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.HTTPTestClient().
GET("/id/1").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/12").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/123").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/aaa").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/id/123a").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should test prefix path using regex pattern for /id/{int} ignoring non-digits characters at end of string", func() {
host := "echo.regex.br"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/use-regex": `true`,
}
ing := framework.NewSingleIngress(host, "/id/[0-9]+$", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.HTTPTestClient().
GET("/id/1").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/aaa").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/id/123a").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
ginkgo.It("should test prefix path using fixed path size regex pattern /id/{int}{3}", func() {
host := "echo.regex.size.br"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/use-regex": `true`,
}
ing := framework.NewSingleIngress(host, "/id/[0-9]{3}$", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.HTTPTestClient().
GET("/id/99").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/id/123").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/9999").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/id/123a").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
ginkgo.It("should correctly route multi-segment path patterns", func() {
host := "echo.multi.segment.br"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/use-regex": `true`,
}
ing := framework.NewSingleIngress(host, "/id/[0-9]+/post/[a-zA-Z]+$", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.HTTPTestClient().
GET("/id/123/post/abc").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/id/123/post/abc123").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/id/abc/post/abc").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
})

View file

@ -87,14 +87,14 @@ func provisionIngress(hostname string, f *framework.Framework) {
func checkIngress(hostname string, f *framework.Framework) {
resp := f.HTTPTestClientWithTLSConfig(&tls.Config{
ServerName: hostname,
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
}).
GET("/").
WithURL(f.GetURL(framework.HTTPS)).
WithHeader("Host", hostname).
Expect().
Raw()
defer resp.Body.Close()
assert.Equal(ginkgo.GinkgoT(), resp.StatusCode, http.StatusOK)
// check the returned secret is not the fake one

View file

@ -25,6 +25,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const loadBalanceHost = "load-balance.com"
var _ = framework.DescribeSetting("[Load Balancer] load-balance", func() {
f := framework.NewDefaultFramework("lb-configmap")
@ -33,7 +35,7 @@ var _ = framework.DescribeSetting("[Load Balancer] load-balance", func() {
})
ginkgo.It("should apply the configmap load-balance setting", func() {
host := "load-balance.com"
host := loadBalanceHost
f.UpdateNginxConfigMapData("load-balance", "ewma")

View file

@ -35,12 +35,13 @@ var _ = framework.DescribeSetting("[Load Balancer] EWMA", func() {
f.NewEchoDeployment(framework.WithDeploymentReplicas(3))
f.SetNginxConfigMapData(map[string]string{
"worker-processes": "2",
"load-balance": "ewma"},
"load-balance": "ewma",
},
)
})
ginkgo.It("does not fail requests", func() {
host := "load-balance.com"
host := loadBalanceHost
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil))
f.WaitForNginxServer(host,
@ -52,7 +53,9 @@ var _ = framework.DescribeSetting("[Load Balancer] EWMA", func() {
assert.Nil(ginkgo.GinkgoT(), err)
assert.Equal(ginkgo.GinkgoT(), algorithm, "ewma")
re, _ := regexp.Compile(fmt.Sprintf(`%v.*`, framework.EchoService))
re, err := regexp.Compile(fmt.Sprintf(`%v.*`, framework.EchoService))
assert.Nil(ginkgo.GinkgoT(), err, "error compiling regex")
replicaRequestCount := map[string]int{}
for i := 0; i < 30; i++ {

View file

@ -37,7 +37,7 @@ var _ = framework.DescribeSetting("[Load Balancer] round-robin", func() {
})
ginkgo.It("should evenly distribute requests with round-robin (default algorithm)", func() {
host := "load-balance.com"
host := loadBalanceHost
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil))
f.WaitForNginxServer(host,
@ -45,7 +45,9 @@ var _ = framework.DescribeSetting("[Load Balancer] round-robin", func() {
return strings.Contains(server, "server_name load-balance.com")
})
re, _ := regexp.Compile(fmt.Sprintf(`%v.*`, framework.EchoService))
re, err := regexp.Compile(fmt.Sprintf(`%v.*`, framework.EchoService))
assert.Nil(ginkgo.GinkgoT(), err, "error compiling regex")
replicaRequestCount := map[string]int{}
for i := 0; i < 600; i++ {

View file

@ -245,7 +245,6 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
})
})
})
@ -254,7 +253,6 @@ func extractReloadCount(mf *dto.MetricFamily) (float64, error) {
vec, err := expfmt.ExtractSamples(&expfmt.DecodeOptions{
Timestamp: model.Now(),
}, mf)
if err != nil {
return 0, err
}

View file

@ -26,7 +26,6 @@ import (
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
@ -199,20 +198,18 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic configuration", func() {
})
})
func ensureIngress(f *framework.Framework, host string, deploymentName string) *networking.Ingress {
ing := createIngress(f, host, deploymentName)
func ensureIngress(f *framework.Framework, host, deploymentName string) {
createIngress(f, host, deploymentName)
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
return ing
}
func createIngress(f *framework.Framework, host string, deploymentName string) *networking.Ingress {
ing := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, deploymentName, 80,
func createIngress(f *framework.Framework, host, deploymentName string) {
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, deploymentName, 80,
map[string]string{
"nginx.ingress.kubernetes.io/load-balance": "ewma",
},
@ -223,21 +220,19 @@ func createIngress(f *framework.Framework, host string, deploymentName string) *
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) &&
strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
return ing
}
func ensureHTTPSRequest(f *framework.Framework, url string, host string, expectedDNSName string) {
func ensureHTTPSRequest(f *framework.Framework, url, host, expectedDNSName string) {
resp := f.HTTPTestClientWithTLSConfig(&tls.Config{
ServerName: host,
InsecureSkipVerify: true,
InsecureSkipVerify: true, //nolint:gosec // Ignore the gosec error in testing
}).
GET("/").
WithURL(url).
WithHeader("Host", host).
Expect().
Raw()
defer resp.Body.Close()
assert.Equal(ginkgo.GinkgoT(), resp.StatusCode, http.StatusOK)
assert.Equal(ginkgo.GinkgoT(), len(resp.TLS.PeerCertificates), 1)
assert.Equal(ginkgo.GinkgoT(), resp.TLS.PeerCertificates[0].DNSNames[0], expectedDNSName)

View file

@ -100,7 +100,6 @@ var _ = framework.DescribeSetting("nginx-configuration", func() {
f := framework.NewSimpleFramework("nginxconfiguration")
ginkgo.It("start nginx with default configuration", func() {
f.NGINXWithConfigDeployment("default-nginx", cfgOK)
f.WaitForPod("app=default-nginx", 60*time.Second, false)
framework.Sleep(5 * time.Second)
@ -113,20 +112,16 @@ var _ = framework.DescribeSetting("nginx-configuration", func() {
})
ginkgo.It("fails when using alias directive", func() {
f.NGINXDeployment("alias-nginx", cfgAlias, false)
// This should fail with a crashloopback because our NGINX does not have
// alias directive!
f.WaitForPod("app=alias-nginx", 60*time.Second, true)
})
ginkgo.It("fails when using root directive", func() {
f.NGINXDeployment("root-nginx", cfgRoot, false)
// This should fail with a crashloopback because our NGINX does not have
// root directive!
f.WaitForPod("app=root-nginx", 60*time.Second, true)
})
})

View file

@ -62,7 +62,7 @@ export KUBECONFIG="${KUBECONFIG:-$HOME/.kube/kind-config-$KIND_CLUSTER_NAME}"
if [ "${SKIP_CLUSTER_CREATION:-false}" = "false" ]; then
echo "[dev-env] creating Kubernetes cluster with kind"
export K8S_VERSION=${K8S_VERSION:-v1.26.3@sha256:61b92f38dff6ccc29969e7aa154d34e38b89443af1a2c14e6cfbd2df6419c66f}
export K8S_VERSION=${K8S_VERSION:-v1.29.2@sha256:51a1434a5397193442f0be2a297b488b6c919ce8a3931be0ce822606ea5ca245}
kind create cluster \
--verbosity=${KIND_LOG_LEVEL} \
@ -78,7 +78,7 @@ fi
if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then
if ! command -v ginkgo &> /dev/null; then
go install github.com/onsi/ginkgo/v2/ginkgo@v2.9.5
go install github.com/onsi/ginkgo/v2/ginkgo@v2.17.1
fi
echo "[dev-env] building image"
make -C ${DIR}/../../ clean-image build image
@ -104,13 +104,12 @@ if [ "${SKIP_CERT_MANAGER_CREATION:-false}" = "false" ]; then
fi
echo "[dev-env] running helm chart e2e tests..."
# Uses a custom chart-testing image to avoid timeouts waiting for namespace deletion.
# The changes can be found here: https://github.com/aledbf/chart-testing/commit/41fe0ae0733d0c9a538099fb3cec522e888e3d82
docker run --rm --interactive --network host \
--name ct \
--volume $KUBECONFIG:/root/.kube/config \
--volume "${DIR}/../../":/workdir \
--workdir /workdir \
aledbf/chart-testing:v3.3.1-next ct install \
registry.k8s.io/ingress-nginx/e2e-test-runner:v20240404-436df3e4@sha256:6bcba53b14d396177414e01f20e9111f1c009ac3b476a9b7668bb98d12bd5e85 \
ct install \
--charts charts/ingress-nginx \
--helm-extra-args "--timeout 60s"

View file

@ -78,6 +78,8 @@ kubectl run --rm \
--env="E2E_NODES=${E2E_NODES}" \
--env="FOCUS=${FOCUS}" \
--env="IS_CHROOT=${IS_CHROOT:-false}"\
--env="ENABLE_VALIDATIONS=${ENABLE_VALIDATIONS:-false}"\
--env="SKIP_OPENTELEMETRY_TESTS=${SKIP_OPENTELEMETRY_TESTS:-false}"\
--env="E2E_CHECK_LEAKS=${E2E_CHECK_LEAKS}" \
--env="NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE}" \
--env="HTTPBUN_IMAGE=${HTTPBUN_IMAGE}" \

View file

@ -39,13 +39,14 @@ fi
KIND_LOG_LEVEL="1"
IS_CHROOT="${IS_CHROOT:-false}"
ENABLE_VALIDATIONS="${ENABLE_VALIDATIONS:-false}"
export KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-ingress-nginx-dev}
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Use 1.0.0-dev to make sure we use the latest configuration in the helm template
export TAG=1.0.0-dev
export ARCH=${ARCH:-amd64}
export REGISTRY=ingress-controller
NGINX_BASE_IMAGE=$(cat "$DIR"/../../NGINX_BASE)
NGINX_BASE_IMAGE=${NGINX_BASE_IMAGE:-$(cat "$DIR"/../../NGINX_BASE)}
export NGINX_BASE_IMAGE=$NGINX_BASE_IMAGE
export DOCKER_CLI_EXPERIMENTAL=enabled
export KUBECONFIG="${KUBECONFIG:-$HOME/.kube/kind-config-$KIND_CLUSTER_NAME}"
@ -63,7 +64,7 @@ echo "Running e2e with nginx base image ${NGINX_BASE_IMAGE}"
if [ "${SKIP_CLUSTER_CREATION}" = "false" ]; then
echo "[dev-env] creating Kubernetes cluster with kind"
export K8S_VERSION=${K8S_VERSION:-v1.26.3@sha256:61b92f38dff6ccc29969e7aa154d34e38b89443af1a2c14e6cfbd2df6419c66f}
export K8S_VERSION=${K8S_VERSION:-v1.29.2@sha256:51a1434a5397193442f0be2a297b488b6c919ce8a3931be0ce822606ea5ca245}
# delete the cluster if it exists
if kind get clusters | grep "${KIND_CLUSTER_NAME}"; then
@ -84,10 +85,10 @@ fi
if [ "${SKIP_INGRESS_IMAGE_CREATION}" = "false" ]; then
echo "[dev-env] building image"
if [ "${IS_CHROOT}" = "true" ]; then
make -C "${DIR}"/../../ clean-image build image-chroot
make BASE_IMAGE="${NGINX_BASE_IMAGE}" -C "${DIR}"/../../ clean-image build image-chroot
docker tag ${REGISTRY}/controller-chroot:${TAG} ${REGISTRY}/controller:${TAG}
else
make -C "${DIR}"/../../ clean-image build image
make BASE_IMAGE="${NGINX_BASE_IMAGE}" -C "${DIR}"/../../ clean-image build image
fi
echo "[dev-env] .. done building controller images"
@ -95,7 +96,7 @@ fi
if [ "${SKIP_E2E_IMAGE_CREATION}" = "false" ]; then
if ! command -v ginkgo &> /dev/null; then
go install github.com/onsi/ginkgo/v2/ginkgo@v2.9.5
go install github.com/onsi/ginkgo/v2/ginkgo@v2.17.1
fi
echo "[dev-env] .. done building controller images"

View file

@ -50,9 +50,9 @@ server {
f.UpdateNginxConfigMapData("http-snippet", snippet)
//TODO: currently using a self hosted HTTPBun instance results in a 499, we
//should move away from using httpbun.com once we have the httpbun
//deployment as part of the framework
// TODO: currently using a self hosted HTTPBun instance results in a 499, we
// should move away from using httpbun.com once we have the httpbun
// deployment as part of the framework
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, map[string]string{
"nginx.ingress.kubernetes.io/auth-signin": "https://httpbun.com/bearer/d4bcba7a-0def-4a31-91a7-47e420adf44b",
"nginx.ingress.kubernetes.io/auth-url": "https://httpbun.com/basic-auth/user/passwd",
@ -91,7 +91,7 @@ func smugglingRequest(host, addr string, port int) (string, error) {
// wait for /_hidden/index.html response
framework.Sleep()
var buf = make([]byte, 1024)
buf := make([]byte, 1024)
r := bufio.NewReader(conn)
_, err = r.Read(buf)
if err != nil {

View file

@ -29,48 +29,50 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
var pathtype = networking.PathTypePrefix
var _ = framework.IngressNginxDescribe("[Service] backend status code 503", func() {
f := framework.NewDefaultFramework("service-backend")
var (
pathtype = networking.PathTypePrefix
_ = framework.IngressNginxDescribe("[Service] backend status code 503", func() {
f := framework.NewDefaultFramework("service-backend")
ginkgo.It("should return 503 when backend service does not exist", func() {
host := "nonexistent.svc.com"
ginkgo.It("should return 503 when backend service does not exist", func() {
host := "nonexistent.svc.com"
bi := buildIngressWithNonexistentService(host, f.Namespace, "/")
f.EnsureIngress(bi)
bi := buildIngressWithNonexistentService(host, f.Namespace, "/")
f.EnsureIngress(bi)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusServiceUnavailable)
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusServiceUnavailable)
})
ginkgo.It("should return 503 when all backend service endpoints are unavailable", func() {
host := "unavailable.svc.com"
bi, bs := buildIngressWithUnavailableServiceEndpoints(host, f.Namespace, "/")
f.EnsureService(bs)
f.EnsureIngress(bi)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusServiceUnavailable)
})
})
ginkgo.It("should return 503 when all backend service endpoints are unavailable", func() {
host := "unavailable.svc.com"
bi, bs := buildIngressWithUnavailableServiceEndpoints(host, f.Namespace, "/")
f.EnsureService(bs)
f.EnsureIngress(bi)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusServiceUnavailable)
})
})
)
func buildIngressWithNonexistentService(host, namespace, path string) *networking.Ingress {
backendService := "nonexistent-svc"
@ -146,14 +148,15 @@ func buildIngressWithUnavailableServiceEndpoints(host, namespace, path string) (
Name: backendService,
Namespace: namespace,
},
Spec: corev1.ServiceSpec{Ports: []corev1.ServicePort{
{
Name: "tcp",
Port: 80,
TargetPort: intstr.FromInt(80),
Protocol: "TCP",
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Name: "tcp",
Port: 80,
TargetPort: intstr.FromInt(80),
Protocol: "TCP",
},
},
},
Selector: map[string]string{
"app": backendService,
},

View file

@ -30,16 +30,17 @@ import (
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/internal/nginx"
"k8s.io/ingress-nginx/test/e2e/framework"
)
const echoHost = "echo"
var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
f := framework.NewDefaultFramework("type-externalname", framework.WithHTTPBunEnabled())
ginkgo.It("works with external name set to incomplete fqdn", func() {
f.NewEchoDeployment()
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -75,7 +76,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should return 200 for service type=ExternalName without a port defined", func() {
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -115,7 +116,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should return 200 for service type=ExternalName with a port defined", func() {
host := "echo"
host := echoHost
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
f.EnsureService(svc)
@ -145,7 +146,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should return status 502 for service type=ExternalName with an invalid host", func() {
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -181,7 +182,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should return 200 for service type=ExternalName using a port name", func() {
host := "echo"
host := echoHost
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
f.EnsureService(svc)
@ -222,7 +223,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should return 200 for service type=ExternalName using FQDN with trailing dot", func() {
host := "echo"
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
@ -258,7 +259,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
})
ginkgo.It("should update the external name after a service update", func() {
host := "echo"
host := echoHost
svc := framework.BuildNIPExternalNameService(f, f.HTTPBunIP, host)
f.EnsureService(svc)
@ -307,7 +308,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
Get(context.TODO(), framework.NIPService, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error obtaining external service")
//Deploy a new instance to switch routing to
// Deploy a new instance to switch routing to
ip := f.NewHttpbunDeployment(framework.WithDeploymentName("eu-server"))
svc.Spec.ExternalName = framework.BuildNIPHost(ip)
@ -330,22 +331,18 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
assert.Contains(ginkgo.GinkgoT(), body, `"X-Forwarded-Host": "echo"`)
ginkgo.By("checking the service is updated to use new host")
curlCmd := fmt.Sprintf(
"curl --fail --silent http://localhost:%v/configuration/backends",
nginx.StatusPort,
)
output, err := f.ExecIngressPod(curlCmd)
dbgCmd := "/dbg backends all"
output, err := f.ExecIngressPod(dbgCmd)
assert.Nil(ginkgo.GinkgoT(), err)
assert.Contains(
ginkgo.GinkgoT(),
output,
fmt.Sprintf("{\"address\":\"%s\"", framework.BuildNIPHost(ip)),
fmt.Sprintf(`"address": %q`, framework.BuildNIPHost(ip)),
)
})
ginkgo.It("should sync ingress on external name service addition/deletion", func() {
host := "echo"
host := echoHost
// Create the Ingress first
ing := framework.NewSingleIngress(host,

View file

@ -64,7 +64,6 @@ var _ = framework.IngressNginxDescribe("[Service] Nil Service Backend", func() {
WithHeader("Host", invalidHost).
Expect().
Status(http.StatusNotFound)
})
})

View file

@ -28,7 +28,6 @@ var _ = framework.DescribeSetting("access-log", func() {
f := framework.NewDefaultFramework("access-log")
ginkgo.Context("access-log-path", func() {
ginkgo.It("use the default configuration", func() {
f.WaitForNginxConfiguration(
func(cfg string) bool {
@ -50,7 +49,6 @@ var _ = framework.DescribeSetting("access-log", func() {
})
ginkgo.Context("http-access-log-path", func() {
ginkgo.It("use the specified configuration", func() {
f.UpdateNginxConfigMapData("http-access-log-path", "/tmp/nginx/http-access.log")
f.WaitForNginxConfiguration(
@ -63,7 +61,6 @@ var _ = framework.DescribeSetting("access-log", func() {
})
ginkgo.Context("stream-access-log-path", func() {
ginkgo.It("use the specified configuration", func() {
f.UpdateNginxConfigMapData("stream-access-log-path", "/tmp/nginx/stream-access.log")
f.WaitForNginxConfiguration(
@ -76,7 +73,6 @@ var _ = framework.DescribeSetting("access-log", func() {
})
ginkgo.Context("http-access-log-path & stream-access-log-path", func() {
ginkgo.It("use the specified configuration", func() {
f.SetNginxConfigMapData(map[string]string{
"http-access-log-path": "/tmp/nginx/http-access.log",

View file

@ -0,0 +1,54 @@
/*
Copyright 2023 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 settings
import (
"strings"
"github.com/onsi/ginkgo/v2"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeSetting("aio-write", func() {
f := framework.NewDefaultFramework("aio-write")
ginkgo.It("should be enabled by default", func() {
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "aio_write on")
})
})
ginkgo.It("should be enabled when setting is true", func() {
f.UpdateNginxConfigMapData("enable-aio-write", "true")
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "aio_write on")
})
})
ginkgo.It("should be disabled when setting is false", func() {
f.UpdateNginxConfigMapData("enable-aio-write", "false")
f.WaitForNginxConfiguration(
func(cfg string) bool {
return !strings.Contains(cfg, "aio_write on")
})
})
})

View file

@ -34,6 +34,14 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() {
})
ginkgo.It("[BAD_ANNOTATIONS] should drop an ingress if there is an invalid character in some annotation", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "invalid-value-test"
annotations := map[string]string{
@ -65,6 +73,15 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() {
})
ginkgo.It("[BAD_ANNOTATIONS] should drop an ingress if there is a forbidden word in some annotation", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "forbidden-value-test"
annotations := map[string]string{
@ -100,7 +117,14 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() {
})
ginkgo.It("[BAD_ANNOTATIONS] should allow an ingress if there is a default blocklist config in place", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
hostValid := "custom-allowed-value-test"
annotationsValid := map[string]string{
"nginx.ingress.kubernetes.io/configuration-snippet": `
@ -131,6 +155,14 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() {
})
ginkgo.It("[BAD_ANNOTATIONS] should drop an ingress if there is a custom blocklist config in place and allow others to pass", func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
host := "custom-forbidden-value-test"
annotations := map[string]string{
@ -159,6 +191,5 @@ var _ = framework.DescribeAnnotation("Bad annotation values", func() {
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
})

View file

@ -30,10 +30,12 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const fooHost = "foo"
var _ = framework.IngressNginxDescribe("[SSL] [Flag] default-ssl-certificate", func() {
f := framework.NewDefaultFramework("default-ssl-certificate")
var tlsConfig *tls.Config
secretName := "my-custom-cert"
secretName := "my-custom-cert" //nolint:gosec // Ignore the gosec error in testing
service := framework.EchoService
port := 80
@ -78,7 +80,7 @@ var _ = framework.IngressNginxDescribe("[SSL] [Flag] default-ssl-certificate", f
})
ginkgo.It("uses default ssl certificate for host based ingress when configured certificate does not match host", func() {
host := "foo"
host := fooHost
ing := f.EnsureIngress(framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, service, port, nil))
_, err := framework.CreateIngressTLSSecret(f.KubeClientSet,

View file

@ -48,7 +48,7 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() {
})
ginkgo.It("should ignore catch all Ingress with backend", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleCatchAllIngress("catch-all", f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -67,7 +67,7 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() {
})
ginkgo.It("should ignore catch all Ingress with backend and rules", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleIngressWithBackendAndRules(host, "/", host, f.Namespace, framework.EchoService, 80, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -79,7 +79,7 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() {
})
ginkgo.It("should delete Ingress updated to catch-all", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -121,7 +121,7 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() {
})
ginkgo.It("should allow Ingress with rules", func() {
host := "foo"
host := fooHost
ing := framework.NewSingleIngress("not-catch-all", "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)

View file

@ -95,6 +95,5 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-service-external-name", f
WithHeader("Host", externalhost).
Expect().
StatusRange(httpexpect.Status5xx)
})
})

View file

@ -44,12 +44,14 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-sync-events", func() {
return strings.Contains(server, fmt.Sprintf("server_name %v", host))
})
//nolint:goconst //string interpolation
events, err := f.KubeClientSet.CoreV1().Events(ing.Namespace).List(context.TODO(), metav1.ListOptions{FieldSelector: "reason=Sync,involvedObject.name=" + host})
assert.Nil(ginkgo.GinkgoT(), err, "listing events")
assert.NotEmpty(ginkgo.GinkgoT(), events.Items, "got events")
})
//nolint:dupl // Ignore dupl errors for similar test case
ginkgo.It("should create sync events", func() {
host := "disable-sync-events-false"
f.NewEchoDeployment(framework.WithDeploymentReplicas(1))
@ -77,6 +79,7 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-sync-events", func() {
assert.NotEmpty(ginkgo.GinkgoT(), events.Items, "got events")
})
//nolint:dupl // Ignore dupl errors for similar test case
ginkgo.It("should not create sync events", func() {
host := "disable-sync-events-true"
f.NewEchoDeployment(framework.WithDeploymentReplicas(1))
@ -103,5 +106,4 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-sync-events", func() {
assert.Empty(ginkgo.GinkgoT(), events.Items, "got events")
})
})

View file

@ -47,6 +47,7 @@ var _ = framework.DescribeSetting("enable-real-ip", func() {
f.WaitForNginxServer(host,
func(server string) bool {
//nolint:goconst //already a const
return strings.Contains(server, "server_name "+host) &&
!strings.Contains(server, "proxy_set_header X-Forwarded-Proto $full_x_forwarded_proto;")
})

View file

@ -26,6 +26,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const forwardedHeadersHost = "forwarded-headers"
var _ = framework.DescribeSetting("use-forwarded-headers", func() {
f := framework.NewDefaultFramework("forwarded-headers")
@ -37,7 +39,7 @@ var _ = framework.DescribeSetting("use-forwarded-headers", func() {
})
ginkgo.It("should trust X-Forwarded headers when setting is true", func() {
host := "forwarded-headers"
host := forwardedHeadersHost
f.UpdateNginxConfigMapData(setting, "true")
@ -89,7 +91,7 @@ var _ = framework.DescribeSetting("use-forwarded-headers", func() {
})
ginkgo.It("should not trust X-Forwarded headers when setting is false", func() {
host := "forwarded-headers"
host := forwardedHeadersHost
f.UpdateNginxConfigMapData(setting, "false")

View file

@ -19,11 +19,10 @@ package settings
import (
"context"
"fmt"
"net/http"
"path/filepath"
"strings"
"net/http"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
@ -55,7 +54,7 @@ var _ = framework.DescribeSetting("Geoip2", func() {
})
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller deployment flags")
filename := fmt.Sprintf("/etc/nginx/geoip/%s.mmdb", edition)
filename := fmt.Sprintf("/etc/ingress-controller/geoip/%s.mmdb", edition)
exec, err := f.ExecIngressPod(fmt.Sprintf(`sh -c "mkdir -p '%s' && wget -O '%s' '%s' 2>&1"`, filepath.Dir(filename), filename, testdataURL))
framework.Logf(exec)
assert.Nil(ginkgo.GinkgoT(), err, fmt.Sprintln("error downloading test geoip2 db", filename))
@ -70,10 +69,17 @@ var _ = framework.DescribeSetting("Geoip2", func() {
ginkgo.It("should only allow requests from specific countries", func() {
ginkgo.Skip("GeoIP test are temporarily disabled")
f.UpdateNginxConfigMapData("use-geoip2", "true")
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "true",
"use-geoip2": "true",
})
defer func() {
f.SetNginxConfigMapData(map[string]string{
"allow-snippet-annotations": "false",
})
}()
httpSnippetAllowingOnlyAustralia :=
`map $geoip2_city_country_code $blocked_country {
httpSnippetAllowingOnlyAustralia := `map $geoip2_city_country_code $blocked_country {
default 1;
AU 0;
}`
@ -85,8 +91,7 @@ var _ = framework.DescribeSetting("Geoip2", func() {
return strings.Contains(cfg, "map $geoip2_city_country_code $blocked_country")
})
configSnippet :=
`if ($blocked_country) {
configSnippet := `if ($blocked_country) {
return 403;
}`
@ -119,4 +124,52 @@ var _ = framework.DescribeSetting("Geoip2", func() {
Expect().
Status(http.StatusOK)
})
ginkgo.It("should up and running nginx controller using autoreload flag", func() {
edition := "GeoLite2-Country"
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--maxmind-edition-ids="+edition)
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1().Deployments(f.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
return err
})
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller deployment flags")
filename := fmt.Sprintf("/etc/ingress-controller/geoip/%s.mmdb", edition)
exec, err := f.ExecIngressPod(fmt.Sprintf(`sh -c "mkdir -p '%s' && wget -O '%s' '%s' 2>&1"`, filepath.Dir(filename), filename, testdataURL))
framework.Logf(exec)
assert.Nil(ginkgo.GinkgoT(), err, fmt.Sprintln("error downloading test geoip2 db", filename))
f.SetNginxConfigMapData(map[string]string{
"use-geoip2": "true",
"geoip2-autoreload-in-minutes": "5",
})
// Check Configmap Autoreload Patterns
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, fmt.Sprintf("geoip2 %s", filename)) &&
strings.Contains(cfg, "auto_reload 5m;")
},
)
// Check if Nginx could up, running and routing with auto_reload configs
host := "ping.com"
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, host) &&
strings.Contains(server, "location /")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
})
})

View file

@ -31,6 +31,11 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
disable = "false"
noAuthLocaltionSetting = "no-auth-locations"
)
var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
f := framework.NewDefaultFramework(
"global-external-auth",
@ -46,7 +51,7 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
fooPath := "/foo"
barPath := "/bar"
noAuthSetting := "no-auth-locations"
noAuthSetting := noAuthLocaltionSetting
noAuthLocations := barPath
enableGlobalExternalAuthAnnotation := "nginx.ingress.kubernetes.io/enable-global-auth"
@ -56,7 +61,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.Context("when global external authentication is configured", func() {
ginkgo.BeforeEach(func() {
globalExternalAuthURL := fmt.Sprintf("http://%s.%s.svc.cluster.local:80/status/401", framework.HTTPBunService, f.Namespace)
@ -85,7 +89,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It("should return status code 401 when request any protected service", func() {
ginkgo.By("Sending a request to protected service /foo")
f.HTTPTestClient().
GET(fooPath).
@ -102,7 +105,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It("should return status code 200 when request whitelisted (via no-auth-locations) service and 401 when request protected service", func() {
ginkgo.By("Adding a no-auth-locations for /bar to configMap")
f.UpdateNginxConfigMapData(noAuthSetting, noAuthLocations)
f.WaitForNginxServer(host,
@ -126,10 +128,9 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It("should return status code 200 when request whitelisted (via ingress annotation) service and 401 when request protected service", func() {
ginkgo.By("Adding an ingress rule for /bar with annotation enable-global-auth = false")
err := framework.UpdateIngress(f.KubeClientSet, f.Namespace, "bar-ingress", func(ingress *networking.Ingress) error {
ingress.ObjectMeta.Annotations[enableGlobalExternalAuthAnnotation] = "false"
ingress.ObjectMeta.Annotations[enableGlobalExternalAuthAnnotation] = disable
return nil
})
assert.Nil(ginkgo.GinkgoT(), err)
@ -155,9 +156,8 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It("should still return status code 200 after auth backend is deleted using cache", func() {
globalExternalAuthCacheKeySetting := "global-auth-cache-key"
globalExternalAuthCacheKey := "foo"
globalExternalAuthCacheKey := fooHost
globalExternalAuthCacheDurationSetting := "global-auth-cache-duration"
globalExternalAuthCacheDuration := "200 201 401 30m"
globalExternalAuthURL := fmt.Sprintf("http://%s.%s.svc.cluster.local:80/status/200", framework.HTTPBunService, f.Namespace)
@ -197,7 +197,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It(`should proxy_method method when global-auth-method is configured`, func() {
globalExternalAuthMethodSetting := "global-auth-method"
globalExternalAuthMethod := "GET"
@ -210,7 +209,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It(`should add custom error page when global-auth-signin url is configured`, func() {
globalExternalAuthSigninSetting := "global-auth-signin"
globalExternalAuthSignin := "http://foo.com/global-error-page"
@ -223,7 +221,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It(`should add auth headers when global-auth-response-headers is configured`, func() {
globalExternalAuthResponseHeadersSetting := "global-auth-response-headers"
globalExternalAuthResponseHeaders := "Foo, Bar"
@ -237,7 +234,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
})
ginkgo.It(`should set request-redirect when global-auth-request-redirect is configured`, func() {
globalExternalAuthRequestRedirectSetting := "global-auth-request-redirect"
globalExternalAuthRequestRedirect := "Foo-Redirect"
@ -260,7 +256,6 @@ var _ = framework.DescribeSetting("[Security] global-auth-url", func() {
return strings.Contains(server, globalExternalAuthSnippet)
})
})
})
ginkgo.Context("cookie set by external authentication server", func() {
@ -322,7 +317,6 @@ http {
f.WaitForNginxServer(host, func(server string) bool {
return strings.Contains(server, "server_name "+host)
})
})
ginkgo.It("user retains cookie by default", func() {

View file

@ -31,7 +31,6 @@ var _ = framework.IngressNginxDescribe("global-options", func() {
ginkgo.It("should have worker_rlimit_nofile option", func() {
f.WaitForNginxConfiguration(func(server string) bool {
return strings.Contains(server, fmt.Sprintf("worker_rlimit_nofile %d;", rlimitMaxNumFiles()-1024))
})
})

110
test/e2e/settings/grpc.go Normal file
View file

@ -0,0 +1,110 @@
/*
Copyright 2024 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 settings
import (
"context"
"crypto/tls"
"fmt"
"strings"
pb "github.com/moul/pb/grpcbin/go-grpc"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
const echoHost = "echo"
var _ = framework.DescribeSetting("GRPC", func() {
f := framework.NewDefaultFramework("grpc-buffersize", framework.WithHTTPBunEnabled())
ginkgo.It("should set the correct GRPC Buffer Size", func() {
f.SetNginxConfigMapData(map[string]string{
"grpc-buffer-size-kb": "8",
})
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "grpc_buffer_size 8k")
})
f.NewGRPCBinDeployment()
host := echoHost
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "grpcbin-test",
Namespace: f.Namespace,
},
Spec: corev1.ServiceSpec{
ExternalName: fmt.Sprintf("grpcbin.%v.svc.cluster.local", f.Namespace),
Type: corev1.ServiceTypeExternalName,
Ports: []corev1.ServicePort{
{
Name: host,
Port: 9000,
TargetPort: intstr.FromInt(9000),
Protocol: "TCP",
},
},
},
}
f.EnsureService(svc)
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
}
ing := framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, "grpcbin-test", 9000, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "grpc_pass grpc://upstream_balancer;")
})
conn, err := grpc.Dial(f.GetNginxIP()+":443",
grpc.WithTransportCredentials(
credentials.NewTLS(&tls.Config{
ServerName: echoHost,
InsecureSkipVerify: true, //nolint:gosec // Ignore certificate validation in testing
}),
),
)
assert.Nil(ginkgo.GinkgoT(), err, "error creating a connection")
defer conn.Close()
client := pb.NewGRPCBinClient(conn)
ctx := context.Background()
res, err := client.HeadersUnary(ctx, &pb.EmptyMessage{})
assert.Nil(ginkgo.GinkgoT(), err)
metadata := res.GetMetadata()
assert.Equal(ginkgo.GinkgoT(), metadata["content-type"].Values[0], "application/grpc")
assert.Equal(ginkgo.GinkgoT(), metadata[":authority"].Values[0], host)
})
})

View file

@ -18,6 +18,7 @@ package settings
import (
"fmt"
"net/http"
"strings"
"github.com/onsi/ginkgo/v2"
@ -29,11 +30,27 @@ import (
var _ = framework.DescribeSetting("gzip", func() {
f := framework.NewDefaultFramework("gzip")
host := "gzip"
ginkgo.BeforeEach(func() {
f.NewHttpbunDeployment()
f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBunService, 80, nil))
})
ginkgo.It("should be disabled by default", func() {
f.WaitForNginxConfiguration(
func(cfg string) bool {
return !strings.Contains(cfg, "gzip on;")
})
},
)
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentEncoding()
})
ginkgo.It("should be enabled with default settings", func() {
@ -50,7 +67,16 @@ var _ = framework.DescribeSetting("gzip", func() {
strings.Contains(cfg, fmt.Sprintf("gzip_types %s;", defaultCfg.GzipTypes)) &&
strings.Contains(cfg, "gzip_proxied any;") &&
strings.Contains(cfg, "gzip_vary on;")
})
},
)
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentEncoding("gzip")
})
ginkgo.It("should set gzip_comp_level to 4", func() {
@ -61,7 +87,16 @@ var _ = framework.DescribeSetting("gzip", func() {
func(cfg string) bool {
return strings.Contains(cfg, "gzip on;") &&
strings.Contains(cfg, "gzip_comp_level 4;")
})
},
)
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentEncoding("gzip")
})
ginkgo.It("should set gzip_disable to msie6", func() {
@ -72,28 +107,87 @@ var _ = framework.DescribeSetting("gzip", func() {
func(cfg string) bool {
return strings.Contains(cfg, "gzip on;") &&
strings.Contains(cfg, `gzip_disable "msie6";`)
})
},
)
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
WithHeader("User-Agent", "Mozilla/4.8 [en] (Windows NT 5.1; U)").
Expect().
Status(http.StatusOK).
ContentEncoding("gzip")
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
WithHeader("User-Agent", "Mozilla/45.0 (compatible; MSIE 6.0; Windows NT 5.1)").
Expect().
Status(http.StatusOK).
ContentEncoding()
})
ginkgo.It("should set gzip_min_length to 100", func() {
f.UpdateNginxConfigMapData("use-gzip", "true")
f.UpdateNginxConfigMapData("gzip-min-length", "100")
f.UpdateNginxConfigMapData("gzip-types", "application/octet-stream")
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "gzip on;") &&
strings.Contains(cfg, "gzip_min_length 100;")
})
strings.Contains(cfg, "gzip_min_length 100;") &&
strings.Contains(cfg, "gzip_types application/octet-stream;")
},
)
f.HTTPTestClient().
GET("/bytes/99").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentType("application/octet-stream").
ContentEncoding()
f.HTTPTestClient().
GET("/bytes/100").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentType("application/octet-stream").
ContentEncoding("gzip")
})
ginkgo.It("should set gzip_types to application/javascript", func() {
ginkgo.It("should set gzip_types to text/html", func() {
f.UpdateNginxConfigMapData("use-gzip", "true")
f.UpdateNginxConfigMapData("gzip-types", "application/javascript")
f.UpdateNginxConfigMapData("gzip-types", "text/html")
f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "gzip on;") &&
strings.Contains(cfg, "gzip_types application/javascript;")
})
strings.Contains(cfg, "gzip_types text/html;")
},
)
f.HTTPTestClient().
GET("/xml").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentType("application/xml").
ContentEncoding()
f.HTTPTestClient().
GET("/html").
WithHeader("Host", host).
WithHeader("Accept-Encoding", "gzip").
Expect().
Status(http.StatusOK).
ContentType("text/html").
ContentEncoding("gzip")
})
})

View file

@ -36,7 +36,6 @@ var _ = framework.DescribeSetting("hash size", func() {
})
ginkgo.Context("Check server names hash size", func() {
ginkgo.It("should set server_names_hash_bucket_size", func() {
f.UpdateNginxConfigMapData("server-name-hash-bucket-size", "512")
@ -52,11 +51,9 @@ var _ = framework.DescribeSetting("hash size", func() {
return strings.Contains(server, "server_names_hash_max_size 4096;")
})
})
})
ginkgo.Context("Check proxy header hash size", func() {
ginkgo.It("should set proxy-headers-hash-bucket-size", func() {
f.UpdateNginxConfigMapData("proxy-headers-hash-bucket-size", "512")
@ -72,11 +69,9 @@ var _ = framework.DescribeSetting("hash size", func() {
return strings.Contains(server, "proxy_headers_hash_max_size 4096;")
})
})
})
ginkgo.Context("Check the variable hash size", func() {
ginkgo.It("should set variables-hash-bucket-size", func() {
f.UpdateNginxConfigMapData("variables-hash-bucket-size", "512")
@ -92,11 +87,9 @@ var _ = framework.DescribeSetting("hash size", func() {
return strings.Contains(server, "variables_hash_max_size 512;")
})
})
})
ginkgo.Context("Check the map hash size", func() {
ginkgo.It("should set vmap-hash-bucket-size", func() {
f.UpdateNginxConfigMapData("map-hash-bucket-size", "512")
@ -104,7 +97,5 @@ var _ = framework.DescribeSetting("hash size", func() {
return strings.Contains(server, "map_hash_bucket_size 512;")
})
})
})
})

View file

@ -36,6 +36,8 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
const barHost = "bar"
var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
f := framework.NewDefaultFramework("ingress-class")
@ -66,7 +68,7 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
ginkgo.Context("With default ingress class config", func() {
ginkgo.It("should ignore Ingress with a different class annotation", func() {
invalidHost := "foo"
invalidHost := fooHost
annotations := map[string]string{
ingressclass.IngressKey: "testclass",
}
@ -75,7 +77,7 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHost := "bar"
validHost := barHost
annotationClass := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
@ -385,7 +387,6 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusOK)
})
})
ginkgo.Context("With specific ingress-class flags", func() {
@ -411,13 +412,13 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
})
ginkgo.It("should ignore Ingress with no class and accept the correctly configured Ingresses", func() {
invalidHost := "bar"
invalidHost := barHost
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHost := "foo"
validHost := fooHost
annotations := map[string]string{
ingressclass.IngressKey: "testclass",
}
@ -455,7 +456,6 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusNotFound)
})
})
ginkgo.Context("With watch-ingress-without-class flag", func() {
@ -480,13 +480,13 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
})
ginkgo.It("should watch Ingress with no class and ignore ingress with a different class", func() {
validHost := "bar"
validHost := barHost
ing := framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
invalidHost := "foo"
invalidHost := fooHost
annotations := map[string]string{
ingressclass.IngressKey: "testclass123",
}
@ -511,7 +511,6 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusNotFound)
})
})
ginkgo.Context("With ingress-class-by-name flag", func() {
@ -579,11 +578,9 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusNotFound)
})
})
ginkgo.Context("Without IngressClass Cluster scoped Permission", func() {
ginkgo.BeforeEach(func() {
icname := fmt.Sprintf("ic-%s", f.Namespace)
@ -629,8 +626,7 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
})
ginkgo.It("should watch Ingress with correct annotation", func() {
validHost := "foo"
validHost := fooHost
annotations := map[string]string{
ingressclass.IngressKey: "testclass",
}
@ -650,7 +646,6 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
})
ginkgo.It("should ignore Ingress with only IngressClassName", func() {
invalidHost := "noclassforyou"
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, nil)
@ -666,6 +661,5 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusNotFound)
})
})
})

View file

@ -21,6 +21,7 @@ import (
"strings"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -50,7 +51,6 @@ var _ = framework.DescribeSetting("keep-alive keep-alive-requests", func() {
f.WaitForNginxConfiguration(func(server string) bool {
return strings.Contains(server, `keepalive_requests 200;`)
})
})
})
@ -59,7 +59,8 @@ var _ = framework.DescribeSetting("keep-alive keep-alive-requests", func() {
f.UpdateNginxConfigMapData("upstream-keepalive-connections", "128")
f.WaitForNginxConfiguration(func(server string) bool {
match, _ := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive 128;`, server)
match, err := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive 128;`, server)
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error matching the upstream keepalive time")
return match
})
})
@ -68,7 +69,8 @@ var _ = framework.DescribeSetting("keep-alive keep-alive-requests", func() {
f.UpdateNginxConfigMapData("upstream-keepalive-timeout", "120")
f.WaitForNginxConfiguration(func(server string) bool {
match, _ := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_timeout\s*120s;`, server)
match, err := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_timeout\s*120s;`, server)
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error matching the upstream keepalive time")
return match
})
})
@ -77,7 +79,8 @@ var _ = framework.DescribeSetting("keep-alive keep-alive-requests", func() {
f.UpdateNginxConfigMapData("upstream-keepalive-time", "75s")
f.WaitForNginxConfiguration(func(server string) bool {
match, _ := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_time\s*75s;`, server)
match, err := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_time\s*75s;`, server)
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error matching the upstream keepalive time")
return match
})
})
@ -86,7 +89,8 @@ var _ = framework.DescribeSetting("keep-alive keep-alive-requests", func() {
f.UpdateNginxConfigMapData("upstream-keepalive-requests", "200")
f.WaitForNginxConfiguration(func(server string) bool {
match, _ := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_requests\s*200;`, server)
match, err := regexp.MatchString(`upstream\supstream_balancer\s\{[\s\S]*keepalive_requests\s*200;`, server)
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error matching the upstream keepalive time")
return match
})
})

View file

@ -28,7 +28,6 @@ import (
)
var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", func() {
host := "forwarded-headers"
f := framework.NewDefaultFramework("forwarded-port-headers", framework.WithHTTPBunEnabled())
@ -44,7 +43,6 @@ var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", fun
ginkgo.Context("with a plain HTTP ingress", func() {
ginkgo.It("should set X-Forwarded-Port headers accordingly when listening on a non-default HTTP port", func() {
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -64,9 +62,7 @@ var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", fun
})
ginkgo.Context("with a TLS enabled ingress", func() {
ginkgo.It("should set X-Forwarded-Port header to 443", func() {
ing := framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
@ -94,7 +90,6 @@ var _ = framework.IngressNginxDescribe("[Flag] custom HTTP and HTTPS ports", fun
})
ginkgo.Context("when external authentication is configured", func() {
ginkgo.It("should set the X-Forwarded-Port header to 443", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", f.HTTPBunIP),

View file

@ -36,7 +36,6 @@ var _ = framework.DescribeSetting("log-format-*", func() {
})
ginkgo.Context("Check log-format-escape-json and log-format-escape-none", func() {
ginkgo.It("should not configure log-format escape by default", func() {
f.WaitForNginxConfiguration(
func(cfg string) bool {
@ -78,7 +77,6 @@ var _ = framework.DescribeSetting("log-format-*", func() {
})
ginkgo.Context("Check log-format-upstream with log-format-escape-json and log-format-escape-none", func() {
ginkgo.It("log-format-escape-json enabled", func() {
f.SetNginxConfigMapData(map[string]string{
"log-format-escape-json": "true",

View file

@ -29,12 +29,12 @@ import (
var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector", func() {
f := framework.NewDefaultFramework("namespace-selector")
notMatchedHost, matchedHost := "bar", "foo"
notMatchedHost, matchedHost := barHost, fooHost
var notMatchedNs string
var matchedNs string
// create a test namespace, under which create an ingress and backend deployment
prepareTestIngress := func(baseName string, host string, labels map[string]string) string {
prepareTestIngress := func(host string, labels map[string]string) string {
ns, err := framework.CreateKubeNamespaceWithLabel(f.BaseName, labels, f.KubeClientSet)
assert.Nil(ginkgo.GinkgoT(), err, "creating test namespace")
f.NewEchoDeployment(framework.WithDeploymentNamespace(ns))
@ -49,8 +49,8 @@ var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector",
}
ginkgo.BeforeEach(func() {
notMatchedNs = prepareTestIngress(notMatchedHost, notMatchedHost, nil) // create namespace without label "foo=bar"
matchedNs = prepareTestIngress(matchedHost, matchedHost, map[string]string{"foo": "bar"})
notMatchedNs = prepareTestIngress(notMatchedHost, nil) // create namespace without label "foo=bar"
matchedNs = prepareTestIngress(matchedHost, map[string]string{fooHost: barHost})
})
ginkgo.AfterEach(func() {
@ -59,9 +59,7 @@ var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector",
})
ginkgo.Context("With specific watch-namespace-selector flags", func() {
ginkgo.It("should ingore Ingress of namespace without label foo=bar and accept those of namespace with label foo=bar", func() {
ginkgo.It("should ignore Ingress of namespace without label foo=bar and accept those of namespace with label foo=bar", func() {
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name bar") &&
strings.Contains(cfg, "server_name foo")
@ -86,7 +84,7 @@ var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector",
if ns.Labels == nil {
ns.Labels = make(map[string]string)
}
ns.Labels["foo"] = "bar"
ns.Labels[fooHost] = barHost
_, err = f.KubeClientSet.CoreV1().Namespaces().Update(context.TODO(), ns, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "labeling not matched namespace")
@ -97,7 +95,7 @@ var _ = framework.IngressNginxDescribeSerial("[Flag] watch namespace selector",
if ing.Labels == nil {
ing.Labels = make(map[string]string)
}
ing.Labels["foo"] = "bar"
ing.Labels[fooHost] = barHost
_, err = f.KubeClientSet.NetworkingV1().Ingresses(notMatchedNs).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress")

View file

@ -18,12 +18,12 @@ package settings
import (
"fmt"
"golang.org/x/crypto/bcrypt"
"net/http"
"strings"
"github.com/onsi/ginkgo/v2"
"github.com/stretchr/testify/assert"
"golang.org/x/crypto/bcrypt"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -34,7 +34,7 @@ var _ = framework.DescribeSetting("[Security] no-auth-locations", func() {
f := framework.NewDefaultFramework("no-auth-locations")
setting := "no-auth-locations"
username := "foo"
username := fooHost
password := "bar"
secretName := "test-secret"
host := "no-auth-locations"
@ -100,7 +100,8 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: namespace,
Annotations: map[string]string{"nginx.ingress.kubernetes.io/auth-type": "basic",
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/auth-type": "basic",
"nginx.ingress.kubernetes.io/auth-secret": secretName,
"nginx.ingress.kubernetes.io/auth-realm": "test auth",
},
@ -147,7 +148,6 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s
}
func buildSecret(username, password, name, namespace string) *corev1.Secret {
//out, err := exec.Command("openssl", "passwd", "-crypt", password).CombinedOutput()
out, err := bcrypt.GenerateFromPassword([]byte(password), 14)
assert.Nil(ginkgo.GinkgoT(), err, "creating password")

View file

@ -44,6 +44,5 @@ var _ = framework.DescribeSetting("Add no tls redirect locations", func() {
f.WaitForNginxConfiguration(func(server string) bool {
return strings.Contains(server, "force_no_ssl_redirect = true,")
})
})
})

Some files were not shown because too many files have changed in this diff Show more