diff --git a/kubernetes/samples/charts/apache-webtier/templates/deployment.yaml b/kubernetes/samples/charts/apache-webtier/templates/deployment.yaml index ec7622f1708..4cdf9722c2d 100644 --- a/kubernetes/samples/charts/apache-webtier/templates/deployment.yaml +++ b/kubernetes/samples/charts/apache-webtier/templates/deployment.yaml @@ -33,6 +33,10 @@ spec: - name: {{ template "apache.fullname" . }} hostPath: path: {{ .Values.volumePath | quote }} +{{- end }} +{{- if .Values.imagePullSecrets }} + imagePullSecrets: + - name: {{ (index .Values.imagePullSecrets 0).name }} {{- end }} containers: - name: {{ template "apache.fullname" . }} diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/ItTwoDomainsLoadBalancers.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/ItTwoDomainsLoadBalancers.java index 962334961ba..c9ad42bff80 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/ItTwoDomainsLoadBalancers.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/ItTwoDomainsLoadBalancers.java @@ -14,9 +14,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import com.gargoylesoftware.htmlunit.WebClient; @@ -82,6 +84,8 @@ import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT; import static oracle.weblogic.kubernetes.TestConstants.ADMIN_SERVER_NAME_BASE; import static oracle.weblogic.kubernetes.TestConstants.ADMIN_USERNAME_DEFAULT; +import static oracle.weblogic.kubernetes.TestConstants.APACHE_IMAGE; +import static oracle.weblogic.kubernetes.TestConstants.APACHE_RELEASE_NAME; import static oracle.weblogic.kubernetes.TestConstants.DOMAIN_API_VERSION; import static oracle.weblogic.kubernetes.TestConstants.DOMAIN_VERSION; import static oracle.weblogic.kubernetes.TestConstants.K8S_NODEPORT_HOST; @@ -90,6 +94,10 @@ import static oracle.weblogic.kubernetes.TestConstants.OCR_REGISTRY; import static oracle.weblogic.kubernetes.TestConstants.OCR_SECRET_NAME; import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; +import static oracle.weblogic.kubernetes.TestConstants.REPO_DEFAULT; +import static oracle.weblogic.kubernetes.TestConstants.REPO_PASSWORD; +import static oracle.weblogic.kubernetes.TestConstants.REPO_REGISTRY; +import static oracle.weblogic.kubernetes.TestConstants.REPO_USERNAME; import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; import static oracle.weblogic.kubernetes.TestConstants.VOYAGER_CHART_NAME; import static oracle.weblogic.kubernetes.actions.ActionConstants.APP_DIR; @@ -104,6 +112,10 @@ import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; import static oracle.weblogic.kubernetes.actions.TestActions.deletePod; import static oracle.weblogic.kubernetes.actions.TestActions.deleteSecret; +import static oracle.weblogic.kubernetes.actions.TestActions.dockerLogin; +import static oracle.weblogic.kubernetes.actions.TestActions.dockerPull; +import static oracle.weblogic.kubernetes.actions.TestActions.dockerPush; +import static oracle.weblogic.kubernetes.actions.TestActions.dockerTag; import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; import static oracle.weblogic.kubernetes.actions.TestActions.listIngresses; import static oracle.weblogic.kubernetes.actions.TestActions.listJobs; @@ -111,6 +123,7 @@ import static oracle.weblogic.kubernetes.actions.TestActions.listSecrets; import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; import static oracle.weblogic.kubernetes.actions.TestActions.startDomain; +import static oracle.weblogic.kubernetes.actions.TestActions.uninstallApache; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallOperator; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallTraefik; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallVoyager; @@ -127,6 +140,7 @@ import static oracle.weblogic.kubernetes.utils.CommonTestUtils.createSecretWithTLSCertKey; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.createSecretWithUsernamePassword; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getPodCreationTime; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.installAndVerifyApache; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.installAndVerifyOperator; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.installAndVerifyTraefik; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.installAndVerifyVoyager; @@ -175,16 +189,14 @@ public class ItTwoDomainsLoadBalancers { private static Path clusterViewAppPath; private static LoggingFacade logger = null; private static Path dstFile = null; - - // create standard, reusable retry/backoff policy - private static final ConditionFactory withStandardRetryPolicy - = with().pollDelay(2, SECONDS) - .and().with().pollInterval(10, SECONDS) - .atMost(5, MINUTES).await(); + private static HelmParams apacheHelmParams1 = null; + private static HelmParams apacheHelmParams2 = null; + private static String kindRepoApacheImage = APACHE_IMAGE; // domain constants private final String clusterName = "cluster-1"; private final int replicaCount = 2; + private final String managedServerPort = "8001"; private int t3ChannelPort = 0; private int replicasAfterScale; @@ -244,6 +256,34 @@ public static void initAll(@Namespaces(6) List namespaces) { logger.info("Using image {0}", kindRepoImage); image = kindRepoImage; isUseSecret = false; + + // The kind clusters can't pull Apache webtier image from OCIR using the image pull secret. + // Try the following instead: + // 1. docker login + // 2. docker pull + // 3. docker tag with the KIND_REPO value + // 4. docker push to KIND_REPO + + ConditionFactory withStandardRetryPolicy + = with().pollDelay(0, SECONDS) + .and().with().pollInterval(10, SECONDS) + .atMost(30, MINUTES).await(); + + withStandardRetryPolicy + .conditionEvaluationListener( + condition -> logger.info("Waiting for docker login to be successful" + + "(elapsed time {0} ms, remaining time {1} ms)", + condition.getElapsedTimeInMS(), + condition.getRemainingTimeInMS())) + .until(() -> dockerLogin(REPO_REGISTRY, REPO_USERNAME, REPO_PASSWORD)); + + withStandardRetryPolicy + .conditionEvaluationListener( + condition -> logger.info("Waiting for pullImageFromOcirAndPushToKind for image {0} to be successful" + + "(elapsed time {1} ms, remaining time {2} ms)", APACHE_IMAGE, + condition.getElapsedTimeInMS(), + condition.getRemainingTimeInMS())) + .until(pullImageFromOcirAndPushToKind(APACHE_IMAGE)); } } @@ -274,8 +314,8 @@ public void testTwoDomainsManagedByTwoOperators() { // restart domain1 and verify no impact on domain2 restartDomain1AndVerifyNoImpactOnDomain2(replicasAfterScale, domain1Namespace, domain2Namespace); - // shutdown both domains and verify the pods were shutdown - shutdownBothDomainsAndVerify(domainNamespaces); + // shutdown domain2 and verify the pods were shutdown + shutdownDomainAndVerify(domain2Namespace, domain2Uid); } /** @@ -332,13 +372,16 @@ public void testDeployAppAndInstallIngressControllers() { "Application archive is not available"); clusterViewAppPath = Paths.get(distDir.toString(), "clusterview.war"); - // deploy clusterview application + // deploy clusterview application in default namespace for (String domainUid : domainUids) { // admin/managed server name here should match with model yaml in MII_BASIC_WDT_MODEL_FILE String adminServerPodName = domainUid + "-admin-server"; - deployApplication(domainUid, adminServerPodName); + deployApplication(defaultNamespace, domainUid, adminServerPodName); } + // deploy clusterview application in domain1Namespace + deployApplication(domain1Namespace, domain1Uid, domain1Uid + "-admin-server"); + // create TLS secret for https traffic for (String domainUid : domainUids) { createCertKeyFiles(domainUid); @@ -348,6 +391,18 @@ public void testDeployAppAndInstallIngressControllers() { // create loadbalancing rules for Traefik createTraefikIngressRoutingRules(); createVoyagerIngressRoutingRules(); + + // install and verify Apache + apacheHelmParams1 = assertDoesNotThrow( + () -> installAndVerifyApache(domain1Namespace, kindRepoApacheImage, 0, 0, domain1Uid)); + + LinkedHashMap clusterNamePortMap = new LinkedHashMap<>(); + for (int i = 0; i < numberOfDomains; i++) { + clusterNamePortMap.put(domainUids.get(i) + "-cluster-cluster-1", managedServerPort); + } + apacheHelmParams2 = assertDoesNotThrow( + () -> installAndVerifyApache(defaultNamespace, kindRepoApacheImage, 0, 0, domain1Uid, + PV_ROOT + "/" + this.getClass().getSimpleName(), "apache-sample-host", clusterNamePortMap)); } /** @@ -378,7 +433,8 @@ public void testTraefikHttpHostRoutingAcrossDomains() { // verify load balancing works when 2 domains are running in the same namespace logger.info("Verifying http traffic"); for (String domainUid : domainUids) { - verifyClusterLoadbalancing(domainUid, "http", getTraefikLbNodePort(false)); + verifyClusterLoadbalancing(domainUid, defaultNamespace, "http", getTraefikLbNodePort(false), + replicaCount, true, ""); } } @@ -394,7 +450,8 @@ public void testTraefikHostHttpsRoutingAcrossDomains() { logger.info("Verifying https traffic"); for (String domainUid : domainUids) { - verifyClusterLoadbalancing(domainUid, "https", getTraefikLbNodePort(true)); + verifyClusterLoadbalancing(domainUid, defaultNamespace, "https", getTraefikLbNodePort(true), + replicaCount, true, ""); } } @@ -412,7 +469,52 @@ public void testVoyagerHostHttpRoutingAcrossDomains() { logger.info("Verifying http traffic"); for (String domainUid : domainUids) { String ingressName = domainUid + "-ingress-host-routing"; - verifyClusterLoadbalancing(domainUid, "http", getVoyagerLbNodePort(ingressName)); + verifyClusterLoadbalancing(domainUid, defaultNamespace, "http", getVoyagerLbNodePort(ingressName), + replicaCount, true, ""); + } + } + + /** + * Verify Apache load balancer default sample through HTTP channel. + * Configure the Apache webtier as a load balancer for a WebLogic domain using the default configuration. + * It only support HTTP protocol. + * For details, please see + * https://github.com/oracle/weblogic-kubernetes-operator/tree/master/kubernetes/samples/charts/apache-samples/default-sample + */ + @Order(8) + @Test + @DisplayName("verify Apache load balancer default sample through HTTP channel") + public void testApacheDefaultSample() { + + // verify Apache default sample + logger.info("Verifying Apache default sample"); + int httpNodePort = getApacheNodePort(domain1Namespace, "http"); + verifyClusterLoadbalancing(domain1Uid, domain1Namespace, "http", httpNodePort, 3, false, "/weblogic"); + } + + /** + * Verify Apache load balancer custom sample through HTTP and HTTPS channel. + * Configure the Apache webtier as a load balancer for multiple WebLogic domains using a custom configuration. + * Create a custom Apache plugin configuration file named custom_mod_wl_apache.conf in a directory specified + * in helm chart parameter volumePath. + * For more details, please check: + * https://github.com/oracle/weblogic-kubernetes-operator/tree/master/kubernetes/samples/charts/apache-samples/custom-sample + */ + @Order(9) + @Test + @DisplayName("verify Apache load balancer custom sample through HTTP and HTTPS channel") + public void testApacheCustomSample() { + + // verify Apache custom sample + logger.info("Verifying Apache custom sample"); + for (int i = 1; i <= numberOfDomains; i++) { + int httpNodePort = getApacheNodePort(defaultNamespace, "http"); + verifyClusterLoadbalancing(domainUids.get(i - 1), defaultNamespace, "http", httpNodePort, replicaCount, + false, "/weblogic" + i); + + int httpsNodePort = getApacheNodePort(defaultNamespace, "https"); + verifyClusterLoadbalancing(domainUids.get(i - 1), defaultNamespace, "https", httpsNodePort, replicaCount, + false, "/weblogic" + i); } } @@ -437,6 +539,21 @@ public void tearDownAll() { .isTrue(); } + // uninstall Apache + if (apacheHelmParams1 != null) { + assertThat(uninstallApache(apacheHelmParams1)) + .as("Test whether uninstallApache in domain1Namespace returns true") + .withFailMessage("uninstallApache() in domain1Namespace did not return true") + .isTrue(); + } + + if (apacheHelmParams2 != null) { + assertThat(uninstallApache(apacheHelmParams2)) + .as("Test whether uninstallApache in default namespace returns true") + .withFailMessage("uninstallApache() in default namespace did not return true") + .isTrue(); + } + // uninstall operator which manages default namespace logger.info("uninstalling operator which manages default namespace"); if (operatorHelmParams != null) { @@ -912,38 +1029,27 @@ private void getBothDomainsPodsOriginalCreationTimestamp(List domainUids } /** - * Shutdown both domains and verify all the server pods were shutdown. + * Shutdown domain and verify all the server pods were shutdown. * - * @param domainNamespaces list of domain namespaces + * @param domainNamespace the namespace where the domain exists + * @param domainUid the uid of the domain to shutdown */ - private void shutdownBothDomainsAndVerify(List domainNamespaces) { + private void shutdownDomainAndVerify(String domainNamespace, String domainUid) { - // shutdown both domains - logger.info("Shutting down both domains"); - for (int i = 0; i < numberOfDomains; i++) { - shutdownDomain(domainUids.get(i), domainNamespaces.get(i)); - } + // shutdown domain + logger.info("Shutting down domain {0} in namespace {1}", domainUid, domainNamespace); + shutdownDomain(domainUid, domainNamespace); // verify all the pods were shutdown - logger.info("Verifying all server pods were shutdown for both domains"); - for (int i = 0; i < numberOfDomains; i++) { - // check admin server pod was shutdown - checkPodDoesNotExist(domainUids.get(i) + "-" + ADMIN_SERVER_NAME_BASE, - domainUids.get(i), domainNamespaces.get(i)); - - for (int j = 1; j <= replicaCount; j++) { - String managedServerPodName = domainUids.get(i) + "-" + MANAGED_SERVER_NAME_BASE + j; - checkPodDoesNotExist(managedServerPodName, domainUids.get(i), domainNamespaces.get(i)); - } - } + logger.info("Verifying all server pods were shutdown for the domain"); + // check admin server pod was shutdown + checkPodDoesNotExist(domainUid + "-" + ADMIN_SERVER_NAME_BASE, + domainUid, domainNamespace); - // check the scaled up managed servers in domain1 were shutdown - logger.info("Verifying the scaled up managed servers in domain1 were shutdown"); - for (int i = replicaCount + 1; i <= replicasAfterScale; i++) { - String managedServerPodName = domain1Uid + "-" + MANAGED_SERVER_NAME_BASE + i; - checkPodDoesNotExist(managedServerPodName, domain1Uid, domain1Namespace); + for (int i = 1; i <= replicaCount; i++) { + String managedServerPodName = domainUid + "-" + MANAGED_SERVER_NAME_BASE + i; + checkPodDoesNotExist(managedServerPodName, domainUid, domainNamespace); } - } /** @@ -1233,14 +1339,25 @@ private static int getVoyagerLbNodePort(String ingressName) { return ingressServiceNodePort; } - private static void deployApplication(String domainUid, String adminServerPodName) { + private static int getApacheNodePort(String namespace, String channelName) { + String apacheServiceName = APACHE_RELEASE_NAME + "-" + namespace.substring(3) + "-apache-webtier"; + + // get Apache service NodePort + int apacheNodePort = assertDoesNotThrow(() -> + getServiceNodePort(namespace, apacheServiceName, channelName), + "Getting Apache service NodePort failed"); + logger.info("NodePort for {0} is: {1} :", apacheServiceName, apacheNodePort); + return apacheNodePort; + } + + private static void deployApplication(String namespace, String domainUid, String adminServerPodName) { logger.info("Getting node port for admin server default channel"); int serviceNodePort = assertDoesNotThrow(() -> - getServiceNodePort(defaultNamespace, adminServerPodName + "-external", "default"), + getServiceNodePort(namespace, adminServerPodName + "-external", "default"), "Getting admin server node port failed"); - logger.info("Deploying application {0} in domain {1} cluster target cluster-1", - clusterViewAppPath, domainUid); + logger.info("Deploying application {0} to domain {1} cluster target cluster-1 in namespace {2}", + clusterViewAppPath, domainUid, namespace); ExecResult result = DeployUtil.deployUsingRest(K8S_NODEPORT_HOST, String.valueOf(serviceNodePort), ADMIN_USERNAME_DEFAULT, ADMIN_PASSWORD_DEFAULT, @@ -1291,15 +1408,42 @@ private int getTraefikLbNodePort(boolean isHttps) { "Getting web node port for Traefik loadbalancer failed"); } - private void verifyClusterLoadbalancing(String domainUid, String protocol, int lbPort) { - - //access application in managed servers through Traefik load balancer + /** + * Verify cluster load balancing with ClusterViewServlet app. + * + * @param domainUid uid of the domain in which the cluster exists + * @param namespace namespace in which the domain exists + * @param protocol protocol used to test, accepted value: http or https + * @param lbPort load balancer service port + * @param replicaCount replica count of the managed servers in the cluster + * @param hostRouting whether it is a host base routing + * @param apacheLocationString location string in apache configuration + */ + private void verifyClusterLoadbalancing(String domainUid, + String namespace, + String protocol, + int lbPort, + int replicaCount, + boolean hostRouting, + String apacheLocationString) { + + // access application in managed servers through load balancer logger.info("Accessing the clusterview app through load balancer to verify all servers in cluster"); - String curlRequest = String.format("curl --silent --show-error -ks --noproxy '*' " - + "-H 'host: %s' %s://%s:%s/clusterview/ClusterViewServlet" - + "\"?user=" + ADMIN_USERNAME_DEFAULT - + "&password=" + ADMIN_PASSWORD_DEFAULT + "\"", - domainUid + "." + defaultNamespace + "." + "cluster-1.test", protocol, K8S_NODEPORT_HOST, lbPort); + String curlRequest; + if (hostRouting) { + curlRequest = String.format("curl --silent --show-error -ks --noproxy '*' " + + "-H 'host: %s' %s://%s:%s/clusterview/ClusterViewServlet" + + "\"?user=" + ADMIN_USERNAME_DEFAULT + + "&password=" + ADMIN_PASSWORD_DEFAULT + "\"", + domainUid + "." + namespace + "." + "cluster-1.test", protocol, K8S_NODEPORT_HOST, lbPort); + } else { + curlRequest = String.format("curl --silent --show-error -ks --noproxy '*' " + + "%s://%s:%s" + apacheLocationString + "/clusterview/ClusterViewServlet" + + "\"?user=" + ADMIN_USERNAME_DEFAULT + + "&password=" + ADMIN_PASSWORD_DEFAULT + "\"", + protocol, K8S_NODEPORT_HOST, lbPort); + } + List managedServers = new ArrayList<>(); for (int i = 1; i <= replicaCount; i++) { managedServers.add(MANAGED_SERVER_NAME_BASE + i); @@ -1308,34 +1452,25 @@ private void verifyClusterLoadbalancing(String domainUid, String protocol, int l // verify each managed server can see other member in the cluster verifyServerCommunication(curlRequest, managedServers); - boolean hostRouting = false; - //access application in managed servers through Traefik load balancer and bind domain in the JNDI tree + boolean containsCorrectDomainUid = false; logger.info("Verifying the requests are routed to correct domain and cluster"); - String curlCmd = String.format("curl --silent --show-error -ks --noproxy '*' " - + "-H 'host: %s' %s://%s:%s/clusterview/ClusterViewServlet" - + "\"?user=" + ADMIN_USERNAME_DEFAULT - + "&password=" + ADMIN_PASSWORD_DEFAULT + "\"", - domainUid + "." + defaultNamespace + "." + "cluster-1.test", protocol, K8S_NODEPORT_HOST, lbPort, domainUid); - - // call the webapp and verify the bound domain name to determine - // the requests are sent to the correct cluster members. for (int i = 0; i < 10; i++) { ExecResult result; try { - logger.info(curlCmd); - result = ExecCommand.exec(curlCmd, true); + logger.info("executing curl command: {0}", curlRequest); + result = ExecCommand.exec(curlRequest, true); String response = result.stdout().trim(); logger.info("Response for iteration {0}: exitValue {1}, stdout {2}, stderr {3}", i, result.exitValue(), response, result.stderr()); if (response.contains(domainUid)) { - hostRouting = true; + containsCorrectDomainUid = true; break; } } catch (IOException | InterruptedException ex) { // ignore } } - assertTrue(hostRouting, "Host routing is not working"); + assertTrue(containsCorrectDomainUid, "The request was not routed to the correct domain"); } /** @@ -1379,4 +1514,13 @@ private static boolean adminNodePortAccessible(int nodePort, String userName, St return adminAccessible; } + + private static Callable pullImageFromOcirAndPushToKind(String apacheImage) { + return (() -> { + kindRepoApacheImage = KIND_REPO + apacheImage.substring(REPO_DEFAULT.length()); + logger.info("pulling image {0} from OCIR, tag it as image {1} and push to KIND repo", + apacheImage, kindRepoApacheImage); + return dockerPull(apacheImage) && dockerTag(apacheImage, kindRepoApacheImage) && dockerPush(kindRepoApacheImage); + }); + } } diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/TestConstants.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/TestConstants.java index 8b5bf9b3510..88784a6a548 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/TestConstants.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/TestConstants.java @@ -93,7 +93,14 @@ public interface TestConstants { public static final String VOYAGER_CHART_NAME = "voyager"; public static final String VOYAGER_CHART_VERSION = "12.0.0"; - // ELK Stack and WebLogic Logging Exporter constants + // Apache constants + public static final String APACHE_IMAGE_NAME = "phx.ocir.io/weblogick8s/oracle/apache"; + public static final String APACHE_IMAGE_VERSION = "12.2.1.3"; + public static final String APACHE_IMAGE = APACHE_IMAGE_NAME + ":" + APACHE_IMAGE_VERSION; + public static final String APACHE_RELEASE_NAME = "apache-release" + BUILD_ID; + public static final String APACHE_SAMPLE_CHART_DIR = "../kubernetes/samples/charts/apache-webtier"; + + // ELK Stack and WebLogic logging exporter constants public static final String ELASTICSEARCH_NAME = "elasticsearch"; public static final String ELK_STACK_VERSION = "7.8.1"; public static final String ELASTICSEARCH_IMAGE = ELASTICSEARCH_NAME + ":" + ELK_STACK_VERSION; diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/TestActions.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/TestActions.java index e337f65fb94..99c02c0a051 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/TestActions.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/TestActions.java @@ -26,6 +26,8 @@ import io.kubernetes.client.openapi.models.V1ServiceAccount; import io.kubernetes.client.openapi.models.V1ServiceList; import oracle.weblogic.domain.DomainList; +import oracle.weblogic.kubernetes.actions.impl.Apache; +import oracle.weblogic.kubernetes.actions.impl.ApacheParams; import oracle.weblogic.kubernetes.actions.impl.AppBuilder; import oracle.weblogic.kubernetes.actions.impl.AppParams; import oracle.weblogic.kubernetes.actions.impl.ClusterRole; @@ -385,6 +387,16 @@ public static boolean installTraefik(TraefikParams params) { return Traefik.install(params); } + /** + * Install Apache ingress controller. + * + * @param params the parameters to Helm install command, such as release name, namespace, repo url, + * repo name and chart name + * @return true on success, false otherwise + */ + public static boolean installApache(ApacheParams params) { + return Apache.install(params); + } /** * Upgrade NGINX release. @@ -406,6 +418,16 @@ public static boolean upgradeVoyager(VoyagerParams params) { return Voyager.upgrade(params); } + /** + * Upgrade Apache release. + * + * @param params the parameters to Helm upgrade command, such as release name and http/https nodeport + * @return true on success, false otherwise + */ + public static boolean upgradeApache(ApacheParams params) { + return Apache.upgrade(params); + } + /** * Uninstall the NGINX release. * @@ -436,6 +458,16 @@ public static boolean uninstallVoyager(HelmParams params) { return Voyager.uninstall(params); } + /** + * Uninstall the Apache release. + * + * @param params the parameters to Helm uninstall command, such as release name and namespace + * @return true on success, false otherwise + */ + public static boolean uninstallApache(HelmParams params) { + return Apache.uninstall(params); + } + /** * Create an ingress for the WebLogic domain with domainUid in the specified domain namespace. * The ingress host is set to 'domainUid.clusterName.test'. diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/Apache.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/Apache.java new file mode 100644 index 00000000000..1ec8b012bfd --- /dev/null +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/Apache.java @@ -0,0 +1,45 @@ +// Copyright (c) 2020, Oracle Corporation and/or its affiliates. +// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +package oracle.weblogic.kubernetes.actions.impl; + +import oracle.weblogic.kubernetes.actions.impl.primitive.Helm; +import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; + +/** + * Utility class for Apache load balancer. + */ +public class Apache { + + /** + * Install Apache Helm chart. + * + * @param params the parameters to Helm install command such as release name, namespace, repo url or chart dir, + * chart name and chart values + * @return true on success, false otherwise + */ + public static boolean install(ApacheParams params) { + return Helm.install(params.getHelmParams(), params.getValues()); + } + + /** + * Upgrade Apache Helm release. + * + * @param params the parameters to Helm upgrade command such as release name, namespace and chart values to override + * @return true on success, false otherwise + */ + public static boolean upgrade(ApacheParams params) { + return Helm.upgrade(params.getHelmParams(), params.getValues()); + } + + /** + * Uninstall Apache Helm release. + * + * @param params the parameters to Helm uninstall command such as release name and namespace + * @return true on success, false otherwise + */ + public static boolean uninstall(HelmParams params) { + return Helm.uninstall(params); + } + +} diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/ApacheParams.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/ApacheParams.java new file mode 100644 index 00000000000..b94ce74bae7 --- /dev/null +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/impl/ApacheParams.java @@ -0,0 +1,129 @@ +// Copyright (c) 2020, Oracle Corporation and/or its affiliates. +// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +package oracle.weblogic.kubernetes.actions.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; + +/** + * All parameters needed to install Apache load balancer. + */ +public class ApacheParams { + + // The default values can be found here: + // weblogic-kubernetes-operator/kubernetes/samples/charts/apache-webtier/values.yaml + private static final String IMAGE = "image"; + private static final String IMAGE_PULL_POLICY = "imagePullPolicy"; + private static final String IMAGE_PULL_SECRETS = "imagePullSecrets"; + private static final String VOLUME_PATH = "volumePath"; + private static final String HTTP_NODEPORT = "httpNodePort"; + private static final String HTTPS_NODEPORT = "httpsNodePort"; + private static final String VIRTUAL_HOSTNAME = "virtualHostName"; + private static final String CUSTOM_CERT = "customCert"; + private static final String CUSTOM_KEY = "customKey"; + private static final String DOMAIN_UID = "domainUID"; + + private String image = null; + private String imagePullPolicy = null; + private Map imagePullSecrets = null; + private String volumePath = null; + private int httpNodePort = 0; + private int httpsNodePort = 0; + private String virtualHostName = null; + private String customCert = null; + private String customKey = null; + private String domainUID = null; + private HelmParams helmParams; + + public ApacheParams image(String image) { + this.image = image; + return this; + } + + public ApacheParams imagePullPolicy(String imagePullPolicy) { + this.imagePullPolicy = imagePullPolicy; + return this; + } + + public ApacheParams imagePullSecrets(Map imagePullSecrets) { + this.imagePullSecrets = imagePullSecrets; + return this; + } + + public ApacheParams volumePath(String volumePath) { + this.volumePath = volumePath; + return this; + } + + public ApacheParams httpNodePort(int httpNodePort) { + this.httpNodePort = httpNodePort; + return this; + } + + public ApacheParams httpsNodePort(int httpsNodePort) { + this.httpsNodePort = httpsNodePort; + return this; + } + + public ApacheParams virtualHostName(String virtualHostName) { + this.virtualHostName = virtualHostName; + return this; + } + + public ApacheParams customCert(String customCert) { + this.customCert = customCert; + return this; + } + + public ApacheParams customKey(String customKey) { + this.customKey = customKey; + return this; + } + + public ApacheParams domainUID(String domainUID) { + this.domainUID = domainUID; + return this; + } + + public ApacheParams helmParams(HelmParams helmParams) { + this.helmParams = helmParams; + return this; + } + + public HelmParams getHelmParams() { + return helmParams; + } + + /** + * Loads Helm values into a value map. + * + * @return Map of values + */ + public Map getValues() { + Map values = new HashMap<>(); + + values.put(IMAGE, image); + values.put(IMAGE_PULL_POLICY, imagePullPolicy); + values.put(IMAGE_PULL_SECRETS, imagePullSecrets); + values.put(VOLUME_PATH, volumePath); + + if (httpNodePort >= 0) { + values.put(HTTP_NODEPORT, httpNodePort); + } + if (httpsNodePort >= 0) { + values.put(HTTPS_NODEPORT, httpsNodePort); + } + + values.put(VIRTUAL_HOSTNAME, virtualHostName); + values.put(CUSTOM_CERT, customCert); + values.put(CUSTOM_KEY, customKey); + values.put(DOMAIN_UID, domainUID); + + values.values().removeIf(Objects::isNull); + return values; + } +} diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java index 84a0fb935ed..783442ba925 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java @@ -8,7 +8,9 @@ import java.util.concurrent.Callable; import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.models.V1Secret; import oracle.weblogic.kubernetes.actions.impl.LoggingExporter; +import oracle.weblogic.kubernetes.assertions.impl.Apache; import oracle.weblogic.kubernetes.assertions.impl.Application; import oracle.weblogic.kubernetes.assertions.impl.ClusterRole; import oracle.weblogic.kubernetes.assertions.impl.ClusterRoleBinding; @@ -30,6 +32,8 @@ import oracle.weblogic.kubernetes.assertions.impl.WitAssertion; import org.joda.time.DateTime; +import static oracle.weblogic.kubernetes.actions.TestActions.listSecrets; + /** * General assertions needed by the tests to validate CRD, Domain, Pods etc. */ @@ -65,6 +69,16 @@ public static Callable isNginxReady(String namespace) { return Nginx.isReady(namespace); } + /** + * Check if there are ready Apache pods in the specified namespace. + * + * @param namespace in which to check if Apache pods are in the ready state + * @return true if there are ready Apache pods in the specified namespace , false otherwise + */ + public static Callable isApacheReady(String namespace) { + return Apache.isReady(namespace); + } + /** * Check traefik controller pod is ready in the specified namespace. * @@ -630,4 +644,24 @@ public static boolean clusterRoleExists(String clusterRoleName) throws ApiExcept public static boolean clusterRoleBindingExists(String clusterRoleBindingName) throws ApiException { return ClusterRoleBinding.clusterRoleBindingExists(clusterRoleBindingName); } + + /** + * Check whether the secret exists in the specified namespace. + * + * @param secretName name of the secret + * @param namespace namespace in which the secret exists + * @return true if secret exists, false otherwise + */ + public static boolean secretExists(String secretName, String namespace) { + for (V1Secret secret : listSecrets(namespace).getItems()) { + if (secret.getMetadata() != null) { + String name = secret.getMetadata().getName(); + if (name != null && name.equals(secretName)) { + return true; + } + } + } + + return false; + } } diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Apache.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Apache.java new file mode 100644 index 00000000000..bd9aeb103be --- /dev/null +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Apache.java @@ -0,0 +1,32 @@ +// Copyright (c) 2020, Oracle Corporation and/or its affiliates. +// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +package oracle.weblogic.kubernetes.assertions.impl; + +import java.util.concurrent.Callable; + +/** + * Assertions for Apache load balancer. + */ +public class Apache { + + /** + * Check if the Apache pod is running in the specified namespace. + * + * @param namespace in which to check if the Apache pod is running + * @return true if the Apache pod is running, false otherwise + */ + public static Callable isRunning(String namespace) { + return () -> Kubernetes.isApachePodRunning(namespace); + } + + /** + * Check if the Apache pod is ready in the specified namespace. + * + * @param namespace in which to check the Apache pod is ready + * @return true if the Apache pod is in the ready state, false otherwise + */ + public static Callable isReady(String namespace) { + return () -> Kubernetes.isApachePodReady(namespace); + } +} diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java index 5c12999eb40..a4cac8c8223 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java @@ -38,6 +38,7 @@ import org.joda.time.DateTime; import static io.kubernetes.client.util.Yaml.dump; +import static oracle.weblogic.kubernetes.TestConstants.APACHE_RELEASE_NAME; import static oracle.weblogic.kubernetes.TestConstants.TRAEFIK_RELEASE_NAME; import static oracle.weblogic.kubernetes.actions.TestActions.getPodRestartVersion; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.getPodCreationTimestamp; @@ -344,6 +345,34 @@ public static boolean isNginxPodReady(String namespace) throws ApiException { return isPodReady(namespace, labelSelector, "nginx-ingress-controller"); } + /** + * Checks if a Apache pod is running in the specified namespace. + * The method assumes the Apache pod name contains "APACHE_RELEAE_NAME-namespace.substring(3)-apache-webtier". + * + * @param namespace in which to check if the Apache pod is running + * @return true if the pod is running, otherwise false + * @throws ApiException if Kubernetes client API call fails + */ + public static boolean isApachePodRunning(String namespace) throws ApiException { + + return isPodRunning(namespace, null, + APACHE_RELEASE_NAME + "-" + namespace.substring(3) + "-apache-webtier"); + } + + /** + * Check whether the Apache pod is ready in the specified namespace. + * The method assumes the Apache pod name contains "APACHE_RELEASE_NAME-namespace.substring(3)-apache-webtier". + * + * @param namespace in which to check if the Apache pod is ready + * @return true if the pod is in the ready state, false otherwise + * @throws ApiException if Kubernetes client API call fails + */ + public static boolean isApachePodReady(String namespace) throws ApiException { + String labelSelector = null; + return isPodReady(namespace, labelSelector, + APACHE_RELEASE_NAME + "-" + namespace.substring(3) + "-apache-webtier"); + } + /** * Checks if traefik pod is running in the specified namespace. * diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/extensions/ImageBuilders.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/extensions/ImageBuilders.java index f52ef6f821e..0575ec93168 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/extensions/ImageBuilders.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/extensions/ImageBuilders.java @@ -48,6 +48,8 @@ import static oracle.weblogic.kubernetes.TestConstants.OCR_USERNAME; import static oracle.weblogic.kubernetes.TestConstants.REPO_DUMMY_VALUE; import static oracle.weblogic.kubernetes.TestConstants.REPO_NAME; +import static oracle.weblogic.kubernetes.TestConstants.REPO_PASSWORD; +import static oracle.weblogic.kubernetes.TestConstants.REPO_REGISTRY; import static oracle.weblogic.kubernetes.TestConstants.REPO_USERNAME; import static oracle.weblogic.kubernetes.TestConstants.WDT_BASIC_APP_NAME; import static oracle.weblogic.kubernetes.TestConstants.WDT_BASIC_IMAGE_DOMAINHOME; @@ -133,6 +135,44 @@ public void beforeAll(ExtensionContext context) { assertFalse(operatorImage.isEmpty(), "Image name can not be empty"); assertTrue(Operator.buildImage(operatorImage), "docker build failed for Operator"); + // docker login to OCR if OCR_USERNAME and OCR_PASSWORD is provided in env var + if (!OCR_USERNAME.equals(REPO_DUMMY_VALUE)) { + withStandardRetryPolicy + .conditionEvaluationListener( + condition -> logger.info("Waiting for docker login to be successful" + + "(elapsed time {0} ms, remaining time {1} ms)", + condition.getElapsedTimeInMS(), + condition.getRemainingTimeInMS())) + .until(() -> dockerLogin(OCR_REGISTRY, OCR_USERNAME, OCR_PASSWORD)); + } + + // The following code is for pulling WLS images if running tests in Kind cluster + if (KIND_REPO != null) { + // The kind clusters can't pull images from OCR using the image pull secret. + // It may be a containerd bug. We are going to workaround this issue. + // The workaround will be to: + // 1. docker login + // 2. docker pull + // 3. docker tag with the KIND_REPO value + // 4. docker push this new image name + // 5. use this image name to create the domain resource + Collection images = new ArrayList<>(); + images.add(WLS_BASE_IMAGE_NAME + ":" + WLS_BASE_IMAGE_TAG); + images.add(JRF_BASE_IMAGE_NAME + ":" + JRF_BASE_IMAGE_TAG); + images.add(DB_IMAGE_NAME + ":" + DB_IMAGE_TAG); + + for (String image : images) { + withStandardRetryPolicy + .conditionEvaluationListener( + condition -> logger.info("Waiting for pullImageFromOcrAndPushToKind for image {0} to be successful" + + "(elapsed time {1} ms, remaining time {2} ms)", image, + condition.getElapsedTimeInMS(), + condition.getRemainingTimeInMS())) + .until(pullImageFromOcrAndPushToKind(image) + ); + } + } + if (System.getenv("SKIP_BASIC_IMAGE_BUILD") == null) { // build MII basic image miiBasicImage = MII_BASIC_IMAGE_NAME + ":" + MII_BASIC_IMAGE_TAG; @@ -178,9 +218,10 @@ public void beforeAll(ExtensionContext context) { + "(elapsed time {0} ms, remaining time {1} ms)", condition.getElapsedTimeInMS(), condition.getRemainingTimeInMS())) - .until(() -> dockerLogin(OCR_REGISTRY, OCR_USERNAME, OCR_PASSWORD)); + .until(() -> dockerLogin(REPO_REGISTRY, REPO_USERNAME, REPO_PASSWORD)); } } + // push the images to repo if (!REPO_NAME.isEmpty()) { @@ -205,41 +246,6 @@ public void beforeAll(ExtensionContext context) { } } - // The following code is for pulling WLS images if running tests in Kind cluster - if (KIND_REPO != null) { - // We can't figure out why the kind clusters can't pull images from OCR using the image pull secret. There - // is some evidence it may be a containerd bug. Therefore, we are going to "give up" and workaround the issue. - // The workaround will be to: - // 1. docker login - // 2. docker pull - // 3. docker tag with the KIND_REPO value - // 4. docker push this new image name - // 5. use this image name to create the domain resource - Collection images = new ArrayList<>(); - images.add(WLS_BASE_IMAGE_NAME + ":" + WLS_BASE_IMAGE_TAG); - images.add(JRF_BASE_IMAGE_NAME + ":" + JRF_BASE_IMAGE_TAG); - images.add(DB_IMAGE_NAME + ":" + DB_IMAGE_TAG); - - withStandardRetryPolicy - .conditionEvaluationListener( - condition -> logger.info("Waiting for docker login to be successful" - + "(elapsed time {0} ms, remaining time {1} ms)", - condition.getElapsedTimeInMS(), - condition.getRemainingTimeInMS())) - .until(() -> dockerLogin(OCR_REGISTRY, OCR_USERNAME, OCR_PASSWORD)); - - for (String image : images) { - withStandardRetryPolicy - .conditionEvaluationListener( - condition -> logger.info("Waiting for pullImageFromOcrAndPushToKind for image {0} to be successful" - + "(elapsed time {1} ms, remaining time {2} ms)", image, - condition.getElapsedTimeInMS(), - condition.getRemainingTimeInMS())) - .until(pullImageFromOcrAndPushToKind(image) - ); - } - } - // set initialization success to true, not counting the istio installation as not all tests use istio isInitializationSuccessful = true; logger.info("Installing istio before any test suites are run"); diff --git a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java index fffe702351e..5760fcd57e5 100644 --- a/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java +++ b/new-integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -52,6 +53,7 @@ import oracle.weblogic.domain.Domain; import oracle.weblogic.kubernetes.TestConstants; import oracle.weblogic.kubernetes.actions.TestActions; +import oracle.weblogic.kubernetes.actions.impl.ApacheParams; import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; import oracle.weblogic.kubernetes.actions.impl.LoggingExporterParams; import oracle.weblogic.kubernetes.actions.impl.NginxParams; @@ -71,6 +73,8 @@ import static java.nio.file.Files.readString; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; +import static oracle.weblogic.kubernetes.TestConstants.APACHE_RELEASE_NAME; +import static oracle.weblogic.kubernetes.TestConstants.APACHE_SAMPLE_CHART_DIR; import static oracle.weblogic.kubernetes.TestConstants.APPSCODE_REPO_NAME; import static oracle.weblogic.kubernetes.TestConstants.APPSCODE_REPO_URL; import static oracle.weblogic.kubernetes.TestConstants.DEFAULT_EXTERNAL_REST_IDENTITY_SECRET_NAME; @@ -145,6 +149,7 @@ import static oracle.weblogic.kubernetes.actions.TestActions.getPodCreationTimestamp; import static oracle.weblogic.kubernetes.actions.TestActions.getPodLog; import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.installApache; import static oracle.weblogic.kubernetes.actions.TestActions.installElasticsearch; import static oracle.weblogic.kubernetes.actions.TestActions.installGrafana; import static oracle.weblogic.kubernetes.actions.TestActions.installKibana; @@ -166,6 +171,7 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.credentialsValid; import static oracle.weblogic.kubernetes.assertions.TestAssertions.doesImageExist; import static oracle.weblogic.kubernetes.assertions.TestAssertions.domainExists; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.isApacheReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.isElkStackPodReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.isGrafanaReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.isHelmReleaseDeployed; @@ -183,6 +189,7 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.podStateNotChanged; import static oracle.weblogic.kubernetes.assertions.TestAssertions.pvExists; import static oracle.weblogic.kubernetes.assertions.TestAssertions.pvcExists; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.secretExists; import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceDoesNotExist; import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceExists; import static oracle.weblogic.kubernetes.utils.ExecCommand.exec; @@ -607,6 +614,182 @@ public static HelmParams installAndVerifyVoyager(String voyagerNamespace, return voyagerHelmParams; } + /** + * Install Apache and wait up to five minutes until the Apache pod is ready. + * + * @param apacheNamespace the namespace in which the Apache will be installed + * @param image the image name of Apache webtier + * @param httpNodePort the http nodeport of Apache + * @param httpsNodePort the https nodeport of Apache + * @param domainUid the uid of the domain to which Apache will route the services + * @return the Apache Helm installation parameters + */ + public static HelmParams installAndVerifyApache(String apacheNamespace, + String image, + int httpNodePort, + int httpsNodePort, + String domainUid) throws IOException { + return installAndVerifyApache(apacheNamespace, image, httpNodePort, httpsNodePort, domainUid, + null, null, null); + } + + /** + * Install Apache and wait up to five minutes until the Apache pod is ready. + * + * @param apacheNamespace the namespace in which the Apache will be installed + * @param image the image name of Apache webtier + * @param httpNodePort the http nodeport of Apache + * @param httpsNodePort the https nodeport of Apache + * @param domainUid the uid of the domain to which Apache will route the services + * @param volumePath the path to put your own custom_mod_wl_apache.conf file + * @param virtualHostName the VirtualHostName of the Apache HTTP server which is used to enable custom SSL config + * @param clusterNamePortMap the map with clusterName as key and cluster port number as value + * @return the Apache Helm installation parameters + */ + public static HelmParams installAndVerifyApache(String apacheNamespace, + String image, + int httpNodePort, + int httpsNodePort, + String domainUid, + String volumePath, + String virtualHostName, + LinkedHashMap clusterNamePortMap) + throws IOException { + + LoggingFacade logger = getLogger(); + + // Create Docker registry secret in the apache namespace to pull the Apache webtier image from repository + if (!secretExists(REPO_SECRET_NAME, apacheNamespace)) { + logger.info("Creating Docker registry secret in namespace {0}", apacheNamespace); + createDockerRegistrySecret(apacheNamespace); + } + + // map with secret + Map secretNameMap = new HashMap<>(); + secretNameMap.put("name", REPO_SECRET_NAME); + + // Helm install parameters + HelmParams apacheHelmParams = new HelmParams() + .releaseName(APACHE_RELEASE_NAME + "-" + apacheNamespace.substring(3)) + .namespace(apacheNamespace) + .chartDir(APACHE_SAMPLE_CHART_DIR); + + // Apache chart values to override + ApacheParams apacheParams = new ApacheParams() + .helmParams(apacheHelmParams) + .imagePullSecrets(secretNameMap) + .image(image) + .imagePullPolicy("Always") + .domainUID(domainUid); + + if (httpNodePort >= 0 && httpsNodePort >= 0) { + apacheParams + .httpNodePort(httpNodePort) + .httpsNodePort(httpsNodePort); + } + + if (volumePath != null && clusterNamePortMap != null) { + // create a custom Apache plugin configuration file named custom_mod_wl_apache.conf + // and put it under the directory specified in volumePath + // this file provides a custom Apache plugin configuration to fine tune the behavior of Apache + Path customConf = Paths.get(volumePath, "custom_mod_wl_apache.conf"); + ArrayList lines = new ArrayList<>(); + lines.add(""); + lines.add("WebLogicHost ${WEBLOGIC_HOST}"); + lines.add("WebLogicPort ${WEBLOGIC_PORT}"); + lines.add(""); + + // Directive for weblogic admin Console deployed on Weblogic Admin Server + lines.add(""); + lines.add("SetHandler weblogic-handler"); + lines.add("WebLogicHost " + domainUid + "-admin-server"); + lines.add("WebLogicPort ${WEBLOGIC_PORT}"); + lines.add(""); + + // Directive for all application deployed on weblogic cluster with a prepath defined by LOCATION variable + // For example, if the LOCAITON is set to '/weblogic1', all applications deployed on the cluster can be accessed + // via http://myhost:myport/weblogic1/application_end_url + // where 'myhost' is the IP of the machine that runs the Apache web tier, and + // 'myport' is the port that the Apache web tier is publicly exposed to. + // Note that LOCATION cannot be set to '/' unless this is the only Location module configured. + // create a LOCATION variable for each domain cluster + int i = 1; + for (String clusterName : clusterNamePortMap.keySet()) { + lines.add(""); + lines.add("WLSRequest On"); + lines.add("WebLogicCluster " + clusterName + ":" + clusterNamePortMap.get(clusterName)); + lines.add("PathTrim /weblogic" + i); + lines.add(""); + i++; + } + + try { + Files.write(customConf, lines); + } catch (IOException ioex) { + logger.info("Got IOException while write to a file"); + throw ioex; + } + + apacheParams.volumePath(volumePath); + } + + if (virtualHostName != null) { + // create the certificate and private key + String certFile = RESULTS_ROOT + "/apache-sample.crt"; + String keyFile = RESULTS_ROOT + "/apache-sample.key"; + + Map envs = new HashMap<>(); + envs.put("VIRTUAL_HOST_NAME", virtualHostName); + envs.put("SSL_CERT_FILE", certFile); + envs.put("SSL_CERT_KEY_FILE", keyFile); + + String command = "sh ../kubernetes/samples/charts/apache-samples/custom-sample/certgen.sh"; + CommandParams params = Command + .defaultCommandParams() + .command(command) + .env(envs) + .saveResults(true) + .redirect(true); + + Command.withParams(params).execute(); + + String customCert = Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(certFile))); + String customKey = Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(keyFile))); + + // set the Apache helm install parameters + apacheParams.virtualHostName(virtualHostName); + apacheParams.customCert(customCert); + apacheParams.customKey(customKey); + } + + // install Apache + assertThat(installApache(apacheParams)) + .as("Test Apache installation succeeds") + .withFailMessage("Apache installation is failed") + .isTrue(); + + // verify that Apache is installed + logger.info("Checking Apache release {0} status in namespace {1}", + APACHE_RELEASE_NAME + "-" + apacheNamespace.substring(3), apacheNamespace); + assertTrue(isHelmReleaseDeployed(APACHE_RELEASE_NAME + "-" + apacheNamespace.substring(3), apacheNamespace), + String.format("Apache release %s is not in deployed status in namespace %s", + APACHE_RELEASE_NAME + "-" + apacheNamespace.substring(3), apacheNamespace)); + logger.info("Apache release {0} status is deployed in namespace {1}", + APACHE_RELEASE_NAME + "-" + apacheNamespace.substring(3), apacheNamespace); + + // wait until the Apache pod is ready. + withStandardRetryPolicy + .conditionEvaluationListener( + condition -> logger.info( + "Waiting for Apache to be ready in namespace {0} (elapsed time {1}ms, remaining time {2}ms)", + apacheNamespace, + condition.getElapsedTimeInMS(), + condition.getRemainingTimeInMS())) + .until(assertDoesNotThrow(() -> isApacheReady(apacheNamespace), "isApacheReady failed with ApiException")); + + return apacheHelmParams; + } + /** * Uninstall Elasticsearch. * @@ -2672,5 +2855,4 @@ public static void verifyDefaultTokenExists() { return false; }); } - }