2018-04-01 20:09:27 +00:00
|
|
|
/*
|
|
|
|
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 lua
|
|
|
|
|
|
|
|
import (
|
2018-08-24 22:52:09 +00:00
|
|
|
"crypto/tls"
|
2018-04-01 20:09:27 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2018-04-12 18:21:42 +00:00
|
|
|
"regexp"
|
2018-04-01 20:09:27 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/parnurzeal/gorequest"
|
|
|
|
|
|
|
|
extensions "k8s.io/api/extensions/v1beta1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
|
|
|
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
|
|
|
)
|
|
|
|
|
2018-06-13 18:15:45 +00:00
|
|
|
const (
|
|
|
|
logDynamicConfigSuccess = "Dynamic reconfiguration succeeded"
|
|
|
|
logDynamicConfigFailure = "Dynamic reconfiguration failed"
|
|
|
|
logRequireBackendReload = "Configuration changes detected, backend reload required"
|
|
|
|
logBackendReloadSuccess = "Backend successfully reloaded"
|
|
|
|
logInitialConfigSync = "Initial synchronization of the NGINX configuration"
|
2018-08-24 02:06:16 +00:00
|
|
|
waitForLuaSync = 5 * time.Second
|
2018-06-13 18:15:45 +00:00
|
|
|
)
|
|
|
|
|
2018-04-01 20:09:27 +00:00
|
|
|
var _ = framework.IngressNginxDescribe("Dynamic Configuration", func() {
|
|
|
|
f := framework.NewDefaultFramework("dynamic-configuration")
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
2018-10-29 21:39:04 +00:00
|
|
|
f.NewEchoDeploymentWithReplicas(1)
|
2018-08-24 02:06:16 +00:00
|
|
|
ensureIngress(f, "foo.com")
|
2018-04-01 20:09:27 +00:00
|
|
|
})
|
|
|
|
|
2018-10-24 18:42:40 +00:00
|
|
|
It("configures balancer Lua middleware correctly", func() {
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-10-24 18:42:40 +00:00
|
|
|
return strings.Contains(cfg, "balancer.init_worker()") && strings.Contains(cfg, "balancer.balance()")
|
|
|
|
})
|
|
|
|
|
|
|
|
host := "foo.com"
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxServer(host, func(server string) bool {
|
2018-10-24 18:42:40 +00:00
|
|
|
return strings.Contains(server, "balancer.rewrite()") && strings.Contains(server, "balancer.log()")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
It("sets nameservers for Lua", func() {
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-07-28 17:56:41 +00:00
|
|
|
r := regexp.MustCompile(`configuration.nameservers = { [".,0-9a-zA-Z]+ }`)
|
|
|
|
return r.MatchString(cfg)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-04-12 23:44:09 +00:00
|
|
|
Context("when only backends change", func() {
|
2018-08-24 02:06:16 +00:00
|
|
|
It("handles endpoints only changes", func() {
|
|
|
|
var nginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
nginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
2018-04-12 23:44:09 +00:00
|
|
|
|
|
|
|
replicas := 2
|
2018-10-29 21:39:04 +00:00
|
|
|
err := framework.UpdateDeployment(f.KubeClientSet, f.IngressController.Namespace, "http-svc", replicas, nil)
|
2018-04-05 15:00:37 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
2018-07-28 17:56:41 +00:00
|
|
|
time.Sleep(waitForLuaSync)
|
2018-04-05 15:00:37 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
ensureRequest(f, "foo.com")
|
2018-04-05 15:00:37 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
var newNginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
newNginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
Expect(nginxConfig).Should(Equal(newNginxConfig))
|
2018-04-05 15:00:37 +00:00
|
|
|
})
|
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
It("handles an annotation change", func() {
|
|
|
|
var nginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
nginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
ingress, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Get("foo.com", metav1.GetOptions{})
|
2018-04-12 23:44:09 +00:00
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
|
|
|
|
ingress.ObjectMeta.Annotations["nginx.ingress.kubernetes.io/load-balance"] = "round_robin"
|
2018-04-18 19:15:08 +00:00
|
|
|
_, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Update(ingress)
|
2018-04-12 23:44:09 +00:00
|
|
|
Expect(err).ToNot(HaveOccurred())
|
2018-07-28 17:56:41 +00:00
|
|
|
time.Sleep(waitForLuaSync)
|
2018-04-21 02:32:38 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
ensureRequest(f, "foo.com")
|
|
|
|
|
|
|
|
var newNginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
newNginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
Expect(nginxConfig).Should(Equal(newNginxConfig))
|
2018-04-12 23:44:09 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
It("handles a non backend update", func() {
|
|
|
|
var nginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
nginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
2018-04-18 19:15:08 +00:00
|
|
|
ingress, err := f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Get("foo.com", metav1.GetOptions{})
|
2018-04-12 23:44:09 +00:00
|
|
|
Expect(err).ToNot(HaveOccurred())
|
2018-04-21 03:41:21 +00:00
|
|
|
ingress.Spec.TLS = []extensions.IngressTLS{
|
2018-04-12 23:44:09 +00:00
|
|
|
{
|
|
|
|
Hosts: []string{"foo.com"},
|
|
|
|
SecretName: "foo.com",
|
|
|
|
},
|
|
|
|
}
|
2018-04-27 12:29:08 +00:00
|
|
|
_, err = framework.CreateIngressTLSSecret(f.KubeClientSet,
|
2018-04-12 23:44:09 +00:00
|
|
|
ingress.Spec.TLS[0].Hosts,
|
|
|
|
ingress.Spec.TLS[0].SecretName,
|
|
|
|
ingress.Namespace)
|
|
|
|
Expect(err).ToNot(HaveOccurred())
|
2018-04-18 19:15:08 +00:00
|
|
|
_, err = f.KubeClientSet.ExtensionsV1beta1().Ingresses(f.IngressController.Namespace).Update(ingress)
|
2018-04-12 23:44:09 +00:00
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
var newNginxConfig string
|
2018-10-29 21:39:04 +00:00
|
|
|
f.WaitForNginxConfiguration(func(cfg string) bool {
|
2018-08-24 02:06:16 +00:00
|
|
|
newNginxConfig = cfg
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
Expect(nginxConfig).ShouldNot(Equal(newNginxConfig))
|
2018-04-20 03:02:22 +00:00
|
|
|
})
|
2018-08-24 02:06:16 +00:00
|
|
|
})
|
2018-04-20 03:02:22 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
func ensureIngress(f *framework.Framework, host string) *extensions.Ingress {
|
2018-10-29 21:39:04 +00:00
|
|
|
ing := f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.IngressController.Namespace, "http-svc", 80,
|
2018-08-24 02:06:16 +00:00
|
|
|
&map[string]string{"nginx.ingress.kubernetes.io/load-balance": "ewma"}))
|
2018-10-29 21:39:04 +00:00
|
|
|
|
|
|
|
f.WaitForNginxServer(host,
|
2018-08-24 02:06:16 +00:00
|
|
|
func(server string) bool {
|
|
|
|
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host)) &&
|
|
|
|
strings.Contains(server, "proxy_pass http://upstream_balancer;")
|
2018-04-12 18:21:42 +00:00
|
|
|
})
|
2018-08-24 02:06:16 +00:00
|
|
|
time.Sleep(waitForLuaSync)
|
|
|
|
ensureRequest(f, host)
|
2018-04-12 23:44:09 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
return ing
|
|
|
|
}
|
2018-04-01 20:09:27 +00:00
|
|
|
|
2018-08-24 02:06:16 +00:00
|
|
|
func ensureRequest(f *framework.Framework, host string) {
|
|
|
|
resp, _, errs := gorequest.New().
|
|
|
|
Get(f.IngressController.HTTPURL).
|
|
|
|
Set("Host", host).
|
|
|
|
End()
|
|
|
|
Expect(errs).Should(BeEmpty())
|
|
|
|
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
|
2018-04-01 20:09:27 +00:00
|
|
|
}
|
2018-04-12 18:21:42 +00:00
|
|
|
|
2018-08-24 22:52:09 +00:00
|
|
|
func ensureHTTPSRequest(url string, host string, expectedDNSName string) {
|
|
|
|
resp, _, errs := gorequest.New().
|
|
|
|
Get(url).
|
|
|
|
Set("Host", host).
|
|
|
|
TLSClientConfig(&tls.Config{
|
|
|
|
InsecureSkipVerify: true,
|
|
|
|
ServerName: host,
|
|
|
|
}).
|
|
|
|
End()
|
|
|
|
Expect(errs).Should(BeEmpty())
|
|
|
|
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
|
|
|
|
Expect(len(resp.TLS.PeerCertificates)).Should(BeNumerically("==", 1))
|
|
|
|
Expect(resp.TLS.PeerCertificates[0].DNSNames[0]).Should(Equal(expectedDNSName))
|
|
|
|
}
|
|
|
|
|
2018-04-12 18:21:42 +00:00
|
|
|
func getCookie(name string, cookies []*http.Cookie) (*http.Cookie, error) {
|
|
|
|
for _, cookie := range cookies {
|
|
|
|
if cookie.Name == name {
|
|
|
|
return cookie, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &http.Cookie{}, fmt.Errorf("Cookie does not exist")
|
|
|
|
}
|