Skip to content

Commit 67a15d7

Browse files
MLE-4173: Kubernetes Huge Pages test automation (#167)
* e2e tests for huge pages implementation
1 parent 0b0f86b commit 67a15d7

File tree

4 files changed

+192
-1
lines changed

4 files changed

+192
-1
lines changed

Jenkinsfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ pipeline {
219219
always {
220220
publishTestResults()
221221
sh '''
222+
sudo sysctl -w vm.nr_hugepages=0
222223
export MINIKUBE_HOME=/space; export KUBECONFIG=/space/.kube-config; export GOPATH=/space/go; minikube delete --all --purge
223224
docker system prune --force --filter "until=720h"
224225
docker volume prune --force

makefile

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,24 @@ e2e-test: prepare
100100
@echo "=====Loading marklogc image $(prevDockerImage) to minikube cluster"
101101
minikube image load $(prevDockerImage)
102102

103+
@echo "=====Setting hugepages values to 0 for e2e tests"
104+
sudo sysctl -w vm.nr_hugepages=0
105+
103106
@echo "=====Running e2e tests"
104-
$(if $(saveOutput),gotestsum --junitfile test/test_results/e2e-tests.xml ./test/e2e/... -count=1 -timeout 70m, go test -v -count=1 -timeout 70m ./test/e2e/...)
107+
$(if $(saveOutput),gotestsum --junitfile test/test_results/e2e-tests.xml ./test/e2e/... -count=1 -timeout 70m, go test -v -count=1 -timeout 70m ./test/e2e/...)
108+
109+
@echo "=====Setting hugepages value to 1280 for hugepages-e2e test"
110+
sudo sysctl -w vm.nr_hugepages=1280
111+
112+
@echo "=====Restart minikube cluster"
113+
minikube stop
114+
minikube start
115+
116+
@echo "=====Running hugepages e2e test"
117+
$(if $(saveOutput),gotestsum --junitfile test/test_results/hugePages-tests.xml ./test/hugePages/... -count=1 -timeout 70m, go test -v -count=1 -timeout 70m ./test/hugePages/...)
118+
119+
@echo "=====Resetting hugepages value to 0"
120+
sudo sysctl -w vm.nr_hugepages=0
105121

106122
@echo "=====Delete minikube cluster"
107123
minikube delete

test/hugePages/huge_pages_test.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package hugePages
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"io"
7+
"os"
8+
"strings"
9+
"testing"
10+
"time"
11+
12+
http_helper "github.com/gruntwork-io/terratest/modules/http-helper"
13+
"github.com/gruntwork-io/terratest/modules/k8s"
14+
"github.com/gruntwork-io/terratest/modules/random"
15+
"github.com/marklogic/marklogic-kubernetes/test/testUtil"
16+
"github.com/stretchr/testify/assert"
17+
digestAuth "github.com/xinsnake/go-http-digest-auth-client"
18+
)
19+
20+
func TestHugePagesSettings(t *testing.T) {
21+
// var resp *http.Response
22+
var body []byte
23+
var err error
24+
var podName string
25+
imageRepo, repoPres := os.LookupEnv("dockerRepository")
26+
imageTag, tagPres := os.LookupEnv("dockerVersion")
27+
28+
if !repoPres {
29+
imageRepo = "marklogicdb/marklogic-db"
30+
t.Logf("No imageRepo variable present, setting to default value: " + imageRepo)
31+
}
32+
33+
if !tagPres {
34+
imageTag = "latest"
35+
t.Logf("No imageTag variable present, setting to default value: " + imageTag)
36+
}
37+
38+
username := "admin"
39+
password := "admin"
40+
41+
options := map[string]string{
42+
"persistence.enabled": "false",
43+
"replicaCount": "1",
44+
"image.repository": imageRepo,
45+
"image.tag": imageTag,
46+
"auth.adminUsername": username,
47+
"auth.adminPassword": password,
48+
"logCollection.enabled": "false",
49+
"hugepages.enabled": "true",
50+
"hugepages.mountPath": "/dev/hugepages",
51+
"resources.limits.hugepages-2Mi": "1Gi",
52+
"resources.limits.memory": "8Gi",
53+
"resources.requests.memory": "8Gi",
54+
}
55+
t.Logf("====Installing Helm Chart")
56+
releaseName := "hugepages"
57+
58+
namespaceName := "ml-" + strings.ToLower(random.UniqueId())
59+
kubectlOptions := k8s.NewKubectlOptions("", "", namespaceName)
60+
61+
t.Logf("====Creating namespace: " + namespaceName)
62+
k8s.CreateNamespace(t, kubectlOptions, namespaceName)
63+
64+
defer t.Logf("====Deleting namespace: " + namespaceName)
65+
defer k8s.DeleteNamespace(t, kubectlOptions, namespaceName)
66+
67+
podName = testUtil.HelmInstall(t, options, releaseName, kubectlOptions)
68+
69+
t.Logf("====Describe pod for verifying huge pages")
70+
k8s.RunKubectl(t, kubectlOptions, "describe", "pod", podName)
71+
72+
tlsConfig := tls.Config{}
73+
// wait until the pod is in Ready status
74+
k8s.WaitUntilPodAvailable(t, kubectlOptions, podName, 10, 15*time.Second)
75+
76+
tunnel7997 := k8s.NewTunnel(kubectlOptions, k8s.ResourceTypePod, podName, 7997, 7997)
77+
defer tunnel7997.Close()
78+
tunnel7997.ForwardPort(t)
79+
endpoint7997 := fmt.Sprintf("http://%s", tunnel7997.Endpoint())
80+
81+
// verify if 7997 health check endpoint returns 200
82+
http_helper.HttpGetWithRetryWithCustomValidation(
83+
t,
84+
endpoint7997,
85+
&tlsConfig,
86+
10,
87+
15*time.Second,
88+
func(statusCode int, body string) bool {
89+
return statusCode == 200
90+
},
91+
)
92+
tunnel8002 := k8s.NewTunnel(kubectlOptions, k8s.ResourceTypePod, podName, 8002, 8002)
93+
defer tunnel8002.Close()
94+
tunnel8002.ForwardPort(t)
95+
endpointManage := fmt.Sprintf("http://%s/manage/v2/logs?format=text&filename=ErrorLog.txt", tunnel8002.Endpoint())
96+
request := digestAuth.NewRequest(username, password, "GET", endpointManage, "")
97+
response, err := request.Execute()
98+
if err != nil {
99+
t.Fatalf(err.Error())
100+
}
101+
defer response.Body.Close()
102+
assert.Equal(t, 200, response.StatusCode)
103+
104+
body, err = io.ReadAll(response.Body)
105+
t.Log(string(body))
106+
107+
// Verify if Huge pages are configured on the MarkLogic node
108+
if !strings.Contains(string(body), "Linux Huge Pages: detected 1280") {
109+
t.Errorf("Huge Pages not configured for the node")
110+
}
111+
}

test/template/hugePg_template_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package template_test
2+
3+
import (
4+
"path/filepath"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
appsv1 "k8s.io/api/apps/v1"
10+
11+
"github.com/gruntwork-io/terratest/modules/helm"
12+
"github.com/gruntwork-io/terratest/modules/k8s"
13+
"github.com/gruntwork-io/terratest/modules/random"
14+
)
15+
16+
func TestChartTemplateHugePagesConfig(t *testing.T) {
17+
18+
// Path to the helm chart we will test
19+
helmChartPath, err := filepath.Abs("../../charts")
20+
releaseName := "hugepages"
21+
t.Log(helmChartPath, releaseName)
22+
require.NoError(t, err)
23+
24+
// Set up the namespace; confirm that the template renders the expected value for the namespace.
25+
namespaceName := "ml-" + strings.ToLower(random.UniqueId())
26+
27+
// Setup the args for helm install
28+
options := &helm.Options{
29+
SetValues: map[string]string{
30+
"image.repository": "marklogicdb/marklogic-db",
31+
"image.tag": "latest",
32+
"persistence.enabled": "true",
33+
"logCollection.enabled": "true",
34+
"resources.limits.hugepages-2Mi": "1Gi",
35+
},
36+
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
37+
}
38+
39+
// render the tempate
40+
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/statefulset.yaml"})
41+
42+
var statefulset appsv1.StatefulSet
43+
helm.UnmarshalK8SYaml(t, output, &statefulset)
44+
45+
// Verify the name and namespace matches
46+
require.Equal(t, namespaceName, statefulset.Namespace)
47+
48+
expectedHugePages := "1Gi"
49+
50+
statefulSetContainers := statefulset.Spec.Template.Spec.Containers
51+
resourceLimits := statefulSetContainers[0].Resources.Limits
52+
53+
var actualHugePages string
54+
if value, exist := resourceLimits["hugepages-2Mi"]; exist {
55+
t.Log("ActualHugePages: ", value.String())
56+
actualHugePages = value.String()
57+
} else {
58+
t.Errorf("hugepages-2Mi not found")
59+
}
60+
// Verify the huge pages is configured
61+
require.Equal(t, len(statefulSetContainers), 2)
62+
require.Equal(t, actualHugePages, expectedHugePages)
63+
}

0 commit comments

Comments
 (0)