ingress-nginx-helm/test/e2e/annotations/affinitymode.go
Chen Chen b3060bfbd0
Fix golangci-lint errors (#10196)
* Fix golangci-lint errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix dupl errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix comments

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix errcheck lint errors

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix assert in e2e test

Signed-off-by: z1cheng <imchench@gmail.com>

* Not interrupt the waitForPodsReady

Signed-off-by: z1cheng <imchench@gmail.com>

* Replace string with constant

Signed-off-by: z1cheng <imchench@gmail.com>

* Fix comments

Signed-off-by: z1cheng <imchench@gmail.com>

* Revert write file permision

Signed-off-by: z1cheng <imchench@gmail.com>

---------

Signed-off-by: z1cheng <imchench@gmail.com>
2023-08-31 00:36:48 -07:00

181 lines
6.5 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/v2"
"github.com/stretchr/testify/assert"
"k8s.io/ingress-nginx/test/e2e/framework"
)
const sslRedirectValue = "false"
var _ = framework.DescribeAnnotation("affinitymode", func() {
f := framework.NewDefaultFramework("affinity")
ginkgo.It("Balanced affinity mode should balance", func() {
deploymentName := "affinitybalanceecho"
replicas := 5
f.NewEchoDeployment(
framework.WithDeploymentName(deploymentName),
framework.WithDeploymentReplicas(replicas),
)
host := "affinity-mode-balance.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.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"] = sslRedirectValue
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.NewEchoDeployment(
framework.WithDeploymentName(deploymentName),
framework.WithDeploymentReplicas(replicas),
)
host := "affinity-mode-persistent.com"
annotations := make(map[string]string)
annotations["nginx.ingress.kubernetes.io/affinity"] = "cookie"
annotations["nginx.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"] = sslRedirectValue
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++
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
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
}