Release v1 (#7470)

* Drop v1beta1 from ingress nginx (#7156)

* Drop v1beta1 from ingress nginx

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Fix intorstr logic in controller

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* fixing admission

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* more intorstr fixing

* correct template rendering

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Fix e2e tests for v1 api

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Fix gofmt errors

* This is finally working...almost there...

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Re-add removed validation of AdmissionReview

* Prepare for v1.0.0-alpha.1 release

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Update changelog and matrix table for v1.0.0-alpha.1 (#7274)

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* add docs for syslog feature (#7219)

* Fix link to e2e-tests.md in developer-guide (#7201)

* Use ENV expansion for namespace in args (#7146)

Update the DaemonSet namespace references to use the `POD_NAMESPACE` environment variable in the same way that the Deployment does.

* chart: using Helm builtin capabilities check (#7190)

Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>

* Update proper default value for HTTP2MaxConcurrentStreams in Docs (#6944)

It should be 128 as documented in https://github.com/kubernetes/ingress-nginx/blob/master/internal/ingress/controller/config/config.go#L780

* Fix MaxWorkerOpenFiles calculation on high cores nodes (#7107)

* Fix MaxWorkerOpenFiles calculation on high cores nodes

* Add e2e test for rlimit_nofile

* Fix doc for max-worker-open-files

* ingress/tcp: add additional error logging on failed (#7208)

* Add file containing stable release (#7313)

* Handle named (non-numeric) ports correctly (#7311)

Signed-off-by: Carlos Panato <ctadeu@gmail.com>

* Updated v1beta1 to v1 as its deprecated (#7308)

* remove mercurial from build (#7031)

* Retry to download maxmind DB if it fails (#7242)

* Retry to download maxmind DB if it fails.

Signed-off-by: Sergey Shakuto <sshakuto@infoblox.com>

* Add retries count arg, move retry logic into DownloadGeoLite2DB function

Signed-off-by: Sergey Shakuto <sshakuto@infoblox.com>

* Reorder parameters in DownloadGeoLite2DB

Signed-off-by: Sergey Shakuto <sshakuto@infoblox.com>

* Remove hardcoded value

Signed-off-by: Sergey Shakuto <sshakuto@infoblox.com>

* Release v1.0.0-alpha.1

* Add changelog for v1.0.0-alpha.2

* controller: ignore non-service backends (#7332)

* controller: ignore non-service backends

Signed-off-by: Carlos Panato <ctadeu@gmail.com>

* update per feedback

Signed-off-by: Carlos Panato <ctadeu@gmail.com>

* fix: allow scope/tcp/udp configmap namespace to altered (#7161)

* Lower webhook timeout for digital ocean (#7319)

* Lower webhook timeout for digital ocean

* Set Digital Ocean value controller.admissionWebhooks.timeoutSeconds to 29

* update OWNERS and aliases files (#7365) (#7366)

Signed-off-by: Carlos Panato <ctadeu@gmail.com>

* Downgrade Lua modules for s390x (#7355)

Downgrade Lua modules to last known working version.

* Fix IngressClass logic for newer releases (#7341)

* Fix IngressClass logic for newer releases

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Change e2e tests for the new IngressClass presence

* Fix chart and admission tests

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Fix helm chart test

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@gmail.com>

* Fix reviews

* Remove ingressclass code from admission

* update tag to v1.0.0-beta.1

* update readme and changelog for v1.0.0-beta.1

* Release v1.0.0-beta.1 - helm and manifests (#7422)

* Change the order of annotation just to trigger a new helm release (#7425)

* [cherry-pick] Add dev-v1 branch into helm releaser (#7428)

* Add dev-v1 branch into helm releaser (#7424)

* chore: add link for artifacthub.io/prerelease annotations

Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>

Co-authored-by: Ricardo Katz <rikatz@users.noreply.github.com>

* k8s job ci pipeline for dev-v1 br v1.22.0 (#7453)

* k8s job ci pipeline for dev-v1 br v1.22.0

Signed-off-by: Neha Lohia <nehapithadiya444@gmail.com>

* k8s job ci pipeline for dev-v1 br v1.21.2

Signed-off-by: Neha Lohia <nehapithadiya444@gmail.com>

* remove v1.21.1 version

Signed-off-by: Neha Lohia <nehapithadiya444@gmail.com>

* Add controller.watchIngressWithoutClass config option (#7459)

Signed-off-by: Akshit Grover <akshit.grover2016@gmail.com>

* Release new helm chart with certgen fixed (#7478)

* Update go version, modules and remove ioutil

* Release new helm chart with certgen fixed

* changed appversion, chartversion, TAG, image (#7490)

* Fix CI conflict

* Fix CI conflict

* Fix build.sh from rebase process

* Fix controller_test post rebase

Co-authored-by: Tianhao Guo <rggth09@gmail.com>
Co-authored-by: Ray <61553+rctay@users.noreply.github.com>
Co-authored-by: Bill Cassidy <cassid4@gmail.com>
Co-authored-by: Jintao Zhang <tao12345666333@163.com>
Co-authored-by: Sathish Ramani <rsathishx87@gmail.com>
Co-authored-by: Mansur Marvanov <nanorobocop@gmail.com>
Co-authored-by: Matt1360 <568198+Matt1360@users.noreply.github.com>
Co-authored-by: Carlos Tadeu Panato Junior <ctadeu@gmail.com>
Co-authored-by: Kundan Kumar <kundan.kumar@india.nec.com>
Co-authored-by: Tom Hayward <thayward@infoblox.com>
Co-authored-by: Sergey Shakuto <sshakuto@infoblox.com>
Co-authored-by: Tore <tore.lonoy@gmail.com>
Co-authored-by: Bouke Versteegh <info@boukeversteegh.nl>
Co-authored-by: Shahid <shahid@us.ibm.com>
Co-authored-by: James Strong <strong.james.e@gmail.com>
Co-authored-by: Long Wu Yuan <longwuyuan@gmail.com>
Co-authored-by: Jintao Zhang <zhangjintao9020@gmail.com>
Co-authored-by: Neha Lohia <nehapithadiya444@gmail.com>
Co-authored-by: Akshit Grover <akshit.grover2016@gmail.com>
This commit is contained in:
Ricardo Katz 2021-08-21 17:42:00 -03:00 committed by GitHub
parent f3c50698d9
commit 90c79689c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
226 changed files with 3518 additions and 1940 deletions

View file

@ -14,7 +14,9 @@ controller:
https-port: "1443"
# e2e tests do not require information about ingress status
update-status: "false"
ingressClassResource:
# We will create and remove each IC/ClusterRole/ClusterRoleBinding per test so there's no conflict
enabled: false
scope:
enabled: true

View file

@ -56,14 +56,14 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
ginkgo.By("rejects ingress when memcached is not configured")
_, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), ing, metav1.CreateOptions{})
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), ing, metav1.CreateOptions{})
assert.NotNil(ginkgo.GinkgoT(), err, "creating ingress with global throttle annotations when memcached is not configured")
ginkgo.By("accepts ingress when memcached is not configured")
f.UpdateNginxConfigMapData("global-rate-limit-memcached-host", "memc.default.svc.cluster.local")
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), ing, metav1.CreateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), ing, metav1.CreateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "creating ingress with global throttle annotations when memcached is configured")
f.WaitForNginxServer(host,
@ -76,7 +76,7 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
host := "admission-test"
firstIngress := framework.NewSingleIngress("first-ingress", "/", host, f.Namespace, framework.EchoService, 80, nil)
_, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
f.WaitForNginxServer(host,
@ -85,7 +85,7 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
})
secondIngress := framework.NewSingleIngress("second-ingress", "/", host, f.Namespace, framework.EchoService, 80, nil)
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), secondIngress, metav1.CreateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), secondIngress, metav1.CreateOptions{})
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with the same host and path should return an error")
})
@ -93,7 +93,7 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
host := "admission-test"
firstIngress := framework.NewSingleIngress("first-ingress", "/", host, f.Namespace, framework.EchoService, 80, nil)
_, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "creating ingress")
f.WaitForNginxServer(host,
@ -106,7 +106,7 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
"nginx.ingress.kubernetes.io/canary-by-header": "CanaryByHeader",
}
secondIngress := framework.NewSingleIngress("second-ingress", "/", host, f.Namespace, framework.SlowEchoService, 80, canaryAnnotations)
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), secondIngress, metav1.CreateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), secondIngress, metav1.CreateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "creating an ingress with the same host and path should not return an error using a canary annotation")
})
@ -117,40 +117,11 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
"nginx.ingress.kubernetes.io/configuration-snippet": "something invalid",
}
firstIngress := framework.NewSingleIngress("first-ingress", "/", host, f.Namespace, framework.EchoService, 80, annotations)
_, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Create(context.TODO(), firstIngress, metav1.CreateOptions{})
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid configuration should return an error")
})
ginkgo.It("should not return an error the ingress definition uses the deprecated extensions package", func() {
err := createIngress(f.Namespace, validIngress)
assert.Nil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "extensions")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", "extensions").
Expect().
Status(http.StatusOK)
})
ginkgo.It("should return an error if the ingress definition uses the deprecated extensions package and invalid annotations", func() {
err := createIngress(f.Namespace, invalidIngress)
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), "extensions", metav1.GetOptions{})
if !apierrors.IsNotFound(err) {
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid configuration should return an error")
}
})
ginkgo.It("should not return an error if the Ingress V1 definition is valid", func() {
if !f.IsIngressV1Ready {
ginkgo.Skip("Test requires Kubernetes v1.19 or higher")
}
ginkgo.It("should not return an error if the Ingress V1 definition is valid with Ingress Class", func() {
err := createIngress(f.Namespace, validV1Ingress)
assert.Nil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
@ -165,15 +136,26 @@ var _ = framework.IngressNginxDescribe("[Serial] admission controller", func() {
Status(http.StatusOK)
})
ginkgo.It("should return an error if the Ingress V1 definition contains invalid annotations", func() {
if !f.IsIngressV1Ready {
ginkgo.Skip("Test requires Kubernetes v1.19 or higher")
}
ginkgo.It("should not return an error if the Ingress V1 definition is valid with IngressClass annotation", func() {
err := createIngress(f.Namespace, validV1IngressAnnotation)
assert.Nil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "extensions-class")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", "extensions-class").
Expect().
Status(http.StatusOK)
})
ginkgo.It("should return an error if the Ingress V1 definition contains invalid annotations", func() {
err := createIngress(f.Namespace, invalidV1Ingress)
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress using kubectl")
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), "extensions", metav1.GetOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), "extensions-invalid", metav1.GetOptions{})
if !apierrors.IsNotFound(err) {
assert.NotNil(ginkgo.GinkgoT(), err, "creating an ingress with invalid configuration should return an error")
}
@ -191,49 +173,13 @@ func uninstallChart(f *framework.Framework) error {
}
const (
validIngress = `
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: extensions
spec:
rules:
- host: extensions
http:
paths:
- path: /
backend:
serviceName: echo
servicePort: 80
---
`
invalidIngress = `
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: extensions
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
invalid directive
spec:
rules:
- host: extensions
http:
paths:
- path: /
backend:
serviceName: echo
servicePort: 80
---
`
validV1Ingress = `
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: extensions
spec:
ingressClassName: nginx
rules:
- host: extensions
http:
@ -246,6 +192,28 @@ spec:
port:
number: 80
---
`
validV1IngressAnnotation = `
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: extensions-class
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: extensions-class
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo
port:
number: 80
---
`
@ -253,13 +221,14 @@ spec:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: extensions
name: extensions-invalid
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
invalid directive
spec:
ingressClassName: nginx
rules:
- host: extensions
- host: extensions-invalid
http:
paths:
- path: /

View file

@ -25,9 +25,8 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -84,7 +83,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
ing.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/session-cookie-name"] = "OTHERCOOKIENAME"
_, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
_, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress")
framework.Sleep()
@ -119,6 +118,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
})
ginkgo.It("does not set the path to / on the generated cookie if there's more than one rule referring to the same backend", func() {
pathtype := networking.PathTypePrefix
host := "morethanonerule.foo.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
@ -131,6 +131,7 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
Annotations: annotations,
},
Spec: networking.IngressSpec{
IngressClassName: &f.IngressClass,
Rules: []networking.IngressRule{
{
Host: host,
@ -138,17 +139,27 @@ var _ = framework.DescribeAnnotation("affinity session-cookie-name", func() {
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/something",
Path: "/something",
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
{
Path: "/somewhereelse",
Path: "/somewhereelse",
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},

View file

@ -30,7 +30,7 @@ import (
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"

View file

@ -22,9 +22,7 @@ import (
"strings"
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -32,7 +30,7 @@ const (
canaryService = "echo-canary"
)
var _ = framework.DescribeAnnotation("canary-*", func() {
var _ = framework.DescribeAnnotation("canary", func() {
f := framework.NewDefaultFramework("canary")
ginkgo.BeforeEach(func() {
@ -327,15 +325,25 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
f.Namespace, canaryService, 80, canaryAnnotations)
f.EnsureIngress(canaryIng)
err := framework.UpdateIngress(f.KubeClientSet, f.Namespace, canaryIngName,
func(ingress *networking.Ingress) error {
ingress.ObjectMeta.Annotations = map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
"nginx.ingress.kubernetes.io/canary-by-header": "CanaryByHeader2",
}
return nil
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name foo")
})
newAnnotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
"nginx.ingress.kubernetes.io/canary-by-header": "CanaryByHeader2",
}
modIng := framework.NewSingleIngress(canaryIngName, "/", host,
f.Namespace, canaryService, 80, newAnnotations)
f.UpdateIngress(modIng)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name foo")
})
assert.Nil(ginkgo.GinkgoT(), err)
ginkgo.By("routing requests destined for the mainline ingress to the mainline upstream")
f.HTTPTestClient().
@ -707,6 +715,11 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
f.Namespace, canaryService, 80, canaryAnnotations)
f.EnsureIngress(canaryIng)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name foo")
})
ginkgo.By("returning requests from the mainline only when weight is equal to 0")
f.HTTPTestClient().
GET("/").
@ -719,15 +732,20 @@ var _ = framework.DescribeAnnotation("canary-*", func() {
ginkgo.By("returning requests from the canary only when weight is equal to 100")
err := framework.UpdateIngress(f.KubeClientSet, f.Namespace, canaryIngName,
func(ingress *networking.Ingress) error {
ingress.ObjectMeta.Annotations = map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
"nginx.ingress.kubernetes.io/canary-weight": "100",
}
return nil
newAnnotations := map[string]string{
"nginx.ingress.kubernetes.io/canary": "true",
"nginx.ingress.kubernetes.io/canary-weight": "100",
}
modIng := framework.NewSingleIngress(canaryIngName, "/", host,
f.Namespace, canaryService, 80, newAnnotations)
f.UpdateIngress(modIng)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name foo")
})
assert.Nil(ginkgo.GinkgoT(), err)
f.HTTPTestClient().
GET("/").

View file

@ -22,7 +22,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)

View file

@ -26,7 +26,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"

View file

@ -22,9 +22,8 @@ import (
"github.com/onsi/ginkgo"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -48,9 +47,14 @@ var _ = framework.IngressNginxDescribe("[Default Backend] change default setting
Annotations: annotations,
},
Spec: networking.IngressSpec{
Backend: &networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
IngressClassName: &f.IngressClass,
DefaultBackend: &networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
Rules: []networking.IngressRule{
{

View file

@ -29,12 +29,11 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
@ -62,15 +61,15 @@ var (
type Framework struct {
BaseName string
IsIngressV1Ready bool
IsIngressV1Beta1Ready bool
IsIngressV1Ready bool
// A Kubernetes and Service Catalog client
KubeClientSet kubernetes.Interface
KubeConfig *restclient.Config
APIExtensionsClientSet apiextcs.Interface
Namespace string
Namespace string
IngressClass string
pod *corev1.Pod
}
@ -104,12 +103,15 @@ func (f *Framework) BeforeEach() {
f.KubeClientSet, err = kubernetes.NewForConfig(f.KubeConfig)
assert.Nil(ginkgo.GinkgoT(), err, "creating a kubernetes client")
_, f.IsIngressV1Beta1Ready, f.IsIngressV1Ready = k8s.NetworkingIngressAvailable(f.KubeClientSet)
f.IsIngressV1Ready = k8s.NetworkingIngressAvailable(f.KubeClientSet)
}
f.Namespace, err = CreateKubeNamespace(f.BaseName, f.KubeClientSet)
assert.Nil(ginkgo.GinkgoT(), err, "creating namespace")
f.IngressClass, err = CreateIngressClass(f.Namespace, f.KubeClientSet)
assert.Nil(ginkgo.GinkgoT(), err, "creating IngressClass")
err = f.newIngressController(f.Namespace, f.BaseName)
assert.Nil(ginkgo.GinkgoT(), err, "deploying the ingress controller")
@ -129,6 +131,14 @@ func (f *Framework) AfterEach() {
}()
}(f.KubeClientSet, f.Namespace)
defer func(kubeClient kubernetes.Interface, ingressclass string) {
go func() {
defer ginkgo.GinkgoRecover()
err := deleteIngressClass(kubeClient, ingressclass)
assert.Nil(ginkgo.GinkgoT(), err, "deleting IngressClass")
}()
}(f.KubeClientSet, f.IngressClass)
if !ginkgo.CurrentGinkgoTestDescription().Failed {
return
}
@ -542,7 +552,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 {
ingress, err := kubeClientSet.NetworkingV1beta1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
ingress, err := kubeClientSet.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return err
}
@ -559,7 +569,7 @@ func UpdateIngress(kubeClientSet kubernetes.Interface, namespace string, name st
return err
}
_, err = kubeClientSet.NetworkingV1beta1().Ingresses(namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
_, err = kubeClientSet.NetworkingV1().Ingresses(namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
if err != nil {
return err
}
@ -580,7 +590,9 @@ func NewSingleIngress(name, path, host, ns, service string, port int, annotation
// NewSingleIngressWithMultiplePaths creates a simple ingress rule with multiple paths
func NewSingleIngressWithMultiplePaths(name string, paths []string, host, ns, service string, port int, annotations map[string]string) *networking.Ingress {
pathtype := networking.PathTypePrefix
spec := networking.IngressSpec{
IngressClassName: GetIngressClassName(ns),
Rules: []networking.IngressRule{
{
Host: host,
@ -593,10 +605,15 @@ func NewSingleIngressWithMultiplePaths(name string, paths []string, host, ns, se
for _, path := range paths {
spec.Rules[0].IngressRuleValue.HTTP.Paths = append(spec.Rules[0].IngressRuleValue.HTTP.Paths, networking.HTTPIngressPath{
Path: path,
Path: path,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: service,
ServicePort: intstr.FromInt(port),
Service: &networking.IngressServiceBackend{
Name: service,
Port: networking.ServiceBackendPort{
Number: int32(port),
},
},
},
})
}
@ -605,17 +622,24 @@ func NewSingleIngressWithMultiplePaths(name string, paths []string, host, ns, se
}
func newSingleIngressWithRules(name, path, host, ns, service string, port int, annotations map[string]string, tlsHosts []string) *networking.Ingress {
pathtype := networking.PathTypePrefix
spec := networking.IngressSpec{
IngressClassName: GetIngressClassName(ns),
Rules: []networking.IngressRule{
{
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: path,
Path: path,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: service,
ServicePort: intstr.FromInt(port),
Service: &networking.IngressServiceBackend{
Name: service,
Port: networking.ServiceBackendPort{
Number: int32(port),
},
},
},
},
},
@ -644,10 +668,16 @@ func newSingleIngressWithRules(name, path, host, ns, service string, port int, a
// NewSingleIngressWithBackendAndRules creates an ingress with both a default backend and a rule
func NewSingleIngressWithBackendAndRules(name, path, host, ns, defaultService string, defaultPort int, service string, port int, annotations map[string]string) *networking.Ingress {
pathtype := networking.PathTypePrefix
spec := networking.IngressSpec{
Backend: &networking.IngressBackend{
ServiceName: defaultService,
ServicePort: intstr.FromInt(defaultPort),
IngressClassName: GetIngressClassName(ns),
DefaultBackend: &networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: defaultService,
Port: networking.ServiceBackendPort{
Number: int32(defaultPort),
},
},
},
Rules: []networking.IngressRule{
{
@ -656,10 +686,15 @@ func NewSingleIngressWithBackendAndRules(name, path, host, ns, defaultService st
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: path,
Path: path,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: service,
ServicePort: intstr.FromInt(port),
Service: &networking.IngressServiceBackend{
Name: service,
Port: networking.ServiceBackendPort{
Number: int32(port),
},
},
},
},
},
@ -675,9 +710,14 @@ func NewSingleIngressWithBackendAndRules(name, path, host, ns, defaultService st
// NewSingleCatchAllIngress creates a simple ingress with a catch-all backend
func NewSingleCatchAllIngress(name, ns, service string, port int, annotations map[string]string) *networking.Ingress {
spec := networking.IngressSpec{
Backend: &networking.IngressBackend{
ServiceName: service,
ServicePort: intstr.FromInt(port),
IngressClassName: GetIngressClassName(ns),
DefaultBackend: &networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: service,
Port: networking.ServiceBackendPort{
Number: int32(port),
},
},
},
}
return newSingleIngress(name, ns, annotations, spec)

View file

@ -28,7 +28,7 @@ import (
api "k8s.io/api/core/v1"
core "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilnet "k8s.io/apimachinery/pkg/util/net"
@ -63,7 +63,7 @@ func (f *Framework) EnsureConfigMap(configMap *api.ConfigMap) (*api.ConfigMap, e
// 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 {
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
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")
return ing
@ -334,7 +334,7 @@ func createIngressWithRetries(c kubernetes.Interface, namespace string, obj *net
return fmt.Errorf("Object provided to create is empty")
}
createFunc := func() (bool, error) {
_, err := c.NetworkingV1beta1().Ingresses(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
_, err := c.NetworkingV1().Ingresses(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
if err == nil {
return true, nil
}
@ -355,7 +355,7 @@ func updateIngressWithRetries(c kubernetes.Interface, namespace string, obj *net
return fmt.Errorf("Object provided to create is empty")
}
updateFunc := func() (bool, error) {
_, err := c.NetworkingV1beta1().Ingresses(namespace).Update(context.TODO(), obj, metav1.UpdateOptions{})
_, err := c.NetworkingV1().Ingresses(namespace).Update(context.TODO(), obj, metav1.UpdateOptions{})
if err == nil {
return true, nil
}

View file

@ -24,6 +24,8 @@ import (
"github.com/onsi/ginkgo"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
@ -31,6 +33,8 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/ingress-nginx/internal/k8s"
)
const (
@ -117,6 +121,93 @@ func deleteKubeNamespace(c kubernetes.Interface, namespace string) error {
})
}
// CreateIngressClass creates a new IngressClass related to a test/namespace and also
// the required ClusterRole/ClusterRoleBinding
func CreateIngressClass(namespace string, c kubernetes.Interface) (string, error) {
icname := fmt.Sprintf("ic-%s", namespace)
var err error
ic, err := c.NetworkingV1().IngressClasses().
Create(context.TODO(), &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: icname,
},
Spec: networkingv1.IngressClassSpec{
Controller: k8s.IngressNGINXController,
},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass %s: %v", icname, err)
}
_, err = c.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: icname},
Rules: []rbacv1.PolicyRule{{
APIGroups: []string{"networking.k8s.io"},
Resources: []string{"ingressclasses"},
Verbs: []string{"get", "list", "watch"},
}},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass ClusterRole %s: %v", icname, err)
}
_, err = c.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: icname,
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: icname,
},
Subjects: []rbacv1.Subject{
{
APIGroup: "",
Kind: "ServiceAccount",
Namespace: namespace,
Name: "nginx-ingress",
},
},
}, metav1.CreateOptions{})
if err != nil {
return "", fmt.Errorf("Unexpected error creating IngressClass ClusterRoleBinding %s: %v", icname, err)
}
return ic.Name, nil
}
//deleteIngressClass deletes an IngressClass and its related ClusterRole* objects
func deleteIngressClass(c kubernetes.Interface, ingressclass string) error {
var err error
grace := int64(0)
pb := metav1.DeletePropagationBackground
deleteOptions := metav1.DeleteOptions{
GracePeriodSeconds: &grace,
PropagationPolicy: &pb,
}
err = c.NetworkingV1().IngressClasses().Delete(context.TODO(), ingressclass, deleteOptions)
if err != nil {
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)
}
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 nil
}
//GetIngressClassName returns the default IngressClassName given a namespace
func GetIngressClassName(namespace string) *string {
icname := fmt.Sprintf("ic-%s", namespace)
return &icname
}
// WaitForKubeNamespaceNotExist waits until a namespaces is not present in the cluster
func WaitForKubeNamespaceNotExist(c kubernetes.Interface, namespace string) error {
return wait.Poll(Poll, DefaultTimeout, namespaceNotExist(c, namespace))
@ -223,7 +314,7 @@ func WaitForNoIngressInNamespace(c kubernetes.Interface, namespace, name string)
func noIngressInNamespace(c kubernetes.Interface, namespace, name string) wait.ConditionFunc {
return func() (bool, error) {
ing, err := c.NetworkingV1beta1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
ing, err := c.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return true, nil
}
@ -245,7 +336,7 @@ func WaitForIngressInNamespace(c kubernetes.Interface, namespace, name string) e
func ingressInNamespace(c kubernetes.Interface, namespace, name string) wait.ConditionFunc {
return func() (bool, error) {
ing, err := c.NetworkingV1beta1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
ing, err := c.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return false, nil
}

View file

@ -22,15 +22,14 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/util/intstr"
networking "k8s.io/api/networking/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("single ingress - multiple hosts", func() {
f := framework.NewDefaultFramework("simh")
pathprefix := networking.PathTypePrefix
ginkgo.BeforeEach(func() {
f.NewEchoDeploymentWithNameAndReplicas("first-service", 1)
f.NewEchoDeploymentWithNameAndReplicas("second-service", 1)
@ -43,16 +42,21 @@ var _ = framework.IngressNginxDescribe("single ingress - multiple hosts", func()
ing := framework.NewSingleIngress("simh", "/", "first.host", f.Namespace, "first-service", 80, annotations)
ing.Spec.Rules = append(ing.Spec.Rules, networkingv1beta1.IngressRule{
ing.Spec.Rules = append(ing.Spec.Rules, networking.IngressRule{
Host: "second.host",
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{
IngressRuleValue: networking.IngressRuleValue{
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
Backend: networkingv1beta1.IngressBackend{
ServiceName: "second-service",
ServicePort: intstr.FromInt(80),
Path: "/",
PathType: &pathprefix,
Backend: networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: "second-service",
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},

View file

@ -22,7 +22,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -35,9 +35,6 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
})
ginkgo.It("should choose exact location for /exact", func() {
if !f.IsIngressV1Beta1Ready {
ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
}
host := "exact.path"
@ -45,7 +42,7 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";`,
}
var exactPathType = networkingv1beta1.PathTypeExact
var 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

@ -23,7 +23,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -34,12 +34,9 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefi
f.NewEchoDeployment()
})
var exactPathType = networkingv1beta1.PathTypeExact
var exactPathType = networking.PathTypeExact
ginkgo.It("should choose the correct location", func() {
if !f.IsIngressV1Beta1Ready {
ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
}
host := "mixed.path"

View file

@ -22,9 +22,8 @@ import (
"strings"
"github.com/onsi/ginkgo"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -62,9 +61,14 @@ var _ = framework.IngressNginxDescribe("[Ingress] definition without host", func
Namespace: f.Namespace,
},
Spec: networking.IngressSpec{
Backend: &networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
IngressClassName: &f.IngressClass,
DefaultBackend: &networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
Rules: []networking.IngressRule{
{

View file

@ -103,7 +103,7 @@ func checkIngress(hostname string, f *framework.Framework) {
}
func deleteIngress(hostname string, f *framework.Framework) {
err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Delete(context.TODO(), hostname, metav1.DeleteOptions{})
err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Delete(context.TODO(), hostname, metav1.DeleteOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error deleting ingress")
}

View file

@ -28,7 +28,7 @@ import (
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
@ -45,7 +45,7 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
ginkgo.It("picks up the certificate when we add TLS spec to existing ingress", func() {
ensureIngress(f, host, framework.EchoService)
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Spec.TLS = []networking.IngressTLS{
{
@ -59,7 +59,7 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
ing.Namespace)
assert.Nil(ginkgo.GinkgoT(), err)
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
time.Sleep(waitForLuaSync)
@ -147,7 +147,7 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
})
ginkgo.It("picks up the updated certificate without reloading", func() {
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ensureHTTPSRequest(f, fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.GetURL(framework.HTTPS)), host, host)
@ -183,7 +183,7 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
})
ginkgo.It("falls back to using default certificate when secret gets deleted without reloading", func() {
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ensureHTTPSRequest(f, fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.GetURL(framework.HTTPS)), host, host)
@ -217,11 +217,11 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
ginkgo.It("picks up a non-certificate only change", func() {
newHost := "foo2.com"
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Spec.Rules[0].Host = newHost
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
time.Sleep(waitForLuaSync)
@ -231,11 +231,11 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic certificates", func() {
})
ginkgo.It("removes HTTPS configuration when we delete TLS spec", func() {
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Spec.TLS = []networking.IngressTLS{}
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
time.Sleep(waitForLuaSync)

View file

@ -26,7 +26,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
@ -172,11 +172,11 @@ var _ = framework.IngressNginxDescribe("[Lua] dynamic configuration", func() {
return true
})
ingress, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), "foo.com", metav1.GetOptions{})
ingress, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), "foo.com", metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingress.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/load-balance"] = "round_robin"
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
f.HTTPTestClient().

View file

@ -36,6 +36,8 @@ cleanup() {
trap cleanup EXIT
export KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-ingress-nginx-dev}
if ! command -v kind --version &> /dev/null; then
echo "kind is not installed. Use the package manager or visit the official site https://kind.sigs.k8s.io/"
exit 1
@ -43,14 +45,17 @@ fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-ingress-nginx-dev}
# 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
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.20.2@sha256:8f7ea6e7642c0da54f04a7ee10431549c0257315b3a634f6ef2fecaaedb19bab}
export K8S_VERSION=${K8S_VERSION:-v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6}
kind create cluster \
--verbosity=${KIND_LOG_LEVEL} \
@ -61,8 +66,23 @@ if [ "${SKIP_CLUSTER_CREATION:-false}" = "false" ]; then
echo "Kubernetes cluster:"
kubectl get nodes -o wide
fi
if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then
if ! command -v ginkgo &> /dev/null; then
go get github.com/onsi/ginkgo/ginkgo@v1.16.4
fi
echo "[dev-env] building image"
make -C ${DIR}/../../ clean-image build image
fi
KIND_WORKERS=$(kind get nodes --name="${KIND_CLUSTER_NAME}" | awk '{printf (NR>1?",":"") $1}')
echo "[dev-env] copying docker images to cluster..."
kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes=${KIND_WORKERS} ${REGISTRY}/controller:${TAG}
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

View file

@ -58,7 +58,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.20.2@sha256:8f7ea6e7642c0da54f04a7ee10431549c0257315b3a634f6ef2fecaaedb19bab}
export K8S_VERSION=${K8S_VERSION:-v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6}
kind create cluster \
--verbosity=${KIND_LOG_LEVEL} \
@ -73,7 +73,7 @@ fi
if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then
if ! command -v ginkgo &> /dev/null; then
go get github.com/onsi/ginkgo/ginkgo
go get github.com/onsi/ginkgo/ginkgo@v1.16.4
fi
echo "[dev-env] building image"

View file

@ -22,13 +22,14 @@ import (
"github.com/onsi/ginkgo"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"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")
@ -79,6 +80,7 @@ func buildIngressWithNonexistentService(host, namespace, path string) *networkin
Namespace: namespace,
},
Spec: networking.IngressSpec{
IngressClassName: framework.GetIngressClassName(namespace),
Rules: []networking.IngressRule{
{
Host: host,
@ -86,10 +88,15 @@ func buildIngressWithNonexistentService(host, namespace, path string) *networkin
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: path,
Path: path,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: backendService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: backendService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},
@ -109,6 +116,7 @@ func buildIngressWithUnavailableServiceEndpoints(host, namespace, path string) (
Namespace: namespace,
},
Spec: networking.IngressSpec{
IngressClassName: framework.GetIngressClassName(namespace),
Rules: []networking.IngressRule{
{
Host: host,
@ -116,10 +124,15 @@ func buildIngressWithUnavailableServiceEndpoints(host, namespace, path string) (
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: path,
Path: path,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: backendService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: backendService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},

View file

@ -25,8 +25,8 @@ import (
"github.com/gavv/httpexpect/v2"
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
core "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
@ -42,7 +42,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
host := "echo"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -73,7 +73,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
ginkgo.It("should return 200 for service type=ExternalName without a port defined", func() {
host := "echo"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -107,7 +107,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
ginkgo.It("should return 200 for service type=ExternalName with a port defined", func() {
host := "echo"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -148,7 +148,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"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -179,7 +179,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
ginkgo.It("should return 200 for service type=ExternalName using a port name", func() {
host := "echo"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -203,7 +203,15 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
"nginx.ingress.kubernetes.io/upstream-vhost": "httpbin.org",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBinService, 80, annotations)
ing.Spec.Rules[0].HTTP.Paths[0].Backend.ServicePort = intstr.FromString(host)
namedBackend := networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: framework.HTTPBinService,
Port: networking.ServiceBackendPort{
Name: host,
},
},
}
ing.Spec.Rules[0].HTTP.Paths[0].Backend = namedBackend
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
@ -221,7 +229,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"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -252,7 +260,7 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
ginkgo.It("should update the external name after a service update", func() {
host := "echo"
svc := &core.Service{
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: framework.HTTPBinService,
Namespace: f.Namespace,
@ -276,7 +284,15 @@ var _ = framework.IngressNginxDescribe("[Service] Type ExternalName", func() {
"nginx.ingress.kubernetes.io/upstream-vhost": "httpbin.org",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.HTTPBinService, 80, annotations)
ing.Spec.Rules[0].HTTP.Paths[0].Backend.ServicePort = intstr.FromString(host)
namedBackend := networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: framework.HTTPBinService,
Port: networking.ServiceBackendPort{
Name: host,
},
},
}
ing.Spec.Rules[0].HTTP.Paths[0].Backend = namedBackend
f.EnsureIngress(ing)
f.WaitForNginxServer(host,

View file

@ -24,9 +24,8 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -98,9 +97,13 @@ var _ = framework.IngressNginxDescribe("[Flag] disable-catch-all", func() {
err := framework.UpdateIngress(f.KubeClientSet, f.Namespace, host, func(ingress *networking.Ingress) error {
ingress.Spec.Rules = nil
ingress.Spec.Backend = &networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
ingress.Spec.DefaultBackend = &networking.IngressBackend{
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
}
return nil
})

2
test/e2e/settings/global_external_auth.go Executable file → Normal file
View file

@ -25,7 +25,7 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)

View file

@ -0,0 +1,58 @@
/*
Copyright 2020 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 (
"fmt"
"strings"
"syscall"
"github.com/onsi/ginkgo"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("global-options", func() {
f := framework.NewDefaultFramework("global-options")
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))
})
})
ginkgo.It("should have worker_rlimit_nofile option and be independent on amount of worker processes", func() {
f.SetNginxConfigMapData(map[string]string{
"worker-processes": "11",
})
f.WaitForNginxConfiguration(func(server string) bool {
return strings.Contains(server, "worker_processes 11;") &&
strings.Contains(server, fmt.Sprintf("worker_rlimit_nofile %d;", rlimitMaxNumFiles()-1024))
})
})
})
// rlimitMaxNumFiles returns hard limit for RLIMIT_NOFILE
func rlimitMaxNumFiles() int {
var rLimit syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
if err != nil {
return 0
}
return int(rLimit.Max)
}

View file

@ -18,7 +18,6 @@ package settings
import (
"context"
"fmt"
"net/http"
"strings"
"sync"
@ -26,13 +25,11 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
networking "k8s.io/api/networking/v1beta1"
rbacv1 "k8s.io/api/rbac/v1"
networkingv1 "k8s.io/api/networking/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/internal/ingress/annotations/class"
"k8s.io/ingress-nginx/internal/k8s"
"k8s.io/ingress-nginx/internal/ingress/controller/ingressclass"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -41,43 +38,20 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
var doOnce sync.Once
testIngressClassName := "test-new-ingress-class"
otherIngressClassName := "test-new-ingress-class"
otherController := "k8s.io/other-class"
ginkgo.BeforeEach(func() {
f.NewEchoDeploymentWithReplicas(1)
doOnce.Do(func() {
f.KubeClientSet.RbacV1().ClusterRoles().Create(context.TODO(), &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: "ingress-nginx-class"},
Rules: []rbacv1.PolicyRule{{
APIGroups: []string{"networking.k8s.io"},
Resources: []string{"ingressclasses"},
Verbs: []string{"get", "list", "watch"},
}},
}, metav1.CreateOptions{})
f.KubeClientSet.RbacV1().ClusterRoleBindings().Create(context.TODO(), &rbacv1.ClusterRoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-nginx-class",
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: "ingress-nginx-class",
},
}, metav1.CreateOptions{})
if !f.IsIngressV1Beta1Ready {
return
}
_, err := f.KubeClientSet.NetworkingV1beta1().IngressClasses().
Create(context.TODO(), &networking.IngressClass{
_, err := f.KubeClientSet.NetworkingV1().IngressClasses().
Create(context.TODO(), &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{
Name: testIngressClassName,
Name: otherIngressClassName,
},
Spec: networking.IngressClassSpec{
Controller: k8s.IngressNGINXController,
Spec: networkingv1.IngressClassSpec{
Controller: otherController,
},
}, metav1.CreateOptions{})
@ -87,17 +61,23 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
})
})
ginkgo.Context("Without a specific ingress-class", func() {
ginkgo.It("should ignore Ingress with class", func() {
ginkgo.Context("With default ingress class config", func() {
ginkgo.It("should ignore Ingress with a different class annotation", func() {
invalidHost := "foo"
annotations := map[string]string{
class.IngressKey: "testclass",
ingressclass.IngressKey: "testclass",
}
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, annotations)
// We should drop the ingressClassName here as we just want to rely on the annotation in this test
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHost := "bar"
ing = framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, nil)
annotationClass := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
ing = framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, annotationClass)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
@ -117,14 +97,300 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Expect().
Status(http.StatusOK)
})
ginkgo.It("should ignore Ingress with different controller class", func() {
invalidHost := "foo-1"
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = &otherIngressClassName
f.EnsureIngress(ing)
validHost := "bar-1"
ing = framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name foo-1") &&
strings.Contains(cfg, "server_name bar-1")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", invalidHost).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHost).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should accept both Ingresses with default IngressClassName and IngressClass annotation", func() {
validHostAnnotation := "foo-ok"
annotationClass := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
ing := framework.NewSingleIngress(validHostAnnotation, "/", validHostAnnotation, f.Namespace, framework.EchoService, 80, annotationClass)
// We need to drop the Class here as we just want the annotation
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHostClass := "bar-ok"
ing = framework.NewSingleIngress(validHostClass, "/", validHostClass, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name foo-ok") &&
strings.Contains(cfg, "server_name bar-ok")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHostAnnotation).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHostClass).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should ignore Ingress without IngressClass configuration", func() {
invalidHost := "foo-invalid"
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHostClass := "bar-valid"
ing = framework.NewSingleIngress(validHostClass, "/", validHostClass, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name foo-invalid") &&
strings.Contains(cfg, "server_name bar-valid")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", invalidHost).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHostClass).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should delete Ingress when class is removed", func() {
hostAnnotation := "foo-annotation"
annotations := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
ing := framework.NewSingleIngress(hostAnnotation, "/", hostAnnotation, f.Namespace, framework.EchoService, 80, annotations)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
hostClass := "foo-class"
ing = framework.NewSingleIngress(hostClass, "/", hostClass, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name foo-annotation") &&
strings.Contains(cfg, "server_name foo-class")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostAnnotation).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostClass).
Expect().
Status(http.StatusOK)
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostAnnotation, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
delete(ing.Annotations, ingressclass.IngressKey)
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ing.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingWithClass, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostClass, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingWithClass.Spec.IngressClassName = nil
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ingWithClass.Namespace).Update(context.TODO(), ingWithClass, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name foo-annotation") &&
!strings.Contains(cfg, "server_name foo-class")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostAnnotation).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostClass).
Expect().
Status(http.StatusNotFound)
})
ginkgo.It("should serve Ingress when class is added", func() {
hostNoAnnotation := "foo-no-annotation"
ing := framework.NewSingleIngress(hostNoAnnotation, "/", hostNoAnnotation, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
hostNoClass := "foo-no-class"
ing = framework.NewSingleIngress(hostNoClass, "/", hostNoClass, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name foo-no-nnotation") &&
!strings.Contains(cfg, "server_name foo-no-class")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostNoAnnotation).
Expect().
Status(http.StatusNotFound)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostNoClass).
Expect().
Status(http.StatusNotFound)
ing, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostNoAnnotation, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
annotation := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
ing.Annotations = annotation
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ing.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingWithClass, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostNoClass, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingWithClass.Spec.IngressClassName = framework.GetIngressClassName(f.Namespace)
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ingWithClass.Namespace).Update(context.TODO(), ingWithClass, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name foo-no-annotation") &&
strings.Contains(cfg, "server_name foo-no-class")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostNoAnnotation).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostNoClass).
Expect().
Status(http.StatusOK)
})
ginkgo.It("should serve Ingress when class is updated between annotation and ingressClassName", func() {
hostAnnotation2class := "foo-annotation2class"
annotationClass := map[string]string{
ingressclass.IngressKey: ingressclass.DefaultAnnotationValue,
}
ing := framework.NewSingleIngress(hostAnnotation2class, "/", hostAnnotation2class, f.Namespace, framework.EchoService, 80, annotationClass)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
hostClass2Annotation := "foo-class2annotation"
ing = framework.NewSingleIngress(hostClass2Annotation, "/", hostClass2Annotation, f.Namespace, framework.EchoService, 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name foo-annotation2class") &&
strings.Contains(cfg, "server_name foo-class2annotation")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostAnnotation2class).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostClass2Annotation).
Expect().
Status(http.StatusOK)
ingAnnotation2Class, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostAnnotation2class, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
delete(ingAnnotation2Class.Annotations, ingressclass.IngressKey)
ingAnnotation2Class.Spec.IngressClassName = framework.GetIngressClassName(ingAnnotation2Class.Namespace)
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ingAnnotation2Class.Namespace).Update(context.TODO(), ingAnnotation2Class, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingClass2Annotation, err := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), hostClass2Annotation, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ingClass2Annotation.Spec.IngressClassName = nil
ingClass2Annotation.Annotations = annotationClass
_, err = f.KubeClientSet.NetworkingV1().Ingresses(ingClass2Annotation.Namespace).Update(context.TODO(), ingClass2Annotation, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name foo-annotation2class") &&
strings.Contains(cfg, "server_name foo-class2annotation")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostAnnotation2class).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", hostClass2Annotation).
Expect().
Status(http.StatusOK)
})
})
ginkgo.Context("With a specific ingress-class", func() {
ginkgo.Context("With specific ingress-class flags", func() {
ginkgo.BeforeEach(func() {
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
args := []string{}
for _, v := range deployment.Spec.Template.Spec.Containers[0].Args {
if strings.Contains(v, "--ingress-class") {
if strings.Contains(v, "--ingress-class") && strings.Contains(v, "--controller-class") {
continue
}
@ -132,6 +398,7 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
}
args = append(args, "--ingress-class=testclass")
args = append(args, "--controller-class=k8s.io/other-class")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1().Deployments(f.Namespace).Update(context.TODO(), deployment, metav1.UpdateOptions{})
@ -140,25 +407,93 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
assert.Nil(ginkgo.GinkgoT(), err, "updating ingress controller deployment flags")
})
ginkgo.It("should ignore Ingress with no class", func() {
ginkgo.It("should ignore Ingress with no class and accept the correctly configured Ingresses", func() {
invalidHost := "bar"
ing := framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
validHost := "foo"
annotations := map[string]string{
class.IngressKey: "testclass",
ingressclass.IngressKey: "testclass",
}
ing = framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, annotations)
// Delete the IngressClass as we want just the annotation here
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
f.WaitForNginxServer(validHost, func(cfg string) bool {
return strings.Contains(cfg, "server_name foo")
})
validHostClass := "foobar123"
ing = framework.NewSingleIngress(validHostClass, "/", validHostClass, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = &otherIngressClassName
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name bar")
return !strings.Contains(cfg, "server_name bar") &&
strings.Contains(cfg, "server_name foo") &&
strings.Contains(cfg, "server_name foobar123")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHost).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", validHostClass).
Expect().
Status(http.StatusOK)
f.HTTPTestClient().
GET("/").
WithHeader("Host", invalidHost).
Expect().
Status(http.StatusNotFound)
})
})
ginkgo.Context("With watch-ingress-without-class flag", func() {
ginkgo.BeforeEach(func() {
err := f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
args := []string{}
for _, v := range deployment.Spec.Template.Spec.Containers[0].Args {
if strings.Contains(v, "--watch-ingress-without-class") && strings.Contains(v, "--controller-class") {
continue
}
args = append(args, v)
}
args = append(args, "--watch-ingress-without-class")
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")
})
ginkgo.It("should watch Ingress with no class and ignore ingress with a different class", func() {
validHost := "bar"
ing := framework.NewSingleIngress(validHost, "/", validHost, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
invalidHost := "foo"
annotations := map[string]string{
ingressclass.IngressKey: "testclass123",
}
ing = framework.NewSingleIngress(invalidHost, "/", invalidHost, f.Namespace, framework.EchoService, 80, annotations)
ing.Spec.IngressClassName = nil
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, "server_name bar") &&
!strings.Contains(cfg, "server_name foo")
})
f.HTTPTestClient().
@ -174,168 +509,5 @@ var _ = framework.IngressNginxDescribe("[Flag] ingress-class", func() {
Status(http.StatusNotFound)
})
ginkgo.It("should delete Ingress when class is removed", func() {
host := "foo"
annotations := map[string]string{
class.IngressKey: "testclass",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host, func(cfg string) bool {
return strings.Contains(cfg, "server_name foo")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
ing, err := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
delete(ing.Annotations, class.IngressKey)
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(ing.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, "server_name foo")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
})
ginkgo.It("check scenarios for IngressClass and ingress.class annotation", func() {
if !f.IsIngressV1Beta1Ready {
ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
}
pod := f.GetIngressNGINXPod()
crb, err := f.KubeClientSet.RbacV1().ClusterRoleBindings().Get(context.Background(), "ingress-nginx-class", metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "searching cluster role binding")
// add service of current namespace
crb.Subjects = append(crb.Subjects, rbacv1.Subject{
APIGroup: "",
Kind: "ServiceAccount",
Name: pod.Spec.ServiceAccountName,
Namespace: f.Namespace,
})
_, err = f.KubeClientSet.RbacV1().ClusterRoleBindings().Update(context.Background(), crb, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "searching cluster role binding")
err = f.UpdateIngressControllerDeployment(func(deployment *appsv1.Deployment) error {
args := []string{}
for _, v := range deployment.Spec.Template.Spec.Containers[0].Args {
if strings.Contains(v, "--ingress-class") {
continue
}
args = append(args, v)
}
args = append(args, fmt.Sprintf("--ingress-class=%v", testIngressClassName))
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")
host := "ingress.class"
ginkgo.By("only having IngressClassName")
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)
ing.Spec.IngressClassName = &testIngressClassName
f.EnsureIngress(ing)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
ginkgo.By("only having ingress.class annotation")
ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Annotations = map[string]string{
class.IngressKey: testIngressClassName,
}
ing.Spec.IngressClassName = nil
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
f.WaitForNginxConfiguration(func(cfg string) bool {
return strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
})
framework.Sleep()
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusOK)
ginkgo.By("having an invalid ingress.class annotation and no IngressClassName")
ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Annotations = map[string]string{
class.IngressKey: "invalid",
}
ing.Spec.IngressClassName = nil
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
ginkgo.By("not having ingress.class annotation and invalid IngressClassName")
ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
ing.Annotations = map[string]string{}
invalidClassName := "invalidclass"
ing.Spec.IngressClassName = &invalidClassName
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Update(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
f.WaitForNginxConfiguration(func(cfg string) bool {
return !strings.Contains(cfg, fmt.Sprintf("server_name %v", host))
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusNotFound)
})
})

View file

@ -25,9 +25,8 @@ import (
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -96,6 +95,7 @@ var _ = framework.DescribeSetting("[Security] no-auth-locations", func() {
})
func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName string) *networking.Ingress {
pathtype := networking.PathTypePrefix
return &networking.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
@ -106,6 +106,7 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s
},
},
Spec: networking.IngressSpec{
IngressClassName: framework.GetIngressClassName(namespace),
Rules: []networking.IngressRule{
{
Host: host,
@ -113,17 +114,27 @@ func buildBasicAuthIngressWithSecondPath(host, namespace, secretName, pathName s
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
Path: "/",
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
{
Path: pathName,
Path: pathName,
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},

View file

@ -21,13 +21,13 @@ import (
"github.com/onsi/ginkgo"
networking "k8s.io/api/networking/v1beta1"
networking "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeSetting("server-tokens", func() {
pathtype := networking.PathTypePrefix
f := framework.NewDefaultFramework("server-tokens")
serverTokens := "server-tokens"
@ -57,6 +57,7 @@ var _ = framework.DescribeSetting("server-tokens", func() {
Annotations: map[string]string{},
},
Spec: networking.IngressSpec{
IngressClassName: &f.IngressClass,
Rules: []networking.IngressRule{
{
Host: serverTokens,
@ -64,10 +65,15 @@ var _ = framework.DescribeSetting("server-tokens", func() {
HTTP: &networking.HTTPIngressRuleValue{
Paths: []networking.HTTPIngressPath{
{
Path: "/",
Path: "/",
PathType: &pathtype,
Backend: networking.IngressBackend{
ServiceName: framework.EchoService,
ServicePort: intstr.FromInt(80),
Service: &networking.IngressServiceBackend{
Name: framework.EchoService,
Port: networking.ServiceBackendPort{
Number: int32(80),
},
},
},
},
},

View file

@ -84,17 +84,17 @@ var _ = framework.IngressNginxDescribe("[Status] status update", func() {
err = cmd.Process.Kill()
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error terminating kubectl proxy")
ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error getting %s/%v Ingress", f.Namespace, host)
ing.Status.LoadBalancer.Ingress = []apiv1.LoadBalancerIngress{}
_, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).UpdateStatus(context.TODO(), ing, metav1.UpdateOptions{})
_, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).UpdateStatus(context.TODO(), ing, metav1.UpdateOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error cleaning Ingress status")
framework.Sleep(10 * time.Second)
err = f.KubeClientSet.CoreV1().
ConfigMaps(f.Namespace).
Delete(context.TODO(), "ingress-controller-leader-nginx", metav1.DeleteOptions{})
Delete(context.TODO(), "ingress-controller-leader", metav1.DeleteOptions{})
assert.Nil(ginkgo.GinkgoT(), err, "unexpected error deleting leader election configmap")
_, cmd, err = f.KubectlProxy(port)
@ -109,7 +109,7 @@ var _ = framework.IngressNginxDescribe("[Status] status update", func() {
}()
err = wait.Poll(5*time.Second, 4*time.Minute, func() (done bool, err error) {
ing, err = f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
ing, err = f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace).Get(context.TODO(), host, metav1.GetOptions{})
if err != nil {
return false, nil
}

View file

@ -73,6 +73,10 @@ controller:
periodSeconds: 1
service:
type: NodePort
electionID: ingress-controller-leader
ingressClassResource:
# We will create and remove each IC/ClusterRole/ClusterRoleBinding per test so there's no conflict
enabled: false
extraArgs:
tcp-services-configmap: $NAMESPACE/tcp-services
# e2e tests do not require information about ingress status