Skip to content

Commit 134ac54

Browse files
authored
Merge pull request #950 from oracle/session-migration-tests
READY TO MERGE: Completed JIRA OWLS-71984 - Migrate Session Migration test suite to GitHub
2 parents d809757 + c144468 commit 134ac54

File tree

10 files changed

+922
-1
lines changed

10 files changed

+922
-1
lines changed

integration-tests/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ Configuration Overrides Usecases
9797
| JMS Resource Override | Override UniformDistributedTopic Delivery Failure Parameters, `redelivery-limit` and `expiration-policy`. The JMX test client verifies the serverConfig MBean tree for the expected delivery failure parameters, `redelivery-limit` and `expiration-policy`. |
9898
| WLDF Resource Override | Override `wldf-instrumentation-monitor` and `harvester` in a diagnostics module. The test client verifies the new instrumentation monitors/harvesters set by getting the WLDF resource from serverConfig tree with expected values. |
9999

100+
| Session Migration | Use Case |
101+
| --- | --- |
102+
| Primary Server Repick | A backup server becomes the primary server when a primary server fails|
103+
| HTTP Session Migration | Verify in-memory HTTP session State replication |
100104

101105
# Directory Configuration and Structure
102106

integration-tests/src/test/java/oracle/kubernetes/operator/BaseTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class BaseTest {
6363
private static String leaseId = "";
6464
private static String branchName = "";
6565
private static String appLocationInPod = "/u01/oracle/apps";
66+
private static String appLocationOnHost;
6667
private static Properties appProps;
6768

6869
// Set QUICKTEST env var to true to run a small subset of tests.
@@ -183,6 +184,8 @@ public static void initialize(String appPropsFile) throws Exception {
183184
}
184185
}
185186

