ingress-nginx-helm/test/e2e/annotations/affinitymode.go
Manuel Alejandro de Brito Fontes 108637bb1c Migrate to structured logging (klog)
2020-09-27 18:59:57 -03:00

173 lines
6.3 KiB
Go

/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package annotations
import (
"fmt"
"net/http"
"reflect"
"strings"
"github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeAnnotation("affinitymode", func() {
f := framework.NewDefaultFramework("affinity")
ginkgo.It("Balanced affinity mode should balance", func() {
deploymentName := "affinitybalanceecho"
replicas := 5
f.NewEchoDeploymentWithNameAndReplicas(deploymentName, replicas)
host := "affinity-mode-balance.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["ginx.ingress.kubernetes.io/session-cookie-name"] = "hello-cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-expires"] = "172800"
annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "172800"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
annotations["nginx.ingress.kubernetes.io/affinity-mode"] = "balanced"
annotations["nginx.ingress.kubernetes.io/session-cookie-hash"] = "sha1"
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, deploymentName, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
// Check configuration
ingress := f.GetIngress(f.Namespace, host)
returnedAnnotations := ingress.GetAnnotations()
isItEqual := reflect.DeepEqual(annotations, returnedAnnotations)
assert.Equal(ginkgo.GinkgoT(), isItEqual, true)
})
ginkgo.It("Check persistent affinity mode", func() {
deploymentName := "affinitypersistentecho"
replicas := 5
f.NewEchoDeploymentWithNameAndReplicas(deploymentName, replicas)
host := "affinity-mode-persistent.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["ginx.ingress.kubernetes.io/session-cookie-name"] = "hello-cookie"
annotations["nginx.ingress.kubernetes.io/session-cookie-expires"] = "172800"
annotations["nginx.ingress.kubernetes.io/session-cookie-max-age"] = "172800"
annotations["nginx.ingress.kubernetes.io/ssl-redirect"] = "false"
annotations["nginx.ingress.kubernetes.io/affinity-mode"] = "persistent"
annotations["nginx.ingress.kubernetes.io/session-cookie-hash"] = "sha1"
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, deploymentName, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, fmt.Sprintf("server_name %s ;", host))
})
// Check configuration
ingress := f.GetIngress(f.Namespace, host)
returnedAnnotations := ingress.GetAnnotations()
isItEqual := reflect.DeepEqual(annotations, returnedAnnotations)
assert.Equal(ginkgo.GinkgoT(), isItEqual, true)
// Make a request
request := f.HTTPTestClient().GET("/").WithHeader("Host", host)
response := request.Expect()
// Get the responder host name
originalHostName := getHostnameFromResponseBody(response.Body().Raw())
// Send new requests and add new backends. Check which backend responded to the sent request
cookies := getCookiesFromHeader(response.Header("Set-Cookie").Raw())
for sendRequestNumber := 0; sendRequestNumber < 10; sendRequestNumber++ {
replicas = replicas + 1
err := framework.UpdateDeployment(f.KubeClientSet, f.Namespace, deploymentName, replicas, nil)
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
response = request.WithCookies(cookies).Expect()
newHostName := getHostnameFromResponseBody(response.Body().Raw())
assert.Equal(ginkgo.GinkgoT(), originalHostName, newHostName,
fmt.Sprintf("Response number %v is not from the same host. Original host: %s, response returned: %s", sendRequestNumber, originalHostName, newHostName))
}
// remove all backends
replicas = 0
err := framework.UpdateDeployment(f.KubeClientSet, f.Namespace, deploymentName, replicas, nil)
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
// validate, there is no backend to serve the request
response = request.WithCookies(cookies).Expect().Status(http.StatusServiceUnavailable)
// create brand new backends
replicas = 2
err = framework.UpdateDeployment(f.KubeClientSet, f.Namespace, deploymentName, replicas, nil)
assert.Nil(ginkgo.GinkgoT(), err)
framework.Sleep()
// wait brand new backends to spawn
response = request.WithCookies(cookies).Expect()
try := 0
for (response.Raw().StatusCode == http.StatusServiceUnavailable) && (try < 30) {
framework.Sleep()
response = request.WithCookies(cookies).Expect()
try++
}
assert.LessOrEqual(ginkgo.GinkgoT(), try, 29, "Tries reached it's maximum, backends did not deployed in time")
// brand new backends equals new hostname
newHostName := getHostnameFromResponseBody(response.Body().Raw())
assert.NotEqual(ginkgo.GinkgoT(), originalHostName, newHostName,
fmt.Sprintf("Response is from the same host (That should not be possible). Original host: %s, response returned: %s", originalHostName, newHostName))
})
})
func getHostnameFromResponseBody(rawResponseBody string) string {
lines := strings.Split(strings.TrimSpace(rawResponseBody), "\n")
for _, line := range lines {
if strings.Contains(line, "Hostname") {
hostnameParts := strings.Split(strings.TrimSpace(line), ":")
if len(hostnameParts) == 2 {
return strings.TrimSpace(hostnameParts[1])
}
return ""
}
}
return ""
}
func getCookiesFromHeader(rawheader string) map[string]string {
cookies := make(map[string]string)
parts := strings.Split(strings.TrimSpace(rawheader), ";")
for _, part := range parts {
subparts := strings.Split(strings.TrimSpace(part), "=")
if len(subparts) == 2 {
cookies[subparts[0]] = subparts[1]
} else {
cookies[subparts[0]] = ""
}
}
return cookies
}