Merge branch 'master' into xff

This commit is contained in:
Dario Nieuwenhuis 2018-08-16 18:15:14 +02:00 committed by GitHub
commit b5bcb93a4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1532 changed files with 65966 additions and 34963 deletions

View file

@ -21,7 +21,6 @@
"bodySize": "1m",
"enableDynamicTlsRecords": true,
"enableSpdy": false,
"enableVtsStatus": true,
"errorLogLevel": "notice",
"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/plain text/x-component",
"hsts": true,
@ -46,7 +45,6 @@
"useGzip": true,
"useHttp2": true,
"proxyStreamTimeout": "600s",
"vtsStatusZoneSize": "10m",
"workerProcesses": 1,
"limitConnZoneVariable": "$the_real_ip"
},
@ -117,9 +115,7 @@
"keyFilename": "",
"caFilename": "",
"pemSha": ""
},
"vtsDefaultFilterKey": "$uri $server_name"
}
}, {
"path": "/",
"isDefBackend": true,

View file

@ -32,11 +32,15 @@ import (
"k8s.io/ingress-nginx/test/e2e/framework"
)
// TODO(elvinefendi) merge this with Affinity tests in test/e2e/lua/dynamic_configuration.go
var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
f := framework.NewDefaultFramework("affinity")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
err := f.DisableDynamicConfiguration()
Expect(err).NotTo(HaveOccurred())
err = f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
})
@ -105,7 +109,6 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/affinity": "cookie",
"nginx.ingress.kubernetes.io/session-cookie-name": "SERVERID",
"nginx.ingress.kubernetes.io/rewrite-target": "/something",
},
},
Spec: v1beta1.IngressSpec{
@ -146,7 +149,120 @@ var _ = framework.IngressNginxDescribe("Annotations - Affinity", func() {
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(fmt.Sprintf("request_uri=http://%v:8080/something/", host)))
Expect(body).Should(ContainSubstring(fmt.Sprintf("request_uri=http://%v:8080/", host)))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("SERVERID="))
})
It("should set the path to /something on the generated cookie", func() {
host := "example.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/affinity": "cookie",
"nginx.ingress.kubernetes.io/session-cookie-name": "SERVERID",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/something",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/something"))
})
It("should set the path to / on the generated cookie if there's more than one rule referring to the same backend", func() {
host := "example.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/affinity": "cookie",
"nginx.ingress.kubernetes.io/session-cookie-name": "SERVERID",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/something",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
{
Path: "/somewhereelese",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://sticky-"+f.IngressController.Namespace+"-http-svc-80;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("Path=/;"))
})
})

View file

@ -19,6 +19,7 @@ package annotations
import (
"fmt"
"net/http"
"net/url"
"os/exec"
"time"
@ -27,7 +28,9 @@ import (
"github.com/parnurzeal/gorequest"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -265,6 +268,77 @@ var _ = framework.IngressNginxDescribe("Annotations - Auth", func() {
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
})
Context("when external authentication is configured", func() {
host := "auth"
BeforeEach(func() {
err := f.NewHttpbinDeployment()
Expect(err).NotTo(HaveOccurred())
var httpbinIP string
err = wait.PollImmediate(time.Second, time.Minute, func() (bool, error) {
e, err := f.KubeClientSet.CoreV1().Endpoints(f.IngressController.Namespace).Get("httpbin", metav1.GetOptions{})
if errors.IsNotFound(err) {
return false, nil
}
if err != nil {
return false, err
}
if len(e.Subsets) < 1 || len(e.Subsets[0].Addresses) < 1 {
return false, nil
}
httpbinIP = e.Subsets[0].Addresses[0].IP
return true, nil
})
Expect(err).NotTo(HaveOccurred())
bi, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &map[string]string{
"nginx.ingress.kubernetes.io/auth-url": fmt.Sprintf("http://%s/basic-auth/user/password", httpbinIP),
"nginx.ingress.kubernetes.io/auth-signin": "http://$host/auth/start",
}))
Expect(err).NotTo(HaveOccurred())
Expect(bi).NotTo(BeNil())
err = f.WaitForNginxServer(host, func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("return 503"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should return status code 200 when signed in", func() {
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Retry(10, 1*time.Second, http.StatusNotFound).
Set("Host", host).
SetBasicAuth("user", "password").
End()
for _, err := range errs {
Expect(err).NotTo(HaveOccurred())
}
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
})
It("should redirect to signin url when not signed in", func() {
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Retry(10, 1*time.Second, http.StatusNotFound).
Set("Host", host).
RedirectPolicy(func(req gorequest.Request, via []gorequest.Request) error {
return http.ErrUseLastResponse
}).
Param("a", "b").
Param("c", "d").
End()
for _, err := range errs {
Expect(err).NotTo(HaveOccurred())
}
Expect(resp.StatusCode).Should(Equal(http.StatusFound))
Expect(resp.Header.Get("Location")).Should(Equal(fmt.Sprintf("http://%s/auth/start?rd=http://%s%s", host, host, url.QueryEscape("/?a=b&c=d"))))
})
})
})
// TODO: test Digest Auth

