Skip to content

Commit 5511ee2

Browse files
pengzhoumlPeng Zhou
andauthored
MLE-22366 Test for image upgrade (#331)
* MLE-22366: automation for upgrade tests * add upgrade sanity test to make file * fix by copilot * fix lint issue --------- Co-authored-by: Peng Zhou <[email protected]>
1 parent f6f1e19 commit 5511ee2

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-0
lines changed

makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ template-test: prepare
195195
@echo "=====Running template tests"
196196
$(if $(saveOutput),gotestsum --junitfile test/test_results/testplate-tests.xml ./test/template/... -count=1, go test -v -count=1 ./test/template/...)
197197

198+
.PHONY: sanity-upgrade-tests
199+
sanity-upgrade-tests: prepare
200+
@echo "=====Running sanity upgrade tests"
201+
$(if $(saveOutput),gotestsum --junitfile test/test_results/upgrade-tests.xml ./test/upgrade/... -count=1, go test -v -count=1 ./test/upgrade/...)
202+
198203
#***************************************************************************
199204
# test
200205
#***************************************************************************
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package e2e
2+
3+
/********************************************************************************
4+
*
5+
* Test: MlImageUpgrade
6+
* This test verifies the upgrade of MarkLogic Docker images in a Kubernetes environment.
7+
*
8+
********************************************************************************/
9+
10+
import (
11+
"io"
12+
"path/filepath"
13+
"strings"
14+
"testing"
15+
"time"
16+
17+
"github.com/gruntwork-io/terratest/modules/helm"
18+
"github.com/gruntwork-io/terratest/modules/k8s"
19+
"github.com/gruntwork-io/terratest/modules/random"
20+
"github.com/imroc/req/v3"
21+
"github.com/marklogic/marklogic-kubernetes/test/testUtil"
22+
"github.com/tidwall/gjson"
23+
)
24+
25+
type DockerImage struct {
26+
Repo string
27+
Tag string
28+
Version string
29+
Type string
30+
Description string
31+
}
32+
33+
func TestMlImageUpgrade(t *testing.T) {
34+
var helmChartPath string
35+
var initialChartVersion string
36+
37+
adminUsername := "admin"
38+
adminPassword := "admin"
39+
40+
// Path to the helm chart we will test
41+
helmChartPath, err := filepath.Abs("../../charts")
42+
if err != nil {
43+
t.Fatalf(err.Error())
44+
}
45+
46+
upgradeImageList := [][]DockerImage{
47+
{
48+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-rootless-2.1.3", Version: "11030000", Type: "rootless", Description: "MarkLogic 11.3.1 UBI8 Rootless"},
49+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi-rootless", Tag: "latest-12-ubi-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI8 Rootless"},
50+
},
51+
{
52+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi9-rootless-2.1.3", Version: "11030000", Type: "rootless", Description: "MarkLogic 11.3.1 UBI9 Rootless"},
53+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-rootless", Tag: "latest-12-ubi9-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI9 Rootless"},
54+
},
55+
{
56+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-rootless-2.1.3", Version: "11030000", Type: "rootless", Description: "MarkLogic 11.3.1 UBI8 Rootless"},
57+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-rootless", Tag: "latest-12-ubi9-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI9 Rootless"},
58+
},
59+
{
60+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI8 Root"},
61+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi", Tag: "latest-12", Version: "12000000", Type: "root", Description: "MarkLogic 12 UBI8 Root"},
62+
},
63+
{
64+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi9-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI9 Root"},
65+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9", Tag: "latest-12", Version: "12000000", Type: "root", Description: "MarkLogic 12 UBI9 Root"},
66+
},
67+
{
68+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI8 Root"},
69+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9", Tag: "latest-12", Version: "12000000", Type: "root", Description: "MarkLogic 12 UBI9 Root"},
70+
},
71+
{
72+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI8 Root"},
73+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi-rootless", Tag: "latest-12-ubi-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI8 Rootless"},
74+
},
75+
{
76+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi9-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI9 Root"},
77+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-rootless", Tag: "latest-12-ubi9-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI9 Rootless"},
78+
},
79+
{
80+
DockerImage{Repo: "progressofficial/marklogic-db", Tag: "11.3.1-ubi-2.1.3", Version: "11030000", Type: "root", Description: "MarkLogic 11.3.1 UBI8 Root"},
81+
DockerImage{Repo: "ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-rootless", Tag: "latest-12-ubi9-rootless", Version: "12000000", Type: "rootless", Description: "MarkLogic 12 UBI9 Rootless"},
82+
},
83+
}
84+
85+
for i, image := range upgradeImageList {
86+
originalImage := image[0]
87+
upgradeImage := image[1]
88+
t.Logf("Running upgrade test %d with images: %s -> %s", i+1, originalImage.Description, upgradeImage.Description)
89+
90+
namespaceName := "ml-" + strings.ToLower(random.UniqueId())
91+
kubectlOptions := k8s.NewKubectlOptions("", "", namespaceName)
92+
valuesMap := map[string]string{
93+
"persistence.enabled": "true",
94+
"replicaCount": "1",
95+
"image.repository": originalImage.Repo,
96+
"image.tag": originalImage.Tag,
97+
"auth.adminUsername": adminUsername,
98+
"auth.adminPassword": adminPassword,
99+
"auth.walletPassword": "admin",
100+
}
101+
if originalImage.Type == "root" {
102+
valuesMap["containerSecurityContext.allowPrivilegeEscalation"] = "true"
103+
}
104+
105+
options := &helm.Options{
106+
KubectlOptions: kubectlOptions,
107+
SetValues: valuesMap,
108+
Version: initialChartVersion,
109+
ExtraArgs: map[string][]string{
110+
"install": {"--hide-notes"},
111+
},
112+
}
113+
114+
t.Logf("====Creating namespace: " + namespaceName)
115+
k8s.CreateNamespace(t, kubectlOptions, namespaceName)
116+
117+
t.Logf("====Setting helm chart path to %s", helmChartPath)
118+
t.Logf("====Installing Helm Chart")
119+
releaseName := "test-ml-upgrade"
120+
podName := testUtil.HelmInstall(t, options, releaseName, kubectlOptions, helmChartPath)
121+
122+
tunnel := k8s.NewTunnel(
123+
kubectlOptions, k8s.ResourceTypePod, podName, 8002, 8002)
124+
tunnel.ForwardPort(t)
125+
client := req.C().EnableInsecureSkipVerify()
126+
127+
currentMLVersion := getMLVersion(t, client, adminUsername, adminPassword)
128+
if currentMLVersion != originalImage.Version {
129+
t.Fatalf("Expected ML version to start with %s, but got %s",
130+
originalImage.Version, currentMLVersion)
131+
} else {
132+
t.Logf("ML version successfully installed: %s", currentMLVersion)
133+
}
134+
tunnel.Close()
135+
136+
// create options for helm upgrade
137+
upgradeOptionsMap := map[string]string{
138+
"image.repository": upgradeImage.Repo,
139+
"image.tag": upgradeImage.Tag,
140+
"persistence.enabled": "true",
141+
"replicaCount": "1",
142+
"logCollection.enabled": "false",
143+
}
144+
145+
if upgradeImage.Type == "root" {
146+
upgradeOptionsMap["containerSecurityContext.allowPrivilegeEscalation"] = "true"
147+
}
148+
149+
if originalImage.Type == "root" && upgradeImage.Type == "rootless" {
150+
t.Logf("====Performing root to rootless upgrade")
151+
upgradeOptionsMap["rootToRootlessUpgrade"] = "true"
152+
}
153+
154+
//set helm options for upgrading helm chart version
155+
helmUpgradeOptions := &helm.Options{
156+
KubectlOptions: kubectlOptions,
157+
SetValues: upgradeOptionsMap,
158+
ExtraArgs: map[string][]string{
159+
"upgrade": {"--hide-notes"},
160+
},
161+
}
162+
163+
helm.Upgrade(t, helmUpgradeOptions, helmChartPath, releaseName)
164+
t.Logf("====Waiting for pod to be available after upgrade")
165+
166+
k8s.RunKubectl(t, kubectlOptions, "delete", "pod", podName)
167+
k8s.WaitUntilPodAvailable(t, kubectlOptions, podName, 15, 15*time.Second)
168+
169+
t.Logf("====Checking if the pod is running after upgrade")
170+
pod := k8s.GetPod(t, kubectlOptions, podName)
171+
if pod.Status.Phase != "Running" {
172+
t.Fatalf("Pod %s is not running after upgrade, status: %s", podName, pod.Status.Phase)
173+
}
174+
175+
tunnel8001 := k8s.NewTunnel(
176+
kubectlOptions, k8s.ResourceTypePod, podName, 8001, 8001)
177+
tunnel8001.ForwardPort(t)
178+
179+
tunnel8002 := k8s.NewTunnel(
180+
kubectlOptions, k8s.ResourceTypePod, podName, 8002, 8002)
181+
tunnel8002.ForwardPort(t)
182+
183+
resp, err := client.R().
184+
SetDigestAuth(adminUsername, adminPassword).
185+
Post("http://localhost:8001/security-upgrade-go.xqy")
186+
187+
if err != nil {
188+
t.Fatalf("Error in upgrading ML Security DB: %s", err.Error())
189+
}
190+
body, err := io.ReadAll(resp.Body)
191+
if err != nil {
192+
t.Logf("error in reading the response: %s", err.Error())
193+
}
194+
if resp.StatusCode != 200 {
195+
t.Logf("Expected status code 200, got %d. Response: %s",
196+
resp.StatusCode, string(body))
197+
}
198+
199+
t.Logf("====Checking if the image is updated after upgrade")
200+
upgradedMLVersion := getMLVersion(t, client, adminUsername, adminPassword)
201+
t.Logf("====Current ML Version after upgrade: %s", upgradedMLVersion)
202+
203+
if upgradedMLVersion != upgradeImage.Version {
204+
t.Fatalf("Expected ML version to start with %s, but got %s",
205+
upgradeImage.Version, upgradedMLVersion)
206+
} else {
207+
t.Logf("ML version successfully upgraded to %s", upgradedMLVersion)
208+
}
209+
t.Logf("====Deleting namespace: " + namespaceName)
210+
tunnel8001.Close()
211+
tunnel8002.Close()
212+
k8s.DeleteNamespace(t, kubectlOptions, namespaceName)
213+
}
214+
}
215+
216+
func getMLVersion(t *testing.T, client *req.Client, adminUsername, adminPassword string) string {
217+
resp, err := client.R().
218+
SetDigestAuth(adminUsername, adminPassword).
219+
Get("http://localhost:8002/manage/v2?format=json")
220+
221+
if err != nil {
222+
t.Fatalf(err.Error())
223+
}
224+
body, err := io.ReadAll(resp.Body)
225+
if err != nil {
226+
t.Logf("error in reading the response: %s", err.Error())
227+
}
228+
if resp.StatusCode != 200 {
229+
t.Fatalf("Expected status code 200, got %d. Response: %s",
230+
resp.StatusCode, string(body))
231+
}
232+
mlVersion := gjson.Get(string(body), `local-cluster-default.effective-version`).String()
233+
return mlVersion
234+
}

0 commit comments

Comments
 (0)