Skip to content

Commit bb941c7

Browse files
committed
Merge remote-tracking branch 'origin/main' into release/4.0
2 parents 0cc1aec + d41df97 commit bb941c7

File tree

6 files changed

+349
-5
lines changed

6 files changed

+349
-5
lines changed

ItOpenshiftIstioMiiDomain.java

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
// Copyright (c) 2022, 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.weblogic.kubernetes;
5+
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.Paths;
9+
import java.util.Collections;
10+
import java.util.HashMap;
11+
import java.util.List;
12+
import java.util.Map;
13+
14+
import io.kubernetes.client.openapi.models.V1EnvVar;
15+
import io.kubernetes.client.openapi.models.V1LocalObjectReference;
16+
import io.kubernetes.client.openapi.models.V1ObjectMeta;
17+
import io.kubernetes.client.openapi.models.V1SecretReference;
18+
import io.kubernetes.client.util.Yaml;
19+
import oracle.weblogic.domain.Cluster;
20+
import oracle.weblogic.domain.Configuration;
21+
import oracle.weblogic.domain.Domain;
22+
import oracle.weblogic.domain.DomainSpec;
23+
import oracle.weblogic.domain.Istio;
24+
import oracle.weblogic.domain.Model;
25+
import oracle.weblogic.domain.OnlineUpdate;
26+
import oracle.weblogic.domain.ServerPod;
27+
import oracle.weblogic.kubernetes.actions.impl.primitive.Command;
28+
import oracle.weblogic.kubernetes.actions.impl.primitive.CommandParams;
29+
import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams;
30+
import oracle.weblogic.kubernetes.annotations.IntegrationTest;
31+
import oracle.weblogic.kubernetes.annotations.Namespaces;
32+
import oracle.weblogic.kubernetes.logging.LoggingFacade;
33+
import oracle.weblogic.kubernetes.utils.ExecResult;
34+
import oracle.weblogic.kubernetes.utils.FileUtils;
35+
import org.junit.jupiter.api.BeforeAll;
36+
import org.junit.jupiter.api.DisplayName;
37+
import org.junit.jupiter.api.Tag;
38+
import org.junit.jupiter.api.Test;
39+
40+
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT;
41+
import static oracle.weblogic.kubernetes.TestConstants.ADMIN_USERNAME_DEFAULT;
42+
import static oracle.weblogic.kubernetes.TestConstants.DOMAIN_API_VERSION;
43+
import static oracle.weblogic.kubernetes.TestConstants.MII_BASIC_IMAGE_NAME;
44+
import static oracle.weblogic.kubernetes.TestConstants.MII_BASIC_IMAGE_TAG;
45+
import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_CHART_DIR;
46+
import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_RELEASE_NAME;
47+
import static oracle.weblogic.kubernetes.TestConstants.TEST_IMAGES_REPO_SECRET_NAME;
48+
import static oracle.weblogic.kubernetes.TestConstants.WEBLOGIC_SLIM;
49+
import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR;
50+
import static oracle.weblogic.kubernetes.actions.ActionConstants.WORK_DIR;
51+
import static oracle.weblogic.kubernetes.utils.ApplicationUtils.checkAppUsingHostHeader;
52+
import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkPodReadyAndServiceExists;
53+
import static oracle.weblogic.kubernetes.utils.ConfigMapUtils.createConfigMapAndVerify;
54+
import static oracle.weblogic.kubernetes.utils.DomainUtils.createDomainAndVerify;
55+
import static oracle.weblogic.kubernetes.utils.FileUtils.generateFileFromTemplate;
56+
import static oracle.weblogic.kubernetes.utils.ImageUtils.createTestRepoSecret;
57+
import static oracle.weblogic.kubernetes.utils.IstioUtils.createAdminServer;
58+
import static oracle.weblogic.kubernetes.utils.IstioUtils.deployHttpIstioGatewayAndVirtualservice;
59+
import static oracle.weblogic.kubernetes.utils.IstioUtils.deployIstioDestinationRule;
60+
import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator;
61+
import static oracle.weblogic.kubernetes.utils.PodUtils.setPodAntiAffinity;
62+
import static oracle.weblogic.kubernetes.utils.SecretUtils.createSecretWithUsernamePassword;
63+
import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger;
64+
import static org.apache.commons.io.FileUtils.deleteQuietly;
65+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
66+
import static org.junit.jupiter.api.Assertions.assertEquals;
67+
import static org.junit.jupiter.api.Assertions.assertNotNull;
68+
import static org.junit.jupiter.api.Assertions.assertTrue;
69+
70+
/**
71+
*
72+
* A sample mii domain tests running in Openshift service mesh. The test assumes that the service mesh istio operator is
73+
* running in istio-system namespace. All the service mesh related operators are installed and running as per this
74+
* documentation. https://docs.openshift.com/container-platform/4.10/service_mesh/v2x/installing-ossm.html
75+
*/
76+
@DisplayName("Test Openshift servce mesh istio enabled WebLogic Domain in mii model")
77+
@Tag("openshift")
78+
@IntegrationTest
79+
class ItOpenshiftIstioMiiDomain {
80+
81+
private static String opNamespace = null;
82+
private static String domainNamespace = null;
83+
84+
private String domainUid = "openshift-istio-mii";
85+
private String configMapName = "dynamicupdate-istio-configmap";
86+
private final String clusterName = "cluster-1"; // do not modify
87+
private final String adminServerPodName = domainUid + "-admin-server";
88+
private final String managedServerPrefix = domainUid + "-managed-server";
89+
private final String workManagerName = "newWM";
90+
private final int replicaCount = 2;
91+
92+
private static LoggingFacade logger = null;
93+
94+
/**
95+
* Install Operator.
96+
* @param namespaces list of namespaces created by the IntegrationTestWatcher
97+
*/
98+
@BeforeAll
99+
public static void initAll(@Namespaces(2) List<String> namespaces) {
100+
logger = getLogger();
101+
102+
// get a new unique opNamespace
103+
logger.info("Assign unique namespace for Operator");
104+
assertNotNull(namespaces.get(0), "Namespace list is null");
105+
opNamespace = namespaces.get(0);
106+
107+
logger.info("Assign unique namespace for Domain");
108+
assertNotNull(namespaces.get(1), "Namespace list is null");
109+
domainNamespace = namespaces.get(1);
110+
111+
// edit service member roll to include operator and domain namespace so that
112+
// Openshift service mesh can add istio side cars to the operator and WebLogic pods.
113+
Path smrYaml = Paths.get(WORK_DIR, "openshift", "servicememberroll.yaml");
114+
assertDoesNotThrow(() -> {
115+
deleteQuietly(smrYaml.getParent().toFile());
116+
Files.createDirectories(smrYaml.getParent());
117+
});
118+
assertDoesNotThrow(() -> {
119+
FileUtils.copy(Paths.get(RESOURCE_DIR, "openshift", "servicememberroll.yaml"),
120+
smrYaml);
121+
FileUtils.replaceStringInFile(smrYaml.toString(), "OPERATOR_NAMESPACE", opNamespace);
122+
FileUtils.replaceStringInFile(smrYaml.toString(), "DOMAIN_NAMESPACE", domainNamespace);
123+
});
124+
logger.info("Run kubectl to create the service member roll");
125+
CommandParams params = new CommandParams().defaults();
126+
params.command("kubectl apply -f " + smrYaml.toString());
127+
boolean result = Command.withParams(params).execute();
128+
assertTrue(result, "Failed to create service member roll");
129+
130+
// install and verify operator with istio side car injection set to true
131+
String opSa = opNamespace + "-sa";
132+
HelmParams opHelmParams
133+
= new HelmParams().releaseName(OPERATOR_RELEASE_NAME)
134+
.namespace(opNamespace)
135+
.chartDir(OPERATOR_CHART_DIR);
136+
137+
installAndVerifyOperator(opNamespace,
138+
opSa, // operator service account
139+
false, // with REST api enabled
140+
0, // externalRestHttpPort
141+
opHelmParams, // operator helm parameters
142+
false, // ElkintegrationEnabled
143+
null, // domainspaceSelectionStrategy
144+
null, // domainspaceSelector
145+
false, // enableClusterRolebinding
146+
"INFO", // operator pod log level
147+
-1, // domainPresenceFailureRetryMaxCount
148+
-1, // domainPresenceFailureRetrySeconds
149+
true, // openshift istio injection
150+
domainNamespace // domainNamespace
151+
);
152+
}
153+
154+
/**
155+
* Create a domain using model-in-image model.
156+
* Inject sidecar.istio.io in domain resource under global serverPod object.
157+
* Set localhostBindingsEnabled to true in istio configuration.
158+
* Add istio configuration with default readinessPort.
159+
* Do not add any AdminService under AdminServer configuration.
160+
* Deploy istio gateways and virtual service.
161+
* Verify server pods are in ready state and services are created.
162+
* Verify login to WebLogic console is successful thru istio ingress port.
163+
* Deploy a web application thru istio http ingress port using REST api.
164+
* Access web application thru istio http ingress port using curl.
165+
*/
166+
@Test
167+
@DisplayName("Create WebLogic Domain with mii model with openshift service mesh")
168+
void testIstioModelInImageDomain() {
169+
170+
// Create the repo secret to pull the image
171+
// this secret is used only for non-kind cluster
172+
createTestRepoSecret(domainNamespace);
173+
174+
// create secret for admin credentials
175+
logger.info("Create secret for admin credentials");
176+
String adminSecretName = "weblogic-credentials";
177+
assertDoesNotThrow(() -> createSecretWithUsernamePassword(
178+
adminSecretName,
179+
domainNamespace,
180+
ADMIN_USERNAME_DEFAULT,
181+
ADMIN_PASSWORD_DEFAULT),
182+
String.format("createSecret failed for %s", adminSecretName));
183+
184+
// create encryption secret
185+
logger.info("Create encryption secret");
186+
String encryptionSecretName = "encryptionsecret";
187+
assertDoesNotThrow(() -> createSecretWithUsernamePassword(
188+
encryptionSecretName,
189+
domainNamespace,
190+
"weblogicenc",
191+
"weblogicenc"),
192+
String.format("createSecret failed for %s", encryptionSecretName));
193+
194+
// create WDT config map without any files
195+
createConfigMapAndVerify(configMapName, domainUid, domainNamespace, Collections.emptyList());
196+
// create the domain object
197+
Domain domain = createDomainResource(domainUid,
198+
domainNamespace,
199+
adminSecretName,
200+
TEST_IMAGES_REPO_SECRET_NAME,
201+
encryptionSecretName,
202+
replicaCount,
203+
MII_BASIC_IMAGE_NAME + ":" + MII_BASIC_IMAGE_TAG,
204+
configMapName);
205+
logger.info(Yaml.dump(domain));
206+
207+
// create model in image domain
208+
createDomainAndVerify(domain, domainNamespace);
209+
210+
logger.info("Check admin service {0} is created in namespace {1}",
211+
adminServerPodName, domainNamespace);
212+
checkPodReadyAndServiceExists(adminServerPodName, domainUid, domainNamespace);
213+
// check managed server services created
214+
for (int i = 1; i <= replicaCount; i++) {
215+
logger.info("Check managed service {0} is created in namespace {1}",
216+
managedServerPrefix + i, domainNamespace);
217+
checkPodReadyAndServiceExists(managedServerPrefix + i, domainUid, domainNamespace);
218+
}
219+
220+
String clusterService = domainUid + "-cluster-" + clusterName + "." + domainNamespace + ".svc.cluster.local";
221+
222+
Map<String, String> templateMap = new HashMap<>();
223+
templateMap.put("NAMESPACE", domainNamespace);
224+
templateMap.put("DUID", domainUid);
225+
templateMap.put("ADMIN_SERVICE",adminServerPodName);
226+
templateMap.put("CLUSTER_SERVICE", clusterService);
227+
templateMap.put("testwebapp", "sample-war");
228+
229+
Path srcHttpFile = Paths.get(RESOURCE_DIR, "istio", "istio-http-template.yaml");
230+
Path targetHttpFile = assertDoesNotThrow(
231+
() -> generateFileFromTemplate(srcHttpFile.toString(), "openshift-istio-http.yaml", templateMap));
232+
logger.info("Generated Http VS/Gateway file path is {0}", targetHttpFile);
233+
234+
boolean deployRes = assertDoesNotThrow(
235+
() -> deployHttpIstioGatewayAndVirtualservice(targetHttpFile));
236+
assertTrue(deployRes, "Failed to deploy Http Istio Gateway/VirtualService");
237+
238+
Path srcDrFile = Paths.get(RESOURCE_DIR, "istio", "istio-dr-template.yaml");
239+
Path targetDrFile = assertDoesNotThrow(
240+
() -> generateFileFromTemplate(srcDrFile.toString(), "openshift-istio-dr.yaml", templateMap));
241+
logger.info("Generated DestinationRule file path is {0}", targetDrFile);
242+
243+
deployRes = assertDoesNotThrow(
244+
() -> deployIstioDestinationRule(targetDrFile));
245+
assertTrue(deployRes, "Failed to deploy Istio DestinationRule");
246+
247+
// get gateway url
248+
// oc -n istio-system get route istio-ingressgateway -o jsonpath='{.spec.host}'
249+
logger.info("Run kubectl to get ingress gateway route");
250+
CommandParams params = new CommandParams().defaults();
251+
params.command("kubectl get route -n istio-system istio-ingressgateway -o jsonpath='{.spec.host}'");
252+
ExecResult result = Command.withParams(params).executeAndReturnResult();
253+
assertEquals(0, result.exitValue());
254+
assertNotNull(result.stdout());
255+
String gatewayUrl = result.stdout();
256+
257+
if (!WEBLOGIC_SLIM) {
258+
String consoleUrl = gatewayUrl + "/console/login/LoginForm.jsp";
259+
boolean checkConsole = checkAppUsingHostHeader(consoleUrl, domainNamespace + ".org");
260+
assertTrue(checkConsole, "Failed to access WebLogic console");
261+
logger.info("WebLogic console is accessible");
262+
263+
} else {
264+
logger.info("Skipping WebLogic console test for slim image");
265+
}
266+
267+
String url = "http://" + gatewayUrl + "/sample-war/index.jsp";
268+
logger.info("Application Access URL {0}", url);
269+
boolean checkApp = checkAppUsingHostHeader(url, domainNamespace + ".org");
270+
assertTrue(checkApp, "Failed to access WebLogic application");
271+
}
272+
273+
private Domain createDomainResource(String domainUid, String domNamespace,
274+
String adminSecretName, String repoSecretName,
275+
String encryptionSecretName, int replicaCount,
276+
String miiImage, String configmapName) {
277+
278+
// create the domain CR
279+
Domain domain = new Domain()
280+
.apiVersion(DOMAIN_API_VERSION)
281+
.kind("Domain")
282+
.metadata(new V1ObjectMeta()
283+
.name(domainUid)
284+
.namespace(domNamespace))
285+
.spec(new DomainSpec()
286+
.domainUid(domainUid)
287+
.domainHomeSourceType("FromModel")
288+
.image(miiImage)
289+
.imagePullPolicy("IfNotPresent")
290+
.addImagePullSecretsItem(new V1LocalObjectReference()
291+
.name(repoSecretName))
292+
.webLogicCredentialsSecret(new V1SecretReference()
293+
.name(adminSecretName)
294+
.namespace(domNamespace))
295+
.includeServerOutInPodLog(true)
296+
.serverStartPolicy("IF_NEEDED")
297+
.serverPod(new ServerPod()
298+
.putAnnotationsItem("sidecar.istio.io/inject", "true")
299+
.addEnvItem(new V1EnvVar()
300+
.name("JAVA_OPTIONS")
301+
.value("-Dweblogic.StdoutDebugEnabled=false -Dweblogic.rjvm.enableprotocolswitch=true"))
302+
.addEnvItem(new V1EnvVar()
303+
.name("USER_MEM_ARGS")
304+
.value("-Djava.security.egd=file:/dev/./urandom ")))
305+
.adminServer(createAdminServer())
306+
.addClustersItem(new Cluster()
307+
.clusterName(clusterName)
308+
.replicas(replicaCount))
309+
.configuration(new Configuration()
310+
.istio(new Istio()
311+
.localhostBindingsEnabled(Boolean.FALSE))
312+
.model(new Model()
313+
.domainType("WLS")
314+
.configMap(configmapName)
315+
.onlineUpdate(new OnlineUpdate().enabled(true))
316+
.runtimeEncryptionSecret(encryptionSecretName))
317+
.introspectorJobActiveDeadlineSeconds(300L)));
318+
setPodAntiAffinity(domain);
319+
return domain;
320+
}
321+
}

integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonLBTestUtils.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger;
9090
import static org.apache.commons.io.FileUtils.deleteDirectory;
9191
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
92-
import static org.junit.jupiter.api.Assertions.assertEquals;
9392
import static org.junit.jupiter.api.Assertions.assertFalse;
9493
import static org.junit.jupiter.api.Assertions.assertNotEquals;
9594
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -525,11 +524,16 @@ public static void buildAndDeployClusterviewApp(String domainNamespace, List<Str
525524
for (String domainUid : domainUids) {
526525
// admin/managed server name here should match with model yaml in MII_BASIC_WDT_MODEL_FILE
527526
String adminServerPodName = domainUid + "-admin-server";
528-
deployApplication(domainNamespace, domainUid, adminServerPodName, clusterViewAppPath);
527+
testUntil(() -> deployApplication(domainNamespace, domainUid, adminServerPodName, clusterViewAppPath),
528+
getLogger(),
529+
"deploying application {0} to pod {1} in namespace {2} succeeds",
530+
clusterViewAppPath,
531+
adminServerPodName,
532+
domainNamespace);
529533
}
530534
}
531535

532-
private static void deployApplication(String namespace, String domainUid, String adminServerPodName,
536+
private static boolean deployApplication(String namespace, String domainUid, String adminServerPodName,
533537
Path clusterViewAppPath) {
534538
getLogger().info("Getting node port for admin server default channel");
535539
int serviceNodePort = assertDoesNotThrow(() ->
@@ -545,7 +549,7 @@ private static void deployApplication(String namespace, String domainUid, String
545549
targets, clusterViewAppPath, null, domainUid + "clusterview");
546550
assertNotNull(result, "Application deployment failed");
547551
getLogger().info("Application deployment returned {0}", result.toString());
548-
assertEquals("202", result.stdout(), "Deployment didn't return HTTP status code 202");
552+
return result.stdout().equals("202");
549553
}
550554

551555
/**
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: maistra.io/v1
2+
kind: ServiceMeshMemberRoll
3+
metadata:
4+
name: default
5+
namespace: istio-system
6+
spec:
7+
members:
8+
- OPERATOR_NAMESPACE
9+
- DOMAIN_NAMESPACE

operator/src/main/resources/scripts/model_wdt_mii_filter.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ def toDNS1123Legal(self, address):
144144
def getModel(self):
145145
return self.model
146146

147+
def wlsVersionEarlierThan(self, version):
148+
# unconventional import within function definition for unit testing
149+
from weblogic.management.configuration import LegalHelper
150+
# WLS Domain versions supported by operator are 12.2.1.3 + patches, 12.2.1.4
151+
# and 14.1.1.0 so current version will only be one of these that are listed.
152+
return LegalHelper.versionEarlierThan("14.1.1.0", version)
153+
147154
class SecretManager(object):
148155

149156
def __init__(self, env):

operator/src/test/python/test_wdt_mii_filter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,5 +341,8 @@ def readFile(self, path):
341341

342342
return self.WLS_CRED_PASSWORD
343343

344+
def wlsVersionEarlierThan(self, version):
345+
return False
346+
344347
if __name__ == '__main__':
345348
unittest.main()

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@
643643
<assertj.core.version>3.23.1</assertj.core.version>
644644
<commons.io.version>2.11.0</commons.io.version>
645645
<awaitility-version>4.2.0</awaitility-version>
646-
<client-java-version>16.0.1</client-java-version>
646+
<client-java-version>16.0.2</client-java-version>
647647
<kotlin-stdlib-version>1.7.20</kotlin-stdlib-version>
648648
<okhttp-version>4.10.0</okhttp-version>
649649
<junit.jupiter.version>5.9.1</junit.jupiter.version>

0 commit comments

Comments
 (0)