View file

@ -0,0 +1,292 @@
/*
Copyright 2018 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 (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
v1beta1 "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Client-Body-Buffer-Size", func() {
f := framework.NewDefaultFramework("proxy")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
})
It("should set client_body_buffer_size to 1000", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1000",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1000;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1K", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1K",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1K;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1k", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1k",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1k;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1M", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1M",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1M;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should set client_body_buffer_size to 1M", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1M",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("client_body_buffer_size 1M;"))
})
Expect(err).NotTo(HaveOccurred())
})
It("should not set client_body_buffer_size to invalid 1b", func() {
host := "proxy.foo.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/client-body-buffer-size": "1b",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).ShouldNot(ContainSubstring("client_body_buffer_size 1b;"))
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -18,10 +18,12 @@ package annotations
import (
"fmt"
"net/http"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
@ -49,10 +51,23 @@ var _ = framework.IngressNginxDescribe("Annotations - custom default-backend", f
err = f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) &&
Expect(server).Should(ContainSubstring("proxy_pass http://custom-default-backend"))
return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host)))
})
Expect(err).NotTo(HaveOccurred())
uri := "/alma/armud"
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL+uri).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).To(ContainSubstring("x-code=503"))
Expect(body).To(ContainSubstring(fmt.Sprintf("x-ingress-name=%s", host)))
Expect(body).To(ContainSubstring("x-service-name=invalid"))
Expect(body).To(ContainSubstring(fmt.Sprintf("x-original-uri=%s", uri)))
})
})
})

View file

@ -38,7 +38,7 @@ var _ = framework.IngressNginxDescribe("Annotations - grpc", func() {
host := "grpc"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/grpc-backend": "true",
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
}
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "fortune-teller", 50051, &annotations))
Expect(err).NotTo(HaveOccurred())

View file

@ -0,0 +1,121 @@
/*
Copyright 2018 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"
"strconv"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
func noRedirectPolicyFunc(gorequest.Request, []gorequest.Request) error {
return http.ErrUseLastResponse
}
var _ = framework.IngressNginxDescribe("Annotations - Redirect", func() {
f := framework.NewDefaultFramework("redirect")
BeforeEach(func() {
})
AfterEach(func() {
})
It("should respond with a standard redirect code", func() {
By("setting permanent-redirect annotation")
host := "redirect"
redirectPath := "/something"
redirectURL := "http://redirect.example.com"
annotations := map[string]string{"nginx.ingress.kubernetes.io/permanent-redirect": redirectURL}
ing := framework.NewSingleIngress(host, redirectPath, host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("if ($uri ~* %s) {", redirectPath)) &&
strings.Contains(server, fmt.Sprintf("return 301 %s;", redirectURL))
})
Expect(err).NotTo(HaveOccurred())
By("sending request to redirected URL path")
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL+redirectPath).
Set("Host", host).
RedirectPolicy(noRedirectPolicyFunc).
End()
Expect(errs).To(BeNil())
Expect(resp.StatusCode).Should(BeNumerically("==", http.StatusMovedPermanently))
Expect(resp.Header.Get("Location")).Should(Equal(redirectURL))
Expect(body).Should(ContainSubstring("nginx/"))
})
It("should respond with a custom redirect code", func() {
By("setting permanent-redirect-code annotation")
host := "redirect"
redirectPath := "/something"
redirectURL := "http://redirect.example.com"
redirectCode := http.StatusFound
annotations := map[string]string{
"nginx.ingress.kubernetes.io/permanent-redirect": redirectURL,
"nginx.ingress.kubernetes.io/permanent-redirect-code": strconv.Itoa(redirectCode),
}
ing := framework.NewSingleIngress(host, redirectPath, host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("if ($uri ~* %s) {", redirectPath)) &&
strings.Contains(server, fmt.Sprintf("return %d %s;", redirectCode, redirectURL))
})
Expect(err).NotTo(HaveOccurred())
By("sending request to redirected URL path")
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL+redirectPath).
Set("Host", host).
RedirectPolicy(noRedirectPolicyFunc).
End()
Expect(errs).To(BeNil())
Expect(resp.StatusCode).Should(BeNumerically("==", redirectCode))
Expect(resp.Header.Get("Location")).Should(Equal(redirectURL))
Expect(body).Should(ContainSubstring("nginx/"))
})
})

View file

@ -0,0 +1,120 @@
/*
Copyright 2017 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"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Rewrite", func() {
f := framework.NewDefaultFramework("rewrite")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
})
It("should rewrite request URL", func() {
By("setting rewrite-target annotation")
host := "rewrite.foo.com"
annotations := map[string]string{"nginx.ingress.kubernetes.io/rewrite-target": "/"}
expectBodyRequestURI := fmt.Sprintf("request_uri=http://%v:8080/", host)
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "rewrite (?i)/something/(.*) /$1 break;") &&
strings.Contains(server, "rewrite (?i)/something / break;")
})
Expect(err).NotTo(HaveOccurred())
By("sending request to Ingress rule path (lowercase)")
resp, body, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
Set("Host", host).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(expectBodyRequestURI))
By("sending request to Ingress rule path (mixed case)")
resp, body, errs = gorequest.New().
Get(f.IngressController.HTTPURL+"/SomeThing").
Set("Host", host).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(expectBodyRequestURI))
})
It("should write rewrite logs", func() {
By("setting enable-rewrite-log annotation")
host := "rewrite.bar.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/rewrite-target": "/",
"nginx.ingress.kubernetes.io/enable-rewrite-log": "true",
}
ing := framework.NewSingleIngress(host, "/something", host, f.IngressController.Namespace, "http-svc", 80, &annotations)
_, err := f.EnsureIngress(ing)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "rewrite_log on;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
Set("Host", host).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
logs, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(logs).To(ContainSubstring(`"(?i)/something" matches "/something", client:`))
Expect(logs).To(ContainSubstring(`rewritten data: "/", args: "",`))
})
})

View file

@ -1,100 +0,0 @@
/*
Copyright 2017 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 (
"net/http"
"strings"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
"k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Rewrite Log", func() {
f := framework.NewDefaultFramework("rewrite-log")
BeforeEach(func() {
err := f.NewEchoDeploymentWithReplicas(2)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
})
It("should write rewrite logs", func() {
host := "rewrite.bar.com"
ing, err := f.EnsureIngress(&v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: f.IngressController.Namespace,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/rewrite-target": "/",
"nginx.ingress.kubernetes.io/enable-rewrite-log": "true",
},
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: "/something",
Backend: v1beta1.IngressBackend{
ServiceName: "http-svc",
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
})
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "rewrite_log on;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL+"/something").
Set("Host", host).
End()
Expect(len(errs)).Should(Equal(0))
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
time.Sleep(5 * time.Second)
logs, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(logs).To(ContainSubstring(`"/something" matches "/something", client:`))
Expect(logs).To(ContainSubstring(`rewritten data: "/", args: "",`))
})
})

1664
test/e2e/dind-cluster-v1.11.sh Executable file

File diff suppressed because it is too large Load diff

23
test/e2e/down.sh Executable file
View file

@ -0,0 +1,23 @@
#!/bin/bash
# Copyright 2017 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.
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
export PATH="$HOME/.kubeadm-dind-cluster:$SCRIPT_ROOT/build:$PATH"
dind-cluster-v1.11.sh down
dind-cluster-v1.11.sh clean

View file

@ -33,6 +33,7 @@ import (
_ "k8s.io/ingress-nginx/test/e2e/annotations"
_ "k8s.io/ingress-nginx/test/e2e/defaultbackend"
_ "k8s.io/ingress-nginx/test/e2e/lua"
_ "k8s.io/ingress-nginx/test/e2e/servicebackend"
_ "k8s.io/ingress-nginx/test/e2e/settings"
_ "k8s.io/ingress-nginx/test/e2e/ssl"
)
@ -52,3 +53,9 @@ func RunE2ETests(t *testing.T) {
glog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunID, config.GinkgoConfig.ParallelNode)
ginkgo.RunSpecs(t, "nginx-ingress-controller e2e suite")
}
var _ = ginkgo.SynchronizedAfterSuite(func() {
// Run on all Ginkgo nodes
framework.Logf("Running AfterSuite actions on all nodes")
framework.RunCleanupActions()
}, func() {})

View file

@ -37,35 +37,45 @@ func (f *Framework) NewEchoDeployment() error {
// NewEchoDeploymentWithReplicas creates a new deployment of the echoserver image in a particular namespace. Number of
// replicas is configurable
func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
return f.NewDeployment("http-svc", "gcr.io/kubernetes-e2e-test-images/echoserver:2.1", 8080, replicas)
}
// NewHttpbinDeployment creates a new single replica deployment of the httpbin image in a particular namespace.
func (f *Framework) NewHttpbinDeployment() error {
return f.NewDeployment("httpbin", "kennethreitz/httpbin", 80, 1)
}
// NewDeployment creates a new deployment in a particular namespace.
func (f *Framework) NewDeployment(name, image string, port int32, replicas int32) error {
deployment := &extensions.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "http-svc",
Name: name,
Namespace: f.IngressController.Namespace,
},
Spec: extensions.DeploymentSpec{
Replicas: NewInt32(replicas),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "http-svc",
"app": name,
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "http-svc",
"app": name,
},
},
Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: NewInt64(0),
Containers: []corev1.Container{
{
Name: "http-svc",
Image: "gcr.io/google_containers/echoserver:1.10",
Name: name,
Image: image,
Env: []corev1.EnvVar{},
Ports: []corev1.ContainerPort{
{
Name: "http",
ContainerPort: 8080,
ContainerPort: port,
},
},
},
@ -81,7 +91,7 @@ func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
}
if d == nil {
return fmt.Errorf("unexpected error creating deployement for echoserver")
return fmt.Errorf("unexpected error creating deployement %s", name)
}
err = WaitForPodsReady(f.KubeClientSet, 5*time.Minute, int(replicas), f.IngressController.Namespace, metav1.ListOptions{
@ -93,7 +103,7 @@ func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "http-svc",
Name: name,
Namespace: f.IngressController.Namespace,
},
Spec: corev1.ServiceSpec{
@ -101,12 +111,12 @@ func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
{
Name: "http",
Port: 80,
TargetPort: intstr.FromInt(8080),
TargetPort: intstr.FromInt(int(port)),
Protocol: "TCP",
},
},
Selector: map[string]string{
"app": "http-svc",
"app": name,
},
},
}
@ -117,7 +127,7 @@ func (f *Framework) NewEchoDeploymentWithReplicas(replicas int32) error {
}
if s == nil {
return fmt.Errorf("unexpected error creating service for echoserver deployment")
return fmt.Errorf("unexpected error creating service %s", name)
}
return nil

View file

@ -50,22 +50,10 @@ func (f *Framework) ExecCommand(pod *v1.Pod, command string) (string, error) {
// NewIngressController deploys a new NGINX Ingress controller in a namespace
func (f *Framework) NewIngressController(namespace string) error {
var (
execOut bytes.Buffer
execErr bytes.Buffer
)
cmd := exec.Command("./wait-for-nginx.sh", namespace)
cmd.Stdout = &execOut
cmd.Stderr = &execErr
err := cmd.Run()
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("could not execute: %v", err)
}
if execErr.Len() > 0 {
return fmt.Errorf("stderr: %v", execErr.String())
return fmt.Errorf("Unexpected error waiting for ingress controller deployment: %v.\nLogs:\n%v", err, string(out))
}
return nil

View file

@ -15,7 +15,7 @@ package framework
import (
"fmt"
"os/exec"
"os"
"strings"
"time"
@ -112,13 +112,11 @@ func (f *Framework) BeforeEach() {
})
Expect(err).NotTo(HaveOccurred())
By("Building NGINX HTTP URL")
HTTPURL, err := f.GetNginxURL(HTTP)
Expect(err).NotTo(HaveOccurred())
f.IngressController.HTTPURL = HTTPURL
By("Building NGINX HTTPS URL")
HTTPSURL, err := f.GetNginxURL(HTTPS)
Expect(err).NotTo(HaveOccurred())
@ -135,6 +133,13 @@ func (f *Framework) AfterEach() {
By("Waiting for test namespace to no longer exist")
err := DeleteKubeNamespace(f.KubeClientSet, f.IngressController.Namespace)
Expect(err).NotTo(HaveOccurred())
if CurrentGinkgoTestDescription().Failed {
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
By("Dumping NGINX logs after a failure running a test")
Logf("%v", log)
}
}
// IngressNginxDescribe wrapper function for ginkgo describe. Adds namespacing.
@ -145,11 +150,7 @@ func IngressNginxDescribe(text string, body func()) bool {
// GetNginxIP returns the IP address of the minikube cluster
// where the NGINX ingress controller is running
func (f *Framework) GetNginxIP() (string, error) {
out, err := exec.Command("minikube", "ip").Output()
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
return os.Getenv("NODE_IP"), nil
}
// GetNginxPort returns the number of TCP port where NGINX is running
@ -426,3 +427,19 @@ func NewSingleIngress(name, path, host, ns, service string, port int, annotation
return ing
}
// DisableDynamicConfiguration disables dynamic configuration
func (f *Framework) DisableDynamicConfiguration() error {
return UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--enable-dynamic-configuration=false")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := f.KubeClientSet.AppsV1beta1().Deployments(f.IngressController.Namespace).Update(deployment)
if err != nil {
return err
}
return nil
})
}

View file

@ -226,7 +226,7 @@ func fileInFS(file string, fs file.Filesystem) wait.ConditionFunc {
}
if stat == nil {
return false, fmt.Errorf("file %v does not exists", file)
return false, fmt.Errorf("file %v does not exist", file)
}
if stat.Size() > 0 {

View file

@ -27,23 +27,28 @@ import (
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
appsv1beta1 "k8s.io/api/apps/v1beta1"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
"k8s.io/ingress-nginx/test/e2e/framework"
)
const (
logDynamicConfigSuccess = "Dynamic reconfiguration succeeded"
logDynamicConfigFailure = "Dynamic reconfiguration failed"
logRequireBackendReload = "Configuration changes detected, backend reload required"
logBackendReloadSuccess = "Backend successfully reloaded"
logSkipBackendReload = "Changes handled by the dynamic configuration, skipping backend reload"
logInitialConfigSync = "Initial synchronization of the NGINX configuration"
waitForLuaSync = 2 * time.Second
)
var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
f := framework.NewDefaultFramework("dynamic-configuration")
BeforeEach(func() {
err := enableDynamicConfiguration(f.IngressController.Namespace, f.KubeClientSet)
Expect(err).NotTo(HaveOccurred())
err = f.NewEchoDeploymentWithReplicas(1)
err := f.NewEchoDeploymentWithReplicas(1)
Expect(err).NotTo(HaveOccurred())
host := "foo.com"
@ -57,8 +62,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
})
Expect(err).NotTo(HaveOccurred())
// give some time for Lua to sync the backend
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -69,8 +73,16 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(log).ToNot(ContainSubstring("could not dynamically reconfigure"))
Expect(log).To(ContainSubstring("first sync of Nginx configuration"))
Expect(log).ToNot(ContainSubstring(logDynamicConfigFailure))
Expect(log).To(ContainSubstring(logDynamicConfigSuccess))
})
It("should set nameservers for Lua", func() {
err := f.WaitForNginxConfiguration(func(cfg string) bool {
r := regexp.MustCompile(`configuration.nameservers = { [".,0-9a-zA-Z]+ }`)
return r.MatchString(cfg)
})
Expect(err).NotTo(HaveOccurred())
})
Context("when only backends change", func() {
@ -85,7 +97,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
replicas := 2
err := framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", replicas, nil)
Expect(err).NotTo(HaveOccurred())
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
@ -94,14 +106,14 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
restOfLogs := log[index:]
By("POSTing new backends to Lua endpoint")
Expect(restOfLogs).To(ContainSubstring("dynamic reconfiguration succeeded"))
Expect(restOfLogs).ToNot(ContainSubstring("could not dynamically reconfigure"))
Expect(restOfLogs).To(ContainSubstring(logDynamicConfigSuccess))
Expect(restOfLogs).ToNot(ContainSubstring(logDynamicConfigFailure))
By("skipping Nginx reload")
Expect(restOfLogs).ToNot(ContainSubstring("backend reload required"))
Expect(restOfLogs).ToNot(ContainSubstring("ingress backend successfully reloaded"))
Expect(restOfLogs).To(ContainSubstring("skipping reload"))
Expect(restOfLogs).ToNot(ContainSubstring("first sync of Nginx configuration"))
Expect(restOfLogs).ToNot(ContainSubstring(logRequireBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logBackendReloadSuccess))
Expect(restOfLogs).To(ContainSubstring(logSkipBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logInitialConfigSync))
})
It("should be able to update endpoints even when the update POST size(request body) > size(client_body_buffer_size)", func() {
@ -116,7 +128,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
replicas = 4
err = framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", replicas, nil)
Expect(err).NotTo(HaveOccurred())
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
@ -155,7 +167,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
ingress.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/load-balance"] = "round_robin"
_, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Update(ingress)
Expect(err).ToNot(HaveOccurred())
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
@ -164,14 +176,14 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
restOfLogs := log[index:]
By("POSTing new backends to Lua endpoint")
Expect(restOfLogs).To(ContainSubstring("dynamic reconfiguration succeeded"))
Expect(restOfLogs).ToNot(ContainSubstring("could not dynamically reconfigure"))
Expect(restOfLogs).To(ContainSubstring(logDynamicConfigSuccess))
Expect(restOfLogs).ToNot(ContainSubstring(logDynamicConfigFailure))
By("skipping Nginx reload")
Expect(restOfLogs).ToNot(ContainSubstring("backend reload required"))
Expect(restOfLogs).ToNot(ContainSubstring("ingress backend successfully reloaded"))
Expect(restOfLogs).To(ContainSubstring("skipping reload"))
Expect(restOfLogs).ToNot(ContainSubstring("first sync of Nginx configuration"))
Expect(restOfLogs).ToNot(ContainSubstring(logRequireBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logBackendReloadSuccess))
Expect(restOfLogs).To(ContainSubstring(logSkipBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logInitialConfigSync))
})
})
@ -208,10 +220,10 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
Expect(log).ToNot(BeEmpty())
By("reloading Nginx")
Expect(log).To(ContainSubstring("ingress backend successfully reloaded"))
Expect(log).To(ContainSubstring(logBackendReloadSuccess))
By("POSTing new backends to Lua endpoint")
Expect(log).To(ContainSubstring("dynamic reconfiguration succeeded"))
Expect(log).To(ContainSubstring(logDynamicConfigSuccess))
By("still be proxying requests through Lua balancer")
err = f.WaitForNginxServer("foo.com",
@ -231,7 +243,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
err = framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", 2, nil)
Expect(err).NotTo(HaveOccurred())
time.Sleep(10 * time.Second)
time.Sleep(waitForLuaSync)
resp, body, errs := gorequest.New().
Get(fmt.Sprintf("%s?a-unique-request-uri", f.IngressController.HTTPURL)).
@ -275,7 +287,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
By("Increasing the number of service replicas")
err = framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", 2, nil)
Expect(err).NotTo(HaveOccurred())
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
By("Making a first request")
host := "foo.com"
@ -331,7 +343,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
}
_, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Update(ingress)
Expect(err).ToNot(HaveOccurred())
time.Sleep(5 * time.Second)
time.Sleep(waitForLuaSync)
By("Making a request")
host := "foo.com"
@ -349,21 +361,6 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
})
})
func enableDynamicConfiguration(namespace string, kubeClientSet kubernetes.Interface) error {
return framework.UpdateDeployment(kubeClientSet, namespace, "nginx-ingress-controller", 1,
func(deployment *appsv1beta1.Deployment) error {
args := deployment.Spec.Template.Spec.Containers[0].Args
args = append(args, "--enable-dynamic-configuration")
deployment.Spec.Template.Spec.Containers[0].Args = args
_, err := kubeClientSet.AppsV1beta1().Deployments(namespace).Update(deployment)
if err != nil {
return err
}
return nil
})
}
func ensureIngress(f *framework.Framework, host string) (*extensions.Ingress, error) {
return f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, &map[string]string{
"nginx.ingress.kubernetes.io/load-balance": "ewma",

View file

@ -0,0 +1,170 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package servicebackend
import (
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
corev1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Service backend - 503", func() {
f := framework.NewDefaultFramework("service-backend")
BeforeEach(func() {
})
AfterEach(func() {
})
It("should return 503 when backend service does not exist", func() {
host := "nonexistent.svc.com"
bi := buildIngressWithNonexistentService(host, f.IngressController.Namespace, "/")
ing, err := f.EnsureIngress(bi)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "return 503;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(503))
})
It("should return 503 when all backend service endpoints are unavailable", func() {
host := "unavailable.svc.com"
bi, bs := buildIngressWithUnavailableServiceEndpoints(host, f.IngressController.Namespace, "/")
svc, err := f.EnsureService(bs)
Expect(err).NotTo(HaveOccurred())
Expect(svc).NotTo(BeNil())
ing, err := f.EnsureIngress(bi)
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
err = f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "return 503;")
})
Expect(err).NotTo(HaveOccurred())
resp, _, errs := gorequest.New().
Get(f.IngressController.HTTPURL).
Set("Host", host).
End()
Expect(len(errs)).Should(BeNumerically("==", 0))
Expect(resp.StatusCode).Should(Equal(503))
})
})
func buildIngressWithNonexistentService(host, namespace, path string) *v1beta1.Ingress {
backendService := "nonexistent-svc"
return &v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: namespace,
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: path,
Backend: v1beta1.IngressBackend{
ServiceName: backendService,
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
}
}
func buildIngressWithUnavailableServiceEndpoints(host, namespace, path string) (*v1beta1.Ingress, *corev1.Service) {
backendService := "unavailable-svc"
return &v1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: host,
Namespace: namespace,
},
Spec: v1beta1.IngressSpec{
Rules: []v1beta1.IngressRule{
{
Host: host,
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
{
Path: path,
Backend: v1beta1.IngressBackend{
ServiceName: backendService,
ServicePort: intstr.FromInt(80),
},
},
},
},
},
},
},
},
}, &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: backendService,
Namespace: namespace,
},
Spec: corev1.ServiceSpec{Ports: []corev1.ServicePort{
{
Name: "tcp",
Port: 80,
TargetPort: intstr.FromInt(80),
Protocol: "TCP",
},
},
Selector: map[string]string{
"app": backendService,
},
},
}
}

View file

@ -0,0 +1,91 @@
/*
Copyright 2018 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 (
"regexp"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Configmap change", func() {
f := framework.NewDefaultFramework("configmap-change")
BeforeEach(func() {
err := f.NewEchoDeployment()
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
})
It("should reload after an update in the configuration", func() {
host := "configmap-change"
ing, err := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80, nil))
Expect(err).NotTo(HaveOccurred())
Expect(ing).NotTo(BeNil())
wlKey := "whitelist-source-range"
wlValue := "1.1.1.1"
By("adding a whitelist-source-range")
err = f.UpdateNginxConfigMapData(wlKey, wlValue)
Expect(err).NotTo(HaveOccurred())
checksumRegex := regexp.MustCompile("Configuration checksum:\\s+(\\d+)")
checksum := ""
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
// before returning, extract the current checksum
match := checksumRegex.FindStringSubmatch(cfg)
if len(match) > 0 {
checksum = match[1]
}
return strings.Contains(cfg, "geo $the_real_ip $deny_") &&
strings.Contains(cfg, "1.1.1.1 0")
})
Expect(err).NotTo(HaveOccurred())
Expect(checksum).NotTo(BeEmpty())
By("changing error-log-level")
err = f.UpdateNginxConfigMapData("error-log-level", "debug")
Expect(err).NotTo(HaveOccurred())
newChecksum := ""
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
match := checksumRegex.FindStringSubmatch(cfg)
if len(match) > 0 {
newChecksum = match[1]
}
return strings.ContainsAny(cfg, "error_log /var/log/nginx/error.log debug;")
})
Expect(err).NotTo(HaveOccurred())
Expect(checksum).NotTo(BeEquivalentTo(newChecksum))
})
})

View file

@ -0,0 +1,43 @@
/*
Copyright 2018 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"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Main Snippet", func() {
f := framework.NewDefaultFramework("main-snippet")
mainSnippet := "main-snippet"
It("should add value of main-snippet setting to nginx config", func() {
expectedComment := "# main snippet"
err := f.UpdateNginxConfigMapData(mainSnippet, expectedComment)
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedComment)
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -0,0 +1,64 @@
/*
Copyright 2018 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"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Multi Accept", func() {
multiAccept := "enable-multi-accept"
f := framework.NewDefaultFramework(multiAccept)
It("should be enabled by default", func() {
expectedDirective := "multi_accept on;"
err := f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
It("should be enabled when set to true", func() {
expectedDirective := "multi_accept on;"
err := f.UpdateNginxConfigMapData(multiAccept, "true")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
It("should be disabled when set to false", func() {
expectedDirective := "multi_accept off;"
err := f.UpdateNginxConfigMapData(multiAccept, "false")
Expect(err).NotTo(HaveOccurred())
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, expectedDirective)
})
Expect(err).NotTo(HaveOccurred())
})
})

View file

@ -51,7 +51,7 @@ var _ = framework.IngressNginxDescribe("Server Tokens", func() {
err = f.WaitForNginxConfiguration(
func(cfg string) bool {
return strings.Contains(cfg, "server_tokens off") &&
strings.Contains(cfg, "more_set_headers \"Server: \"")
strings.Contains(cfg, "more_clear_headers Server;")
})
Expect(err).NotTo(HaveOccurred())
})

View file

@ -14,41 +14,37 @@
# See the License for the specific language governing permissions and
# limitations under the License.
export JSONPATH='{range .items[*]}{@.metadata.name}:{range @.status.conditions[*]}{@.type}={@.status};{end}{end}'
set -e
echo "downloading kubectl..."
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$KUBERNETES_VERSION/bin/linux/amd64/kubectl && \
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "downloading minikube..."
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && \
chmod +x minikube && \
sudo mv minikube /usr/local/bin/
if test -e kubectl; then
echo "skipping download of kubectl"
else
echo "downloading kubectl..."
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.11.0/bin/linux/amd64/kubectl && \
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
fi
echo "starting minikube..."
# Using a lower value for sync-frequency to speed up the tests (during the cleanup of resources inside a namespace)
mkdir -p ${HOME}/.kube
touch ${HOME}/.kube/config
export KUBECONFIG=${HOME}/.kube/config
export MINIKUBE_WANTUPDATENOTIFICATION=false
export MINIKUBE_WANTREPORTERRORPROMPT=false
export MINIKUBE_HOME=$HOME
mkdir $HOME/.kube || true
touch $HOME/.kube/config
echo "starting Kubernetes cluster..."
$DIR/dind-cluster-v1.11.sh up
export KUBECONFIG=$HOME/.kube/config
kubectl config use-context dind
# --vm-driver=none, use host docker (avoid docker-in-docker)
# --bootstrapper=localkube, works around https://github.com/kubernetes/minikube/issues/2704
sudo -E minikube start \
--bootstrapper=localkube \
--vm-driver=none \
--kubernetes-version=$KUBERNETES_VERSION \
--extra-config=kubelet.sync-frequency=1s \
--extra-config=apiserver.authorization-mode=RBAC
echo "Kubernetes cluster:"
kubectl get nodes -o wide
minikube update-context
export TAG=dev
export ARCH=amd64
export REGISTRY=${REGISTRY:-ingress-controller}
echo "waiting for kubernetes cluster"
until kubectl get nodes -o jsonpath="$JSONPATH" 2>&1 | grep -q "Ready=True";
do
sleep 1;
done
echo "building container..."
make -C ${DIR}/../../ build container
echo "copying docker image to cluster..."
DEV_IMAGE=${REGISTRY}/nginx-ingress-controller:${TAG}
${DIR}/dind-cluster-v1.11.sh copy-image ${DEV_IMAGE}

View file

@ -14,11 +14,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export NAMESPACE=$1
echo "deploying NGINX Ingress controller in namespace $NAMESPACE"
function on_exit {
local error_code="$?"
test $error_code == 0 && return;
echo "Obtaining ingress controller pod logs..."
kubectl logs -l app=ingress-nginx -n $NAMESPACE
}
trap on_exit EXIT
sed "s@\${NAMESPACE}@${NAMESPACE}@" $DIR/../manifests/ingress-controller/mandatory.yaml | kubectl apply --namespace=$NAMESPACE -f -
cat $DIR/../manifests/ingress-controller/service-nodeport.yaml | kubectl apply --namespace=$NAMESPACE -f -
# wait for the deployment and fail if there is an error before starting the execution of any test
kubectl rollout status \
--request-timeout=3m \
--namespace $NAMESPACE \
deployment nginx-ingress-controller

View file

@ -260,6 +260,14 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
ports:
- name: http
containerPort: 80
@ -284,5 +292,3 @@ spec:
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
securityContext:
privileged: true