Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 00a5a62

Browse files
committed
Merge branch 'vz-sessiontests' into 'main'
Add session migration tests to v8o See merge request weblogic-cloud/weblogic-kubernetes-operator!4460
2 parents 5185daa + b461f12 commit 00a5a62

File tree

5 files changed

+401
-34
lines changed

5 files changed

+401
-34
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
// Copyright (c) 2023, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package oracle.verrazzano.weblogic.kubernetes;
5+
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.Collections;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Optional;
13+
14+
import io.kubernetes.client.custom.Quantity;
15+
import io.kubernetes.client.openapi.models.V1ObjectMeta;
16+
import io.kubernetes.client.util.Yaml;
17+
import oracle.verrazzano.weblogic.ApplicationConfiguration;
18+
import oracle.verrazzano.weblogic.ApplicationConfigurationSpec;
19+
import oracle.verrazzano.weblogic.Component;
20+
import oracle.verrazzano.weblogic.ComponentSpec;
21+
import oracle.verrazzano.weblogic.Components;
22+
import oracle.verrazzano.weblogic.Destination;
23+
import oracle.verrazzano.weblogic.IngressRule;
24+
import oracle.verrazzano.weblogic.IngressTrait;
25+
import oracle.verrazzano.weblogic.IngressTraitSpec;
26+
import oracle.verrazzano.weblogic.IngressTraits;
27+
import oracle.verrazzano.weblogic.Path;
28+
import oracle.verrazzano.weblogic.Workload;
29+
import oracle.verrazzano.weblogic.WorkloadSpec;
30+
import oracle.verrazzano.weblogic.kubernetes.annotations.VzIntegrationTest;
31+
import oracle.weblogic.domain.DomainResource;
32+
import oracle.weblogic.kubernetes.annotations.Namespaces;
33+
import oracle.weblogic.kubernetes.logging.LoggingFacade;
34+
import org.junit.jupiter.api.BeforeAll;
35+
import org.junit.jupiter.api.DisplayName;
36+
import org.junit.jupiter.api.Tag;
37+
import org.junit.jupiter.api.Test;
38+
39+
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT;
40+
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_SERVER_NAME_BASE;
41+
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_USERNAME_DEFAULT;
42+
import static oracle.weblogic.kubernetes.TestConstants.MANAGED_SERVER_NAME_BASE;
43+
import static oracle.weblogic.kubernetes.TestConstants.TEST_IMAGES_REPO_SECRET_NAME;
44+
import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.createApplication;
45+
import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.createComponent;
46+
import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkPodReadyAndServiceExists;
47+
import static oracle.weblogic.kubernetes.utils.CommonTestUtils.generateNewModelFileWithUpdatedDomainUid;
48+
import static oracle.weblogic.kubernetes.utils.ConfigMapUtils.createConfigMapAndVerify;
49+
import static oracle.weblogic.kubernetes.utils.ImageUtils.createMiiImageAndVerify;
50+
import static oracle.weblogic.kubernetes.utils.ImageUtils.createTestRepoSecret;
51+
import static oracle.weblogic.kubernetes.utils.ImageUtils.imageRepoLoginAndPushImageToRegistry;
52+
import static oracle.weblogic.kubernetes.utils.IstioUtils.createIstioDomainResource;
53+
import static oracle.weblogic.kubernetes.utils.SecretUtils.createSecretWithUsernamePassword;
54+
import static oracle.weblogic.kubernetes.utils.SessionMigrationUtil.getOrigModelFile;
55+
import static oracle.weblogic.kubernetes.utils.SessionMigrationUtil.getServerAndSessionInfoAndVerify;
56+
import static oracle.weblogic.kubernetes.utils.SessionMigrationUtil.shutdownServerAndVerify;
57+
import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger;
58+
import static oracle.weblogic.kubernetes.utils.VerrazzanoUtils.getIstioHost;
59+
import static oracle.weblogic.kubernetes.utils.VerrazzanoUtils.getLoadbalancerAddress;
60+
import static oracle.weblogic.kubernetes.utils.VerrazzanoUtils.setLabelToNamespace;
61+
import static oracle.weblogic.kubernetes.utils.VerrazzanoUtils.verifyVzApplicationAccess;
62+
import static org.junit.jupiter.api.Assertions.assertAll;
63+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
64+
import static org.junit.jupiter.api.Assertions.assertEquals;
65+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
66+
import static org.junit.jupiter.api.Assertions.assertNotNull;
67+
import static org.junit.jupiter.api.Assertions.assertTrue;
68+
69+
@DisplayName("Test WLS Session Migration when istio is enabled")
70+
@VzIntegrationTest
71+
@Tag("v8o")
72+
class ItVzIstioSessionMigration {
73+
74+
private static String domainNamespace = null;
75+
76+
// constants for creating domain image using model in image
77+
private static final String SESSMIGR_IMAGE_NAME = "istio-sessmigr-mii-image";
78+
79+
// constants for web service
80+
private static final String SESSMIGR_APP_NAME = "sessmigr-app";
81+
private static final String SESSMIGR_APP_WAR_NAME = "sessmigr-war";
82+
private static final int SESSION_STATE = 4;
83+
private static Map<String, String> httpAttrMap;
84+
85+
// constants for operator and WebLogic domain
86+
private static String domainUid = "istio-sessmigr-domain";
87+
private static String clusterName = "cluster-1";
88+
private static String adminServerPodName = domainUid + "-" + ADMIN_SERVER_NAME_BASE;
89+
private static String managedServerPrefix = domainUid + "-" + MANAGED_SERVER_NAME_BASE;
90+
private static int managedServerPort = 7100;
91+
private static String finalPrimaryServerName = null;
92+
private static String configMapName = "istio-configmap";
93+
private static int replicaCount = 2;
94+
private static DomainResource domain;
95+
96+
97+
private static LoggingFacade logger = null;
98+
99+
private static Map<String, Quantity> resourceRequest = new HashMap<>();
100+
private static Map<String, Quantity> resourceLimit = new HashMap<>();
101+
102+
/**
103+
* Build custom image using model in image with model files
104+
* and create a verrazzano application with a dynamic cluster.
105+
*
106+
* @param namespaces list of namespaces created by the IntegrationTestWatcher by the
107+
* JUnit engine parameter resolution mechanism
108+
*/
109+
@BeforeAll
110+
public static void initAll(@Namespaces(1) List<String> namespaces) {
111+
logger = getLogger();
112+
113+
logger.info("Assign unique namespace for Domain");
114+
assertNotNull(namespaces.get(0), "Namespace list is null");
115+
domainNamespace = namespaces.get(0);
116+
assertDoesNotThrow(() -> setLabelToNamespace(Arrays.asList(domainNamespace)));
117+
118+
// Generate the model.sessmigr.yaml file at RESULTS_ROOT
119+
String destSessionMigrYamlFile =
120+
generateNewModelFileWithUpdatedDomainUid(domainUid, "ItVzIstioSessionMigration", getOrigModelFile());
121+
122+
List<String> appList = new ArrayList<>();
123+
appList.add(SESSMIGR_APP_NAME);
124+
125+
// build the model file list
126+
final List<String> modelList = Collections.singletonList(destSessionMigrYamlFile);
127+
128+
// create image with model files
129+
logger.info("Create image with model file and verify");
130+
String miiImage = createMiiImageAndVerify(SESSMIGR_IMAGE_NAME, modelList, appList);
131+
132+
// repo login and push image to registry if necessary
133+
imageRepoLoginAndPushImageToRegistry(miiImage);
134+
135+
// set resource request and limit
136+
resourceRequest.put("cpu", new Quantity("250m"));
137+
resourceRequest.put("memory", new Quantity("768Mi"));
138+
resourceLimit.put("cpu", new Quantity("2"));
139+
resourceLimit.put("memory", new Quantity("2Gi"));
140+
141+
// create secret for admin credentials
142+
logger.info("Create secret for admin credentials");
143+
String adminSecretName = "weblogic-credentials";
144+
assertDoesNotThrow(() -> createSecretWithUsernamePassword(
145+
adminSecretName,
146+
domainNamespace,
147+
ADMIN_USERNAME_DEFAULT,
148+
ADMIN_PASSWORD_DEFAULT),
149+
String.format("createSecret failed for %s", adminSecretName));
150+
151+
// create encryption secret
152+
logger.info("Create encryption secret");
153+
String encryptionSecretName = "encryptionsecret";
154+
assertDoesNotThrow(() -> createSecretWithUsernamePassword(
155+
encryptionSecretName,
156+
domainNamespace,
157+
"weblogicenc",
158+
"weblogicenc"),
159+
String.format("createSecret failed for %s", encryptionSecretName));
160+
161+
domain = createDomainCrAndVerify(adminSecretName, encryptionSecretName, miiImage);
162+
createVzApplication();
163+
164+
// map to save HTTP response data
165+
httpAttrMap = new HashMap<String, String>();
166+
httpAttrMap.put("sessioncreatetime", "(.*)sessioncreatetime>(.*)</sessioncreatetime(.*)");
167+
httpAttrMap.put("sessionid", "(.*)sessionid>(.*)</sessionid(.*)");
168+
httpAttrMap.put("primary", "(.*)primary>(.*)</primary(.*)");
169+
httpAttrMap.put("secondary", "(.*)secondary>(.*)</secondary(.*)");
170+
httpAttrMap.put("count", "(.*)countattribute>(.*)</countattribute(.*)");
171+
}
172+
173+
/**
174+
* In an istio enabled Environment, test sends a HTTP request to set http session state(count number),
175+
* get the primary and secondary server name, session create time and session state and from the util method
176+
* and save HTTP session info, then stop the primary server by changing ServerStartPolicy to Never and
177+
* patching domain. Send another HTTP request to get http session state (count number), primary server
178+
* and session create time. Verify that a new primary server is selected and HTTP session state is migrated.
179+
*/
180+
@Test
181+
@DisplayName("Verify session migration in an istio enabled environment")
182+
void testSessionMigrationIstioEnabled() {
183+
final String primaryServerAttr = "primary";
184+
final String secondaryServerAttr = "secondary";
185+
final String sessionCreateTimeAttr = "sessioncreatetime";
186+
final String countAttr = "count";
187+
final String webServiceSetUrl = SESSMIGR_APP_WAR_NAME + "/?setCounter=" + SESSION_STATE;
188+
final String webServiceGetUrl = SESSMIGR_APP_WAR_NAME + "/?getCounter";
189+
final String clusterAddress = domainUid + "-cluster-" + clusterName;
190+
String serverName = managedServerPrefix + "1";
191+
192+
// send a HTTP request to set http session state(count number) and save HTTP session info
193+
// before shutting down the primary server
194+
Map<String, String> httpDataInfo = getServerAndSessionInfoAndVerify(domainNamespace,
195+
adminServerPodName, serverName, clusterAddress, managedServerPort, webServiceSetUrl, " -c ");
196+
197+
// get server and session info from web service deployed on the cluster
198+
String origPrimaryServerName = httpDataInfo.get(primaryServerAttr);
199+
String origSecondaryServerName = httpDataInfo.get(secondaryServerAttr);
200+
String origSessionCreateTime = httpDataInfo.get(sessionCreateTimeAttr);
201+
logger.info("Got the primary server {0}, the secondary server {1} "
202+
+ "and session create time {2} before shutting down the primary server.",
203+
origPrimaryServerName, origSecondaryServerName, origSessionCreateTime);
204+
205+
// stop the primary server by changing ServerStartPolicy to Never and patching domain
206+
logger.info("Shut down the primary server {0}", origPrimaryServerName);
207+
shutdownServerAndVerify(domainUid, domainNamespace, origPrimaryServerName);
208+
209+
// send a HTTP request to get server and session info after shutting down the primary server
210+
serverName = domainUid + "-" + origSecondaryServerName;
211+
httpDataInfo = getServerAndSessionInfoAndVerify(domainNamespace, adminServerPodName,
212+
serverName, clusterAddress, managedServerPort, webServiceGetUrl, " -b ");
213+
214+
// get server and session info from web service deployed on the cluster
215+
String primaryServerName = httpDataInfo.get(primaryServerAttr);
216+
String sessionCreateTime = httpDataInfo.get(sessionCreateTimeAttr);
217+
String countStr = httpDataInfo.get(countAttr);
218+
int count;
219+
if (countStr.equalsIgnoreCase("null")) {
220+
count = managedServerPort;
221+
} else {
222+
count = Optional.ofNullable(countStr).map(Integer::valueOf).orElse(managedServerPort);
223+
}
224+
logger.info("After patching the domain, the primary server changes to {0} "
225+
+ ", session create time {1} and session state {2}",
226+
primaryServerName, sessionCreateTime, countStr);
227+
228+
// verify that a new primary server is picked and HTTP session state is migrated
229+
assertAll("Check that WebLogic server and session vars is not null or empty",
230+
() -> assertNotEquals(origPrimaryServerName, primaryServerName,
231+
"After the primary server stopped, another server should become the new primary server"),
232+
() -> assertEquals(origSessionCreateTime, sessionCreateTime,
233+
"After the primary server stopped, HTTP session state should be migrated to the new primary server"),
234+
() -> assertEquals(SESSION_STATE, count,
235+
"After the primary server stopped, HTTP session state should be migrated to the new primary server")
236+
);
237+
238+
finalPrimaryServerName = primaryServerName;
239+
240+
logger.info("Done testSessionMigration \nThe new primary server is {0}, it was {1}. "
241+
+ "\nThe session state was set to {2}, it is migrated to the new primary server.",
242+
primaryServerName, origPrimaryServerName, SESSION_STATE);
243+
}
244+
245+
private static void createVzApplication() {
246+
247+
Component component = new Component()
248+
.apiVersion("core.oam.dev/v1alpha2")
249+
.kind("Component")
250+
.metadata(new V1ObjectMeta()
251+
.name(domainUid)
252+
.namespace(domainNamespace))
253+
.spec(new ComponentSpec()
254+
.workLoad(new Workload()
255+
.apiVersion("oam.verrazzano.io/v1alpha1")
256+
.kind("VerrazzanoWebLogicWorkload")
257+
.spec(new WorkloadSpec()
258+
.template(domain))));
259+
260+
Map<String, String> keyValueMap = new HashMap<>();
261+
keyValueMap.put("version", "v1.0.0");
262+
keyValueMap.put("description", "My vz wls application");
263+
264+
ApplicationConfiguration application = new ApplicationConfiguration()
265+
.apiVersion("core.oam.dev/v1alpha2")
266+
.kind("ApplicationConfiguration")
267+
.metadata(new V1ObjectMeta()
268+
.name("myvzsessiondomain")
269+
.namespace(domainNamespace)
270+
.annotations(keyValueMap))
271+
.spec(new ApplicationConfigurationSpec()
272+
.components(Arrays.asList(new Components()
273+
.componentName(domainUid)
274+
.traits(Arrays.asList(new IngressTraits()
275+
.trait(new IngressTrait()
276+
.apiVersion("oam.verrazzano.io/v1alpha1")
277+
.kind("IngressTrait")
278+
.metadata(new V1ObjectMeta()
279+
.name("mydomain-ingress")
280+
.namespace(domainNamespace))
281+
.spec(new IngressTraitSpec()
282+
.ingressRules(Arrays.asList(
283+
new IngressRule()
284+
.paths(Arrays.asList(new Path()
285+
.path("/console")
286+
.pathType("Prefix")))
287+
.destination(new Destination()
288+
.host(adminServerPodName)
289+
.port(7001)),
290+
new IngressRule()
291+
.paths(Arrays.asList(new Path()
292+
.path("/sessmigr-app")
293+
.pathType("Prefix")))
294+
.destination(new Destination()
295+
.host(domainUid + "-cluster-" + clusterName)
296+
.port(managedServerPort)))))))))));
297+
298+
logger.info(Yaml.dump(component));
299+
logger.info(Yaml.dump(application));
300+
301+
logger.info("Deploying components");
302+
assertDoesNotThrow(() -> createComponent(component));
303+
logger.info("Deploying application");
304+
assertDoesNotThrow(() -> createApplication(application));
305+
306+
// check admin server pod is ready
307+
logger.info("Wait for admin server pod {0} to be ready in namespace {1}",
308+
adminServerPodName, domainNamespace);
309+
checkPodReadyAndServiceExists(adminServerPodName, domainUid, domainNamespace);
310+
// check managed server pods are ready
311+
for (int i = 1; i <= replicaCount; i++) {
312+
logger.info("Wait for managed server pod {0} to be ready in namespace {1}",
313+
managedServerPrefix + i, domainNamespace);
314+
checkPodReadyAndServiceExists(managedServerPrefix + i, domainUid, domainNamespace);
315+
}
316+
317+
// get istio gateway host and loadbalancer address
318+
String host = getIstioHost(domainNamespace);
319+
String address = getLoadbalancerAddress();
320+
321+
// verify WebLogic console page is accessible through istio/loadbalancer
322+
String message = "Oracle WebLogic Server Administration Console";
323+
String consoleUrl = "https://" + host + "/console/login/LoginForm.jsp --resolve " + host + ":443:" + address;
324+
assertTrue(verifyVzApplicationAccess(consoleUrl, message), "Failed to get WebLogic administration console");
325+
}
326+
327+
private static DomainResource createDomainCrAndVerify(String adminSecretName,
328+
String encryptionSecretName,
329+
String miiImage) {
330+
331+
// Create the repo secret to pull the image
332+
// this secret is used only for non-kind cluster
333+
createTestRepoSecret(domainNamespace);
334+
335+
// create WDT config map without any files
336+
createConfigMapAndVerify(configMapName, domainUid, domainNamespace, Collections.emptyList());
337+
338+
// create the domain object
339+
DomainResource domain = createIstioDomainResource(domainUid,
340+
domainNamespace,
341+
adminSecretName,
342+
TEST_IMAGES_REPO_SECRET_NAME,
343+
encryptionSecretName,
344+
replicaCount,
345+
miiImage,
346+
configMapName,
347+
clusterName);
348+
return domain;
349+
}
350+
351+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /