Skip to content

Commit 95d2924

Browse files
Merge remote-tracking branch 'origin/develop' into voyager-integ-test
2 parents 09cd4d1 + 52194eb commit 95d2924

23 files changed

+1947
-60
lines changed

docs-source/content/userguide/managing-domains/persistent-storage/_index.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,41 @@ Persistent volumes can point to different storage locations, for example NFS ser
2222

2323
The persistent volume for the domain must be created using the appropriate tools before running the script to create the domain. In the simplest case, namely the `HOST_PATH` provider, this means creating a directory on the Kubernetes master and ensuring that it has the correct permissions:
2424

25-
```
25+
```bash
2626
$ mkdir -m 777 -p /path/to/domain1PersistentVolume
2727
```
2828

2929
**Note regarding NFS**: In the current GA version, the OCI Container Engine for Kubernetes supports network block storage that can be shared across nodes with access permission RWOnce (meaning that only one can write, others can read only). At this time, the WebLogic on Kubernetes domain created by the WebLogic Server Kubernetes Operator, requires a shared file system to store the WebLogic domain configuration, which MUST be accessible from all the pods across the nodes. As a workaround, you need to install an NFS server on one node and share the file system across all the nodes.
3030

3131
Currently, we recommend that you use NFS version 3.0 for running WebLogic Server on OCI Container Engine for Kubernetes. During certification, we found that when using NFS 4.0, the servers in the WebLogic domain went into a failed state intermittently. Because multiple threads use NFS (default store, diagnostics store, Node Manager, logging, and `domain_home`), there are issues when accessing the file store. These issues are removed by changing the NFS to version 3.0.
3232

33+
#### Persistent volume GID annotation
34+
35+
The `HOST_PATH` directory permissions can be made more secure by using a Kubernetes annotation on the
36+
persistent volume that provides the group identifier (GID) which will be added to pods using the persistent volume.
37+
38+
For example, if the GID of the directory is `6789`, then the directory can be updated to remove permissions
39+
other than for the user and group along with the persistent volume being annotated with the specified GID:
40+
41+
```bash
42+
$ chmod 770 /path/to/domain1PersistentVolume
43+
$ kubectl annotate pv domain1-weblogic-sample-pv pv.beta.kubernetes.io/gid=6789
44+
```
45+
46+
Typically, after the domain is created and servers are running, the group ownership of the persistent volume files
47+
can be updated to the specified GID which will provide read access to the group members. Normally
48+
files created from a pod onto the persistent volume will have UID `1000` and GID `1000` which is the
49+
`oracle` user from the WebLogic Docker image.
50+
51+
An example of updating the group ownership on the persistent volume would be as follows:
52+
53+
```bash
54+
$ cd /path/to/domain1PersistentVolume
55+
$ sudo chgrp 6789 applications domains logs stores
56+
$ sudo chgrp -R 6789 domains/
57+
$ sudo chgrp -R 6789 logs/
58+
```
59+
3360
### YAML files
3461

3562
Persistent volumes and claims are described in YAML files. For each persistent volume, you should create one persistent volume YAML file and one persistent volume claim YAML file. In the example below, you will find two YAML templates, one for the volume and one for the claim. As stated above, they either can be dedicated to a specific domain, or shared across multiple domains. For the use cases where a volume will be dedicated to a particular domain, it is a best practice to label it with `weblogic.domainUID=[domain name]`. This makes it easy to search for, and clean up resources associated with that particular domain.

integration-tests/USECASES.MD

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ Also the below use cases are covered for Quick test:
3434
| | |
3535
| --- | --- |
3636
| Operator Configuration | operator2 deployed in weblogic-operator2 namespace and manages domains test2 namespace |
37-
| Domain Configuration | Domain on PV using WDT <p> Domain home in image using WLST <p> Domain home in image using WDT <p> Domain with serverStartPolicy ADMIN_ONLY <p> Domain with auto and custom situational configuration <p> Two domains managed by two operators <p> Domain with Recycle weblogicDomainStorageReclaimPolicy <p> Domain with default sample values |
38-
37+
| Domain Configuration | Domain on PV using WDT <p> Domain home in image using WLST <p> Domain home in image using WDT <p> Domain with serverStartPolicy ADMIN_ONLY <p> Domain with auto and custom situational configuration <p> Two domains managed by two operators <p> Domain with Recycle weblogicDomainStorageReclaimPolicy <p> Domain with default sample values <p> Domain on PV with two configured clusters <p> Domain on PV with one configured cluster and one dynamic cluster |
3938

4039
Basic Use Cases described above are verified in all the domain configurations. Also the below use cases are covered:
4140

@@ -96,5 +95,10 @@ Configuration Overrides Usecases
9695

9796
| Server Discovery | Use Case |
9897
| --- | --- |
99-
| Discover a newly started server | stop operator and apply the modified domain.yaml with replicas count increated, restart Operator and verify that the cluster is scaled up accordingly |
100-
| Discover dead weblogic servers | stop Operator, kill admin server and all managed servers in the cluster, restart Operator and verify that it restarts all dead servers |
98+
| Discover a newly started server | Stop operator and apply the modified domain.yaml with replicas count increased, restart Operator and verify that the cluster is scaled up accordingly |
99+
| Discover dead weblogic servers | Stop Operator, kill admin server and all managed servers in the cluster, restart Operator and verify that it restarts all dead servers |
100+
101+
| Sticky Session | Use Case |
102+
| --- | --- |
103+
| Server affinity | Use a web application deployed on Weblogic cluster to track HTTP session. Test server-affinity by sending two HTTP requests to Weblogic and verify that all requests are directed to same Weblogic server |
104+
| Session state isolation | Verify that values saved in a client session state are not visible to another client |

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class BaseTest {
6464
private static int waitTimePod = 5;
6565
private static String leaseId = "";
6666
private static String branchName = "";
67-
private static String appLocationInPod = "/u01/oracle/apps";
67+
protected static String appLocationInPod = "/u01/oracle/apps";
6868
private static String appLocationOnHost;
6969
private static Properties appProps;
7070

@@ -213,6 +213,17 @@ public static void initialize(String appPropsFile) throws Exception {
213213
logger.info("Env var BRANCH_NAME " + System.getenv("BRANCH_NAME"));
214214
}
215215

216+
/**
217+
* Call the basic usecases tests
218+
*
219+
* @param domain
220+
* @throws Exception
221+
*/
222+
protected void testBasicUseCases(Domain domain) throws Exception {
223+
testAdminT3Channel(domain);
224+
testAdminServerExternalService(domain);
225+
}
226+
216227
/**
217228
* Access Admin REST endpoint using admin node host and node port
218229
*
@@ -339,13 +350,24 @@ public void testWSLoadBalancing(Domain domain) throws Exception {
339350
logger.info("Done - testWSLoadBalancing");
340351
}
341352

353+
/**
354+
* use default cluster service port 8011
355+
*
356+
* @param operator
357+
* @param domain
358+
* @throws Exception
359+
*/
360+
public void testDomainLifecyle(Operator operator, Domain domain) throws Exception {
361+
testDomainLifecyle(operator, domain, 8011);
362+
}
363+
342364
/**
343365
* Restarting the domain should not have any impact on Operator managing the domain, web app load
344366
* balancing and node port service
345367
*
346368
* @throws Exception
347369
*/
348-
public void testDomainLifecyle(Operator operator, Domain domain) throws Exception {
370+
public void testDomainLifecyle(Operator operator, Domain domain, int port) throws Exception {
349371
logger.info("Inside testDomainLifecyle");
350372
domain.destroy();
351373
domain.create();
@@ -362,7 +384,7 @@ public void testDomainLifecyle(Operator operator, Domain domain) throws Exceptio
362384
// intermittent failure, see OWLS-73416
363385
// testWSLoadBalancing(domain);
364386
domain.verifyAdminServerExternalService(getUsername(), getPassword());
365-
domain.verifyHasClusterServiceChannelPort("TCP", 8011, TESTWEBAPP + "/");
387+
domain.verifyHasClusterServiceChannelPort("TCP", port, TESTWEBAPP + "/");
366388
logger.info("Done - testDomainLifecyle");
367389
}
368390

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
// Copyright 2018, 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+
package oracle.kubernetes.operator;
5+
6+
import static org.junit.Assert.assertTrue;
7+
8+
import java.io.IOException;
9+
import java.nio.charset.StandardCharsets;
10+
import java.nio.file.Files;
11+
import java.nio.file.Paths;
12+
import java.nio.file.StandardCopyOption;
13+
import java.nio.file.StandardOpenOption;
14+
import java.util.Map;
15+
import oracle.kubernetes.operator.utils.Domain;
16+
import oracle.kubernetes.operator.utils.K8sTestUtils;
17+
import oracle.kubernetes.operator.utils.Operator;
18+
import oracle.kubernetes.operator.utils.TestUtils;
19+
import org.junit.AfterClass;
20+
import org.junit.BeforeClass;
21+
import org.junit.FixMethodOrder;
22+
import org.junit.Test;
23+
import org.junit.runners.MethodSorters;
24+
25+
/**
26+
* Multiple clusters in a domain tests
27+
*
28+
* <p>More than 1 cluster is created in a domain , like configured and dynamic
29+
*/
30+
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
31+
public class ITMultipleClusters extends BaseTest {
32+
33+
private static Operator operator1;
34+
private static final String TWO_CONFIGURED_CLUSTER_SCRIPT =
35+
"create-domain-two-configured-cluster.py";
36+
private static final String TWO_MIXED_CLUSTER_SCRIPT = "create-domain-two-mixed-cluster.py";
37+
private static String template;
38+
private static final String DOMAINUID = "twoconfigclustdomain";
39+
40+
/**
41+
* This method gets called only once before any of the test methods are executed. It does the
42+
* initialization of the integration test properties defined in OperatorIT.properties and setting
43+
* the resultRoot, pvRoot and projectRoot attributes.
44+
*
45+
* @throws Exception
46+
*/
47+
@BeforeClass
48+
public static void staticPrepare() throws Exception {
49+
// initialize test properties and create the directories
50+
initialize(APP_PROPS_FILE);
51+
template =
52+
BaseTest.getProjectRoot() + "/kubernetes/samples/scripts/common/domain-template.yaml";
53+
}
54+
55+
/**
56+
* Releases k8s cluster lease, archives result, pv directories
57+
*
58+
* @throws Exception
59+
*/
60+
@AfterClass
61+
public static void staticUnPrepare() throws Exception {
62+
logger.info("+++++++++++++++++++++++++++++++++---------------------------------+");
63+
logger.info("BEGIN");
64+
logger.info("Run once, release cluster lease");
65+
tearDown(new Object() {}.getClass().getEnclosingClass().getSimpleName());
66+
logger.info("SUCCESS");
67+
}
68+
69+
/**
70+
* Create 2 configured clusters in a domain each having 2 managed servers. Verify the managed
71+
* servers are running and verify the basic use cases.
72+
*
73+
* @throws Exception
74+
*/
75+
@Test
76+
public void testCreateDomainTwoConfiguredCluster() throws Exception {
77+
78+
String testMethodName = new Object() {}.getClass().getEnclosingMethod().getName();
79+
logTestBegin(testMethodName);
80+
81+
logger.info("Creating Operator & waiting for the script to complete execution");
82+
// create operator1
83+
if (operator1 == null) {
84+
operator1 = TestUtils.createOperator(OPERATOR1_YAML);
85+
}
86+
Domain domain = null;
87+
boolean testCompletedSuccessfully = false;
88+
try {
89+
Map<String, Object> domainMap = TestUtils.loadYaml(DOMAINONPV_WLST_YAML);
90+
domainMap.put("domainUID", DOMAINUID);
91+
domainMap.put("clusterType", "CONFIGURED");
92+
domainMap.put(
93+
"createDomainPyScript",
94+
"integration-tests/src/test/resources/domain-home-on-pv/"
95+
+ TWO_CONFIGURED_CLUSTER_SCRIPT);
96+
addCluster2ToDomainTemplate();
97+
domain = TestUtils.createDomain(domainMap);
98+
domain.verifyDomainCreated();
99+
verifyServersStatus(domain);
100+
testBasicUseCases(domain);
101+
if (!SMOKETEST) {
102+
domain.testWlsLivenessProbe();
103+
}
104+
testCompletedSuccessfully = true;
105+
} finally {
106+
if (domain != null && !SMOKETEST && (JENKINS || testCompletedSuccessfully)) {
107+
domain.destroy();
108+
}
109+
restoreDomainTemplate();
110+
}
111+
logger.info("SUCCESS - " + testMethodName);
112+
}
113+
114+
/**
115+
* Create 2 clusters(configured and dynamic) in a domain each having 2 managed servers. Verify the
116+
* managed servers are running and verify the basic use cases.
117+
*
118+
* @throws Exception
119+
*/
120+
@Test
121+
public void testCreateDomainTwoMixedCluster() throws Exception {
122+
String DOMAINUID = "twomixedclusterdomain";
123+
String testMethodName = new Object() {}.getClass().getEnclosingMethod().getName();
124+
logTestBegin(testMethodName);
125+
String template =
126+
BaseTest.getProjectRoot() + "/kubernetes/samples/scripts/common/domain-template.yaml";
127+
logger.info("Creating Operator & waiting for the script to complete execution");
128+
if (operator1 == null) {
129+
operator1 = TestUtils.createOperator(OPERATOR1_YAML);
130+
}
131+
Domain domain = null;
132+
boolean testCompletedSuccessfully = false;
133+
try {
134+
Map<String, Object> domainMap = TestUtils.loadYaml(DOMAINONPV_WLST_YAML);
135+
domainMap.put("domainUID", DOMAINUID);
136+
domainMap.put(
137+
"createDomainPyScript",
138+
"integration-tests/src/test/resources/domain-home-on-pv/" + TWO_MIXED_CLUSTER_SCRIPT);
139+
addCluster2ToDomainTemplate();
140+
domain = TestUtils.createDomain(domainMap);
141+
domain.verifyDomainCreated();
142+
verifyServersStatus(domain);
143+
testBasicUseCases(domain);
144+
if (!SMOKETEST) {
145+
domain.testWlsLivenessProbe();
146+
}
147+
testCompletedSuccessfully = true;
148+
} finally {
149+
if (domain != null && !SMOKETEST && (JENKINS || testCompletedSuccessfully)) {
150+
domain.destroy();
151+
}
152+
restoreDomainTemplate();
153+
}
154+
logger.info("SUCCESS - " + testMethodName);
155+
}
156+
157+
/**
158+
* Append a second cluster to the domain template
159+
*
160+
* @throws IOException when append fails
161+
*/
162+
private void addCluster2ToDomainTemplate() throws IOException {
163+
String add =
164+
" - clusterName: %CLUSTER_NAME%-2\n"
165+
+ " serverStartState: \"RUNNING\"\n"
166+
+ " replicas: %INITIAL_MANAGED_SERVER_REPLICAS%\n";
167+
logger.info("Making a backup of the domain template file:" + template);
168+
if (!Files.exists(Paths.get(template + ".org"))) {
169+
Files.copy(Paths.get(template), Paths.get(template + ".org"));
170+
}
171+
Files.write(Paths.get(template), add.getBytes(), StandardOpenOption.APPEND);
172+
byte[] readAllBytes = Files.readAllBytes(Paths.get(template));
173+
logger.info(new String(readAllBytes, StandardCharsets.UTF_8));
174+
}
175+
176+
/**
177+
* Restore the domain template to original state when test is finished
178+
*
179+
* @throws IOException
180+
*/
181+
private void restoreDomainTemplate() throws IOException {
182+
Files.copy(
183+
Paths.get(template + ".org"), Paths.get(template), StandardCopyOption.REPLACE_EXISTING);
184+
Files.delete(Paths.get(template + ".org"));
185+
}
186+
187+
/**
188+
* Verifies all of the servers in the cluster are in Running status
189+
*
190+
* @param Domain
191+
*/
192+
private void verifyServersStatus(Domain domain) {
193+
K8sTestUtils testUtil = new K8sTestUtils();
194+
String domain1LabelSelector = String.format("weblogic.domainUID in (%s)", DOMAINUID);
195+
String namespace = domain.getDomainNS();
196+
String pods[] = {
197+
DOMAINUID + "-" + domain.getAdminServerName(),
198+
DOMAINUID + "-managed-server",
199+
DOMAINUID + "-managed-server1",
200+
DOMAINUID + "-managed-server2",
201+
DOMAINUID + "-new-managed-server1",
202+
DOMAINUID + "-new-managed-server2",
203+
};
204+
for (String pod : pods) {
205+
assertTrue(
206+
pod + " Pod not running", testUtil.isPodRunning(namespace, domain1LabelSelector, pod));
207+
}
208+
}
209+
}

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,4 @@ private Domain testAdvancedUseCasesForADomain(Operator operator, Domain domain)
502502
}
503503
return domain;
504504
}
505-
506-
private void testBasicUseCases(Domain domain) throws Exception {
507-
testAdminT3Channel(domain);
508-
testAdminServerExternalService(domain);
509-
}
510505
}

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,15 @@ public static void staticPrepare() throws Exception {
8989
*/
9090
@AfterClass
9191
public static void staticUnPrepare() throws Exception {
92-
logger.info("+++++++++++++++++++++++++++++++++---------------------------------+");
93-
logger.info("BEGIN");
94-
logger.info("Run once, release cluster lease");
92+
if (!QUICKTEST) {
93+
logger.info("++++++++++++++++++++++++++++++++++");
94+
logger.info("BEGIN");
95+
logger.info("Run once, release cluster lease");
9596

96-
tearDown(new Object() {}.getClass().getEnclosingClass().getSimpleName());
97+
tearDown(new Object() {}.getClass().getEnclosingClass().getSimpleName());
9798

98-
logger.info("SUCCESS");
99+
logger.info("SUCCESS");
100+
}
99101
}
100102

101103
/**

0 commit comments

Comments
 (0)