diff --git a/test/e2e/annotations/affinity.go b/test/e2e/annotations/affinity.go new file mode 100644 index 000000000..0f80dddde --- /dev/null +++ b/test/e2e/annotations/affinity.go @@ -0,0 +1,152 @@ +/* +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" + + 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 - Affinity", func() { + f := framework.NewDefaultFramework("affinity") + + BeforeEach(func() { + err := f.NewEchoDeploymentWithReplicas(2) + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + }) + + It("should set sticky cookie SERVERID", func() { + host := "sticky.foo.com" + + ing, err := f.EnsureIngress(&v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: host, + Namespace: f.Namespace.Name, + 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: "/", + 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.Namespace.Name+"-http-svc-80;") + }) + Expect(err).NotTo(HaveOccurred()) + + resp, _, errs := gorequest.New(). + Get(f.NginxHTTPURL). + 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("SERVERID=")) + }) + + It("should redirect to '/something' with enabled affinity", func() { + host := "example.com" + + ing, err := f.EnsureIngress(&v1beta1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: host, + Namespace: f.Namespace.Name, + 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{ + 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 strings.Contains(server, "proxy_pass http://sticky-"+f.Namespace.Name+"-http-svc-80;") + }) + Expect(err).NotTo(HaveOccurred()) + + resp, body, errs := gorequest.New(). + Get(f.NginxHTTPURL). + Set("Host", host). + End() + + 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(resp.Header.Get("Set-Cookie")).Should(ContainSubstring("SERVERID=")) + }) +}) diff --git a/test/e2e/framework/echo.go b/test/e2e/framework/echo.go index 1868bd4d2..98e67b187 100644 --- a/test/e2e/framework/echo.go +++ b/test/e2e/framework/echo.go @@ -29,15 +29,21 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) -// NewEchoDeployment creates a new deployment of the echoserver image in a particular namespace +// NewEchoDeployment creates a new single replica deployment of the echoserver image in a particular namespace func (f *Framework) NewEchoDeployment() error { + return f.NewEchoDeploymentWithReplicas(1) +} + +// 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 { deployment := &extensions.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: "http-svc", Namespace: f.Namespace.Name, }, Spec: extensions.DeploymentSpec{ - Replicas: NewInt32(1), + Replicas: NewInt32(replicas), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ "app": "http-svc", @@ -78,7 +84,7 @@ func (f *Framework) NewEchoDeployment() error { return fmt.Errorf("unexpected error creating deployement for echoserver") } - err = f.WaitForPodsReady(10*time.Second, 1, metav1.ListOptions{ + err = f.WaitForPodsReady(10*time.Second, int(replicas), metav1.ListOptions{ LabelSelector: fields.SelectorFromSet(fields.Set(d.Spec.Template.ObjectMeta.Labels)).String(), }) if err != nil {