Merge branch 'master' of https://github.com/kubernetes/ingress-nginx into proxyssl

This commit is contained in:
Gabor Lekeny 2019-08-16 06:21:53 +02:00
commit 65b9e2c574
391 changed files with 23957 additions and 20447 deletions

View file

@ -20,7 +20,6 @@
"whitelist-source-range": null
},
"bodySize": "1m",
"enableDynamicTlsRecords": true,
"enableSpdy": false,
"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/javascript text/plain text/x-component",

View file

@ -18,6 +18,7 @@ COPY e2e.sh /e2e.sh
COPY cloud-generic /cloud-generic
COPY cluster-wide /cluster-wide
COPY overlay /overlay
COPY namespace-overlays /namespace-overlays
RUN sed -E -i 's|^- .*deploy/cloud-generic$|- ../cloud-generic|' /overlay/kustomization.yaml
COPY wait-for-nginx.sh /
COPY e2e.test /

View file

@ -0,0 +1,12 @@
- op: replace
path: /spec/template/spec/containers/0/ports/0/containerPort
value: 1080
- op: replace
path: /spec/template/spec/containers/0/ports/1/containerPort
value: 1443
- op: add
path: /spec/template/spec/containers/0/args/-
value: --http-port=1080
- op: add
path: /spec/template/spec/containers/0/args/-
value: --https-port=1443

View file

@ -0,0 +1,16 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: nginx-ingress-controller
path: deployment-patch.yaml
- target:
version: v1
kind: Service
name: ingress-nginx
path: service-patch.yaml
bases:
- ../../overlay

View file

@ -0,0 +1,6 @@
- op: replace
path: /spec/ports/0/targetPort
value: 1080
- op: replace
path: /spec/ports/1/targetPort
value: 1443

View file

@ -168,17 +168,13 @@ var _ = framework.IngressNginxDescribe("Annotations - AuthTLS", func() {
})
func assertSslClientCertificateConfig(f *framework.Framework, host string, verifyClient string, verifyDepth string) {
sslCertDirective := "ssl_certificate /etc/ingress-controller/ssl/default-fake-certificate.pem;"
sslKeyDirective := "ssl_certificate_key /etc/ingress-controller/ssl/default-fake-certificate.pem;"
sslClientCertDirective := fmt.Sprintf("ssl_client_certificate /etc/ingress-controller/ssl/%s-%s.pem;", f.Namespace, host)
sslVerify := fmt.Sprintf("ssl_verify_client %s;", verifyClient)
sslVerifyDepth := fmt.Sprintf("ssl_verify_depth %s;", verifyDepth)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, sslCertDirective) &&
strings.Contains(server, sslKeyDirective) &&
strings.Contains(server, sslClientCertDirective) &&
return strings.Contains(server, sslClientCertDirective) &&
strings.Contains(server, sslVerify) &&
strings.Contains(server, sslVerifyDepth)
})

View file