187+
appLocationOnHost = getProjectRoot() + "/integration-tests/src/test/resources/apps";
188+
186189
logger.info("appProps = " + appProps);
187190
logger.info("maxIterationPod = " + appProps.getProperty("maxIterationsPod"));
188191
logger.info(
@@ -545,6 +548,14 @@ public static String getBranchName() {
545548
return branchName;
546549
}
547550

551+
public static String getAppLocationInPod() {
552+
return appLocationInPod;
553+
}
554+
555+
public static String getAppLocationOnHost() {
556+
return appLocationOnHost;
557+
}
558+
548559
private void copyScalingScriptToPod(
549560
String dirPathToCreate, String domainUID, String podName, String domainNS) throws Exception {
550561

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
// Copyright 2019, Oracle Corporation and/or its affiliates. All rights reserved.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at
3+
// http://oss.oracle.com/licenses/upl.
4+
5+
package oracle.kubernetes.operator;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
import java.util.regex.Matcher;
10+
import java.util.regex.Pattern;
11+
import oracle.kubernetes.operator.utils.Domain;
12+
import oracle.kubernetes.operator.utils.ExecCommand;
13+
import oracle.kubernetes.operator.utils.ExecResult;
14+
import oracle.kubernetes.operator.utils.Operator;
15+
import oracle.kubernetes.operator.utils.TestUtils;
16+
import org.junit.AfterClass;
17+
import org.junit.Assume;
18+
import org.junit.BeforeClass;
19+
import org.junit.FixMethodOrder;
20+
import org.junit.Test;
21+
import org.junit.runners.MethodSorters;
22+
23+
/**
24+
* Simple JUnit test file used for testing Operator.
25+
*
26+
* <p>This test is used for creating Operator(s) and domain(s) which are managed by the Operator(s).
27+
* And to test WLS Session Migration feature
28+
*/
29+
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
30+
public class ITSessionMigration extends BaseTest {
31+
private static final String testAppName = "httpsessionreptestapp";
32+
private static final String scriptName = "buildDeployAppInPod.sh";
33+
34+
private static Map<String, String> httpAttrMap;
35+
36+
private static String httpHeaderFile;
37+
38+
private static Operator operator;
39+
private static Domain domain;
40+
41+
/**
42+
* This method gets called only once before any of the test methods are executed. It does the
43+
* initialization of the integration test properties defined in OperatorIT.properties and setting
44+
* the resultRoot, pvRoot and projectRoot attributes.
45+
*
46+
* <p>It also create operator and verify its deployed successfully. Create domain and verify
47+
* domain is created.
48+
*
49+
* @throws Exception
50+
*/
51+
@BeforeClass
52+
public static void staticPrepare() throws Exception {
53+
if (!QUICKTEST) {
54+
// initialize test properties and create the directories
55+
initialize(APP_PROPS_FILE);
56+
57+
// Create operator1
58+
if (operator == null) {
59+
logger.info("Creating Operator & waiting for the script to complete execution");
60+
operator = TestUtils.createOperator(OPERATOR1_YAML);
61+
}
62+
63+
// create domain
64+
if (domain == null) {
65+
logger.info("Creating WLS Domain & waiting for the script to complete execution");
66+
domain = TestUtils.createDomain(DOMAINONPV_WLST_YAML);
67+
domain.verifyDomainCreated();
68+
}
69+
70+
httpHeaderFile = BaseTest.getResultDir() + "/headers";
71+
72+
httpAttrMap = new HashMap<String, String>();
73+
httpAttrMap.put("sessioncreatetime", "(.*)sessioncreatetime>(.*)</sessioncreatetime(.*)");
74+
httpAttrMap.put("sessionid", "(.*)sessionid>(.*)</sessionid(.*)");
75+
httpAttrMap.put("primary", "(.*)primary>(.*)</primary(.*)");
76+
httpAttrMap.put("secondary", "(.*)secondary>(.*)</secondary(.*)");
77+
httpAttrMap.put("count", "(.*)countattribute>(.*)</countattribute(.*)");
78+
79+
// Build WAR in the admin pod and deploy it from the admin pod to a weblogic target
80+
domain.buildDeployJavaAppInPod(
81+
testAppName, scriptName, BaseTest.getUsername(), BaseTest.getPassword());
82+
83+
// Wait some time for deployment gets ready
84+
Thread.sleep(10 * 1000);
85+
}
86+
}
87+
88+
/**
89+
* Releases k8s cluster lease, archives result, pv directories
90+
*
91+
* @throws Exception
92+
*/
93+
@AfterClass
94+
public static void staticUnPrepare() throws Exception {
95+
if (!QUICKTEST) {
96+
logger.info("++++++++++++++++++++++++++++++++++");
97+
logger.info("BEGIN");
98+
logger.info("Run once, release cluster lease");
99+
100+
tearDown();
101+
102+
logger.info("SUCCESS");
103+
}
104+
}
105+
106+
/**
107+
* Verify that a new and running managed server is picked up as the primary server after the
108+
* primary server shut down
109+
*
110+
* @throws Exception
111+
*/
112+
@Test
113+
public void testRepickPrimary() throws Exception {
114+
Assume.assumeFalse(QUICKTEST);
115+
String testMethodName = new Object() {}.getClass().getEnclosingMethod().getName();
116+
logTestBegin(testMethodName);
117+
118+
Map<String, Object> domainMap = domain.getDomainMap();
119+
String domainNS = domainMap.get("namespace").toString();
120+
String domainUid = domain.getDomainUid();
121+
122+
String testAppPath = testAppName + "/CounterServlet";
123+
String sessCreateTime = "sessioncreatetime";
124+
String primaryServ = "primary";
125+
126+
// Send the first HTTP request and save HTTP header/sessionID info
127+
ExecResult result = getHTTPResponse(testAppPath, " -D ");
128+
129+
// Get primary server name & session create time bf primaryServName1 is stopped
130+
String primaryServName1 = getHttpResponseAttribute(result.stdout(), primaryServ);
131+
String sessCreateTime1 = getHttpResponseAttribute(result.stdout(), sessCreateTime);
132+
133+
// Stop primary server
134+
stopPrimaryServer(primaryServName1);
135+
136+
// Send the second HTTP request using HTTP header/sessionID info save before
137+
result = getHTTPResponse(testAppPath, " -b ");
138+
139+
// Get primary server name & session create time af primaryServName1 is stopped
140+
String primaryServName2 = getHttpResponseAttribute(result.stdout(), primaryServ);
141+
String sessCreateTime2 = getHttpResponseAttribute(result.stdout(), sessCreateTime);
142+
143+
// Verify that the same session info is used
144+
Assume.assumeTrue("HTTP Session should NOT change!", sessCreateTime1.equals(sessCreateTime2));
145+
146+
// Verify that a new primary server is picked
147+
Assume.assumeFalse(
148+
"A new primary server should be picked!",
149+
primaryServName1.trim().equals(primaryServName2.trim()));
150+
151+
// Restore test env
152+
TestUtils.checkPodReady(domainUid + "-" + primaryServName1, domainNS);
153+
154+
logger.info(
155+
"SUCCESS - " + testMethodName + ". ms <" + primaryServName2 + "> is new primary server.");
156+
}
157+
158+
/**
159+
* Verify that HTTP session state is migrated to the new primary server after the primary server
160+
* shut down
161+
*
162+
* @throws Exception
163+
*/
164+
@Test
165+
public void testHttpSessionMigr() throws Exception {
166+
Assume.assumeFalse(QUICKTEST);
167+
String testMethodName = new Object() {}.getClass().getEnclosingMethod().getName();
168+
logTestBegin(testMethodName);
169+
170+
Map<String, Object> domainMap = domain.getDomainMap();
171+
String domainNS = domainMap.get("namespace").toString();
172+
String domainUid = domain.getDomainUid();
173+
174+
int counterNum = 4;
175+
String testAppPath = testAppName + "/CounterServlet";
176+
String webServiceSetUrl = testAppPath + "?setCounter=" + counterNum;
177+
String webServiceGetUrl = testAppPath + "?getCounter";
178+
179+
String primaryServ = "primary";
180+
String count = "count";
181+
182+
// Send the first HTTP request and save HTTP header/sessionID info
183+
ExecResult result = getHTTPResponse(webServiceSetUrl, " -D ");
184+
185+
// Get primary server name & count number bf primaryServName1 is stopped
186+
String primaryServName1 = getHttpResponseAttribute(result.stdout(), primaryServ);
187+
String countattribute1 = getHttpResponseAttribute(result.stdout(), count);
188+
189+
// Stop primary server
190+
stopPrimaryServer(primaryServName1);
191+
192+
// Send the second HTTP request using HTTP header/sessionID info save before
193+
result = getHTTPResponse(webServiceGetUrl, " -b ");
194+
195+
// Get primary server name & count number af primaryServName1 is stopped
196+
String primaryServName2 = getHttpResponseAttribute(result.stdout(), primaryServ);
197+
String countattribute2 = getHttpResponseAttribute(result.stdout(), count);
198+
199+
// Verify that the count number is from a new primary server
200+
Assume.assumeFalse(
201+
"A new primary server should be picked!",
202+
primaryServName1.trim().equals(primaryServName2.trim()));
203+
204+
// Verify that HTTP session state is migrated by checking the count number same
205+
// bf and af primaryServName1 stopped
206+
Assume.assumeTrue(
207+
"HTTP session state is NOT migrated!", countattribute1.equals(countattribute2));
208+
209+
// Restore test env
210+
TestUtils.checkPodReady(domainUid + "-" + primaryServName1, domainNS);
211+
212+
logger.info("SUCCESS - " + testMethodName + ". HTTP session state is migrated!");
213+
}
214+
215+
/**
216+
* Get HTTP response from the web app deployed on wls
217+
*
218+
* @param webServiceURL - web server URL
219+
* @param headerOption - option to save HTTP header info or use it
220+
* @throws Exception
221+
*/
222+
private ExecResult getHTTPResponse(String webServiceURL, String headerOption) throws Exception {
223+
// Send a HTTP request
224+
String curlCmd = buildWebServiceUrl(webServiceURL, headerOption + httpHeaderFile);
225+
logger.info("Send a HTTP request: " + curlCmd);
226+
227+
ExecResult result = ExecCommand.exec(curlCmd);
228+
229+
if (result.exitValue() != 0) {
230+
throw new Exception(
231+
"FAILURE: command "
232+
+ curlCmd
233+
+ " failed, returned "
234+
+ result.stderr()
235+
+ "\n "
236+
+ result.stdout());
237+
}
238+
239+
return result;
240+
}
241+
242+
/**
243+
* Stop the primary server
244+
*
245+
* @param primaryServerName - weblogic primary server name
246+
* @throws Exception
247+
*/
248+
private void stopPrimaryServer(String primaryServerName) throws Exception {
249+
Map<String, Object> domainMap = domain.getDomainMap();
250+
String domainNS = domainMap.get("namespace").toString();
251+
String domainUid = domain.getDomainUid();
252+
253+
// stop primary server
254+
String msPodName = domainUid + "-" + primaryServerName;
255+
String cmd = "kubectl delete po/" + msPodName + " -n " + domainNS;
256+
logger.info("Stop managed server <" + msPodName + "> using command:\n" + cmd);
257+
258+
ExecResult result = ExecCommand.exec(cmd);
259+
if (result.exitValue() != 0) {
260+
throw new Exception("FAILURE: command " + cmd + " failed, returned " + result.stderr());
261+
}
262+
263+
logger.info(result.stdout());
264+
}
265+
266+
/**
267+
* Get the value of a HTTP attribute
268+
*
269+
* @param httpResponseString - HTTP response
270+
* @param attribute - attrubute name to find in the HTTP response
271+
* @throws Exception
272+
*/
273+
private String getHttpResponseAttribute(String httpResponseString, String attribute)
274+
throws Exception {
275+
276+
String attrPatn = httpAttrMap.get(attribute);
277+
278+
Assume.assumeNotNull(attrPatn);
279+
280+
String httpAttribute = null;
281+
282+
Pattern pattern = Pattern.compile(attrPatn);
283+
Matcher matcher = pattern.matcher(httpResponseString);
284+
if (matcher.find()) {
285+
httpAttribute = matcher.group(2);
286+
}
287+
288+
return httpAttribute;
289+
}
290+
291+
/**
292+
* Build web server url
293+
*
294+
* @param curlURLPath - URL path sent by curl
295+
* @param paramToAppend - params need to be appended to the URL path
296+
* @throws Exception
297+
*/
298+
private String buildWebServiceUrl(String curlURLPath, String paramToAppend) throws Exception {
299+
String nodePortHost = domain.getHostNameForCurl();
300+
int nodePort = domain.getLoadBalancerWebPort();
301+
302+
StringBuffer webServiceUrl = new StringBuffer("curl --silent ");
303+
webServiceUrl
304+
.append(" -H 'host: ")
305+
.append(domain.getDomainUid())
306+
.append(".org' ")
307+
.append(" http://")
308+
.append(nodePortHost)
309+
.append(":")
310+
.append(nodePort)
311+
.append("/")
312+
.append(curlURLPath)
313+
.append(paramToAppend);
314+
315+
return webServiceUrl.toString();
316+
}
317+
318+
/**
319+
* Execute a given curl command and verify the results
320+
*
321+
* @param curlCmd - a curl command to execute
322+
* @throws Exception
323+
*/
324+
private ExecResult execCurlCmd(String curlCmd) throws Exception {
325+
logger.info("curl command to exec is:\n" + curlCmd);
326+
327+
ExecResult result = ExecCommand.exec(curlCmd);
328+
329+
if (result.exitValue() != 0) {
330+
throw new Exception(
331+
"FAILURE: command "
332+
+ curlCmd
333+
+ " failed, returned "
334+
+ result.stderr()
335+
+ "\n "
336+
+ result.stdout());
337+
}
338+
339+
return result;
340+
}
341+
}

0 commit comments

Comments
 (0)