@ -32,7 +32,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
AfterEach(func() {
})
It("should set backend protocol to https://", func() {
It("should set backend protocol to https:// and use proxy_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "HTTPS",
@ -47,7 +47,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
})
})
It("should set backend protocol to grpc://", func() {
It("should set backend protocol to grpc:// and use grpc_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
@ -62,7 +62,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
})
})
It("should set backend protocol to grpcs://", func() {
It("should set backend protocol to grpcs:// and use grpc_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "GRPCS",
@ -77,7 +77,22 @@ var _ = framework.IngressNginxDescribe("Annotations - Backendprotocol", func() {
})
})
It("should set backend protocol to ''", func() {
It("should set backend protocol to '' and use fastcgi_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("fastcgi_pass upstream_balancer;"))
})
})
It("should set backend protocol to '' and use ajp_pass", func() {
host := "backendprotocol.foo.com"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "AJP",

View file

@ -0,0 +1,130 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package annotations
import (
"net/http"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - FastCGI", func() {
f := framework.NewDefaultFramework("fastcgi")
BeforeEach(func() {
f.NewFastCGIHelloServerDeployment()
})
It("should use fastcgi_pass in the configuration file", func() {
host := "fastcgi"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
}
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("include /etc/nginx/fastcgi_params;")) &&
Expect(server).Should(ContainSubstring("fastcgi_pass"))
})
})
It("should add fastcgi_index in the configuration file", func() {
host := "fastcgi-index"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
"nginx.ingress.kubernetes.io/fastcgi-index": "index.php",
}
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("fastcgi_index \"index.php\";"))
})
})
It("should add fastcgi_param in the configuration file", func() {
configuration := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "fastcgi-configmap",
Namespace: f.Namespace,
},
Data: map[string]string{
"SCRIPT_FILENAME": "/home/www/scripts/php$fastcgi_script_name",
"REDIRECT_STATUS": "200",
},
}
cm, err := f.EnsureConfigMap(configuration)
Expect(err).NotTo(HaveOccurred(), "failed to create an the configmap")
Expect(cm).NotTo(BeNil(), "expected a configmap but none returned")
host := "fastcgi-params-configmap"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
"nginx.ingress.kubernetes.io/fastcgi-params-configmap": "fastcgi-configmap",
}
ing := framework.NewSingleIngress(host, "/hello", host, f.Namespace, "fastcgi-helloserver", 9000, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("fastcgi_param SCRIPT_FILENAME \"/home/www/scripts/php$fastcgi_script_name\";")) &&
Expect(server).Should(ContainSubstring("fastcgi_param REDIRECT_STATUS \"200\";"))
})
})
It("should return OK for service with backend protocol FastCGI", func() {
host := "fastcgi-helloserver"
path := "/hello"
annotations := map[string]string{
"nginx.ingress.kubernetes.io/backend-protocol": "FCGI",
}
ing := framework.NewSingleIngress(host, path, host, f.Namespace, "fastcgi-helloserver", 9000, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return Expect(server).Should(ContainSubstring("fastcgi_pass"))
})
resp, body, errs := gorequest.New().
Get(f.GetURL(framework.HTTP)+path).
Set("Host", host).
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring("Hello world!"))
})
})

View file

@ -0,0 +1,66 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package annotations
import (
"strings"
. "github.com/onsi/ginkgo"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Annotations - Mirror", func() {
f := framework.NewDefaultFramework("mirror")
host := "mirror.foo.com"
BeforeEach(func() {
f.NewEchoDeployment()
})
AfterEach(func() {
})
It("should set mirror-uri to /mirror", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/mirror-uri": "/mirror",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "mirror /mirror;") && strings.Contains(server, "mirror_request_body on;")
})
})
It("should disable mirror-request-body", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/mirror-uri": "/mirror",
"nginx.ingress.kubernetes.io/mirror-request-body": "off",
}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "mirror /mirror;") && strings.Contains(server, "mirror_request_body off;")
})
})
})

View file

@ -88,9 +88,9 @@ func (f *Framework) ExecCommand(pod *corev1.Pod, command string) (string, error)
}
// NewIngressController deploys a new NGINX Ingress controller in a namespace
func (f *Framework) NewIngressController(namespace string) error {
func (f *Framework) NewIngressController(namespace string, namespaceOverlay string) error {
// Creates an nginx deployment
cmd := exec.Command("./wait-for-nginx.sh", namespace)
cmd := exec.Command("./wait-for-nginx.sh", namespace, namespaceOverlay)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("Unexpected error waiting for ingress controller deployment: %v.\nLogs:\n%v", err, string(out))

View file

@ -0,0 +1,106 @@
/*
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 framework
import (
. "github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/intstr"
)
// NewFastCGIHelloServerDeployment creates a new single replica
// deployment of the fortune teller image in a particular namespace
func (f *Framework) NewFastCGIHelloServerDeployment() {
f.NewNewFastCGIHelloServerDeploymentWithReplicas(1)
}
// NewNewFastCGIHelloServerDeploymentWithReplicas creates a new deployment of the
// fortune teller image in a particular namespace. Number of replicas is configurable
func (f *Framework) NewNewFastCGIHelloServerDeploymentWithReplicas(replicas int32) {
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "fastcgi-helloserver",
Namespace: f.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: NewInt32(replicas),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "fastcgi-helloserver",
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "fastcgi-helloserver",
},
},
Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: NewInt64(0),
Containers: []corev1.Container{
{
Name: "fastcgi-helloserver",
Image: "ingress-controller/fastcgi-helloserver:dev",
Env: []corev1.EnvVar{},
Ports: []corev1.ContainerPort{
{
Name: "fastcgi",
ContainerPort: 9000,
},
},
},
},
},
},
},
}
d, err := f.EnsureDeployment(deployment)
Expect(err).NotTo(HaveOccurred())
Expect(d).NotTo(BeNil(), "expected a fastcgi-helloserver deployment")
err = WaitForPodsReady(f.KubeClientSet, DefaultTimeout, int(replicas), f.Namespace, metav1.ListOptions{
LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(),
})
Expect(err).NotTo(HaveOccurred(), "failed to wait for to become ready")
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "fastcgi-helloserver",
Namespace: f.Namespace,
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Name: "fastcgi",
Port: 9000,
TargetPort: intstr.FromInt(9000),
Protocol: "TCP",
},
},
Selector: map[string]string{
"app": "fastcgi-helloserver",
},
},
}
f.EnsureService(service)
}

View file

@ -103,7 +103,7 @@ func (f *Framework) BeforeEach() {
f.Namespace = ingressNamespace
By("Starting new ingress controller")
err = f.NewIngressController(f.Namespace)
err = f.NewIngressController(f.Namespace, f.BaseName)
Expect(err).NotTo(HaveOccurred())
err = WaitForPodsReady(f.KubeClientSet, DefaultTimeout, 1, f.Namespace, metav1.ListOptions{
@ -165,6 +165,23 @@ func (f *Framework) GetNginxIP() string {
return s.Spec.ClusterIP
}
// GetNginxPodIP returns the IP addres/es of the running pods
func (f *Framework) GetNginxPodIP() []string {
e, err := f.KubeClientSet.
CoreV1().
Endpoints(f.Namespace).
Get("ingress-nginx", metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred(), "unexpected error obtaning NGINX IP address")
eips := make([]string, 0)
for _, s := range e.Subsets {
for _, a := range s.Addresses {
eips = append(eips, a.IP)
}
}
return eips
}
// GetURL returns the URL should be used to make a request to NGINX
func (f *Framework) GetURL(scheme RequestScheme) string {
ip := f.GetNginxIP()

View file

@ -0,0 +1,59 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package framework
import (
"fmt"
"net/http"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
)
// GetMetric returns the current prometheus metric exposed by NGINX
func (f *Framework) GetMetric(metricName, ip string) (*dto.MetricFamily, error) {
url := fmt.Sprintf("http://%v:10254/metrics", ip)
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, fmt.Errorf("creating GET request for URL %q failed: %v", url, err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("executing GET request for URL %q failed: %v", url, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("GET request for URL %q returned HTTP status %s", url, resp.Status)
}
var parser expfmt.TextParser
metrics, err := parser.TextToMetricFamilies(resp.Body)
if err != nil {
return nil, fmt.Errorf("reading text format failed: %v", err)
}
for _, m := range metrics {
if m.GetName() == metricName {
return m, nil
}
}
return nil, fmt.Errorf("there is no metric with name %v", metricName)
}

View file

@ -18,6 +18,7 @@ package framework
import (
"fmt"
"os"
"time"
. "github.com/onsi/ginkgo"
@ -31,7 +32,6 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/ingress-nginx/internal/file"
)
const (
@ -205,13 +205,13 @@ func secretInNamespace(c kubernetes.Interface, namespace, name string) wait.Cond
}
// WaitForFileInFS waits a default amount of time for the specified file is present in the filesystem
func WaitForFileInFS(file string, fs file.Filesystem) error {
return wait.PollImmediate(Poll, DefaultTimeout, fileInFS(file, fs))
func WaitForFileInFS(file string) error {
return wait.PollImmediate(Poll, DefaultTimeout, fileInFS(file))
}
func fileInFS(file string, fs file.Filesystem) wait.ConditionFunc {
func fileInFS(file string) wait.ConditionFunc {
return func() (bool, error) {
stat, err := fs.Stat(file)
stat, err := os.Stat(file)
if err != nil {
return false, err
}

View file

@ -24,6 +24,9 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
extensions "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -67,23 +70,22 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
time.Sleep(waitForLuaSync)
ip := f.GetNginxPodIP()
mf, err := f.GetMetric("nginx_ingress_controller_success", ip[0])
Expect(err).ToNot(HaveOccurred())
Expect(mf).ToNot(BeNil())
rc0, err := extractReloadCount(mf)
Expect(err).ToNot(HaveOccurred())
ensureHTTPSRequest(fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.GetURL(framework.HTTPS)), host, "ingress.local")
_, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
_, err = framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).ToNot(HaveOccurred())
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
})
time.Sleep(waitForLuaSync)
By("serving the configured certificate on HTTPS endpoint")
@ -92,12 +94,17 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(log).ToNot(BeEmpty())
index := strings.Index(log, "id=dummy_log_splitter_foo_bar")
restOfLogs := log[index:]
By("skipping Nginx reload")
Expect(restOfLogs).ToNot(ContainSubstring(logRequireBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logBackendReloadSuccess))
mf, err = f.GetMetric("nginx_ingress_controller_success", ip[0])
Expect(err).ToNot(HaveOccurred())
Expect(mf).ToNot(BeNil())
rc1, err := extractReloadCount(mf)
Expect(err).ToNot(HaveOccurred())
// TODO: This is wrong. We should not require a reload when SSL is configured
Expect(rc0).To(BeEquivalentTo(rc1 - 1))
})
Context("given an ingress with TLS correctly configured", func() {
@ -118,10 +125,7 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
return strings.Contains(server, "listen 443")
})
time.Sleep(waitForLuaSync)
@ -150,19 +154,15 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
!strings.Contains(server, fmt.Sprintf("ssl_certificate_key /etc/ingress-controller/ssl/%s-%s.pem;", ing.Namespace, host)) &&
strings.Contains(server, "listen 443")
return strings.Contains(server, "listen 443")
})
time.Sleep(waitForLuaSync)
By("serving the configured certificate on HTTPS endpoint")
ensureHTTPSRequest(f.GetURL(framework.HTTPS), host, host)
@ -177,39 +177,41 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
Expect(restOfLogs).ToNot(ContainSubstring(logBackendReloadSuccess))
})
It("falls back to using default certificate when secret gets deleted without reloading", func() {
ing, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.Namespace).Get(host, metav1.GetOptions{})
// TODO: Fix
/*
It("falls back to using default certificate when secret gets deleted without reloading", func() {
ing, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.Namespace).Get(host, metav1.GetOptions{})
ensureHTTPSRequest(fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.GetURL(framework.HTTPS)), host, host)
ensureHTTPSRequest(fmt.Sprintf("%s?id=dummy_log_splitter_foo_bar", f.GetURL(framework.HTTPS)), host, host)
f.KubeClientSet.CoreV1().Secrets(ing.Namespace).Delete(ing.Spec.TLS[0].SecretName, nil)
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
ip := f.GetNginxPodIP()
mf, err := f.GetMetric("nginx_ingress_controller_success", ip[0])
Expect(err).ToNot(HaveOccurred())
Expect(mf).ToNot(BeNil())
By("configuring certificate_by_lua and skipping Nginx configuration of the new certificate")
f.WaitForNginxServer(ing.Spec.TLS[0].Hosts[0],
func(server string) bool {
return strings.Contains(server, "ssl_certificate_by_lua_block") &&
strings.Contains(server, "ssl_certificate /etc/ingress-controller/ssl/default-fake-certificate.pem;") &&
strings.Contains(server, "ssl_certificate_key /etc/ingress-controller/ssl/default-fake-certificate.pem;") &&
strings.Contains(server, "listen 443")
})
rc0, err := extractReloadCount(mf)
Expect(err).ToNot(HaveOccurred())
time.Sleep(waitForLuaSync)
err = f.KubeClientSet.CoreV1().Secrets(ing.Namespace).Delete(ing.Spec.TLS[0].SecretName, nil)
Expect(err).ToNot(HaveOccurred())
By("serving the default certificate on HTTPS endpoint")
ensureHTTPSRequest(f.GetURL(framework.HTTPS), host, "ingress.local")
time.Sleep(waitForLuaSync * 2)
log, err := f.NginxLogs()
Expect(err).ToNot(HaveOccurred())
Expect(log).ToNot(BeEmpty())
index := strings.Index(log, "id=dummy_log_splitter_foo_bar")
restOfLogs := log[index:]
By("serving the default certificate on HTTPS endpoint")
ensureHTTPSRequest(f.GetURL(framework.HTTPS), host, "ingress.local")
By("skipping Nginx reload")
Expect(restOfLogs).ToNot(ContainSubstring(logRequireBackendReload))
Expect(restOfLogs).ToNot(ContainSubstring(logBackendReloadSuccess))
})
mf, err = f.GetMetric("nginx_ingress_controller_success", ip[0])
Expect(err).ToNot(HaveOccurred())
Expect(mf).ToNot(BeNil())
rc1, err := extractReloadCount(mf)
Expect(err).ToNot(HaveOccurred())
By("skipping Nginx reload")
// TODO: This is wrong. We should not require a reload when SSL is configured
Expect(rc0).To(BeEquivalentTo(rc1 - 1))
})
*/
It("picks up a non-certificate only change", func() {
newHost := "foo2.com"
@ -236,3 +238,15 @@ var _ = framework.IngressNginxDescribe("Dynamic Certificate", func() {
})
})
})
func extractReloadCount(mf *dto.MetricFamily) (float64, error) {
vec, err := expfmt.ExtractSamples(&expfmt.DecodeOptions{
Timestamp: model.Now(),
}, mf)
if err != nil {
return 0, err
}
return float64(vec[0].Value), nil
}

View file

@ -20,7 +20,6 @@ import (
"crypto/tls"
"fmt"
"net/http"
"regexp"
"strings"
"time"
@ -63,13 +62,6 @@ var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
})
})
It("sets nameservers for Lua", func() {
f.WaitForNginxConfiguration(func(cfg string) bool {
r := regexp.MustCompile(`configuration.nameservers = { [".,0-9a-zA-Z]+ }`)
return r.MatchString(cfg)
})
})
Context("when only backends change", func() {
It("handles endpoints only changes", func() {
var nginxConfig string

View file

@ -55,6 +55,7 @@ kubectl config set-context kubernetes-admin@${KIND_CLUSTER_NAME}
echo "[dev-env] building container"
make -C ${DIR}/../../ build container
make -C ${DIR}/../../ e2e-test-image
make -C ${DIR}/../../images/fastcgi-helloserver/ build container
# Remove after https://github.com/kubernetes/ingress-nginx/pull/4271 is merged
docker tag ${REGISTRY}/nginx-ingress-controller-${ARCH}:${TAG} ${REGISTRY}/nginx-ingress-controller:${TAG}
@ -62,6 +63,7 @@ docker tag ${REGISTRY}/nginx-ingress-controller-${ARCH}:${TAG} ${REGISTRY}/nginx
echo "[dev-env] copying docker images to cluster..."
kind load docker-image --name="${KIND_CLUSTER_NAME}" nginx-ingress-controller:e2e
kind load docker-image --name="${KIND_CLUSTER_NAME}" ${REGISTRY}/nginx-ingress-controller:${TAG}
kind load docker-image --name="${KIND_CLUSTER_NAME}" ${REGISTRY}/fastcgi-helloserver:${TAG}
echo "[dev-env] running e2e tests..."
make -C ${DIR}/../../ e2e-test

View file

@ -41,6 +41,40 @@ var _ = framework.IngressNginxDescribe("Service Type ExternalName", func() {
AfterEach(func() {
})
It("works with external name set to incomplete fdqn", func() {
f.NewEchoDeployment()
host := "echo"
svc := &core.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "httpbin",
Namespace: f.Namespace,
},
Spec: corev1.ServiceSpec{
ExternalName: "http-svc",
Type: corev1.ServiceTypeExternalName,
},
}
f.EnsureService(svc)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "httpbin", 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
resp, _, errs := gorequest.New().
Get(f.GetURL(framework.HTTP)+"/get").
Set("Host", host).
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(200))
})
It("should return 200 for service type=ExternalName without a port defined", func() {
host := "echo"
@ -143,4 +177,45 @@ var _ = framework.IngressNginxDescribe("Service Type ExternalName", func() {
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(503))
})
It("should return 200 for service type=ExternalName using a port name", func() {
host := "echo"
svc := &core.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "httpbin",
Namespace: f.Namespace,
},
Spec: corev1.ServiceSpec{
ExternalName: "httpbin.org",
Type: corev1.ServiceTypeExternalName,
Ports: []corev1.ServicePort{
{
Name: host,
Port: 80,
TargetPort: intstr.FromInt(80),
Protocol: "TCP",
},
},
},
}
f.EnsureService(svc)
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "httpbin", 80, nil)
ing.Spec.Rules[0].HTTP.Paths[0].Backend.ServicePort = intstr.FromString(host)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_pass http://upstream_balancer;")
})
resp, _, errs := gorequest.New().
Get(f.GetURL(framework.HTTP)+"/get").
Set("Host", host).
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(200))
})
})

View file

@ -65,7 +65,7 @@ var _ = framework.IngressNginxDescribe("default-ssl-certificate", func() {
f.EnsureIngress(ing)
By("making sure new ingress is deployed")
expectedConfig := fmt.Sprintf("set $proxy_upstream_name \"%v-%v-%v\";", f.Namespace, service, port)
expectedConfig := fmt.Sprintf(`set $proxy_upstream_name "%v-%v-%v";`, f.Namespace, service, port)
f.WaitForNginxServer("_", func(cfg string) bool {
return strings.Contains(cfg, expectedConfig)
})
@ -87,7 +87,7 @@ var _ = framework.IngressNginxDescribe("default-ssl-certificate", func() {
Expect(err).NotTo(HaveOccurred())
By("making sure new ingress is deployed")
expectedConfig := fmt.Sprintf("set $proxy_upstream_name \"%v-%v-%v\";", f.Namespace, service, port)
expectedConfig := fmt.Sprintf(`set $proxy_upstream_name "%v-%v-%v";`, f.Namespace, service, port)
f.WaitForNginxServer(host, func(cfg string) bool {
return strings.Contains(cfg, expectedConfig)
})

View file

@ -0,0 +1,150 @@
/*
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 settings
import (
"fmt"
"net/http"
"strings"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/parnurzeal/gorequest"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("Listen on nondefault ports", func() {
host := "forwarded-headers"
f := framework.NewDefaultFramework("forwarded-port-headers")
BeforeEach(func() {
f.NewEchoDeployment()
f.WaitForNginxServer("_",
func(server string) bool {
return strings.Contains(server, "listen 1443")
})
})
Context("with a plain HTTP ingress", func() {
It("should set X-Forwarded-Port headers accordingly when listening on a non-default HTTP port", func() {
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name forwarded-headers")
})
resp, body, errs := gorequest.New().
Get(f.GetURL(framework.HTTP)).
Set("Host", host).
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=%d", 1080)))
})
})
Context("with a TLS enabled ingress", func() {
It("should set X-Forwarded-Port header to 443", func() {
ing := framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ing)
tlsConfig, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).NotTo(HaveOccurred())
framework.WaitForTLS(f.GetURL(framework.HTTPS), tlsConfig)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name forwarded-headers")
})
resp, body, errs := gorequest.New().
Get(f.GetURL(framework.HTTPS)).
TLSClientConfig(tlsConfig).
Set("Host", host).
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=443")))
})
Context("when external authentication is configured", func() {
It("should set the X-Forwarded-Port header to 443", func() {
f.NewHttpbinDeployment()
var httpbinIP string
err := framework.WaitForEndpoints(f.KubeClientSet, framework.DefaultTimeout, "httpbin", f.Namespace, 1)
Expect(err).NotTo(HaveOccurred())
e, err := f.KubeClientSet.CoreV1().Endpoints(f.Namespace).Get("httpbin", metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
httpbinIP = e.Subsets[0].Addresses[0].IP
annotations := 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",
}
ing := framework.NewSingleIngressWithTLS(host, "/", host, []string{host}, f.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)
tlsConfig, err := framework.CreateIngressTLSSecret(f.KubeClientSet,
ing.Spec.TLS[0].Hosts,
ing.Spec.TLS[0].SecretName,
ing.Namespace)
Expect(err).NotTo(HaveOccurred())
framework.WaitForTLS(f.GetURL(framework.HTTPS), tlsConfig)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "server_name forwarded-headers")
})
resp, body, errs := gorequest.New().
Get(f.GetURL(framework.HTTPS)).
TLSClientConfig(tlsConfig).
Set("Host", host).
SetBasicAuth("user", "password").
End()
Expect(errs).Should(BeEmpty())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=443")))
})
})
})
})

View file

@ -0,0 +1,53 @@
/*
Copyright 2016 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 (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.IngressNginxDescribe("LuaSharedDict", func() {
f := framework.NewDefaultFramework("lua-shared-dicts")
host := "lua-shared-dicts"
BeforeEach(func() {
f.NewEchoDeployment()
})
AfterEach(func() {
})
It("configures lua shared dicts", func() {
ingress := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, nil)
f.EnsureIngress(ingress)
f.UpdateNginxConfigMapData("lua-shared-dicts", "configuration_data:60,certificate_data:300, my_dict: 15 , invalid: 1a")
ngxCfg := ""
f.WaitForNginxConfiguration(func(cfg string) bool {
ngxCfg = cfg
return true
})
Expect(ngxCfg).Should(ContainSubstring("lua_shared_dict configuration_data 60M;"))
Expect(ngxCfg).Should(ContainSubstring("lua_shared_dict certificate_data 20M;"))
Expect(ngxCfg).Should(ContainSubstring("lua_shared_dict my_dict 15M;"))
})
})

View file

@ -22,6 +22,7 @@ fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export NAMESPACE=$1
export NAMESPACE_OVERLAY=$2
echo "deploying NGINX Ingress controller in namespace $NAMESPACE"
@ -60,6 +61,21 @@ bases:
- ../cluster-wide-$NAMESPACE
EOF
# Use the namespace overlay if it was requested
if [[ ! -z "$NAMESPACE_OVERLAY" && -d "$DIR/namespace-overlays/$NAMESPACE_OVERLAY" ]]; then
echo "Namespace overlay $NAMESPACE_OVERLAY is being used for namespace $NAMESPACE"
OVERLAY="$DIR/namespace-overlays/$NAMESPACE"
mkdir "$OVERLAY"
cat << EOF > "$OVERLAY/kustomization.yaml"
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: $NAMESPACE
bases:
- ../../namespace-overlays/$NAMESPACE_OVERLAY
- ../../cluster-wide-$NAMESPACE
EOF
fi
kubectl apply --kustomize "$OVERLAY"
# wait for the deployment and fail if there is an error before starting the execution of any test