From 4d95dab205dc5fadcc9ab107426982879172ed63 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Tue, 2 Nov 2021 00:31:38 +0000 Subject: [PATCH 01/10] added shutdown for domains --- .../weblogic/kubernetes/ItMonitoringExporterSamples.java | 4 +++- .../weblogic/kubernetes/ItMonitoringExporterSideCar.java | 5 ++++- .../weblogic/kubernetes/ItMonitoringExporterWebApp.java | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java index 25c5d8a6eb6..a5c2f223333 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java @@ -64,6 +64,7 @@ import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; import static oracle.weblogic.kubernetes.assertions.TestAssertions.isPodReady; @@ -445,7 +446,8 @@ public void tearDownAll() { if (wdtImage != null) { deleteImage(miiImage); } - + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain1Namespace, domain1Uid); uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); promHelmParams = null; grafanaHelmParams = null; diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java index 2dacc10b700..0c5a12beaeb 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java @@ -38,6 +38,7 @@ import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.getDomainCustomResource; @@ -400,7 +401,9 @@ public void tearDownAll() { .withFailMessage("uninstallNginx() did not return true") .isTrue(); } - + shutdownDomain(domain1Namespace, domain1Uid); + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain3Namespace, domain3Uid); uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java index 683d8aa03fe..80316bb2d5a 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java @@ -52,6 +52,7 @@ import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.copyFileToPod; import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; @@ -420,6 +421,10 @@ public void tearDownAll() { .isTrue(); } + shutdownDomain(domain1Namespace, domain1Uid); + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain3Namespace, domain3Uid); + // delete mii domain images created if (miiImage != null) { deleteImage(miiImage); From 7e0f8470a6fe95ba0c505ae4d484dd4f2d10a1bf Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Tue, 2 Nov 2021 18:22:28 +0000 Subject: [PATCH 02/10] added shutdown domain to methods --- .../ItMonitoringExporterSamples.java | 81 +- .../ItMonitoringExporterSamples.java.new | 781 +++++++++++++++ .../ItMonitoringExporterSideCar.java | 153 +-- .../ItMonitoringExporterSideCar.java.new | 439 +++++++++ .../ItMonitoringExporterWebApp.java | 162 ++-- .../ItMonitoringExporterWebApp.java.new | 898 ++++++++++++++++++ 6 files changed, 2322 insertions(+), 192 deletions(-) create mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new create mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new create mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java index a5c2f223333..937c9c3e40d 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java @@ -256,43 +256,48 @@ public static void initAll(@Namespaces(6) List namespaces) { @Test @DisplayName("Test End to End example from MonitoringExporter github project.") void testEndToEndViaChart() throws Exception { - wdtImage = createAndVerifyDomainInImage(); - logger.info("Create wdt domain and verify that it's running"); - createAndVerifyDomain(wdtImage, domain2Uid, domain2Namespace, "Image", replicaCount, - false, null,null); - ingressHost2List = - createIngressForDomainAndVerify(domain2Uid, domain2Namespace, clusterNameMsPortMap); - logger.info("Installing Prometheus and Grafana"); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain2Namespace, - domain2Uid); - - installWebhook(); - installCoordinator(domain2Namespace); - - logger.info("verify access to Monitoring Exporter"); - verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0), managedServersCount,nodeportshttp); - logger.info("verify metrics via prometheus"); - String testappPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp",nodeportPrometheus); - logger.info("fire alert by scaling down"); - fireAlert(); - logger.info("switch to monitor another domain"); - logger.info("create and verify WebLogic domain image using model in image with model files"); - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, - true, null, null); - - String oldRegex = String.format("regex: %s;%s", domain2Namespace, domain2Uid); - String newRegex = String.format("regex: %s;%s", domain1Namespace, domain1Uid); - editPrometheusCM(oldRegex, newRegex, monitoringNS, prometheusReleaseName + "-server"); - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - checkPromGrafanaLatestVersion(); + try { + wdtImage = createAndVerifyDomainInImage(); + logger.info("Create wdt domain and verify that it's running"); + createAndVerifyDomain(wdtImage, domain2Uid, domain2Namespace, "Image", replicaCount, + false, null, null); + ingressHost2List = + createIngressForDomainAndVerify(domain2Uid, domain2Namespace, clusterNameMsPortMap); + logger.info("Installing Prometheus and Grafana"); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain2Namespace, + domain2Uid); + + installWebhook(); + installCoordinator(domain2Namespace); + + logger.info("verify access to Monitoring Exporter"); + verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0), managedServersCount, nodeportshttp); + logger.info("verify metrics via prometheus"); + String testappPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp", nodeportPrometheus); + logger.info("fire alert by scaling down"); + fireAlert(); + logger.info("switch to monitor another domain"); + logger.info("create and verify WebLogic domain image using model in image with model files"); + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, + true, null, null); + + String oldRegex = String.format("regex: %s;%s", domain2Namespace, domain2Uid); + String newRegex = String.format("regex: %s;%s", domain1Namespace, domain1Uid); + editPrometheusCM(oldRegex, newRegex, monitoringNS, prometheusReleaseName + "-server"); + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr", nodeportPrometheus); + checkPromGrafanaLatestVersion(); + } finally { + shutdownDomain(domain1Namespace, domain1Uid); + shutdownDomain(domain2Namespace, domain2Uid); + } } /** @@ -446,8 +451,6 @@ public void tearDownAll() { if (wdtImage != null) { deleteImage(miiImage); } - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain1Namespace, domain1Uid); uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); promHelmParams = null; grafanaHelmParams = null; diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new new file mode 100644 index 00000000000..a5c2f223333 --- /dev/null +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new @@ -0,0 +1,781 @@ +// Copyright (c) 2021, Oracle 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; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import io.kubernetes.client.custom.IntOrString; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.models.V1Container; +import io.kubernetes.client.openapi.models.V1ContainerPort; +import io.kubernetes.client.openapi.models.V1Deployment; +import io.kubernetes.client.openapi.models.V1DeploymentSpec; +import io.kubernetes.client.openapi.models.V1DeploymentStrategy; +import io.kubernetes.client.openapi.models.V1LabelSelector; +import io.kubernetes.client.openapi.models.V1LocalObjectReference; +import io.kubernetes.client.openapi.models.V1ObjectMeta; +import io.kubernetes.client.openapi.models.V1Pod; +import io.kubernetes.client.openapi.models.V1PodSpec; +import io.kubernetes.client.openapi.models.V1PodTemplateSpec; +import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServicePort; +import io.kubernetes.client.openapi.models.V1ServiceSpec; +import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; +import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; +import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; +import oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes; +import oracle.weblogic.kubernetes.annotations.IntegrationTest; +import oracle.weblogic.kubernetes.annotations.Namespaces; +import oracle.weblogic.kubernetes.assertions.impl.Deployment; +import oracle.weblogic.kubernetes.logging.LoggingFacade; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT; +import static oracle.weblogic.kubernetes.TestConstants.ADMIN_USERNAME_DEFAULT; +import static oracle.weblogic.kubernetes.TestConstants.GRAFANA_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.K8S_NODEPORT_HOST; +import static oracle.weblogic.kubernetes.TestConstants.MANAGED_SERVER_NAME_BASE; +import static oracle.weblogic.kubernetes.TestConstants.OCIR_SECRET_NAME; +import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; +import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; +import static oracle.weblogic.kubernetes.TestConstants.WEBLOGIC_IMAGE_NAME; +import static oracle.weblogic.kubernetes.TestConstants.WEBLOGIC_IMAGE_TAG; +import static oracle.weblogic.kubernetes.actions.ActionConstants.ITTESTS_DIR; +import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; +import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; +import static oracle.weblogic.kubernetes.actions.ActionConstants.WLS; +import static oracle.weblogic.kubernetes.actions.TestActions.deleteImage; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; +import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; +import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.isPodReady; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.searchPodLogForKey; +import static oracle.weblogic.kubernetes.assertions.impl.Kubernetes.listPods; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getNextFreePort; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.scaleAndVerifyCluster; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.testUntil; +import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; +import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndPushToRepo; +import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndVerify; +import static oracle.weblogic.kubernetes.utils.ImageUtils.dockerLoginAndPushImageToRegistry; +import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.createIngressForDomainAndVerify; +import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyMiiImage; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccessThroughNginx; +import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; +import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; +import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + + +/** + * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running + * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. + * Verify WebLogic metrics can be accessed via NGINX ingress controller. + * Verify WebLogic metrics can be accessed via Prometheus + */ +@DisplayName("Verify end to end sample, provided in the Monitoring Exporter github project") +@IntegrationTest +class ItMonitoringExporterSamples { + + + // domain constants + private static final int replicaCount = 2; + private static int managedServersCount = 2; + private static String domain1Namespace = null; + private static String domain2Namespace = null; + private static String domain1Uid = "monexp-domain-1"; + private static String domain2Uid = "monexp-domain-2"; + + private static HelmParams nginxHelmParams = null; + private static int nodeportshttp = 0; + private static int nodeportshttps = 0; + private static List ingressHost1List = null; + private static List ingressHost2List = null; + + private static String monitoringNS = null; + private static String webhookNS = null; + PrometheusParams promHelmParams = null; + GrafanaParams grafanaHelmParams = null; + + private static V1Service webhookService = null; + private static V1Deployment webhookDepl = null; + private static V1Service coordinatorService = null; + private static V1Deployment coordinatorDepl = null; + // constants for creating domain image using model in image + private static final String MONEXP_MODEL_FILE = "model.monexp.yaml"; + private static final String MONEXP_WDT_FILE = "/demo-domains/domainBuilder/scripts/simple-topology.yaml"; + private static final String MONEXP_IMAGE_NAME = "monexp-image"; + private static final String SESSMIGR_APP_NAME = "sessmigr-app"; + + private static String cluster1Name = "cluster-1"; + private static String cluster2Name = "cluster-2"; + private static String miiImage = null; + private static String wdtImage = null; + private static String webhookImage = null; + private static String exporterImage = null; + private static String coordinatorImage = null; + private static int managedServerPort = 8001; + private static int nodeportPrometheus; + private static String exporterUrl = null; + private static String prometheusDomainRegexValue = null; + private static Map clusterNameMsPortMap; + private static LoggingFacade logger = null; + private static List clusterNames = new ArrayList<>(); + private static String releaseSuffix = "test3"; + private static String prometheusReleaseName = "prometheus" + releaseSuffix; + private static String grafanaReleaseName = "grafana" + releaseSuffix; + private static String monitoringExporterDir; + private static String monitoringExporterSrcDir; + private static String monitoringExporterEndToEndDir; + private static String monitoringExporterAppDir; + + + /** + * Install operator and NGINX. Create model in image domain with multiple clusters. + * Create ingress for the domain. + * + * @param namespaces list of namespaces created by the IntegrationTestWatcher by the + * JUnit engine parameter resolution mechanism + */ + @BeforeAll + + public static void initAll(@Namespaces(6) List namespaces) { + + logger = getLogger(); + monitoringExporterDir = monitoringExporterDir = Paths.get(RESULTS_ROOT, + "ItMonitoringExporterSamples", "monitoringexp").toString(); + monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); + monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end/").toString(); + monitoringExporterAppDir = Paths.get(monitoringExporterDir, "apps").toString(); + + logger.info("Get a unique namespace for operator"); + assertNotNull(namespaces.get(0), "Namespace list is null"); + final String opNamespace = namespaces.get(0); + + logger.info("Get a unique namespace for WebLogic domain1"); + assertNotNull(namespaces.get(1), "Namespace list is null"); + domain1Namespace = namespaces.get(1); + + logger.info("Get a unique namespace for WebLogic domain2"); + assertNotNull(namespaces.get(2), "Namespace list is null"); + domain2Namespace = namespaces.get(2); + + logger.info("Get a unique namespace for monitoring"); + assertNotNull(namespaces.get(3), "Namespace list is null"); + monitoringNS = namespaces.get(3); + + logger.info("Get a unique namespace for webhook"); + assertNotNull(namespaces.get(4), "Namespace list is null"); + webhookNS = namespaces.get(4); + + logger.info("Get a unique namespace for NGINX"); + assertNotNull(namespaces.get(5), "Namespace list is null"); + final String nginxNamespace = namespaces.get(5); + + logger.info("install and verify operator"); + installAndVerifyOperator(opNamespace, domain1Namespace,domain2Namespace); + + logger.info("install monitoring exporter"); + installMonitoringExporter(monitoringExporterDir); + assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", + "pvc-grafana", "pvc-" + grafanaReleaseName)); + + logger.info("create and verify WebLogic domain image using model in image with model files"); + miiImage = createAndVerifyMiiImage(monitoringExporterAppDir, MODEL_DIR + "/" + MONEXP_MODEL_FILE, + SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); + + // install and verify NGINX + nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); + String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; + logger.info("NGINX service name: {0}", nginxServiceName); + nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); + nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); + logger.info("NGINX http node port: {0}", nodeportshttp); + logger.info("NGINX https node port: {0}", nodeportshttps); + clusterNameMsPortMap = new HashMap<>(); + clusterNameMsPortMap.put(cluster1Name, managedServerPort); + clusterNameMsPortMap.put(cluster2Name, managedServerPort); + clusterNames.add(cluster1Name); + clusterNames.add(cluster2Name); + + exporterUrl = String.format("http://%s:%s/wls-exporter/",K8S_NODEPORT_HOST,nodeportshttp); + logger.info("create pv and pvc for monitoring"); + HashMap labels = new HashMap<>(); + labels.put("app", "monitoring"); + labels.put("weblogic.domainUid", domain1Uid); + String pvDir = PV_ROOT + "/ItMonitoringExporterSamples/monexp-persistentVolume/"; + assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels,pvDir)); + assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix, monitoringNS, labels,pvDir)); + assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); + cleanupPromGrafanaClusterRoles(prometheusReleaseName, grafanaReleaseName); + } + + /** + * Test covers end to end sample, provided in the Monitoring Exporter github project. + * Create Prometheus, Grafana, Webhook, Coordinator. + * Create domain in Image with monitoring exporter. + * Verify access to monitoring exporter WebLogic metrics via nginx. + * Check generated by monitoring exporter WebLogic metrics via Prometheus, Grafana. + * Fire Alert using Webhook. + * Change prometheus to add different domain to monitor. + */ + @Test + @DisplayName("Test End to End example from MonitoringExporter github project.") + void testEndToEndViaChart() throws Exception { + wdtImage = createAndVerifyDomainInImage(); + logger.info("Create wdt domain and verify that it's running"); + createAndVerifyDomain(wdtImage, domain2Uid, domain2Namespace, "Image", replicaCount, + false, null,null); + ingressHost2List = + createIngressForDomainAndVerify(domain2Uid, domain2Namespace, clusterNameMsPortMap); + logger.info("Installing Prometheus and Grafana"); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain2Namespace, + domain2Uid); + + installWebhook(); + installCoordinator(domain2Namespace); + + logger.info("verify access to Monitoring Exporter"); + verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0), managedServersCount,nodeportshttp); + logger.info("verify metrics via prometheus"); + String testappPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp",nodeportPrometheus); + logger.info("fire alert by scaling down"); + fireAlert(); + logger.info("switch to monitor another domain"); + logger.info("create and verify WebLogic domain image using model in image with model files"); + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, + true, null, null); + + String oldRegex = String.format("regex: %s;%s", domain2Namespace, domain2Uid); + String newRegex = String.format("regex: %s;%s", domain1Namespace, domain1Uid); + editPrometheusCM(oldRegex, newRegex, monitoringNS, prometheusReleaseName + "-server"); + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); + checkPromGrafanaLatestVersion(); + } + + /** + * Test covers the following use cases. + * Create Prometheus, Grafana from latest version of helm chart + * verify access to monitoring exporter WebLogic metrics via nginx + * check WebLogic metrics via Prometheus + */ + private void checkPromGrafanaLatestVersion() throws Exception { + //uninstall prometheus and grafana if running + uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); + promHelmParams = null; + grafanaHelmParams = null; + prometheusDomainRegexValue = null; + + installPrometheusGrafana(null, null, + domain2Namespace, + domain2Uid); + + + //verify access to Monitoring Exporter + logger.info("verify http access"); + verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0),managedServersCount, nodeportshttp); + //verify metrics via prometheus + String testappPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp",nodeportPrometheus); + } + + private void fireAlert() throws ApiException { + // scale domain2 + logger.info("Scaling cluster {0} of domain {1} in namespace {2} to {3} servers.", + cluster1Name, domain2Uid, domain2Namespace, 1); + managedServersCount = 1; + scaleAndVerifyCluster(cluster1Name, domain2Uid, domain2Namespace, + domain2Uid + "-" + MANAGED_SERVER_NAME_BASE, replicaCount, managedServersCount, + null, null); + + //check webhook log for firing alert + List pods = listPods(webhookNS, "app=webhook").getItems(); + assertNotNull((pods), "No pods are running in namespace : " + webhookNS); + V1Pod pod = pods.stream() + .filter(testpod -> testpod + .getMetadata() + .getName() + .contains("webhook")) + .findAny() + .orElse(null); + + assertNotNull(pod, "Can't find running webhook pod"); + logger.info("Wait for the webhook to fire alert and check webhook log file in {0} namespace ", webhookNS); + + testUntil( + assertDoesNotThrow(() -> searchPodLogForKey(pod, + "Some WLS cluster has only one running server for more than 1 minutes"), + "webhook failed to fire alert"), + logger, + "webhook to fire alert"); + } + + /** + * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. + * @throws ApiException when creating helm charts or pods fails + */ + private void installPrometheusGrafana(String promChartVersion, + String grafanaChartVersion, + String domainNS, + String domainUid + ) throws IOException, ApiException { + final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); + if (promHelmParams == null) { + Path srcPromFile = Paths.get(RESOURCE_DIR, "exporter", "promvalues.yaml"); + + //replace with webhook ns + replaceStringInFile(srcPromFile.toString(), + "webhook.webhook.svc.cluster.local", + String.format("webhook.%s.svc.cluster.local", webhookNS)); + + cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + promHelmParams = installAndVerifyPrometheus(releaseSuffix, + monitoringNS, + promChartVersion, + prometheusRegexValue); + assertNotNull(promHelmParams, " Failed to install prometheus"); + nodeportPrometheus = promHelmParams.getNodePortServer(); + prometheusDomainRegexValue = prometheusRegexValue; + } + //if prometheus already installed change CM for specified domain + if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { + logger.info("update prometheus Config Map with domain info"); + editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, + monitoringNS, prometheusReleaseName + "-server"); + prometheusDomainRegexValue = prometheusRegexValue; + } + logger.info("Prometheus is running"); + + if (grafanaHelmParams == null) { + grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, + monitoringNS, + monitoringExporterEndToEndDir + "/grafana/values.yaml", + grafanaChartVersion); + assertNotNull(grafanaHelmParams, "Grafana failed to install"); + installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); + } + logger.info("Grafana is running"); + } + + /** + * Create a Webhook image, install and verify that pod is running. + * @throws ApiException when creating images or pods fails + */ + private void installWebhook() throws ApiException { + Map labelMap = new HashMap<>(); + labelMap.put("app", "webhook"); + assertTrue(installAndVerifyPodFromCustomImage(monitoringExporterEndToEndDir + "/webhook", + "webhook", + webhookNS, + labelMap, OCIR_SECRET_NAME), "Failed to start webhook"); + } + + /** + * Create a Coordinator image, install and verify that pod is running. + * @param namespace of domain to coordinate + * @throws ApiException when creating images or pods fails + */ + private void installCoordinator(String namespace) throws ApiException { + Map labelMap = new HashMap<>(); + labelMap.put("app", "coordinator"); + assertTrue(installAndVerifyPodFromCustomImage(monitoringExporterSrcDir + "/config_coordinator", + "coordinator", + namespace, + labelMap, "coordsecret"), "Failed to start coordinator"); + } + + @AfterAll + public void tearDownAll() { + + // uninstall NGINX release + logger.info("Uninstalling NGINX"); + if (nginxHelmParams != null) { + assertThat(uninstallNginx(nginxHelmParams)) + .as("Test uninstallNginx1 returns true") + .withFailMessage("uninstallNginx() did not return true") + .isTrue(); + } + + // delete mii domain images created for parameterized test + if (miiImage != null) { + deleteImage(miiImage); + } + if (wdtImage != null) { + deleteImage(miiImage); + } + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain1Namespace, domain1Uid); + uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); + promHelmParams = null; + grafanaHelmParams = null; + prometheusDomainRegexValue = null; + + deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix, monitoringNS); + deletePersistentVolume("pv-testalertmanager" + releaseSuffix); + deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + prometheusReleaseName); + deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + grafanaReleaseName); + deleteNamespace(monitoringNS); + uninstallDeploymentService(webhookDepl, webhookService); + uninstallDeploymentService(coordinatorDepl, coordinatorService); + // delete coordinator and webhook images + if (webhookImage != null) { + deleteImage(webhookImage); + } + if (coordinatorImage != null) { + deleteImage(coordinatorImage); + } + deleteMonitoringExporterTempDir(monitoringExporterDir); + } + + /** + * Create, install Webhook or Coordinator and wait up to five minutes until the pod is ready. + * + * @param dockerFileDir directory where dockerfile is located + * @param baseImageName base image name + * @param namespace namespace + * @return status of installation + */ + public static boolean installAndVerifyPodFromCustomImage(String dockerFileDir, + String baseImageName, + String namespace, + Map labels, + String secretName) throws ApiException { + //build webhook image + String imagePullPolicy = "IfNotPresent"; + String image = createImageAndPushToRepo(dockerFileDir,baseImageName, namespace, secretName, ""); + logger.info("Installing {0} in namespace {1}", baseImageName, namespace); + if (baseImageName.equalsIgnoreCase(("webhook"))) { + webhookImage = image; + createWebHook(webhookImage, imagePullPolicy, namespace, OCIR_SECRET_NAME); + } else if (baseImageName.contains("coordinator")) { + coordinatorImage = image; + createCoordinator(coordinatorImage, imagePullPolicy, namespace, "coordsecret"); + } else { + throw new ApiException("Custom image creation for " + baseImageName + "is not supported"); + } + // wait for the pod to be ready + logger.info("Wait for the {0} pod is ready in namespace {1}", baseImageName, namespace); + testUntil( + assertDoesNotThrow(() -> isPodReady(namespace, labels, baseImageName), + baseImageName + " isPodReady failed with ApiException"), + logger, + "{0} to be running in namespace {1}", + baseImageName, + namespace); + return true; + } + + /** + * Create Webhook deployment and service. + * + * @param image full image name for deployment + * @param imagePullPolicy policy for image + * @param namespace webhook namespace + * @param secretName webhook image secret name + */ + private static void createWebHook(String image, + String imagePullPolicy, + String namespace, + String secretName) throws ApiException { + Map labels = new HashMap(); + labels.put("app", "webhook"); + + webhookDepl = new V1Deployment() + .apiVersion("apps/v1") + .kind("Deployment") + .metadata(new V1ObjectMeta() + .name("webhook") + .namespace(namespace) + .labels(labels)) + .spec(new V1DeploymentSpec() + .replicas(1) + .selector(new V1LabelSelector() + .matchLabels(labels)) + .template(new V1PodTemplateSpec() + .metadata(new V1ObjectMeta() + .labels(labels)) + .spec(new V1PodSpec() + .containers(Arrays.asList( + new V1Container() + .image(image) + .imagePullPolicy(imagePullPolicy) + .name("webhook"))) + .imagePullSecrets(Arrays.asList( + new V1LocalObjectReference() + .name(secretName)))))); + + logger.info("Create deployment for webhook in namespace {0}", + namespace); + boolean deploymentCreated = assertDoesNotThrow(() -> Kubernetes.createDeployment(webhookDepl), + String.format("Create deployment failed with ApiException for webhook in namespace %s", + namespace)); + assertTrue(deploymentCreated, String.format( + "Create deployment failed with ApiException for webhook in namespace %s ", + namespace)); + logger.info("Checking if the deployment is ready {0} completed in namespace {1}", + "webhook", namespace); + testUntil( + Deployment.isReady("webhook", labels, namespace), + logger, + "deployment webhook to be completed in namespace {0}", + namespace); + + webhookService = new V1Service() + .metadata(new V1ObjectMeta() + .name("webhook") + .namespace(namespace) + .labels(labels)) + .spec(new V1ServiceSpec() + .ports(Arrays.asList( + new V1ServicePort() + .port(8080) + .protocol("TCP"))) + .selector(labels)); + + logger.info("Create service for webhook in namespace {0}", + namespace); + boolean serviceCreated = assertDoesNotThrow(() -> Kubernetes.createService(webhookService), + String.format("Create service failed with ApiException for webhook in namespace %s", + namespace)); + assertTrue(serviceCreated, String.format( + "Create service failed with ApiException for webhook in namespace %s ", + namespace)); + // wait for the webhook pod to be ready + logger.info("Wait for the webhook pod is ready in namespace {0}", namespace); + Map labelMap = new HashMap<>(); + labelMap.put("app", "webhook"); + testUntil( + assertDoesNotThrow(() -> isPodReady(namespace, labelMap, "webhook"), + "webhook podIsReady failed with ApiException"), + logger, + "webhook to be running in namespace {0}", + namespace); + } + + /** + * Uninstall provided deployment and service. + */ + private static void uninstallDeploymentService(V1Deployment deployment, V1Service service) { + String namespace = null; + String serviceName = null; + String deploymentName = null; + try { + if (service != null) { + serviceName = service.getMetadata().getName(); + namespace = service.getMetadata().getNamespace(); + Kubernetes.deleteService(serviceName, namespace); + } + } catch (Exception ex) { + logger.warning(ex.getMessage()); + logger.warning("Failed to delete service {0} in namespace {1} ", + serviceName, namespace); + } + try { + if (deployment != null) { + deploymentName = deployment.getMetadata().getName(); + namespace = deployment.getMetadata().getNamespace(); + Kubernetes.deleteDeployment(namespace, deploymentName); + } + } catch (Exception ex) { + logger.warning(ex.getMessage()); + logger.warning("Failed to delete deployment {0} in namespace {1}", + deploymentName, namespace); + } + if (namespace != null) { + deleteNamespace(namespace); + } + } + + /** + * Create Coordinator deployment and service. + * + * @param image full image name for deployment + * @param imagePullPolicy policy for image + * @param namespace coordinator namespace + * @param secretName coordinator secret name + */ + private static void createCoordinator(String image, + String imagePullPolicy, + String namespace, + String secretName) throws ApiException { + if (coordinatorDepl == null) { + Map labels = new HashMap(); + labels.put("app", "coordinator"); + coordinatorDepl = new V1Deployment() + .apiVersion("apps/v1") + .kind("Deployment") + .metadata(new V1ObjectMeta() + .name("coordinator") + .namespace(namespace) + .labels(labels)) + .spec(new V1DeploymentSpec() + .replicas(1) + .selector(new V1LabelSelector() + .matchLabels(labels)) + .strategy(new V1DeploymentStrategy() + .type("Recreate")) + .template(new V1PodTemplateSpec() + .metadata(new V1ObjectMeta() + .labels(labels)) + .spec(new V1PodSpec() + .containers(Arrays.asList( + new V1Container() + .image(image) + .imagePullPolicy(imagePullPolicy) + .name("coordinator") + .ports(Arrays.asList( + new V1ContainerPort() + .containerPort(8999))))) + .imagePullSecrets(Arrays.asList( + new V1LocalObjectReference() + .name(secretName)))))); + + logger.info("Create deployment for coordinator in namespace {0}", + namespace); + boolean deploymentCreated = assertDoesNotThrow(() -> Kubernetes.createDeployment(coordinatorDepl), + String.format("Create deployment failed with ApiException for coordinator in namespace %s", + namespace)); + assertTrue(deploymentCreated, String.format( + "Create deployment failed with ApiException for coordinator in namespace %s ", + namespace)); + testUntil( + Deployment.isReady("coordinator", labels, namespace), + logger, + "deployment coordinator to be completed in namespace {0}", + namespace); + + HashMap annotations = new HashMap<>(); + annotations.put("kubectl.kubernetes.io/last-applied-configuration",""); + coordinatorService = new V1Service() + .metadata(new V1ObjectMeta() + .name("coordinator") + .annotations(annotations) + .namespace(namespace) + .labels(labels)) + .spec(new V1ServiceSpec() + .ports(Arrays.asList( + new V1ServicePort() + .port(8999) + .targetPort(new IntOrString(8999)))) + .type("NodePort") + .selector(labels)); + + logger.info("Create service for coordinator in namespace {0}", + namespace); + boolean success = assertDoesNotThrow(() -> Kubernetes.createService(coordinatorService), + String.format("Create service failed with ApiException for coordinator in namespace %s", + namespace)); + assertTrue(success, "Coordinator service creation failed"); + } + } + + + /** + * Create and verify domain in image from endtoend sample topology with monitoring exporter. + * @return image name + */ + private static String createAndVerifyDomainInImage() { + // create image with model files + logger.info("Create image with model file with monitoring exporter app and verify"); + String app1Path = String.format("%s/wls-exporter.war", monitoringExporterAppDir); + String app2Path = String.format("%s/../operator/integration-tests/apps/testwebapp.war", ITTESTS_DIR); + + List appList = new ArrayList(); + appList.add(app1Path); + appList.add(app2Path); + + int t3ChannelPort = getNextFreePort(); + + Properties p = new Properties(); + p.setProperty("ADMIN_USER", ADMIN_USERNAME_DEFAULT); + p.setProperty("ADMIN_PWD", ADMIN_PASSWORD_DEFAULT); + p.setProperty("DOMAIN_NAME", domain2Uid); + p.setProperty("ADMIN_NAME", "admin-server"); + p.setProperty("PRODUCTION_MODE_ENABLED", "true"); + p.setProperty("CLUSTER_NAME", cluster1Name); + p.setProperty("CLUSTER_TYPE", "DYNAMIC"); + p.setProperty("CONFIGURED_MANAGED_SERVER_COUNT", "2"); + p.setProperty("MANAGED_SERVER_NAME_BASE", "managed-server"); + p.setProperty("T3_CHANNEL_PORT", Integer.toString(t3ChannelPort)); + p.setProperty("T3_PUBLIC_ADDRESS", K8S_NODEPORT_HOST); + p.setProperty("MANAGED_SERVER_PORT", "8001"); + p.setProperty("SERVER_START_MODE", "prod"); + p.setProperty("ADMIN_PORT", "7001"); + p.setProperty("MYSQL_USER", "wluser1"); + p.setProperty("MYSQL_PWD", "wlpwd123"); + // create a temporary WebLogic domain property file as a input for WDT model file + File domainPropertiesFile = assertDoesNotThrow(() -> + File.createTempFile("domain", "properties"), + "Failed to create domain properties file"); + assertDoesNotThrow(() -> + p.store(new FileOutputStream(domainPropertiesFile), "WDT properties file"), + "Failed to write domain properties file"); + + final List propertyList = Collections.singletonList(domainPropertiesFile.getPath()); + + // build the model file list + final List modelList = Collections.singletonList(monitoringExporterEndToEndDir + + MONEXP_WDT_FILE); + + wdtImage = + createImageAndVerify(MONEXP_IMAGE_NAME, + modelList, + appList, + propertyList, + WEBLOGIC_IMAGE_NAME, + WEBLOGIC_IMAGE_TAG, + WLS, + false, + domain2Uid, true); + + // docker login and push image to docker registry if necessary + dockerLoginAndPushImageToRegistry(wdtImage); + + return wdtImage; + } +} \ No newline at end of file diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java index 0c5a12beaeb..1e8dd4eb386 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java @@ -87,7 +87,7 @@ class ItMonitoringExporterSideCar { private static String domain1Namespace = null; private static String domain2Namespace = null; private static String domain3Namespace = null; - + private static String domain1Uid = "monexp-domain-1"; private static String domain2Uid = "monexp-domain-2"; private static String domain3Uid = "monexp-domain-3"; @@ -118,7 +118,7 @@ class ItMonitoringExporterSideCar { private static String releaseSuffix = "test1"; private static String prometheusReleaseName = "prometheus" + releaseSuffix; private static String grafanaReleaseName = "grafana" + releaseSuffix; - private static String monitoringExporterDir; + private static String monitoringExporterDir; /** @@ -195,9 +195,9 @@ public static void initAll(@Namespaces(6) List namespaces) { labels.put("weblogic.domainUid", "test"); String pvDir = PV_ROOT + "/ItMonitoringExporterSideCar/monexp-persistentVolume/"; assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix,monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix, monitoringNS, labels, pvDir)); + assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels, pvDir)); + cleanupPromGrafanaClusterRoles(prometheusReleaseName, grafanaReleaseName); } /** @@ -210,38 +210,42 @@ public static void initAll(@Namespaces(6) List namespaces) { @Test @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar.") void testSideCarBasicFunctionality() throws Exception { + try { + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.yaml"); + String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; + createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", 2, false, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain3Namespace, + domain3Uid); + + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr", nodeportPrometheus); + Domain domain = getDomainCustomResource(domain3Uid, domain3Namespace); + String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); + logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); + assertTrue(monexpConfig.contains("openSessionsHighCount")); + logger.info("Testing replace configuration"); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_jvm.yaml", domain3Uid, domain3Namespace, + "heapFreeCurrent", "heap_free_current", "managed-server1"); + + logger.info("replace monitoring exporter configuration with configuration file with domainQualifier=true."); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml", + domain3Uid, domain3Namespace, + "domainQualifier", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", + "\"domain\":\"wls-sessmigr-domain-1\""); + + logger.info("replace monitoring exporter configuration with configuration file with metricsNameSnakeCase=false."); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml", + domain3Uid, domain3Namespace, + "metricsNameSnakeCase", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", + "sessmigr"); + } finally { + shutdownDomain(domain3Namespace, domain3Uid); + } - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.yaml"); - String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; - createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", 2, false, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain3Namespace, - domain3Uid); - - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - Domain domain = getDomainCustomResource(domain3Uid,domain3Namespace); - String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); - logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); - assertTrue(monexpConfig.contains("openSessionsHighCount")); - logger.info("Testing replace configuration"); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_jvm.yaml", domain3Uid, domain3Namespace, - "heapFreeCurrent", "heap_free_current", "managed-server1"); - - logger.info("replace monitoring exporter configuration with configuration file with domainQualifier=true."); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml", - domain3Uid, domain3Namespace, - "domainQualifier", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", - "\"domain\":\"wls-sessmigr-domain-1\""); - - logger.info("replace monitoring exporter configuration with configuration file with metricsNameSnakeCase=false."); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml", - domain3Uid, domain3Namespace, - "metricsNameSnakeCase", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", - "sessmigr"); } private void changeMonitoringExporterSideCarConfig(String configYamlFile, String domainUid, @@ -299,21 +303,24 @@ private void changeMonitoringExporterSideCarConfig(String configYamlFile, String @Test @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar for domain with two clusters.") void testSideCarBasicFunctionalityTwoClusters() throws Exception { - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.2clusters.yaml"); - String yaml = RESOURCE_DIR + "/exporter/rest_jvm.yaml"; - createAndVerifyDomain(miiImage1, domain1Uid, domain1Namespace, "FromModel", 2, true, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain1Namespace, - domain1Uid); - - // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs - checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", - cluster1Name + "-managed-server1",nodeportPrometheus); - checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster2Name + "-managed-server2%22%7D%5B15s%5D", - cluster2Name + "-managed-server2",nodeportPrometheus); + try { + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.2clusters.yaml"); + String yaml = RESOURCE_DIR + "/exporter/rest_jvm.yaml"; + createAndVerifyDomain(miiImage1, domain1Uid, domain1Namespace, "FromModel", 2, true, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain1Namespace, + domain1Uid); + + // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs + checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", + cluster1Name + "-managed-server1",nodeportPrometheus); + checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster2Name + "-managed-server2%22%7D%5B15s%5D", + cluster2Name + "-managed-server2",nodeportPrometheus); + } finally { + shutdownDomain(domain1Namespace, domain1Uid); + } } /** @@ -327,25 +334,28 @@ void testSideCarBasicFunctionalityTwoClusters() throws Exception { @Test @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar with ssl enabled.") void testSideCarBasicFunctionalityWithSSL() throws Exception { - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.ssl.yaml"); - createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, "FromModel", - 2, false, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain2Namespace, - domain2Uid); - - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - - Domain domain = getDomainCustomResource(domain2Uid,domain2Namespace); - String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); - logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); - assertTrue(monexpConfig.contains("openSessionsHighCount")); + try { + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.ssl.yaml"); + createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, "FromModel", + 2, false, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain2Namespace, + domain2Uid); + + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); + + Domain domain = getDomainCustomResource(domain2Uid,domain2Namespace); + String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); + logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); + assertTrue(monexpConfig.contains("openSessionsHighCount")); + } finally { + shutdownDomain(domain2Namespace, domain2Uid); + } } /** @@ -401,9 +411,6 @@ public void tearDownAll() { .withFailMessage("uninstallNginx() did not return true") .isTrue(); } - shutdownDomain(domain1Namespace, domain1Uid); - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain3Namespace, domain3Uid); uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new new file mode 100644 index 00000000000..0c5a12beaeb --- /dev/null +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new @@ -0,0 +1,439 @@ +// Copyright (c) 2021, Oracle 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; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.kubernetes.client.openapi.ApiException; +import oracle.weblogic.domain.Domain; +import oracle.weblogic.domain.MonitoringExporterConfiguration; +import oracle.weblogic.domain.MonitoringExporterSpecification; +import oracle.weblogic.kubernetes.actions.TestActions; +import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; +import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; +import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; +import oracle.weblogic.kubernetes.annotations.IntegrationTest; +import oracle.weblogic.kubernetes.annotations.Namespaces; +import oracle.weblogic.kubernetes.logging.LoggingFacade; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static oracle.weblogic.kubernetes.TestConstants.GRAFANA_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.OCIR_SECRET_NAME; +import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; +import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; +import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; +import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; +import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; +import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.getDomainCustomResource; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkPodReadyAndServiceExists; +import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getDockerExtraArgs; +import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; +import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndPushToRepo; +import static oracle.weblogic.kubernetes.utils.ImageUtils.createMiiImageAndVerify; +import static oracle.weblogic.kubernetes.utils.ImageUtils.dockerLoginAndPushImageToRegistry; +import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; +import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; +import static oracle.weblogic.kubernetes.utils.PatchDomainUtils.patchDomainResource; +import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; +import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + + +/** + * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running + * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. + * Verify WebLogic metrics can be accessed via NGINX ingress controller. + * Verify WebLogic metrics can be accessed via Prometheus + */ +@DisplayName("Verify WebLogic Metric is processed as expected by " + + "MonitoringExporter Side Car via Prometheus and Grafana") +@IntegrationTest +class ItMonitoringExporterSideCar { + + + // domain constants + + private static String domain1Namespace = null; + private static String domain2Namespace = null; + private static String domain3Namespace = null; + + private static String domain1Uid = "monexp-domain-1"; + private static String domain2Uid = "monexp-domain-2"; + private static String domain3Uid = "monexp-domain-3"; + + private static HelmParams nginxHelmParams = null; + private static int nodeportshttp = 0; + private static int nodeportshttps = 0; + + private static String monitoringNS = null; + PrometheusParams promHelmParams = null; + GrafanaParams grafanaHelmParams = null; + private static String monitoringExporterEndToEndDir = null; + private static String monitoringExporterSrcDir = null; + + // constants for creating domain image using model in image + private static final String MONEXP_IMAGE_NAME = "monexp-image"; + private static final String SESSMIGR_APP_NAME = "sessmigr-app"; + + private static String cluster1Name = "cluster-1"; + private static String cluster2Name = "cluster-2"; + private static String exporterImage = null; + private static int managedServerPort = 8001; + private static int nodeportPrometheus; + private static String prometheusDomainRegexValue = null; + private static Map clusterNameMsPortMap; + private static LoggingFacade logger = null; + private static List clusterNames = new ArrayList<>(); + private static String releaseSuffix = "test1"; + private static String prometheusReleaseName = "prometheus" + releaseSuffix; + private static String grafanaReleaseName = "grafana" + releaseSuffix; + private static String monitoringExporterDir; + + + /** + * Install operator and NGINX. Create model in image domain with multiple clusters. + * Create ingress for the domain. + * + * @param namespaces list of namespaces created by the IntegrationTestWatcher by the + * JUnit engine parameter resolution mechanism + */ + @BeforeAll + + public static void initAll(@Namespaces(6) List namespaces) { + + logger = getLogger(); + + monitoringExporterDir = Paths.get(RESULTS_ROOT, + "ItMonitoringExporterSideCar", "monitoringexp").toString(); + monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); + monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end").toString(); + + logger.info("Get a unique namespace for operator"); + assertNotNull(namespaces.get(0), "Namespace list is null"); + final String opNamespace = namespaces.get(0); + + logger.info("Get a unique namespace for monitoring"); + assertNotNull(namespaces.get(1), "Namespace list is null"); + monitoringNS = namespaces.get(1); + + logger.info("Get a unique namespace for NGINX"); + assertNotNull(namespaces.get(2), "Namespace list is null"); + final String nginxNamespace = namespaces.get(2); + + logger.info("Get a unique namespace for domain1"); + assertNotNull(namespaces.get(3), "Namespace list is null"); + domain1Namespace = namespaces.get(3); + + logger.info("Get a unique namespace for domain2"); + assertNotNull(namespaces.get(4), "Namespace list is null"); + domain2Namespace = namespaces.get(4); + + logger.info("Get a unique namespace for domain3"); + assertNotNull(namespaces.get(5), "Namespace list is null"); + domain3Namespace = namespaces.get(5); + + logger.info("install and verify operator"); + installAndVerifyOperator(opNamespace, + domain1Namespace, domain2Namespace, domain3Namespace); + + logger.info("install monitoring exporter"); + installMonitoringExporter(monitoringExporterDir); + assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", + "pvc-grafana", "pvc-" + grafanaReleaseName)); + exporterImage = assertDoesNotThrow(() -> createImageAndPushToRepo(monitoringExporterSrcDir, "exporter", + domain1Namespace, OCIR_SECRET_NAME, getDockerExtraArgs()), + "Failed to create image for exporter"); + + // install and verify NGINX + nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); + String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; + logger.info("NGINX service name: {0}", nginxServiceName); + nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); + nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); + logger.info("NGINX http node port: {0}", nodeportshttp); + logger.info("NGINX https node port: {0}", nodeportshttps); + clusterNameMsPortMap = new HashMap<>(); + clusterNameMsPortMap.put(cluster1Name, managedServerPort); + clusterNameMsPortMap.put(cluster2Name, managedServerPort); + clusterNames.add(cluster1Name); + clusterNames.add(cluster2Name); + + logger.info("create pv and pvc for monitoring"); + HashMap labels = new HashMap<>(); + labels.put("app", "monitoring"); + labels.put("weblogic.domainUid", "test"); + String pvDir = PV_ROOT + "/ItMonitoringExporterSideCar/monexp-persistentVolume/"; + assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels, pvDir)); + assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix,monitoringNS, labels, pvDir)); + assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); + cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + } + + /** + * Test covers basic functionality for MonitoringExporter SideCar . + * Create Prometheus, Grafana. + * Create Model in Image with monitoring exporter. + * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. + * Check basic functionality of monitoring exporter. + */ + @Test + @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar.") + void testSideCarBasicFunctionality() throws Exception { + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.yaml"); + String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; + createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", 2, false, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain3Namespace, + domain3Uid); + + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); + Domain domain = getDomainCustomResource(domain3Uid,domain3Namespace); + String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); + logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); + assertTrue(monexpConfig.contains("openSessionsHighCount")); + logger.info("Testing replace configuration"); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_jvm.yaml", domain3Uid, domain3Namespace, + "heapFreeCurrent", "heap_free_current", "managed-server1"); + + logger.info("replace monitoring exporter configuration with configuration file with domainQualifier=true."); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml", + domain3Uid, domain3Namespace, + "domainQualifier", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", + "\"domain\":\"wls-sessmigr-domain-1\""); + + logger.info("replace monitoring exporter configuration with configuration file with metricsNameSnakeCase=false."); + changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml", + domain3Uid, domain3Namespace, + "metricsNameSnakeCase", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", + "sessmigr"); + } + + private void changeMonitoringExporterSideCarConfig(String configYamlFile, String domainUid, + String domainNamespace, + String configSearchKey, + String promSearchString, String expectedVal) throws Exception { + String contents = null; + try { + contents = new String(Files.readAllBytes(Paths.get(configYamlFile))); + } catch (IOException e) { + e.printStackTrace(); + } + + MonitoringExporterSpecification monexpSpec = new MonitoringExporterSpecification().configuration(contents); + MonitoringExporterConfiguration monexpCong = monexpSpec.configuration(); + + StringBuffer patchStr = null; + patchStr = new StringBuffer("[{"); + patchStr.append("\"op\": \"replace\",") + .append(" \"path\": \"/spec/monitoringExporter/configuration\",") + .append("\"value\": ") + .append(monexpCong.asJsonString()) + .append("}]"); + logger.info("PatchStr for change Monitoring Exporter Configuration : {0}", patchStr.toString()); + + boolean cmPatched = patchDomainResource(domainUid, domainNamespace, patchStr); + assertTrue(cmPatched, "patchDomainCustomResource(changeMonExporter) failed"); + + Domain domain = assertDoesNotThrow(() -> TestActions.getDomainCustomResource(domainUid, domainNamespace), + String.format("getDomainCustomResource failed with ApiException when tried to get domain %s in namespace %s", + domainUid, domainNamespace)); + assertNotNull(domain, "Got null domain resource after patching"); + String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); + logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); + assertTrue(monexpConfig.contains(configSearchKey)); + + logger.info(domain.getSpec().getMonitoringExporter().toString()); + Thread.sleep(20 * 1000); + String managedServerPodName = domainUid + "-managed-server"; + // check that the managed server pod exists + logger.info("Checking that managed server pod {0} exists and ready in namespace {1}", + managedServerPodName, domainNamespace); + checkPodReadyAndServiceExists(managedServerPodName + "1", domainUid, domainNamespace); + checkPodReadyAndServiceExists(managedServerPodName + "2", domainUid, domainNamespace); + checkMetricsViaPrometheus(promSearchString, expectedVal,nodeportPrometheus); + } + + /** + * Test covers basic functionality for MonitoringExporter SideCar for domain with two clusters. + * Create Prometheus, Grafana. + * Create Model in Image with monitoring exporter. + * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. + * Check basic functionality of monitoring exporter. + */ + @Test + @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar for domain with two clusters.") + void testSideCarBasicFunctionalityTwoClusters() throws Exception { + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.2clusters.yaml"); + String yaml = RESOURCE_DIR + "/exporter/rest_jvm.yaml"; + createAndVerifyDomain(miiImage1, domain1Uid, domain1Namespace, "FromModel", 2, true, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain1Namespace, + domain1Uid); + + // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs + checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", + cluster1Name + "-managed-server1",nodeportPrometheus); + checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster2Name + "-managed-server2%22%7D%5B15s%5D", + cluster2Name + "-managed-server2",nodeportPrometheus); + } + + /** + * Test covers basic functionality for MonitoringExporter SideCar . + * Create Prometheus, Grafana. + * Create Model in Image with SSL enabled. + * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. + * Check basic functionality of monitoring exporter. + */ + + @Test + @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar with ssl enabled.") + void testSideCarBasicFunctionalityWithSSL() throws Exception { + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; + String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.ssl.yaml"); + createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, "FromModel", + 2, false, yaml, exporterImage); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain2Namespace, + domain2Uid); + + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); + + Domain domain = getDomainCustomResource(domain2Uid,domain2Namespace); + String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); + logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); + assertTrue(monexpConfig.contains("openSessionsHighCount")); + } + + /** + * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. + * @throws ApiException when creating helm charts or pods fails + */ + private void installPrometheusGrafana(String promChartVersion, + String grafanaChartVersion, + String domainNS, + String domainUid + ) throws IOException, ApiException { + final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); + if (promHelmParams == null) { + cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + promHelmParams = installAndVerifyPrometheus(releaseSuffix, + monitoringNS, + promChartVersion, + prometheusRegexValue); + assertNotNull(promHelmParams, " Failed to install prometheus"); + nodeportPrometheus = promHelmParams.getNodePortServer(); + prometheusDomainRegexValue = prometheusRegexValue; + } + //if prometheus already installed change CM for specified domain + if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { + logger.info("update prometheus Config Map with domain info"); + editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, monitoringNS, + prometheusReleaseName + "-server"); + prometheusDomainRegexValue = prometheusRegexValue; + } + logger.info("Prometheus is running"); + + if (grafanaHelmParams == null) { + //logger.info("Node Port for Grafana is " + nodeportgrafana); + grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, + monitoringNS, + monitoringExporterEndToEndDir + "/grafana/values.yaml", + grafanaChartVersion); + assertNotNull(grafanaHelmParams, "Grafana failed to install"); + installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); + } + logger.info("Grafana is running"); + } + + + @AfterAll + public void tearDownAll() { + + // uninstall NGINX release + logger.info("Uninstalling NGINX"); + if (nginxHelmParams != null) { + assertThat(uninstallNginx(nginxHelmParams)) + .as("Test uninstallNginx1 returns true") + .withFailMessage("uninstallNginx() did not return true") + .isTrue(); + } + shutdownDomain(domain1Namespace, domain1Uid); + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain3Namespace, domain3Uid); + uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); + + deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); + deletePersistentVolume("pv-testalertmanager" + releaseSuffix); + deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + prometheusReleaseName); + deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + grafanaReleaseName); + deleteNamespace(monitoringNS); + deleteMonitoringExporterTempDir(monitoringExporterDir); + } + + /** + * Create mii image with SESSMIGR application. + */ + private static String createAndVerifyMiiImage(String modelFile) { + // create image with model files + logger.info("Create image with model file and verify"); + + List appList = new ArrayList(); + appList.add(SESSMIGR_APP_NAME); + + // build the model file list + final List modelList = Collections.singletonList(modelFile); + String myImage = + createMiiImageAndVerify(MONEXP_IMAGE_NAME, modelList, appList); + + // docker login and push image to docker registry if necessary + dockerLoginAndPushImageToRegistry(myImage); + + return myImage; + } +} \ No newline at end of file diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java index 80316bb2d5a..04e2d73003b 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java @@ -226,57 +226,61 @@ public static void initAll(@Namespaces(6) List namespaces) { @Test @DisplayName("Test Basic Functionality of Monitoring Exporter.") void testBasicFunctionality() throws Exception { - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, true, null, null); - - // create ingress for the domain - logger.info("Creating ingress for domain {0} in namespace {1}", domain1Uid, domain1Namespace); - ingressHost1List = - createIngressForDomainAndVerify(domain1Uid, domain1Namespace, clusterNameMsPortMap, false); - verifyMonExpAppAccessThroughNginx(ingressHost1List.get(0), 1, nodeportshttp); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain1Namespace, - domain1Uid); - - logger.info("Testing replace configuration"); - replaceConfiguration(); - logger.info("Testing append configuration"); - appendConfiguration(); - logger.info("Testing replace One Attribute Value AsArray configuration"); - replaceOneAttributeValueAsArrayConfiguration(); - logger.info("Testing append One Attribute Value AsArray configuration"); - appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration(); - logger.info("Testing append with empty configuration"); - appendWithEmptyConfiguration(); - logger.info("Testing append with invalid yaml configuration"); - appendWithNotYamlConfiguration(); - logger.info("Testing replace with invalid yaml configuration"); - replaceWithNotYamlConfiguration(); - logger.info("Testing append with corrupted yaml configuration"); - appendWithCorruptedYamlConfiguration(); - logger.info("Testing replace with corrupted yaml configuration"); - replaceWithCorruptedYamlConfiguration(); - logger.info("Testing replace with dublicated values yaml configuration"); - replaceWithDublicatedValuesConfiguration(); - logger.info("Testing append with corrupted yaml configuration"); - appendWithDuplicatedValuesConfiguration(); - logger.info("Testing replace with name snake false yaml configuration"); - replaceMetricsNameSnakeCaseFalseConfiguration(); - logger.info("Testing change with no credentials configuration"); - changeConfigNoCredentials(); - logger.info("Testing change with no invalid user configuration"); - changeConfigInvalidUser(); - logger.info("Testing change with no invalid pass configuration"); - changeConfigInvalidPass(); - logger.info("Testing change with empty user configuration"); - changeConfigEmptyUser(); - logger.info("Testing change with no empty pass configuration"); - changeConfigEmptyPass(); - logger.info("Testing replace with domain qualifier configuration"); - replaceMetricsDomainQualifierTrueConfiguration(); - logger.info("Testing replace with no restPort configuration"); - replaceMetricsNoRestPortConfiguration(); + try { + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, true, null, null); + + // create ingress for the domain + logger.info("Creating ingress for domain {0} in namespace {1}", domain1Uid, domain1Namespace); + ingressHost1List = + createIngressForDomainAndVerify(domain1Uid, domain1Namespace, clusterNameMsPortMap, false); + verifyMonExpAppAccessThroughNginx(ingressHost1List.get(0), 1, nodeportshttp); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain1Namespace, + domain1Uid); + + logger.info("Testing replace configuration"); + replaceConfiguration(); + logger.info("Testing append configuration"); + appendConfiguration(); + logger.info("Testing replace One Attribute Value AsArray configuration"); + replaceOneAttributeValueAsArrayConfiguration(); + logger.info("Testing append One Attribute Value AsArray configuration"); + appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration(); + logger.info("Testing append with empty configuration"); + appendWithEmptyConfiguration(); + logger.info("Testing append with invalid yaml configuration"); + appendWithNotYamlConfiguration(); + logger.info("Testing replace with invalid yaml configuration"); + replaceWithNotYamlConfiguration(); + logger.info("Testing append with corrupted yaml configuration"); + appendWithCorruptedYamlConfiguration(); + logger.info("Testing replace with corrupted yaml configuration"); + replaceWithCorruptedYamlConfiguration(); + logger.info("Testing replace with dublicated values yaml configuration"); + replaceWithDublicatedValuesConfiguration(); + logger.info("Testing append with corrupted yaml configuration"); + appendWithDuplicatedValuesConfiguration(); + logger.info("Testing replace with name snake false yaml configuration"); + replaceMetricsNameSnakeCaseFalseConfiguration(); + logger.info("Testing change with no credentials configuration"); + changeConfigNoCredentials(); + logger.info("Testing change with no invalid user configuration"); + changeConfigInvalidUser(); + logger.info("Testing change with no invalid pass configuration"); + changeConfigInvalidPass(); + logger.info("Testing change with empty user configuration"); + changeConfigEmptyUser(); + logger.info("Testing change with no empty pass configuration"); + changeConfigEmptyPass(); + logger.info("Testing replace with domain qualifier configuration"); + replaceMetricsDomainQualifierTrueConfiguration(); + logger.info("Testing replace with no restPort configuration"); + replaceMetricsNoRestPortConfiguration(); + } finally { + shutdownDomain(domain1Namespace, domain1Uid); + } } @@ -289,30 +293,32 @@ void testBasicFunctionality() throws Exception { //@Test @DisplayName("Test Accesability of Monitoring Exporter dashboard and metrics if admin port is enabled.") void testAdminPortEnabled() throws Exception { - - // create and verify one cluster mii domain with admin port enabled - logger.info("Create domain and verify that it's running"); - String miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, - MODEL_DIR + "/model-adminportenabled.yaml", - SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); - createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, - "FromModel", 2, false, null, null); - logger.info("checking access to wls metrics via https connection"); - - assertTrue(verifyMonExpAppAccess("wls-exporter", - "type: WebAppComponentRuntime", - domain2Uid, - domain2Namespace, - true, null), - "monitoring exporter dashboard page can't be accessed via https"); - - assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", - "wls_servlet_invocation_total_count", - domain2Uid, - domain2Namespace, - true, null), - "monitoring exporter metrics page can't be accessed via https"); - + try { + // create and verify one cluster mii domain with admin port enabled + logger.info("Create domain and verify that it's running"); + String miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, + MODEL_DIR + "/model-adminportenabled.yaml", + SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); + createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, + "FromModel", 2, false, null, null); + logger.info("checking access to wls metrics via https connection"); + + assertTrue(verifyMonExpAppAccess("wls-exporter", + "type: WebAppComponentRuntime", + domain2Uid, + domain2Namespace, + true, null), + "monitoring exporter dashboard page can't be accessed via https"); + + assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", + "wls_servlet_invocation_total_count", + domain2Uid, + domain2Namespace, + true, null), + "monitoring exporter metrics page can't be accessed via https"); + } finally { + shutdownDomain(domain2Namespace, domain2Uid); + } } /** @@ -361,6 +367,7 @@ void testAccessExporterViaHttps() throws Exception { }); } finally { logger.info("Shutting down domain3"); + shutdownDomain(domain3Namespace, domain3Uid); if (miiImage1 != null) { deleteImage(miiImage1); } @@ -420,11 +427,6 @@ public void tearDownAll() { .withFailMessage("uninstallNginx() did not return true") .isTrue(); } - - shutdownDomain(domain1Namespace, domain1Uid); - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain3Namespace, domain3Uid); - // delete mii domain images created if (miiImage != null) { deleteImage(miiImage); diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new new file mode 100644 index 00000000000..80316bb2d5a --- /dev/null +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new @@ -0,0 +1,898 @@ +// Copyright (c) 2021, Oracle 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; + +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.TextPage; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.html.HtmlFileInput; +import com.gargoylesoftware.htmlunit.html.HtmlForm; +import com.gargoylesoftware.htmlunit.html.HtmlPage; +import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput; +import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; +import com.google.gson.Gson; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.models.V1Pod; +import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; +import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; +import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; +import oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes; +import oracle.weblogic.kubernetes.annotations.IntegrationTest; +import oracle.weblogic.kubernetes.annotations.Namespaces; +import oracle.weblogic.kubernetes.logging.LoggingFacade; +import oracle.weblogic.kubernetes.utils.ExecResult; +import oracle.weblogic.kubernetes.utils.MonitoringUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.Yaml; + +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.GRAFANA_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.K8S_NODEPORT_HOST; +import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; +import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; +import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; +import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; +import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; +import static oracle.weblogic.kubernetes.actions.TestActions.deleteImage; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; +import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; +import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; +import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; +import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.copyFileToPod; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; +import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.exec; +import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; +import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.createIngressForDomainAndVerify; +import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccess; +import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccessThroughNginx; +import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; +import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; +import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + + + +/** + * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running + * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. + * Verify WebLogic metrics can be accessed via NGINX ingress controller. + * Verify WebLogic metrics can be accessed via Prometheus + */ +@DisplayName("Verify WebLogic Metric is processed as expected by MonitoringExporter WebApp via Prometheus and Grafana") +@IntegrationTest +class ItMonitoringExporterWebApp { + + + // domain constants + private static String domain1Namespace = null; + private static String domain2Namespace = null; + private static String domain3Namespace = null; + + private static String domain1Uid = "monexp-domain-1"; + private static String domain2Uid = "monexp-domain-2"; + private static String domain3Uid = "monexp-domain-3"; + private static HelmParams nginxHelmParams = null; + private static int nodeportshttp = 0; + private static int nodeportshttps = 0; + private static List ingressHost1List = null; + + private static String monitoringNS = null; + PrometheusParams promHelmParams = null; + GrafanaParams grafanaHelmParams = null; + private static String monitoringExporterEndToEndDir = null; + private static String monitoringExporterSrcDir = null; + private static String monitoringExporterAppDir = null; + // constants for creating domain image using model in image + private static final String MONEXP_MODEL_FILE = "model.monexp.yaml"; + private static final String MONEXP_IMAGE_NAME = "monexp-image"; + private static final String SESSMIGR_APP_NAME = "sessmigr-app"; + + private static String cluster1Name = "cluster-1"; + private static String cluster2Name = "cluster-2"; + private static String miiImage = null; + private static int managedServerPort = 8001; + private static int nodeportPrometheus; + private static String exporterUrl = null; + private static String prometheusDomainRegexValue = null; + private static Map clusterNameMsPortMap; + private static LoggingFacade logger = null; + private static List clusterNames = new ArrayList<>(); + private static String releaseSuffix = "test2"; + private static String prometheusReleaseName = "prometheus" + releaseSuffix; + private static String grafanaReleaseName = "grafana" + releaseSuffix; + private static String monitoringExporterDir; + + + /** + * Install operator and NGINX. Create model in image domain with multiple clusters. + * Create ingress for the domain. + * + * @param namespaces list of namespaces created by the IntegrationTestWatcher by the + * JUnit engine parameter resolution mechanism + */ + @BeforeAll + + public static void initAll(@Namespaces(6) List namespaces) { + + logger = getLogger(); + monitoringExporterDir = monitoringExporterDir = Paths.get(RESULTS_ROOT, + "ItMonitoringExporterWebApp", "monitoringexp").toString(); + monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); + monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end").toString(); + monitoringExporterAppDir = Paths.get(monitoringExporterDir, "apps").toString(); + logger.info("Get a unique namespace for operator"); + assertNotNull(namespaces.get(0), "Namespace list is null"); + final String opNamespace = namespaces.get(0); + + logger.info("Get a unique namespace for monitoring"); + assertNotNull(namespaces.get(1), "Namespace list is null"); + monitoringNS = namespaces.get(1); + + logger.info("Get a unique namespace for NGINX"); + assertNotNull(namespaces.get(2), "Namespace list is null"); + final String nginxNamespace = namespaces.get(2); + + logger.info("Get a unique namespace for domain3"); + assertNotNull(namespaces.get(3), "Namespace list is null"); + domain3Namespace = namespaces.get(3); + + logger.info("Get a unique namespace for domain1"); + assertNotNull(namespaces.get(4), "Namespace list is null"); + domain1Namespace = namespaces.get(4); + + logger.info("Get a unique namespace for domain2"); + assertNotNull(namespaces.get(5), "Namespace list is null"); + domain2Namespace = namespaces.get(5); + + logger.info("install and verify operator"); + installAndVerifyOperator(opNamespace, domain3Namespace, + domain1Namespace, domain2Namespace); + + logger.info("install monitoring exporter"); + installMonitoringExporter(monitoringExporterDir); + assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", + "pvc-grafana", "pvc-" + grafanaReleaseName)); + + logger.info("create and verify WebLogic domain image using model in image with model files"); + miiImage = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, MODEL_DIR + "/" + MONEXP_MODEL_FILE, + SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); + + // install and verify NGINX + nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); + String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; + logger.info("NGINX service name: {0}", nginxServiceName); + nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); + nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); + logger.info("NGINX http node port: {0}", nodeportshttp); + logger.info("NGINX https node port: {0}", nodeportshttps); + clusterNameMsPortMap = new HashMap<>(); + clusterNameMsPortMap.put(cluster1Name, managedServerPort); + clusterNameMsPortMap.put(cluster2Name, managedServerPort); + clusterNames.add(cluster1Name); + clusterNames.add(cluster2Name); + + exporterUrl = String.format("http://%s:%s/wls-exporter/",K8S_NODEPORT_HOST,nodeportshttp); + logger.info("create pv and pvc for monitoring"); + HashMap labels = new HashMap<>(); + labels.put("app", "monitoring"); + labels.put("weblogic.domainUid", "test"); + String pvDir = PV_ROOT + "/ItMonitoringExporterWebApp/monexp-persistentVolume/"; + assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels, pvDir)); + assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix, monitoringNS, labels, pvDir)); + assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); + cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + } + + + /** + * Test covers end to end sample, provided in the Monitoring Exporter github project . + * Create Prometheus, Grafana. + * Create Model in Image with monitoring exporter. + * Verify access to monitoring exporter WebLogic metrics via nginx. + * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. + * Check basic functionality of monitoring exporter. + */ + @Test + @DisplayName("Test Basic Functionality of Monitoring Exporter.") + void testBasicFunctionality() throws Exception { + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, true, null, null); + + // create ingress for the domain + logger.info("Creating ingress for domain {0} in namespace {1}", domain1Uid, domain1Namespace); + ingressHost1List = + createIngressForDomainAndVerify(domain1Uid, domain1Namespace, clusterNameMsPortMap, false); + verifyMonExpAppAccessThroughNginx(ingressHost1List.get(0), 1, nodeportshttp); + installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, + domain1Namespace, + domain1Uid); + + logger.info("Testing replace configuration"); + replaceConfiguration(); + logger.info("Testing append configuration"); + appendConfiguration(); + logger.info("Testing replace One Attribute Value AsArray configuration"); + replaceOneAttributeValueAsArrayConfiguration(); + logger.info("Testing append One Attribute Value AsArray configuration"); + appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration(); + logger.info("Testing append with empty configuration"); + appendWithEmptyConfiguration(); + logger.info("Testing append with invalid yaml configuration"); + appendWithNotYamlConfiguration(); + logger.info("Testing replace with invalid yaml configuration"); + replaceWithNotYamlConfiguration(); + logger.info("Testing append with corrupted yaml configuration"); + appendWithCorruptedYamlConfiguration(); + logger.info("Testing replace with corrupted yaml configuration"); + replaceWithCorruptedYamlConfiguration(); + logger.info("Testing replace with dublicated values yaml configuration"); + replaceWithDublicatedValuesConfiguration(); + logger.info("Testing append with corrupted yaml configuration"); + appendWithDuplicatedValuesConfiguration(); + logger.info("Testing replace with name snake false yaml configuration"); + replaceMetricsNameSnakeCaseFalseConfiguration(); + logger.info("Testing change with no credentials configuration"); + changeConfigNoCredentials(); + logger.info("Testing change with no invalid user configuration"); + changeConfigInvalidUser(); + logger.info("Testing change with no invalid pass configuration"); + changeConfigInvalidPass(); + logger.info("Testing change with empty user configuration"); + changeConfigEmptyUser(); + logger.info("Testing change with no empty pass configuration"); + changeConfigEmptyPass(); + logger.info("Testing replace with domain qualifier configuration"); + replaceMetricsDomainQualifierTrueConfiguration(); + logger.info("Testing replace with no restPort configuration"); + replaceMetricsNoRestPortConfiguration(); + } + + + /** + * Test covers scenario when admin port enabled . + * Create Model in Image with admin port and ssl enabled. + * Check generated monitoring exporter WebLogic metrics via https request. + */ + //commented out untill Issue (see oracle/weblogic-monitoring-exporter#138) will be fixed + //@Test + @DisplayName("Test Accesability of Monitoring Exporter dashboard and metrics if admin port is enabled.") + void testAdminPortEnabled() throws Exception { + + // create and verify one cluster mii domain with admin port enabled + logger.info("Create domain and verify that it's running"); + String miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, + MODEL_DIR + "/model-adminportenabled.yaml", + SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); + createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, + "FromModel", 2, false, null, null); + logger.info("checking access to wls metrics via https connection"); + + assertTrue(verifyMonExpAppAccess("wls-exporter", + "type: WebAppComponentRuntime", + domain2Uid, + domain2Namespace, + true, null), + "monitoring exporter dashboard page can't be accessed via https"); + + assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", + "wls_servlet_invocation_total_count", + domain2Uid, + domain2Namespace, + true, null), + "monitoring exporter metrics page can't be accessed via https"); + + } + + /** + * Verify access to monitoring exporter WebLogic metrics via https. + */ + @Test + @DisplayName("Test Monitoring Exporter access to metrics via https.") + void testAccessExporterViaHttps() throws Exception { + String miiImage1 = null; + + try { + logger.info("create and verify WebLogic domain image using model in image with model files for norestport"); + + miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir + "/norestport", + MODEL_DIR + "/" + MONEXP_MODEL_FILE, SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); + + // create and verify one cluster mii domain + logger.info("Create domain and verify that it's running"); + createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", + 1, true, null, null); + //verify access to Monitoring Exporter + logger.info("checking access to wls metrics via http connection"); + + clusterNames.stream().forEach((clusterName) -> { + assertFalse(verifyMonExpAppAccess("wls-exporter", + "restPort", + domain3Uid, + domain3Namespace, + false, clusterName)); + assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", + "wls_servlet_invocation_total_count", + domain3Uid, + domain3Namespace, + false, clusterName)); + }); + logger.info("checking access to wl metrics via https connection"); + //set to listen only ssl + changeListenPort(domain3Uid, domain3Namespace,"False"); + clusterNames.stream().forEach((clusterName) -> { + assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", + "wls_servlet_invocation_total_count", + domain3Uid, + domain3Namespace, + true, clusterName), + "monitoring exporter metrics page can't be accessed via https"); + }); + } finally { + logger.info("Shutting down domain3"); + if (miiImage1 != null) { + deleteImage(miiImage1); + } + } + } + + /** + * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. + * @throws ApiException when creating helm charts or pods fails + */ + private void installPrometheusGrafana(String promChartVersion, + String grafanaChartVersion, + String domainNS, + String domainUid + ) throws IOException, ApiException { + final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); + if (promHelmParams == null) { + cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); + promHelmParams = installAndVerifyPrometheus(releaseSuffix, + monitoringNS, + promChartVersion, + prometheusRegexValue); + assertNotNull(promHelmParams, " Failed to install prometheus"); + prometheusDomainRegexValue = prometheusRegexValue; + nodeportPrometheus = promHelmParams.getNodePortServer(); + } + //if prometheus already installed change CM for specified domain + if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { + logger.info("update prometheus Config Map with domain info"); + editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, monitoringNS, + prometheusReleaseName + "-server"); + prometheusDomainRegexValue = prometheusRegexValue; + } + logger.info("Prometheus is running"); + + if (grafanaHelmParams == null) { + //logger.info("Node Port for Grafana is " + nodeportgrafana); + grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, + monitoringNS, + monitoringExporterEndToEndDir + "/grafana/values.yaml", + grafanaChartVersion); + assertNotNull(grafanaHelmParams, "Grafana failed to install"); + installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); + } + logger.info("Grafana is running"); + } + + + @AfterAll + public void tearDownAll() { + + // uninstall NGINX release + logger.info("Uninstalling NGINX"); + if (nginxHelmParams != null) { + assertThat(uninstallNginx(nginxHelmParams)) + .as("Test uninstallNginx1 returns true") + .withFailMessage("uninstallNginx() did not return true") + .isTrue(); + } + + shutdownDomain(domain1Namespace, domain1Uid); + shutdownDomain(domain2Namespace, domain2Uid); + shutdownDomain(domain3Namespace, domain3Uid); + + // delete mii domain images created + if (miiImage != null) { + deleteImage(miiImage); + } + + uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); + + deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); + deletePersistentVolume("pv-testalertmanager" + releaseSuffix); + deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + prometheusReleaseName); + deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); + deletePersistentVolume("pv-test" + grafanaReleaseName); + deleteNamespace(monitoringNS); + deleteMonitoringExporterTempDir(monitoringExporterDir); + } + + private void changeConfigNegative(String effect, String configFile, String expectedErrorMsg) + throws Exception { + final WebClient webClient = new WebClient(); + //webClient.addRequestHeader("Host", ingressHost1List.get(0)); + HtmlPage originalPage = webClient.getPage(exporterUrl); + assertNotNull(originalPage); + HtmlPage page = submitConfigureForm(exporterUrl, effect, configFile); + assertTrue((page.asText()).contains(expectedErrorMsg)); + assertTrue(!(page.asText()).contains("Error 500--Internal Server Error")); + } + + private void changeConfigNegativeAuth( + String effect, String configFile, String expectedErrorMsg, String username, String password) + throws Exception { + try { + final WebClient webClient = new WebClient(); + setCredentials(webClient, username, password); + HtmlPage page = submitConfigureForm(exporterUrl, effect, configFile, webClient); + throw new RuntimeException("Expected exception was not thrown "); + } catch (FailingHttpStatusCodeException ex) { + assertTrue((ex.getMessage()).contains(expectedErrorMsg)); + } + } + + private HtmlPage submitConfigureForm(String exporterUrl, String effect, String configFile) + throws Exception { + final WebClient webClient = new WebClient(); + webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); + setCredentials(webClient); + return submitConfigureForm(exporterUrl, effect, configFile, webClient); + } + + private HtmlPage submitConfigureForm( + String exporterUrl, String effect, String configFile, WebClient webClient) throws Exception { + // Get the first page + HtmlPage page1 = webClient.getPage(exporterUrl); + if (page1 == null) { + //try again + page1 = webClient.getPage(exporterUrl); + } + assertNotNull(page1, "can't retrieve exporter dashboard page"); + assertTrue((page1.asText()).contains("This is the WebLogic Monitoring Exporter.")); + + // Get the form that we are dealing with and within that form, + // find the submit button and the field that we want to change.Generated form for cluster had + // extra path for wls-exporter + HtmlForm form = page1.getFirstByXPath("//form[@action='configure']"); + if (form == null) { + form = page1.getFirstByXPath("//form[@action='/wls-exporter/configure']"); + } + assertNotNull(form, "can't retrieve configure form"); + List radioButtons = form.getRadioButtonsByName("effect"); + assertNotNull(radioButtons, "can't retrieve buttons with effect"); + for (HtmlRadioButtonInput radioButton : radioButtons) { + if (radioButton.getValueAttribute().equalsIgnoreCase(effect)) { + radioButton.setChecked(true); + } + } + + HtmlSubmitInput button = + page1.getFirstByXPath("//form//input[@type='submit']"); + assertNotNull(button, "can't retrieve submit button"); + final HtmlFileInput fileField = form.getInputByName("configuration"); + assertNotNull(fileField); + + // Change the value of the text field + fileField.setValueAttribute(configFile); + fileField.setContentType("multipart/form-data"); + + // Now submit the form by clicking the button and get back the second page. + HtmlPage page2 = null; + try { + page2 = button.click(); + assertNotNull(page2, "can't reach page after submit"); + assertFalse((page2.asText()).contains("Error 500--Internal Server Error"), + "page returns Error 500--Internal Server Error"); + } catch (ClassCastException ex) { + logger.info(" Can't generate html page, collecting the error "); + TextPage page3 = button.click(); + assertNotNull(page3, "can't reach page after submit"); + assertTrue(page3.getContent().contains("Unable to contact the REST API"), + "submit does not return html page, here is received page " + + page3.getContent()); + } + return page2; + } + + private static void setCredentials(WebClient webClient) { + String base64encodedUsernameAndPassword = + base64Encode(String.format("%s:%s", + ADMIN_USERNAME_DEFAULT, + ADMIN_PASSWORD_DEFAULT)); + webClient.addRequestHeader("Authorization", "Basic " + base64encodedUsernameAndPassword); + } + + private static void setCredentials(WebClient webClient, String username, String password) { + String base64encodedUsernameAndPassword = base64Encode(username + ":" + password); + webClient.addRequestHeader("Authorization", "Basic " + base64encodedUsernameAndPassword); + } + + private static String base64Encode(String stringToEncode) { + Base64.Encoder enc = Base64.getEncoder(); + return enc.encodeToString(stringToEncode.getBytes()); + } + + /** + * Replace monitoring exporter configuration and verify it was applied to both managed servers. + * + * @throws Exception if test fails + */ + private void replaceConfiguration() throws Exception { + HtmlPage page = submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_jvm.yaml"); + assertNotNull(page, "Failed to replace configuration"); + + assertTrue(page.asText().contains("JVMRuntime"), + "Page does not contain expected JVMRuntime configuration"); + assertFalse(page.asText().contains("WebAppComponentRuntime"), + "Page contains unexpected WebAppComponentRuntime configuration"); + //needs 20 secs to fetch the metrics to prometheus + Thread.sleep(20 * 1000); + // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs + checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", + cluster1Name + "-managed-server1",nodeportPrometheus); + + } + + /** + * Add additional monitoring exporter configuration and verify it was applied. + * + * @throws Exception if test fails + */ + private void appendConfiguration() throws Exception { + + // run append + HtmlPage page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_webapp.yaml"); + assertTrue(page.asText().contains("WebAppComponentRuntime"), + "Page does not contain expected WebAppComponentRuntime configuration"); + // check previous config is there + assertTrue(page.asText().contains("JVMRuntime"), "Page does not contain expected JVMRuntime configuration"); + + String sessionAppPrometheusSearchKey = + "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); + } + + /** + * Replace monitoring exporter configuration with only one attribute and verify it was applied. + * + * @throws Exception if test fails + */ + private void replaceOneAttributeValueAsArrayConfiguration() throws Exception { + HtmlPage page = + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_oneattribval.yaml"); + assertTrue(page.asText().contains("values: invocationTotalCount")); + assertFalse(page.asText().contains("reloadTotal")); + } + + /** + * Append monitoring exporter configuration with one more attribute and verify it was applied + * append to [a] new config [a,b]. + * + * @throws Exception if test fails + */ + private void appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration() + throws Exception { + HtmlPage page = + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_oneattribval.yaml"); + assertTrue(page.asText().contains("values: invocationTotalCount")); + page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_twoattribs.yaml"); + assertTrue(page.asText().contains("values: [invocationTotalCount, executionTimeAverage]")); + } + + /** + * Replace monitoring exporter configuration with empty configuration. + * + * @throws Exception if test fails + */ + private void replaceWithEmptyConfiguration() throws Exception { + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_empty.yaml"); + assertFalse(verifyMonExpAppAccess("wls-exporter","values", domain1Uid, domain1Namespace,false, cluster1Name)); + assertTrue(verifyMonExpAppAccess("wls-exporter","queries", domain1Uid, domain1Namespace,false, cluster1Name)); + } + + /** + * Try to append monitoring exporter configuration with empty configuration. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void appendWithEmptyConfiguration() throws Exception { + HtmlPage originalPage = submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_jvm.yaml"); + assertNotNull(originalPage, "Failed to replace configuration"); + assertTrue(originalPage.asText().contains("JVMRuntime"), + "Page does not contain expected JVMRuntime configuration"); + HtmlPage page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_empty.yaml"); + assertTrue(originalPage.asText().equals(page.asText())); + } + + /** + * Try to append monitoring exporter configuration with configuration file not in the yaml format. + * + * @throws Exception if test fails + */ + private void appendWithNotYamlConfiguration() throws Exception { + changeConfigNegative( + "append", RESOURCE_DIR + "/exporter/rest_notyamlformat.yaml", "Configuration is not in YAML format"); + } + + /** + * Try to replace monitoring exporter configuration with configuration file not in the yaml + * format. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void replaceWithNotYamlConfiguration() throws Exception { + changeConfigNegative( + "replace", RESOURCE_DIR + "/exporter/rest_notyamlformat.yaml", "Configuration is not in YAML format"); + } + + /** + * Try to append monitoring exporter configuration with configuration file in the corrupted yaml + * format. + * + * @throws Exception if test fails + */ + private void appendWithCorruptedYamlConfiguration() throws Exception { + changeConfigNegative( + "append", + RESOURCE_DIR + "/exporter/rest_notyaml.yaml", + "Configuration YAML format has errors while scanning a simple key"); + } + + /** + * Try to replace monitoring exporter configuration with configuration file in the corrupted yaml + * format. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void replaceWithCorruptedYamlConfiguration() throws Exception { + changeConfigNegative( + "replace", + RESOURCE_DIR + "/exporter/rest_notyaml.yaml", + "Configuration YAML format has errors while scanning a simple key"); + } + + /** + * Try to replace monitoring exporter configuration with configuration file with dublicated + * values. + * + * @throws Exception if test fails + */ + private void replaceWithDublicatedValuesConfiguration() throws Exception { + changeConfigNegative( + "replace", + RESOURCE_DIR + "/exporter/rest_dublicatedval.yaml", + "Duplicate values for [deploymentState] at applicationRuntimes.componentRuntimes"); + } + + /** + * Try to append monitoring exporter configuration with configuration file with duplicated values. + * + * @throws Exception if test fails + */ + private void appendWithDuplicatedValuesConfiguration() throws Exception { + changeConfigNegative( + "append", + RESOURCE_DIR + "/exporter/rest_dublicatedval.yaml", + "Duplicate values for [deploymentState] at applicationRuntimes.componentRuntimes"); + } + + /** + * Try to replace monitoring exporter configuration with configuration file with + * NameSnakeCase=false. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void replaceMetricsNameSnakeCaseFalseConfiguration() throws Exception { + HtmlPage page = + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml"); + assertNotNull(page); + assertFalse(page.asText().contains("metricsNameSnakeCase")); + String searchKey = "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(searchKey, "sessmigr",nodeportPrometheus); + } + + /** + * Try to replace monitoring exporter configuration with configuration file with + * no restPort value. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void replaceMetricsNoRestPortConfiguration() throws Exception { + HtmlPage page = + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/norestport.yaml"); + assertNotNull(page); + assertFalse(page.asText().contains("restPort")); + //needs 20 secs to fetch the metrics to prometheus + Thread.sleep(20 * 1000); + // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs + + String prometheusSearchKey1 = + "heap_free_current"; + checkMetricsViaPrometheus(prometheusSearchKey1, "managed-server1",nodeportPrometheus); + } + + /** + * Test to replace monitoring exporter configuration with configuration file with + * domainQualifier=true. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + private void replaceMetricsDomainQualifierTrueConfiguration() throws Exception { + HtmlPage page = + submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml"); + assertNotNull(page); + logger.info("page - " + page.asText()); + assertTrue(page.asText().contains("domainQualifier")); + + String searchKey = "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D"; + checkMetricsViaPrometheus(searchKey, "\"domain\":\"wls-monexp-domain-1" + "\"",nodeportPrometheus); + } + + /** + * Test to change monitoring exporter configuration without authentication. + * + * @throws Exception if failed to apply configuration or check the expected values. + */ + // verify that change configuration fails without authentication + private void changeConfigNoCredentials() throws Exception { + WebClient webClient = new WebClient(); + String expectedErrorMsg = "401 Unauthorized for " + exporterUrl; + try { + HtmlPage page = + submitConfigureForm( + exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", webClient); + throw new RuntimeException("Form was submitted successfully with no credentials"); + } catch (FailingHttpStatusCodeException ex) { + assertTrue((ex.getMessage()).contains(expectedErrorMsg)); + } + } + + /** + * Try to change monitoring exporter configuration with invalid username. + * + * @throws Exception if the expected exception message does not match + */ + private void changeConfigInvalidUser() throws Exception { + changeConfigNegativeAuth( + "replace", + RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", + "401 Unauthorized for " + exporterUrl, + "invaliduser", + ADMIN_PASSWORD_DEFAULT); + } + + /** + * Try to change monitoring exporter configuration with invalid password. + * + * @throws Exception if the expected exception message does not match + */ + private void changeConfigInvalidPass() throws Exception { + changeConfigNegativeAuth( + "replace", + RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", + "401 Unauthorized for " + exporterUrl, + ADMIN_USERNAME_DEFAULT, + "invalidpass"); + } + + /** + * Try to change monitoring exporter configuration with empty username. + * + * @throws Exception if the expected exception message does not match + */ + private void changeConfigEmptyUser() throws Exception { + changeConfigNegativeAuth( + "replace", + RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", + "401 Unauthorized for " + exporterUrl, + "", + ADMIN_PASSWORD_DEFAULT); + } + + /** + * Try to change monitoring exporter configuration with empty pass. + * + * @throws Exception if the expected exception message does not match + */ + private void changeConfigEmptyPass() throws Exception { + changeConfigNegativeAuth( + "replace", + RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", + "401 Unauthorized for " + exporterUrl, + ADMIN_USERNAME_DEFAULT, + ""); + } + + private boolean changeListenPort(String domainUid, String domainNS, String setListenPortEnabled) throws Exception { + // copy changeListenPort.py and callpyscript.sh to Admin Server pod + String adminServerPodName = domainUid + "-" + ADMIN_SERVER_NAME_BASE; + V1Pod adminPod = Kubernetes.getPod(domainNS, null, adminServerPodName); + if (adminPod == null) { + logger.info("The admin pod {0} does not exist in namespace {1}!", adminServerPodName, domainNS); + return false; + } + + logger.info("Copying changeListenPort.py and callpyscript.sh to admin server pod"); + try { + copyFileToPod(domainNS, adminServerPodName, null, + Paths.get(RESOURCE_DIR, "python-scripts", "changeListenPort.py"), + Paths.get("/u01/oracle/changeListenPort.py")); + + copyFileToPod(domainNS, adminServerPodName, null, + Paths.get(RESOURCE_DIR, "bash-scripts", "callpyscript.sh"), + Paths.get("/u01/oracle/callpyscript.sh")); + } catch (ApiException apex) { + logger.severe("Got ApiException while copying file to admin pod {0}", apex.getResponseBody()); + return false; + } catch (IOException ioex) { + logger.severe("Got IOException while copying file to admin pod {0}", ioex.getStackTrace()); + return false; + } + + logger.info("Adding execute mode for callpyscript.sh"); + ExecResult result = exec(adminPod, null, true, + "/bin/sh", "-c", "chmod +x /u01/oracle/callpyscript.sh"); + if (result.exitValue() != 0) { + return false; + } + logger.info("Changing ListenPortEnabled"); + String command = new StringBuffer("/u01/oracle/callpyscript.sh /u01/oracle/changeListenPort.py ") + .append(ADMIN_USERNAME_DEFAULT) + .append(" ") + .append(ADMIN_PASSWORD_DEFAULT) + .append(" t3://") + .append(adminServerPodName) + .append(":7001 ") + .append(setListenPortEnabled) + .append(" ") + .append("managed-server1") + .toString(); + + result = exec(adminPod, null, true, "/bin/sh", "-c", command); + if (result.exitValue() != 0) { + return false; + } + return true; + } + + private static String convertToJson(String yaml) { + final Object loadedYaml = new Yaml().load(yaml); + return new Gson().toJson(loadedYaml, LinkedHashMap.class); + } + +} \ No newline at end of file From c29a44613dbaba7c78411d1bb672303a5ec6a972 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Wed, 3 Nov 2021 16:47:23 +0000 Subject: [PATCH 03/10] removed files --- .../ItMonitoringExporterSamples.java.new | 781 --------------- .../ItMonitoringExporterSideCar.java.new | 439 --------- .../ItMonitoringExporterWebApp.java.new | 898 ------------------ 3 files changed, 2118 deletions(-) delete mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new delete mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new delete mode 100644 integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new deleted file mode 100644 index a5c2f223333..00000000000 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSamples.java.new +++ /dev/null @@ -1,781 +0,0 @@ -// Copyright (c) 2021, Oracle 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; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import io.kubernetes.client.custom.IntOrString; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.models.V1Container; -import io.kubernetes.client.openapi.models.V1ContainerPort; -import io.kubernetes.client.openapi.models.V1Deployment; -import io.kubernetes.client.openapi.models.V1DeploymentSpec; -import io.kubernetes.client.openapi.models.V1DeploymentStrategy; -import io.kubernetes.client.openapi.models.V1LabelSelector; -import io.kubernetes.client.openapi.models.V1LocalObjectReference; -import io.kubernetes.client.openapi.models.V1ObjectMeta; -import io.kubernetes.client.openapi.models.V1Pod; -import io.kubernetes.client.openapi.models.V1PodSpec; -import io.kubernetes.client.openapi.models.V1PodTemplateSpec; -import io.kubernetes.client.openapi.models.V1Service; -import io.kubernetes.client.openapi.models.V1ServicePort; -import io.kubernetes.client.openapi.models.V1ServiceSpec; -import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; -import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; -import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; -import oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes; -import oracle.weblogic.kubernetes.annotations.IntegrationTest; -import oracle.weblogic.kubernetes.annotations.Namespaces; -import oracle.weblogic.kubernetes.assertions.impl.Deployment; -import oracle.weblogic.kubernetes.logging.LoggingFacade; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static oracle.weblogic.kubernetes.TestConstants.ADMIN_PASSWORD_DEFAULT; -import static oracle.weblogic.kubernetes.TestConstants.ADMIN_USERNAME_DEFAULT; -import static oracle.weblogic.kubernetes.TestConstants.GRAFANA_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.K8S_NODEPORT_HOST; -import static oracle.weblogic.kubernetes.TestConstants.MANAGED_SERVER_NAME_BASE; -import static oracle.weblogic.kubernetes.TestConstants.OCIR_SECRET_NAME; -import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; -import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; -import static oracle.weblogic.kubernetes.TestConstants.WEBLOGIC_IMAGE_NAME; -import static oracle.weblogic.kubernetes.TestConstants.WEBLOGIC_IMAGE_TAG; -import static oracle.weblogic.kubernetes.actions.ActionConstants.ITTESTS_DIR; -import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; -import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; -import static oracle.weblogic.kubernetes.actions.ActionConstants.WLS; -import static oracle.weblogic.kubernetes.actions.TestActions.deleteImage; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; -import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; -import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; -import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; -import static oracle.weblogic.kubernetes.assertions.TestAssertions.isPodReady; -import static oracle.weblogic.kubernetes.assertions.TestAssertions.searchPodLogForKey; -import static oracle.weblogic.kubernetes.assertions.impl.Kubernetes.listPods; -import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getNextFreePort; -import static oracle.weblogic.kubernetes.utils.CommonTestUtils.scaleAndVerifyCluster; -import static oracle.weblogic.kubernetes.utils.CommonTestUtils.testUntil; -import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; -import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndPushToRepo; -import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndVerify; -import static oracle.weblogic.kubernetes.utils.ImageUtils.dockerLoginAndPushImageToRegistry; -import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.createIngressForDomainAndVerify; -import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyMiiImage; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccessThroughNginx; -import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; -import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; -import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - - - -/** - * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running - * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. - * Verify WebLogic metrics can be accessed via NGINX ingress controller. - * Verify WebLogic metrics can be accessed via Prometheus - */ -@DisplayName("Verify end to end sample, provided in the Monitoring Exporter github project") -@IntegrationTest -class ItMonitoringExporterSamples { - - - // domain constants - private static final int replicaCount = 2; - private static int managedServersCount = 2; - private static String domain1Namespace = null; - private static String domain2Namespace = null; - private static String domain1Uid = "monexp-domain-1"; - private static String domain2Uid = "monexp-domain-2"; - - private static HelmParams nginxHelmParams = null; - private static int nodeportshttp = 0; - private static int nodeportshttps = 0; - private static List ingressHost1List = null; - private static List ingressHost2List = null; - - private static String monitoringNS = null; - private static String webhookNS = null; - PrometheusParams promHelmParams = null; - GrafanaParams grafanaHelmParams = null; - - private static V1Service webhookService = null; - private static V1Deployment webhookDepl = null; - private static V1Service coordinatorService = null; - private static V1Deployment coordinatorDepl = null; - // constants for creating domain image using model in image - private static final String MONEXP_MODEL_FILE = "model.monexp.yaml"; - private static final String MONEXP_WDT_FILE = "/demo-domains/domainBuilder/scripts/simple-topology.yaml"; - private static final String MONEXP_IMAGE_NAME = "monexp-image"; - private static final String SESSMIGR_APP_NAME = "sessmigr-app"; - - private static String cluster1Name = "cluster-1"; - private static String cluster2Name = "cluster-2"; - private static String miiImage = null; - private static String wdtImage = null; - private static String webhookImage = null; - private static String exporterImage = null; - private static String coordinatorImage = null; - private static int managedServerPort = 8001; - private static int nodeportPrometheus; - private static String exporterUrl = null; - private static String prometheusDomainRegexValue = null; - private static Map clusterNameMsPortMap; - private static LoggingFacade logger = null; - private static List clusterNames = new ArrayList<>(); - private static String releaseSuffix = "test3"; - private static String prometheusReleaseName = "prometheus" + releaseSuffix; - private static String grafanaReleaseName = "grafana" + releaseSuffix; - private static String monitoringExporterDir; - private static String monitoringExporterSrcDir; - private static String monitoringExporterEndToEndDir; - private static String monitoringExporterAppDir; - - - /** - * Install operator and NGINX. Create model in image domain with multiple clusters. - * Create ingress for the domain. - * - * @param namespaces list of namespaces created by the IntegrationTestWatcher by the - * JUnit engine parameter resolution mechanism - */ - @BeforeAll - - public static void initAll(@Namespaces(6) List namespaces) { - - logger = getLogger(); - monitoringExporterDir = monitoringExporterDir = Paths.get(RESULTS_ROOT, - "ItMonitoringExporterSamples", "monitoringexp").toString(); - monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); - monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end/").toString(); - monitoringExporterAppDir = Paths.get(monitoringExporterDir, "apps").toString(); - - logger.info("Get a unique namespace for operator"); - assertNotNull(namespaces.get(0), "Namespace list is null"); - final String opNamespace = namespaces.get(0); - - logger.info("Get a unique namespace for WebLogic domain1"); - assertNotNull(namespaces.get(1), "Namespace list is null"); - domain1Namespace = namespaces.get(1); - - logger.info("Get a unique namespace for WebLogic domain2"); - assertNotNull(namespaces.get(2), "Namespace list is null"); - domain2Namespace = namespaces.get(2); - - logger.info("Get a unique namespace for monitoring"); - assertNotNull(namespaces.get(3), "Namespace list is null"); - monitoringNS = namespaces.get(3); - - logger.info("Get a unique namespace for webhook"); - assertNotNull(namespaces.get(4), "Namespace list is null"); - webhookNS = namespaces.get(4); - - logger.info("Get a unique namespace for NGINX"); - assertNotNull(namespaces.get(5), "Namespace list is null"); - final String nginxNamespace = namespaces.get(5); - - logger.info("install and verify operator"); - installAndVerifyOperator(opNamespace, domain1Namespace,domain2Namespace); - - logger.info("install monitoring exporter"); - installMonitoringExporter(monitoringExporterDir); - assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", - "pvc-grafana", "pvc-" + grafanaReleaseName)); - - logger.info("create and verify WebLogic domain image using model in image with model files"); - miiImage = createAndVerifyMiiImage(monitoringExporterAppDir, MODEL_DIR + "/" + MONEXP_MODEL_FILE, - SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); - - // install and verify NGINX - nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); - String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; - logger.info("NGINX service name: {0}", nginxServiceName); - nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); - nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); - logger.info("NGINX http node port: {0}", nodeportshttp); - logger.info("NGINX https node port: {0}", nodeportshttps); - clusterNameMsPortMap = new HashMap<>(); - clusterNameMsPortMap.put(cluster1Name, managedServerPort); - clusterNameMsPortMap.put(cluster2Name, managedServerPort); - clusterNames.add(cluster1Name); - clusterNames.add(cluster2Name); - - exporterUrl = String.format("http://%s:%s/wls-exporter/",K8S_NODEPORT_HOST,nodeportshttp); - logger.info("create pv and pvc for monitoring"); - HashMap labels = new HashMap<>(); - labels.put("app", "monitoring"); - labels.put("weblogic.domainUid", domain1Uid); - String pvDir = PV_ROOT + "/ItMonitoringExporterSamples/monexp-persistentVolume/"; - assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels,pvDir)); - assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix, monitoringNS, labels,pvDir)); - assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); - cleanupPromGrafanaClusterRoles(prometheusReleaseName, grafanaReleaseName); - } - - /** - * Test covers end to end sample, provided in the Monitoring Exporter github project. - * Create Prometheus, Grafana, Webhook, Coordinator. - * Create domain in Image with monitoring exporter. - * Verify access to monitoring exporter WebLogic metrics via nginx. - * Check generated by monitoring exporter WebLogic metrics via Prometheus, Grafana. - * Fire Alert using Webhook. - * Change prometheus to add different domain to monitor. - */ - @Test - @DisplayName("Test End to End example from MonitoringExporter github project.") - void testEndToEndViaChart() throws Exception { - wdtImage = createAndVerifyDomainInImage(); - logger.info("Create wdt domain and verify that it's running"); - createAndVerifyDomain(wdtImage, domain2Uid, domain2Namespace, "Image", replicaCount, - false, null,null); - ingressHost2List = - createIngressForDomainAndVerify(domain2Uid, domain2Namespace, clusterNameMsPortMap); - logger.info("Installing Prometheus and Grafana"); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain2Namespace, - domain2Uid); - - installWebhook(); - installCoordinator(domain2Namespace); - - logger.info("verify access to Monitoring Exporter"); - verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0), managedServersCount,nodeportshttp); - logger.info("verify metrics via prometheus"); - String testappPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp",nodeportPrometheus); - logger.info("fire alert by scaling down"); - fireAlert(); - logger.info("switch to monitor another domain"); - logger.info("create and verify WebLogic domain image using model in image with model files"); - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, - true, null, null); - - String oldRegex = String.format("regex: %s;%s", domain2Namespace, domain2Uid); - String newRegex = String.format("regex: %s;%s", domain1Namespace, domain1Uid); - editPrometheusCM(oldRegex, newRegex, monitoringNS, prometheusReleaseName + "-server"); - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - checkPromGrafanaLatestVersion(); - } - - /** - * Test covers the following use cases. - * Create Prometheus, Grafana from latest version of helm chart - * verify access to monitoring exporter WebLogic metrics via nginx - * check WebLogic metrics via Prometheus - */ - private void checkPromGrafanaLatestVersion() throws Exception { - //uninstall prometheus and grafana if running - uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); - promHelmParams = null; - grafanaHelmParams = null; - prometheusDomainRegexValue = null; - - installPrometheusGrafana(null, null, - domain2Namespace, - domain2Uid); - - - //verify access to Monitoring Exporter - logger.info("verify http access"); - verifyMonExpAppAccessThroughNginx(ingressHost2List.get(0),managedServersCount, nodeportshttp); - //verify metrics via prometheus - String testappPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22test-webapp%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(testappPrometheusSearchKey, "test-webapp",nodeportPrometheus); - } - - private void fireAlert() throws ApiException { - // scale domain2 - logger.info("Scaling cluster {0} of domain {1} in namespace {2} to {3} servers.", - cluster1Name, domain2Uid, domain2Namespace, 1); - managedServersCount = 1; - scaleAndVerifyCluster(cluster1Name, domain2Uid, domain2Namespace, - domain2Uid + "-" + MANAGED_SERVER_NAME_BASE, replicaCount, managedServersCount, - null, null); - - //check webhook log for firing alert - List pods = listPods(webhookNS, "app=webhook").getItems(); - assertNotNull((pods), "No pods are running in namespace : " + webhookNS); - V1Pod pod = pods.stream() - .filter(testpod -> testpod - .getMetadata() - .getName() - .contains("webhook")) - .findAny() - .orElse(null); - - assertNotNull(pod, "Can't find running webhook pod"); - logger.info("Wait for the webhook to fire alert and check webhook log file in {0} namespace ", webhookNS); - - testUntil( - assertDoesNotThrow(() -> searchPodLogForKey(pod, - "Some WLS cluster has only one running server for more than 1 minutes"), - "webhook failed to fire alert"), - logger, - "webhook to fire alert"); - } - - /** - * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. - * @throws ApiException when creating helm charts or pods fails - */ - private void installPrometheusGrafana(String promChartVersion, - String grafanaChartVersion, - String domainNS, - String domainUid - ) throws IOException, ApiException { - final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); - if (promHelmParams == null) { - Path srcPromFile = Paths.get(RESOURCE_DIR, "exporter", "promvalues.yaml"); - - //replace with webhook ns - replaceStringInFile(srcPromFile.toString(), - "webhook.webhook.svc.cluster.local", - String.format("webhook.%s.svc.cluster.local", webhookNS)); - - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); - promHelmParams = installAndVerifyPrometheus(releaseSuffix, - monitoringNS, - promChartVersion, - prometheusRegexValue); - assertNotNull(promHelmParams, " Failed to install prometheus"); - nodeportPrometheus = promHelmParams.getNodePortServer(); - prometheusDomainRegexValue = prometheusRegexValue; - } - //if prometheus already installed change CM for specified domain - if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { - logger.info("update prometheus Config Map with domain info"); - editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, - monitoringNS, prometheusReleaseName + "-server"); - prometheusDomainRegexValue = prometheusRegexValue; - } - logger.info("Prometheus is running"); - - if (grafanaHelmParams == null) { - grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, - monitoringNS, - monitoringExporterEndToEndDir + "/grafana/values.yaml", - grafanaChartVersion); - assertNotNull(grafanaHelmParams, "Grafana failed to install"); - installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); - } - logger.info("Grafana is running"); - } - - /** - * Create a Webhook image, install and verify that pod is running. - * @throws ApiException when creating images or pods fails - */ - private void installWebhook() throws ApiException { - Map labelMap = new HashMap<>(); - labelMap.put("app", "webhook"); - assertTrue(installAndVerifyPodFromCustomImage(monitoringExporterEndToEndDir + "/webhook", - "webhook", - webhookNS, - labelMap, OCIR_SECRET_NAME), "Failed to start webhook"); - } - - /** - * Create a Coordinator image, install and verify that pod is running. - * @param namespace of domain to coordinate - * @throws ApiException when creating images or pods fails - */ - private void installCoordinator(String namespace) throws ApiException { - Map labelMap = new HashMap<>(); - labelMap.put("app", "coordinator"); - assertTrue(installAndVerifyPodFromCustomImage(monitoringExporterSrcDir + "/config_coordinator", - "coordinator", - namespace, - labelMap, "coordsecret"), "Failed to start coordinator"); - } - - @AfterAll - public void tearDownAll() { - - // uninstall NGINX release - logger.info("Uninstalling NGINX"); - if (nginxHelmParams != null) { - assertThat(uninstallNginx(nginxHelmParams)) - .as("Test uninstallNginx1 returns true") - .withFailMessage("uninstallNginx() did not return true") - .isTrue(); - } - - // delete mii domain images created for parameterized test - if (miiImage != null) { - deleteImage(miiImage); - } - if (wdtImage != null) { - deleteImage(miiImage); - } - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain1Namespace, domain1Uid); - uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); - promHelmParams = null; - grafanaHelmParams = null; - prometheusDomainRegexValue = null; - - deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix, monitoringNS); - deletePersistentVolume("pv-testalertmanager" + releaseSuffix); - deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + prometheusReleaseName); - deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + grafanaReleaseName); - deleteNamespace(monitoringNS); - uninstallDeploymentService(webhookDepl, webhookService); - uninstallDeploymentService(coordinatorDepl, coordinatorService); - // delete coordinator and webhook images - if (webhookImage != null) { - deleteImage(webhookImage); - } - if (coordinatorImage != null) { - deleteImage(coordinatorImage); - } - deleteMonitoringExporterTempDir(monitoringExporterDir); - } - - /** - * Create, install Webhook or Coordinator and wait up to five minutes until the pod is ready. - * - * @param dockerFileDir directory where dockerfile is located - * @param baseImageName base image name - * @param namespace namespace - * @return status of installation - */ - public static boolean installAndVerifyPodFromCustomImage(String dockerFileDir, - String baseImageName, - String namespace, - Map labels, - String secretName) throws ApiException { - //build webhook image - String imagePullPolicy = "IfNotPresent"; - String image = createImageAndPushToRepo(dockerFileDir,baseImageName, namespace, secretName, ""); - logger.info("Installing {0} in namespace {1}", baseImageName, namespace); - if (baseImageName.equalsIgnoreCase(("webhook"))) { - webhookImage = image; - createWebHook(webhookImage, imagePullPolicy, namespace, OCIR_SECRET_NAME); - } else if (baseImageName.contains("coordinator")) { - coordinatorImage = image; - createCoordinator(coordinatorImage, imagePullPolicy, namespace, "coordsecret"); - } else { - throw new ApiException("Custom image creation for " + baseImageName + "is not supported"); - } - // wait for the pod to be ready - logger.info("Wait for the {0} pod is ready in namespace {1}", baseImageName, namespace); - testUntil( - assertDoesNotThrow(() -> isPodReady(namespace, labels, baseImageName), - baseImageName + " isPodReady failed with ApiException"), - logger, - "{0} to be running in namespace {1}", - baseImageName, - namespace); - return true; - } - - /** - * Create Webhook deployment and service. - * - * @param image full image name for deployment - * @param imagePullPolicy policy for image - * @param namespace webhook namespace - * @param secretName webhook image secret name - */ - private static void createWebHook(String image, - String imagePullPolicy, - String namespace, - String secretName) throws ApiException { - Map labels = new HashMap(); - labels.put("app", "webhook"); - - webhookDepl = new V1Deployment() - .apiVersion("apps/v1") - .kind("Deployment") - .metadata(new V1ObjectMeta() - .name("webhook") - .namespace(namespace) - .labels(labels)) - .spec(new V1DeploymentSpec() - .replicas(1) - .selector(new V1LabelSelector() - .matchLabels(labels)) - .template(new V1PodTemplateSpec() - .metadata(new V1ObjectMeta() - .labels(labels)) - .spec(new V1PodSpec() - .containers(Arrays.asList( - new V1Container() - .image(image) - .imagePullPolicy(imagePullPolicy) - .name("webhook"))) - .imagePullSecrets(Arrays.asList( - new V1LocalObjectReference() - .name(secretName)))))); - - logger.info("Create deployment for webhook in namespace {0}", - namespace); - boolean deploymentCreated = assertDoesNotThrow(() -> Kubernetes.createDeployment(webhookDepl), - String.format("Create deployment failed with ApiException for webhook in namespace %s", - namespace)); - assertTrue(deploymentCreated, String.format( - "Create deployment failed with ApiException for webhook in namespace %s ", - namespace)); - logger.info("Checking if the deployment is ready {0} completed in namespace {1}", - "webhook", namespace); - testUntil( - Deployment.isReady("webhook", labels, namespace), - logger, - "deployment webhook to be completed in namespace {0}", - namespace); - - webhookService = new V1Service() - .metadata(new V1ObjectMeta() - .name("webhook") - .namespace(namespace) - .labels(labels)) - .spec(new V1ServiceSpec() - .ports(Arrays.asList( - new V1ServicePort() - .port(8080) - .protocol("TCP"))) - .selector(labels)); - - logger.info("Create service for webhook in namespace {0}", - namespace); - boolean serviceCreated = assertDoesNotThrow(() -> Kubernetes.createService(webhookService), - String.format("Create service failed with ApiException for webhook in namespace %s", - namespace)); - assertTrue(serviceCreated, String.format( - "Create service failed with ApiException for webhook in namespace %s ", - namespace)); - // wait for the webhook pod to be ready - logger.info("Wait for the webhook pod is ready in namespace {0}", namespace); - Map labelMap = new HashMap<>(); - labelMap.put("app", "webhook"); - testUntil( - assertDoesNotThrow(() -> isPodReady(namespace, labelMap, "webhook"), - "webhook podIsReady failed with ApiException"), - logger, - "webhook to be running in namespace {0}", - namespace); - } - - /** - * Uninstall provided deployment and service. - */ - private static void uninstallDeploymentService(V1Deployment deployment, V1Service service) { - String namespace = null; - String serviceName = null; - String deploymentName = null; - try { - if (service != null) { - serviceName = service.getMetadata().getName(); - namespace = service.getMetadata().getNamespace(); - Kubernetes.deleteService(serviceName, namespace); - } - } catch (Exception ex) { - logger.warning(ex.getMessage()); - logger.warning("Failed to delete service {0} in namespace {1} ", - serviceName, namespace); - } - try { - if (deployment != null) { - deploymentName = deployment.getMetadata().getName(); - namespace = deployment.getMetadata().getNamespace(); - Kubernetes.deleteDeployment(namespace, deploymentName); - } - } catch (Exception ex) { - logger.warning(ex.getMessage()); - logger.warning("Failed to delete deployment {0} in namespace {1}", - deploymentName, namespace); - } - if (namespace != null) { - deleteNamespace(namespace); - } - } - - /** - * Create Coordinator deployment and service. - * - * @param image full image name for deployment - * @param imagePullPolicy policy for image - * @param namespace coordinator namespace - * @param secretName coordinator secret name - */ - private static void createCoordinator(String image, - String imagePullPolicy, - String namespace, - String secretName) throws ApiException { - if (coordinatorDepl == null) { - Map labels = new HashMap(); - labels.put("app", "coordinator"); - coordinatorDepl = new V1Deployment() - .apiVersion("apps/v1") - .kind("Deployment") - .metadata(new V1ObjectMeta() - .name("coordinator") - .namespace(namespace) - .labels(labels)) - .spec(new V1DeploymentSpec() - .replicas(1) - .selector(new V1LabelSelector() - .matchLabels(labels)) - .strategy(new V1DeploymentStrategy() - .type("Recreate")) - .template(new V1PodTemplateSpec() - .metadata(new V1ObjectMeta() - .labels(labels)) - .spec(new V1PodSpec() - .containers(Arrays.asList( - new V1Container() - .image(image) - .imagePullPolicy(imagePullPolicy) - .name("coordinator") - .ports(Arrays.asList( - new V1ContainerPort() - .containerPort(8999))))) - .imagePullSecrets(Arrays.asList( - new V1LocalObjectReference() - .name(secretName)))))); - - logger.info("Create deployment for coordinator in namespace {0}", - namespace); - boolean deploymentCreated = assertDoesNotThrow(() -> Kubernetes.createDeployment(coordinatorDepl), - String.format("Create deployment failed with ApiException for coordinator in namespace %s", - namespace)); - assertTrue(deploymentCreated, String.format( - "Create deployment failed with ApiException for coordinator in namespace %s ", - namespace)); - testUntil( - Deployment.isReady("coordinator", labels, namespace), - logger, - "deployment coordinator to be completed in namespace {0}", - namespace); - - HashMap annotations = new HashMap<>(); - annotations.put("kubectl.kubernetes.io/last-applied-configuration",""); - coordinatorService = new V1Service() - .metadata(new V1ObjectMeta() - .name("coordinator") - .annotations(annotations) - .namespace(namespace) - .labels(labels)) - .spec(new V1ServiceSpec() - .ports(Arrays.asList( - new V1ServicePort() - .port(8999) - .targetPort(new IntOrString(8999)))) - .type("NodePort") - .selector(labels)); - - logger.info("Create service for coordinator in namespace {0}", - namespace); - boolean success = assertDoesNotThrow(() -> Kubernetes.createService(coordinatorService), - String.format("Create service failed with ApiException for coordinator in namespace %s", - namespace)); - assertTrue(success, "Coordinator service creation failed"); - } - } - - - /** - * Create and verify domain in image from endtoend sample topology with monitoring exporter. - * @return image name - */ - private static String createAndVerifyDomainInImage() { - // create image with model files - logger.info("Create image with model file with monitoring exporter app and verify"); - String app1Path = String.format("%s/wls-exporter.war", monitoringExporterAppDir); - String app2Path = String.format("%s/../operator/integration-tests/apps/testwebapp.war", ITTESTS_DIR); - - List appList = new ArrayList(); - appList.add(app1Path); - appList.add(app2Path); - - int t3ChannelPort = getNextFreePort(); - - Properties p = new Properties(); - p.setProperty("ADMIN_USER", ADMIN_USERNAME_DEFAULT); - p.setProperty("ADMIN_PWD", ADMIN_PASSWORD_DEFAULT); - p.setProperty("DOMAIN_NAME", domain2Uid); - p.setProperty("ADMIN_NAME", "admin-server"); - p.setProperty("PRODUCTION_MODE_ENABLED", "true"); - p.setProperty("CLUSTER_NAME", cluster1Name); - p.setProperty("CLUSTER_TYPE", "DYNAMIC"); - p.setProperty("CONFIGURED_MANAGED_SERVER_COUNT", "2"); - p.setProperty("MANAGED_SERVER_NAME_BASE", "managed-server"); - p.setProperty("T3_CHANNEL_PORT", Integer.toString(t3ChannelPort)); - p.setProperty("T3_PUBLIC_ADDRESS", K8S_NODEPORT_HOST); - p.setProperty("MANAGED_SERVER_PORT", "8001"); - p.setProperty("SERVER_START_MODE", "prod"); - p.setProperty("ADMIN_PORT", "7001"); - p.setProperty("MYSQL_USER", "wluser1"); - p.setProperty("MYSQL_PWD", "wlpwd123"); - // create a temporary WebLogic domain property file as a input for WDT model file - File domainPropertiesFile = assertDoesNotThrow(() -> - File.createTempFile("domain", "properties"), - "Failed to create domain properties file"); - assertDoesNotThrow(() -> - p.store(new FileOutputStream(domainPropertiesFile), "WDT properties file"), - "Failed to write domain properties file"); - - final List propertyList = Collections.singletonList(domainPropertiesFile.getPath()); - - // build the model file list - final List modelList = Collections.singletonList(monitoringExporterEndToEndDir - + MONEXP_WDT_FILE); - - wdtImage = - createImageAndVerify(MONEXP_IMAGE_NAME, - modelList, - appList, - propertyList, - WEBLOGIC_IMAGE_NAME, - WEBLOGIC_IMAGE_TAG, - WLS, - false, - domain2Uid, true); - - // docker login and push image to docker registry if necessary - dockerLoginAndPushImageToRegistry(wdtImage); - - return wdtImage; - } -} \ No newline at end of file diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new deleted file mode 100644 index 0c5a12beaeb..00000000000 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterSideCar.java.new +++ /dev/null @@ -1,439 +0,0 @@ -// Copyright (c) 2021, Oracle 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; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.kubernetes.client.openapi.ApiException; -import oracle.weblogic.domain.Domain; -import oracle.weblogic.domain.MonitoringExporterConfiguration; -import oracle.weblogic.domain.MonitoringExporterSpecification; -import oracle.weblogic.kubernetes.actions.TestActions; -import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; -import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; -import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; -import oracle.weblogic.kubernetes.annotations.IntegrationTest; -import oracle.weblogic.kubernetes.annotations.Namespaces; -import oracle.weblogic.kubernetes.logging.LoggingFacade; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static oracle.weblogic.kubernetes.TestConstants.GRAFANA_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.OCIR_SECRET_NAME; -import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; -import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; -import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; -import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; -import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; -import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; -import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.getDomainCustomResource; -import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkPodReadyAndServiceExists; -import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getDockerExtraArgs; -import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; -import static oracle.weblogic.kubernetes.utils.ImageUtils.createImageAndPushToRepo; -import static oracle.weblogic.kubernetes.utils.ImageUtils.createMiiImageAndVerify; -import static oracle.weblogic.kubernetes.utils.ImageUtils.dockerLoginAndPushImageToRegistry; -import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; -import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; -import static oracle.weblogic.kubernetes.utils.PatchDomainUtils.patchDomainResource; -import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; -import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - - - -/** - * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running - * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. - * Verify WebLogic metrics can be accessed via NGINX ingress controller. - * Verify WebLogic metrics can be accessed via Prometheus - */ -@DisplayName("Verify WebLogic Metric is processed as expected by " - + "MonitoringExporter Side Car via Prometheus and Grafana") -@IntegrationTest -class ItMonitoringExporterSideCar { - - - // domain constants - - private static String domain1Namespace = null; - private static String domain2Namespace = null; - private static String domain3Namespace = null; - - private static String domain1Uid = "monexp-domain-1"; - private static String domain2Uid = "monexp-domain-2"; - private static String domain3Uid = "monexp-domain-3"; - - private static HelmParams nginxHelmParams = null; - private static int nodeportshttp = 0; - private static int nodeportshttps = 0; - - private static String monitoringNS = null; - PrometheusParams promHelmParams = null; - GrafanaParams grafanaHelmParams = null; - private static String monitoringExporterEndToEndDir = null; - private static String monitoringExporterSrcDir = null; - - // constants for creating domain image using model in image - private static final String MONEXP_IMAGE_NAME = "monexp-image"; - private static final String SESSMIGR_APP_NAME = "sessmigr-app"; - - private static String cluster1Name = "cluster-1"; - private static String cluster2Name = "cluster-2"; - private static String exporterImage = null; - private static int managedServerPort = 8001; - private static int nodeportPrometheus; - private static String prometheusDomainRegexValue = null; - private static Map clusterNameMsPortMap; - private static LoggingFacade logger = null; - private static List clusterNames = new ArrayList<>(); - private static String releaseSuffix = "test1"; - private static String prometheusReleaseName = "prometheus" + releaseSuffix; - private static String grafanaReleaseName = "grafana" + releaseSuffix; - private static String monitoringExporterDir; - - - /** - * Install operator and NGINX. Create model in image domain with multiple clusters. - * Create ingress for the domain. - * - * @param namespaces list of namespaces created by the IntegrationTestWatcher by the - * JUnit engine parameter resolution mechanism - */ - @BeforeAll - - public static void initAll(@Namespaces(6) List namespaces) { - - logger = getLogger(); - - monitoringExporterDir = Paths.get(RESULTS_ROOT, - "ItMonitoringExporterSideCar", "monitoringexp").toString(); - monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); - monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end").toString(); - - logger.info("Get a unique namespace for operator"); - assertNotNull(namespaces.get(0), "Namespace list is null"); - final String opNamespace = namespaces.get(0); - - logger.info("Get a unique namespace for monitoring"); - assertNotNull(namespaces.get(1), "Namespace list is null"); - monitoringNS = namespaces.get(1); - - logger.info("Get a unique namespace for NGINX"); - assertNotNull(namespaces.get(2), "Namespace list is null"); - final String nginxNamespace = namespaces.get(2); - - logger.info("Get a unique namespace for domain1"); - assertNotNull(namespaces.get(3), "Namespace list is null"); - domain1Namespace = namespaces.get(3); - - logger.info("Get a unique namespace for domain2"); - assertNotNull(namespaces.get(4), "Namespace list is null"); - domain2Namespace = namespaces.get(4); - - logger.info("Get a unique namespace for domain3"); - assertNotNull(namespaces.get(5), "Namespace list is null"); - domain3Namespace = namespaces.get(5); - - logger.info("install and verify operator"); - installAndVerifyOperator(opNamespace, - domain1Namespace, domain2Namespace, domain3Namespace); - - logger.info("install monitoring exporter"); - installMonitoringExporter(monitoringExporterDir); - assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", - "pvc-grafana", "pvc-" + grafanaReleaseName)); - exporterImage = assertDoesNotThrow(() -> createImageAndPushToRepo(monitoringExporterSrcDir, "exporter", - domain1Namespace, OCIR_SECRET_NAME, getDockerExtraArgs()), - "Failed to create image for exporter"); - - // install and verify NGINX - nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); - String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; - logger.info("NGINX service name: {0}", nginxServiceName); - nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); - nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); - logger.info("NGINX http node port: {0}", nodeportshttp); - logger.info("NGINX https node port: {0}", nodeportshttps); - clusterNameMsPortMap = new HashMap<>(); - clusterNameMsPortMap.put(cluster1Name, managedServerPort); - clusterNameMsPortMap.put(cluster2Name, managedServerPort); - clusterNames.add(cluster1Name); - clusterNames.add(cluster2Name); - - logger.info("create pv and pvc for monitoring"); - HashMap labels = new HashMap<>(); - labels.put("app", "monitoring"); - labels.put("weblogic.domainUid", "test"); - String pvDir = PV_ROOT + "/ItMonitoringExporterSideCar/monexp-persistentVolume/"; - assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix,monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); - } - - /** - * Test covers basic functionality for MonitoringExporter SideCar . - * Create Prometheus, Grafana. - * Create Model in Image with monitoring exporter. - * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. - * Check basic functionality of monitoring exporter. - */ - @Test - @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar.") - void testSideCarBasicFunctionality() throws Exception { - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.yaml"); - String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; - createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", 2, false, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain3Namespace, - domain3Uid); - - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - Domain domain = getDomainCustomResource(domain3Uid,domain3Namespace); - String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); - logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); - assertTrue(monexpConfig.contains("openSessionsHighCount")); - logger.info("Testing replace configuration"); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_jvm.yaml", domain3Uid, domain3Namespace, - "heapFreeCurrent", "heap_free_current", "managed-server1"); - - logger.info("replace monitoring exporter configuration with configuration file with domainQualifier=true."); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml", - domain3Uid, domain3Namespace, - "domainQualifier", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", - "\"domain\":\"wls-sessmigr-domain-1\""); - - logger.info("replace monitoring exporter configuration with configuration file with metricsNameSnakeCase=false."); - changeMonitoringExporterSideCarConfig(RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml", - domain3Uid, domain3Namespace, - "metricsNameSnakeCase", "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D", - "sessmigr"); - } - - private void changeMonitoringExporterSideCarConfig(String configYamlFile, String domainUid, - String domainNamespace, - String configSearchKey, - String promSearchString, String expectedVal) throws Exception { - String contents = null; - try { - contents = new String(Files.readAllBytes(Paths.get(configYamlFile))); - } catch (IOException e) { - e.printStackTrace(); - } - - MonitoringExporterSpecification monexpSpec = new MonitoringExporterSpecification().configuration(contents); - MonitoringExporterConfiguration monexpCong = monexpSpec.configuration(); - - StringBuffer patchStr = null; - patchStr = new StringBuffer("[{"); - patchStr.append("\"op\": \"replace\",") - .append(" \"path\": \"/spec/monitoringExporter/configuration\",") - .append("\"value\": ") - .append(monexpCong.asJsonString()) - .append("}]"); - logger.info("PatchStr for change Monitoring Exporter Configuration : {0}", patchStr.toString()); - - boolean cmPatched = patchDomainResource(domainUid, domainNamespace, patchStr); - assertTrue(cmPatched, "patchDomainCustomResource(changeMonExporter) failed"); - - Domain domain = assertDoesNotThrow(() -> TestActions.getDomainCustomResource(domainUid, domainNamespace), - String.format("getDomainCustomResource failed with ApiException when tried to get domain %s in namespace %s", - domainUid, domainNamespace)); - assertNotNull(domain, "Got null domain resource after patching"); - String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); - logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); - assertTrue(monexpConfig.contains(configSearchKey)); - - logger.info(domain.getSpec().getMonitoringExporter().toString()); - Thread.sleep(20 * 1000); - String managedServerPodName = domainUid + "-managed-server"; - // check that the managed server pod exists - logger.info("Checking that managed server pod {0} exists and ready in namespace {1}", - managedServerPodName, domainNamespace); - checkPodReadyAndServiceExists(managedServerPodName + "1", domainUid, domainNamespace); - checkPodReadyAndServiceExists(managedServerPodName + "2", domainUid, domainNamespace); - checkMetricsViaPrometheus(promSearchString, expectedVal,nodeportPrometheus); - } - - /** - * Test covers basic functionality for MonitoringExporter SideCar for domain with two clusters. - * Create Prometheus, Grafana. - * Create Model in Image with monitoring exporter. - * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. - * Check basic functionality of monitoring exporter. - */ - @Test - @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar for domain with two clusters.") - void testSideCarBasicFunctionalityTwoClusters() throws Exception { - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.sessmigr.2clusters.yaml"); - String yaml = RESOURCE_DIR + "/exporter/rest_jvm.yaml"; - createAndVerifyDomain(miiImage1, domain1Uid, domain1Namespace, "FromModel", 2, true, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain1Namespace, - domain1Uid); - - // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs - checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", - cluster1Name + "-managed-server1",nodeportPrometheus); - checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster2Name + "-managed-server2%22%7D%5B15s%5D", - cluster2Name + "-managed-server2",nodeportPrometheus); - } - - /** - * Test covers basic functionality for MonitoringExporter SideCar . - * Create Prometheus, Grafana. - * Create Model in Image with SSL enabled. - * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. - * Check basic functionality of monitoring exporter. - */ - - @Test - @DisplayName("Test Basic Functionality of Monitoring Exporter SideCar with ssl enabled.") - void testSideCarBasicFunctionalityWithSSL() throws Exception { - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - String yaml = RESOURCE_DIR + "/exporter/rest_webapp.yaml"; - String miiImage1 = createAndVerifyMiiImage(MODEL_DIR + "/model.ssl.yaml"); - createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, "FromModel", - 2, false, yaml, exporterImage); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain2Namespace, - domain2Uid); - - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - - Domain domain = getDomainCustomResource(domain2Uid,domain2Namespace); - String monexpConfig = domain.getSpec().getMonitoringExporter().toString(); - logger.info("MonitorinExporter new Configuration from crd " + monexpConfig); - assertTrue(monexpConfig.contains("openSessionsHighCount")); - } - - /** - * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. - * @throws ApiException when creating helm charts or pods fails - */ - private void installPrometheusGrafana(String promChartVersion, - String grafanaChartVersion, - String domainNS, - String domainUid - ) throws IOException, ApiException { - final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); - if (promHelmParams == null) { - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); - promHelmParams = installAndVerifyPrometheus(releaseSuffix, - monitoringNS, - promChartVersion, - prometheusRegexValue); - assertNotNull(promHelmParams, " Failed to install prometheus"); - nodeportPrometheus = promHelmParams.getNodePortServer(); - prometheusDomainRegexValue = prometheusRegexValue; - } - //if prometheus already installed change CM for specified domain - if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { - logger.info("update prometheus Config Map with domain info"); - editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, monitoringNS, - prometheusReleaseName + "-server"); - prometheusDomainRegexValue = prometheusRegexValue; - } - logger.info("Prometheus is running"); - - if (grafanaHelmParams == null) { - //logger.info("Node Port for Grafana is " + nodeportgrafana); - grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, - monitoringNS, - monitoringExporterEndToEndDir + "/grafana/values.yaml", - grafanaChartVersion); - assertNotNull(grafanaHelmParams, "Grafana failed to install"); - installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); - } - logger.info("Grafana is running"); - } - - - @AfterAll - public void tearDownAll() { - - // uninstall NGINX release - logger.info("Uninstalling NGINX"); - if (nginxHelmParams != null) { - assertThat(uninstallNginx(nginxHelmParams)) - .as("Test uninstallNginx1 returns true") - .withFailMessage("uninstallNginx() did not return true") - .isTrue(); - } - shutdownDomain(domain1Namespace, domain1Uid); - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain3Namespace, domain3Uid); - uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); - - deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); - deletePersistentVolume("pv-testalertmanager" + releaseSuffix); - deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + prometheusReleaseName); - deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + grafanaReleaseName); - deleteNamespace(monitoringNS); - deleteMonitoringExporterTempDir(monitoringExporterDir); - } - - /** - * Create mii image with SESSMIGR application. - */ - private static String createAndVerifyMiiImage(String modelFile) { - // create image with model files - logger.info("Create image with model file and verify"); - - List appList = new ArrayList(); - appList.add(SESSMIGR_APP_NAME); - - // build the model file list - final List modelList = Collections.singletonList(modelFile); - String myImage = - createMiiImageAndVerify(MONEXP_IMAGE_NAME, modelList, appList); - - // docker login and push image to docker registry if necessary - dockerLoginAndPushImageToRegistry(myImage); - - return myImage; - } -} \ No newline at end of file diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new deleted file mode 100644 index 80316bb2d5a..00000000000 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMonitoringExporterWebApp.java.new +++ /dev/null @@ -1,898 +0,0 @@ -// Copyright (c) 2021, Oracle 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; - -import java.io.IOException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; -import com.gargoylesoftware.htmlunit.TextPage; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlFileInput; -import com.gargoylesoftware.htmlunit.html.HtmlForm; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput; -import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; -import com.google.gson.Gson; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.models.V1Pod; -import oracle.weblogic.kubernetes.actions.impl.GrafanaParams; -import oracle.weblogic.kubernetes.actions.impl.PrometheusParams; -import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams; -import oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes; -import oracle.weblogic.kubernetes.annotations.IntegrationTest; -import oracle.weblogic.kubernetes.annotations.Namespaces; -import oracle.weblogic.kubernetes.logging.LoggingFacade; -import oracle.weblogic.kubernetes.utils.ExecResult; -import oracle.weblogic.kubernetes.utils.MonitoringUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.yaml.snakeyaml.Yaml; - -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.GRAFANA_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.K8S_NODEPORT_HOST; -import static oracle.weblogic.kubernetes.TestConstants.PROMETHEUS_CHART_VERSION; -import static oracle.weblogic.kubernetes.TestConstants.PV_ROOT; -import static oracle.weblogic.kubernetes.TestConstants.RESULTS_ROOT; -import static oracle.weblogic.kubernetes.actions.ActionConstants.MODEL_DIR; -import static oracle.weblogic.kubernetes.actions.ActionConstants.RESOURCE_DIR; -import static oracle.weblogic.kubernetes.actions.TestActions.deleteImage; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolume; -import static oracle.weblogic.kubernetes.actions.TestActions.deletePersistentVolumeClaim; -import static oracle.weblogic.kubernetes.actions.TestActions.getServiceNodePort; -import static oracle.weblogic.kubernetes.actions.TestActions.shutdownDomain; -import static oracle.weblogic.kubernetes.actions.TestActions.uninstallNginx; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.copyFileToPod; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.deleteNamespace; -import static oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes.exec; -import static oracle.weblogic.kubernetes.utils.FileUtils.replaceStringInFile; -import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.createIngressForDomainAndVerify; -import static oracle.weblogic.kubernetes.utils.LoadBalancerUtils.installAndVerifyNginx; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.checkMetricsViaPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.cleanupPromGrafanaClusterRoles; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.createAndVerifyDomain; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.deleteMonitoringExporterTempDir; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.editPrometheusCM; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyGrafana; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installAndVerifyPrometheus; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installMonitoringExporter; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.installVerifyGrafanaDashBoard; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.uninstallPrometheusGrafana; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccess; -import static oracle.weblogic.kubernetes.utils.MonitoringUtils.verifyMonExpAppAccessThroughNginx; -import static oracle.weblogic.kubernetes.utils.OperatorUtils.installAndVerifyOperator; -import static oracle.weblogic.kubernetes.utils.PersistentVolumeUtils.createPvAndPvc; -import static oracle.weblogic.kubernetes.utils.ThreadSafeLogger.getLogger; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - - - -/** - * Verify Prometheus, Grafana, Webhook, Coordinator are installed and running - * Verify the monitoring exporter installed in model in image domain can generate the WebLogic metrics. - * Verify WebLogic metrics can be accessed via NGINX ingress controller. - * Verify WebLogic metrics can be accessed via Prometheus - */ -@DisplayName("Verify WebLogic Metric is processed as expected by MonitoringExporter WebApp via Prometheus and Grafana") -@IntegrationTest -class ItMonitoringExporterWebApp { - - - // domain constants - private static String domain1Namespace = null; - private static String domain2Namespace = null; - private static String domain3Namespace = null; - - private static String domain1Uid = "monexp-domain-1"; - private static String domain2Uid = "monexp-domain-2"; - private static String domain3Uid = "monexp-domain-3"; - private static HelmParams nginxHelmParams = null; - private static int nodeportshttp = 0; - private static int nodeportshttps = 0; - private static List ingressHost1List = null; - - private static String monitoringNS = null; - PrometheusParams promHelmParams = null; - GrafanaParams grafanaHelmParams = null; - private static String monitoringExporterEndToEndDir = null; - private static String monitoringExporterSrcDir = null; - private static String monitoringExporterAppDir = null; - // constants for creating domain image using model in image - private static final String MONEXP_MODEL_FILE = "model.monexp.yaml"; - private static final String MONEXP_IMAGE_NAME = "monexp-image"; - private static final String SESSMIGR_APP_NAME = "sessmigr-app"; - - private static String cluster1Name = "cluster-1"; - private static String cluster2Name = "cluster-2"; - private static String miiImage = null; - private static int managedServerPort = 8001; - private static int nodeportPrometheus; - private static String exporterUrl = null; - private static String prometheusDomainRegexValue = null; - private static Map clusterNameMsPortMap; - private static LoggingFacade logger = null; - private static List clusterNames = new ArrayList<>(); - private static String releaseSuffix = "test2"; - private static String prometheusReleaseName = "prometheus" + releaseSuffix; - private static String grafanaReleaseName = "grafana" + releaseSuffix; - private static String monitoringExporterDir; - - - /** - * Install operator and NGINX. Create model in image domain with multiple clusters. - * Create ingress for the domain. - * - * @param namespaces list of namespaces created by the IntegrationTestWatcher by the - * JUnit engine parameter resolution mechanism - */ - @BeforeAll - - public static void initAll(@Namespaces(6) List namespaces) { - - logger = getLogger(); - monitoringExporterDir = monitoringExporterDir = Paths.get(RESULTS_ROOT, - "ItMonitoringExporterWebApp", "monitoringexp").toString(); - monitoringExporterSrcDir = Paths.get(monitoringExporterDir, "srcdir").toString(); - monitoringExporterEndToEndDir = Paths.get(monitoringExporterSrcDir, "samples", "kubernetes", "end2end").toString(); - monitoringExporterAppDir = Paths.get(monitoringExporterDir, "apps").toString(); - logger.info("Get a unique namespace for operator"); - assertNotNull(namespaces.get(0), "Namespace list is null"); - final String opNamespace = namespaces.get(0); - - logger.info("Get a unique namespace for monitoring"); - assertNotNull(namespaces.get(1), "Namespace list is null"); - monitoringNS = namespaces.get(1); - - logger.info("Get a unique namespace for NGINX"); - assertNotNull(namespaces.get(2), "Namespace list is null"); - final String nginxNamespace = namespaces.get(2); - - logger.info("Get a unique namespace for domain3"); - assertNotNull(namespaces.get(3), "Namespace list is null"); - domain3Namespace = namespaces.get(3); - - logger.info("Get a unique namespace for domain1"); - assertNotNull(namespaces.get(4), "Namespace list is null"); - domain1Namespace = namespaces.get(4); - - logger.info("Get a unique namespace for domain2"); - assertNotNull(namespaces.get(5), "Namespace list is null"); - domain2Namespace = namespaces.get(5); - - logger.info("install and verify operator"); - installAndVerifyOperator(opNamespace, domain3Namespace, - domain1Namespace, domain2Namespace); - - logger.info("install monitoring exporter"); - installMonitoringExporter(monitoringExporterDir); - assertDoesNotThrow(() -> replaceStringInFile(monitoringExporterEndToEndDir + "/grafana/values.yaml", - "pvc-grafana", "pvc-" + grafanaReleaseName)); - - logger.info("create and verify WebLogic domain image using model in image with model files"); - miiImage = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, MODEL_DIR + "/" + MONEXP_MODEL_FILE, - SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); - - // install and verify NGINX - nginxHelmParams = installAndVerifyNginx(nginxNamespace, 0, 0); - String nginxServiceName = nginxHelmParams.getReleaseName() + "-ingress-nginx-controller"; - logger.info("NGINX service name: {0}", nginxServiceName); - nodeportshttp = getServiceNodePort(nginxNamespace, nginxServiceName, "http"); - nodeportshttps = getServiceNodePort(nginxNamespace, nginxServiceName, "https"); - logger.info("NGINX http node port: {0}", nodeportshttp); - logger.info("NGINX https node port: {0}", nodeportshttps); - clusterNameMsPortMap = new HashMap<>(); - clusterNameMsPortMap.put(cluster1Name, managedServerPort); - clusterNameMsPortMap.put(cluster2Name, managedServerPort); - clusterNames.add(cluster1Name); - clusterNames.add(cluster2Name); - - exporterUrl = String.format("http://%s:%s/wls-exporter/",K8S_NODEPORT_HOST,nodeportshttp); - logger.info("create pv and pvc for monitoring"); - HashMap labels = new HashMap<>(); - labels.put("app", "monitoring"); - labels.put("weblogic.domainUid", "test"); - String pvDir = PV_ROOT + "/ItMonitoringExporterWebApp/monexp-persistentVolume/"; - assertDoesNotThrow(() -> createPvAndPvc(prometheusReleaseName, monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc("alertmanager" + releaseSuffix, monitoringNS, labels, pvDir)); - assertDoesNotThrow(() -> createPvAndPvc(grafanaReleaseName, monitoringNS, labels,pvDir)); - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); - } - - - /** - * Test covers end to end sample, provided in the Monitoring Exporter github project . - * Create Prometheus, Grafana. - * Create Model in Image with monitoring exporter. - * Verify access to monitoring exporter WebLogic metrics via nginx. - * Check generated monitoring exporter WebLogic metrics via Prometheus, Grafana. - * Check basic functionality of monitoring exporter. - */ - @Test - @DisplayName("Test Basic Functionality of Monitoring Exporter.") - void testBasicFunctionality() throws Exception { - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - createAndVerifyDomain(miiImage, domain1Uid, domain1Namespace, "FromModel", 1, true, null, null); - - // create ingress for the domain - logger.info("Creating ingress for domain {0} in namespace {1}", domain1Uid, domain1Namespace); - ingressHost1List = - createIngressForDomainAndVerify(domain1Uid, domain1Namespace, clusterNameMsPortMap, false); - verifyMonExpAppAccessThroughNginx(ingressHost1List.get(0), 1, nodeportshttp); - installPrometheusGrafana(PROMETHEUS_CHART_VERSION, GRAFANA_CHART_VERSION, - domain1Namespace, - domain1Uid); - - logger.info("Testing replace configuration"); - replaceConfiguration(); - logger.info("Testing append configuration"); - appendConfiguration(); - logger.info("Testing replace One Attribute Value AsArray configuration"); - replaceOneAttributeValueAsArrayConfiguration(); - logger.info("Testing append One Attribute Value AsArray configuration"); - appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration(); - logger.info("Testing append with empty configuration"); - appendWithEmptyConfiguration(); - logger.info("Testing append with invalid yaml configuration"); - appendWithNotYamlConfiguration(); - logger.info("Testing replace with invalid yaml configuration"); - replaceWithNotYamlConfiguration(); - logger.info("Testing append with corrupted yaml configuration"); - appendWithCorruptedYamlConfiguration(); - logger.info("Testing replace with corrupted yaml configuration"); - replaceWithCorruptedYamlConfiguration(); - logger.info("Testing replace with dublicated values yaml configuration"); - replaceWithDublicatedValuesConfiguration(); - logger.info("Testing append with corrupted yaml configuration"); - appendWithDuplicatedValuesConfiguration(); - logger.info("Testing replace with name snake false yaml configuration"); - replaceMetricsNameSnakeCaseFalseConfiguration(); - logger.info("Testing change with no credentials configuration"); - changeConfigNoCredentials(); - logger.info("Testing change with no invalid user configuration"); - changeConfigInvalidUser(); - logger.info("Testing change with no invalid pass configuration"); - changeConfigInvalidPass(); - logger.info("Testing change with empty user configuration"); - changeConfigEmptyUser(); - logger.info("Testing change with no empty pass configuration"); - changeConfigEmptyPass(); - logger.info("Testing replace with domain qualifier configuration"); - replaceMetricsDomainQualifierTrueConfiguration(); - logger.info("Testing replace with no restPort configuration"); - replaceMetricsNoRestPortConfiguration(); - } - - - /** - * Test covers scenario when admin port enabled . - * Create Model in Image with admin port and ssl enabled. - * Check generated monitoring exporter WebLogic metrics via https request. - */ - //commented out untill Issue (see oracle/weblogic-monitoring-exporter#138) will be fixed - //@Test - @DisplayName("Test Accesability of Monitoring Exporter dashboard and metrics if admin port is enabled.") - void testAdminPortEnabled() throws Exception { - - // create and verify one cluster mii domain with admin port enabled - logger.info("Create domain and verify that it's running"); - String miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir, - MODEL_DIR + "/model-adminportenabled.yaml", - SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); - createAndVerifyDomain(miiImage1, domain2Uid, domain2Namespace, - "FromModel", 2, false, null, null); - logger.info("checking access to wls metrics via https connection"); - - assertTrue(verifyMonExpAppAccess("wls-exporter", - "type: WebAppComponentRuntime", - domain2Uid, - domain2Namespace, - true, null), - "monitoring exporter dashboard page can't be accessed via https"); - - assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", - "wls_servlet_invocation_total_count", - domain2Uid, - domain2Namespace, - true, null), - "monitoring exporter metrics page can't be accessed via https"); - - } - - /** - * Verify access to monitoring exporter WebLogic metrics via https. - */ - @Test - @DisplayName("Test Monitoring Exporter access to metrics via https.") - void testAccessExporterViaHttps() throws Exception { - String miiImage1 = null; - - try { - logger.info("create and verify WebLogic domain image using model in image with model files for norestport"); - - miiImage1 = MonitoringUtils.createAndVerifyMiiImage(monitoringExporterAppDir + "/norestport", - MODEL_DIR + "/" + MONEXP_MODEL_FILE, SESSMIGR_APP_NAME, MONEXP_IMAGE_NAME); - - // create and verify one cluster mii domain - logger.info("Create domain and verify that it's running"); - createAndVerifyDomain(miiImage1, domain3Uid, domain3Namespace, "FromModel", - 1, true, null, null); - //verify access to Monitoring Exporter - logger.info("checking access to wls metrics via http connection"); - - clusterNames.stream().forEach((clusterName) -> { - assertFalse(verifyMonExpAppAccess("wls-exporter", - "restPort", - domain3Uid, - domain3Namespace, - false, clusterName)); - assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", - "wls_servlet_invocation_total_count", - domain3Uid, - domain3Namespace, - false, clusterName)); - }); - logger.info("checking access to wl metrics via https connection"); - //set to listen only ssl - changeListenPort(domain3Uid, domain3Namespace,"False"); - clusterNames.stream().forEach((clusterName) -> { - assertTrue(verifyMonExpAppAccess("wls-exporter/metrics", - "wls_servlet_invocation_total_count", - domain3Uid, - domain3Namespace, - true, clusterName), - "monitoring exporter metrics page can't be accessed via https"); - }); - } finally { - logger.info("Shutting down domain3"); - if (miiImage1 != null) { - deleteImage(miiImage1); - } - } - } - - /** - * Install Prometheus, Grafana using specified helm chart version, and verify that pods are running. - * @throws ApiException when creating helm charts or pods fails - */ - private void installPrometheusGrafana(String promChartVersion, - String grafanaChartVersion, - String domainNS, - String domainUid - ) throws IOException, ApiException { - final String prometheusRegexValue = String.format("regex: %s;%s", domainNS, domainUid); - if (promHelmParams == null) { - cleanupPromGrafanaClusterRoles(prometheusReleaseName,grafanaReleaseName); - promHelmParams = installAndVerifyPrometheus(releaseSuffix, - monitoringNS, - promChartVersion, - prometheusRegexValue); - assertNotNull(promHelmParams, " Failed to install prometheus"); - prometheusDomainRegexValue = prometheusRegexValue; - nodeportPrometheus = promHelmParams.getNodePortServer(); - } - //if prometheus already installed change CM for specified domain - if (!prometheusRegexValue.equals(prometheusDomainRegexValue)) { - logger.info("update prometheus Config Map with domain info"); - editPrometheusCM(prometheusDomainRegexValue, prometheusRegexValue, monitoringNS, - prometheusReleaseName + "-server"); - prometheusDomainRegexValue = prometheusRegexValue; - } - logger.info("Prometheus is running"); - - if (grafanaHelmParams == null) { - //logger.info("Node Port for Grafana is " + nodeportgrafana); - grafanaHelmParams = installAndVerifyGrafana(grafanaReleaseName, - monitoringNS, - monitoringExporterEndToEndDir + "/grafana/values.yaml", - grafanaChartVersion); - assertNotNull(grafanaHelmParams, "Grafana failed to install"); - installVerifyGrafanaDashBoard(grafanaHelmParams.getNodePort(), monitoringExporterEndToEndDir); - } - logger.info("Grafana is running"); - } - - - @AfterAll - public void tearDownAll() { - - // uninstall NGINX release - logger.info("Uninstalling NGINX"); - if (nginxHelmParams != null) { - assertThat(uninstallNginx(nginxHelmParams)) - .as("Test uninstallNginx1 returns true") - .withFailMessage("uninstallNginx() did not return true") - .isTrue(); - } - - shutdownDomain(domain1Namespace, domain1Uid); - shutdownDomain(domain2Namespace, domain2Uid); - shutdownDomain(domain3Namespace, domain3Uid); - - // delete mii domain images created - if (miiImage != null) { - deleteImage(miiImage); - } - - uninstallPrometheusGrafana(promHelmParams.getHelmParams(), grafanaHelmParams); - - deletePersistentVolumeClaim("pvc-alertmanager" + releaseSuffix,monitoringNS); - deletePersistentVolume("pv-testalertmanager" + releaseSuffix); - deletePersistentVolumeClaim("pvc-" + prometheusReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + prometheusReleaseName); - deletePersistentVolumeClaim("pvc-" + grafanaReleaseName, monitoringNS); - deletePersistentVolume("pv-test" + grafanaReleaseName); - deleteNamespace(monitoringNS); - deleteMonitoringExporterTempDir(monitoringExporterDir); - } - - private void changeConfigNegative(String effect, String configFile, String expectedErrorMsg) - throws Exception { - final WebClient webClient = new WebClient(); - //webClient.addRequestHeader("Host", ingressHost1List.get(0)); - HtmlPage originalPage = webClient.getPage(exporterUrl); - assertNotNull(originalPage); - HtmlPage page = submitConfigureForm(exporterUrl, effect, configFile); - assertTrue((page.asText()).contains(expectedErrorMsg)); - assertTrue(!(page.asText()).contains("Error 500--Internal Server Error")); - } - - private void changeConfigNegativeAuth( - String effect, String configFile, String expectedErrorMsg, String username, String password) - throws Exception { - try { - final WebClient webClient = new WebClient(); - setCredentials(webClient, username, password); - HtmlPage page = submitConfigureForm(exporterUrl, effect, configFile, webClient); - throw new RuntimeException("Expected exception was not thrown "); - } catch (FailingHttpStatusCodeException ex) { - assertTrue((ex.getMessage()).contains(expectedErrorMsg)); - } - } - - private HtmlPage submitConfigureForm(String exporterUrl, String effect, String configFile) - throws Exception { - final WebClient webClient = new WebClient(); - webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); - setCredentials(webClient); - return submitConfigureForm(exporterUrl, effect, configFile, webClient); - } - - private HtmlPage submitConfigureForm( - String exporterUrl, String effect, String configFile, WebClient webClient) throws Exception { - // Get the first page - HtmlPage page1 = webClient.getPage(exporterUrl); - if (page1 == null) { - //try again - page1 = webClient.getPage(exporterUrl); - } - assertNotNull(page1, "can't retrieve exporter dashboard page"); - assertTrue((page1.asText()).contains("This is the WebLogic Monitoring Exporter.")); - - // Get the form that we are dealing with and within that form, - // find the submit button and the field that we want to change.Generated form for cluster had - // extra path for wls-exporter - HtmlForm form = page1.getFirstByXPath("//form[@action='configure']"); - if (form == null) { - form = page1.getFirstByXPath("//form[@action='/wls-exporter/configure']"); - } - assertNotNull(form, "can't retrieve configure form"); - List radioButtons = form.getRadioButtonsByName("effect"); - assertNotNull(radioButtons, "can't retrieve buttons with effect"); - for (HtmlRadioButtonInput radioButton : radioButtons) { - if (radioButton.getValueAttribute().equalsIgnoreCase(effect)) { - radioButton.setChecked(true); - } - } - - HtmlSubmitInput button = - page1.getFirstByXPath("//form//input[@type='submit']"); - assertNotNull(button, "can't retrieve submit button"); - final HtmlFileInput fileField = form.getInputByName("configuration"); - assertNotNull(fileField); - - // Change the value of the text field - fileField.setValueAttribute(configFile); - fileField.setContentType("multipart/form-data"); - - // Now submit the form by clicking the button and get back the second page. - HtmlPage page2 = null; - try { - page2 = button.click(); - assertNotNull(page2, "can't reach page after submit"); - assertFalse((page2.asText()).contains("Error 500--Internal Server Error"), - "page returns Error 500--Internal Server Error"); - } catch (ClassCastException ex) { - logger.info(" Can't generate html page, collecting the error "); - TextPage page3 = button.click(); - assertNotNull(page3, "can't reach page after submit"); - assertTrue(page3.getContent().contains("Unable to contact the REST API"), - "submit does not return html page, here is received page " - + page3.getContent()); - } - return page2; - } - - private static void setCredentials(WebClient webClient) { - String base64encodedUsernameAndPassword = - base64Encode(String.format("%s:%s", - ADMIN_USERNAME_DEFAULT, - ADMIN_PASSWORD_DEFAULT)); - webClient.addRequestHeader("Authorization", "Basic " + base64encodedUsernameAndPassword); - } - - private static void setCredentials(WebClient webClient, String username, String password) { - String base64encodedUsernameAndPassword = base64Encode(username + ":" + password); - webClient.addRequestHeader("Authorization", "Basic " + base64encodedUsernameAndPassword); - } - - private static String base64Encode(String stringToEncode) { - Base64.Encoder enc = Base64.getEncoder(); - return enc.encodeToString(stringToEncode.getBytes()); - } - - /** - * Replace monitoring exporter configuration and verify it was applied to both managed servers. - * - * @throws Exception if test fails - */ - private void replaceConfiguration() throws Exception { - HtmlPage page = submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_jvm.yaml"); - assertNotNull(page, "Failed to replace configuration"); - - assertTrue(page.asText().contains("JVMRuntime"), - "Page does not contain expected JVMRuntime configuration"); - assertFalse(page.asText().contains("WebAppComponentRuntime"), - "Page contains unexpected WebAppComponentRuntime configuration"); - //needs 20 secs to fetch the metrics to prometheus - Thread.sleep(20 * 1000); - // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs - checkMetricsViaPrometheus("heap_free_current%7Bname%3D%22" + cluster1Name + "-managed-server1%22%7D%5B15s%5D", - cluster1Name + "-managed-server1",nodeportPrometheus); - - } - - /** - * Add additional monitoring exporter configuration and verify it was applied. - * - * @throws Exception if test fails - */ - private void appendConfiguration() throws Exception { - - // run append - HtmlPage page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_webapp.yaml"); - assertTrue(page.asText().contains("WebAppComponentRuntime"), - "Page does not contain expected WebAppComponentRuntime configuration"); - // check previous config is there - assertTrue(page.asText().contains("JVMRuntime"), "Page does not contain expected JVMRuntime configuration"); - - String sessionAppPrometheusSearchKey = - "wls_servlet_invocation_total_count%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(sessionAppPrometheusSearchKey, "sessmigr",nodeportPrometheus); - } - - /** - * Replace monitoring exporter configuration with only one attribute and verify it was applied. - * - * @throws Exception if test fails - */ - private void replaceOneAttributeValueAsArrayConfiguration() throws Exception { - HtmlPage page = - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_oneattribval.yaml"); - assertTrue(page.asText().contains("values: invocationTotalCount")); - assertFalse(page.asText().contains("reloadTotal")); - } - - /** - * Append monitoring exporter configuration with one more attribute and verify it was applied - * append to [a] new config [a,b]. - * - * @throws Exception if test fails - */ - private void appendArrayWithOneExistedAndOneDifferentAttributeValueAsArrayConfiguration() - throws Exception { - HtmlPage page = - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_oneattribval.yaml"); - assertTrue(page.asText().contains("values: invocationTotalCount")); - page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_twoattribs.yaml"); - assertTrue(page.asText().contains("values: [invocationTotalCount, executionTimeAverage]")); - } - - /** - * Replace monitoring exporter configuration with empty configuration. - * - * @throws Exception if test fails - */ - private void replaceWithEmptyConfiguration() throws Exception { - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_empty.yaml"); - assertFalse(verifyMonExpAppAccess("wls-exporter","values", domain1Uid, domain1Namespace,false, cluster1Name)); - assertTrue(verifyMonExpAppAccess("wls-exporter","queries", domain1Uid, domain1Namespace,false, cluster1Name)); - } - - /** - * Try to append monitoring exporter configuration with empty configuration. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void appendWithEmptyConfiguration() throws Exception { - HtmlPage originalPage = submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_jvm.yaml"); - assertNotNull(originalPage, "Failed to replace configuration"); - assertTrue(originalPage.asText().contains("JVMRuntime"), - "Page does not contain expected JVMRuntime configuration"); - HtmlPage page = submitConfigureForm(exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_empty.yaml"); - assertTrue(originalPage.asText().equals(page.asText())); - } - - /** - * Try to append monitoring exporter configuration with configuration file not in the yaml format. - * - * @throws Exception if test fails - */ - private void appendWithNotYamlConfiguration() throws Exception { - changeConfigNegative( - "append", RESOURCE_DIR + "/exporter/rest_notyamlformat.yaml", "Configuration is not in YAML format"); - } - - /** - * Try to replace monitoring exporter configuration with configuration file not in the yaml - * format. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void replaceWithNotYamlConfiguration() throws Exception { - changeConfigNegative( - "replace", RESOURCE_DIR + "/exporter/rest_notyamlformat.yaml", "Configuration is not in YAML format"); - } - - /** - * Try to append monitoring exporter configuration with configuration file in the corrupted yaml - * format. - * - * @throws Exception if test fails - */ - private void appendWithCorruptedYamlConfiguration() throws Exception { - changeConfigNegative( - "append", - RESOURCE_DIR + "/exporter/rest_notyaml.yaml", - "Configuration YAML format has errors while scanning a simple key"); - } - - /** - * Try to replace monitoring exporter configuration with configuration file in the corrupted yaml - * format. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void replaceWithCorruptedYamlConfiguration() throws Exception { - changeConfigNegative( - "replace", - RESOURCE_DIR + "/exporter/rest_notyaml.yaml", - "Configuration YAML format has errors while scanning a simple key"); - } - - /** - * Try to replace monitoring exporter configuration with configuration file with dublicated - * values. - * - * @throws Exception if test fails - */ - private void replaceWithDublicatedValuesConfiguration() throws Exception { - changeConfigNegative( - "replace", - RESOURCE_DIR + "/exporter/rest_dublicatedval.yaml", - "Duplicate values for [deploymentState] at applicationRuntimes.componentRuntimes"); - } - - /** - * Try to append monitoring exporter configuration with configuration file with duplicated values. - * - * @throws Exception if test fails - */ - private void appendWithDuplicatedValuesConfiguration() throws Exception { - changeConfigNegative( - "append", - RESOURCE_DIR + "/exporter/rest_dublicatedval.yaml", - "Duplicate values for [deploymentState] at applicationRuntimes.componentRuntimes"); - } - - /** - * Try to replace monitoring exporter configuration with configuration file with - * NameSnakeCase=false. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void replaceMetricsNameSnakeCaseFalseConfiguration() throws Exception { - HtmlPage page = - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_snakecasefalse.yaml"); - assertNotNull(page); - assertFalse(page.asText().contains("metricsNameSnakeCase")); - String searchKey = "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(searchKey, "sessmigr",nodeportPrometheus); - } - - /** - * Try to replace monitoring exporter configuration with configuration file with - * no restPort value. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void replaceMetricsNoRestPortConfiguration() throws Exception { - HtmlPage page = - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/norestport.yaml"); - assertNotNull(page); - assertFalse(page.asText().contains("restPort")); - //needs 20 secs to fetch the metrics to prometheus - Thread.sleep(20 * 1000); - // "heap_free_current{name="managed-server1"}[15s]" search for results for last 15secs - - String prometheusSearchKey1 = - "heap_free_current"; - checkMetricsViaPrometheus(prometheusSearchKey1, "managed-server1",nodeportPrometheus); - } - - /** - * Test to replace monitoring exporter configuration with configuration file with - * domainQualifier=true. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - private void replaceMetricsDomainQualifierTrueConfiguration() throws Exception { - HtmlPage page = - submitConfigureForm(exporterUrl, "replace", RESOURCE_DIR + "/exporter/rest_domainqualtrue.yaml"); - assertNotNull(page); - logger.info("page - " + page.asText()); - assertTrue(page.asText().contains("domainQualifier")); - - String searchKey = "wls_servlet_executionTimeAverage%7Bapp%3D%22myear%22%7D%5B15s%5D"; - checkMetricsViaPrometheus(searchKey, "\"domain\":\"wls-monexp-domain-1" + "\"",nodeportPrometheus); - } - - /** - * Test to change monitoring exporter configuration without authentication. - * - * @throws Exception if failed to apply configuration or check the expected values. - */ - // verify that change configuration fails without authentication - private void changeConfigNoCredentials() throws Exception { - WebClient webClient = new WebClient(); - String expectedErrorMsg = "401 Unauthorized for " + exporterUrl; - try { - HtmlPage page = - submitConfigureForm( - exporterUrl, "append", RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", webClient); - throw new RuntimeException("Form was submitted successfully with no credentials"); - } catch (FailingHttpStatusCodeException ex) { - assertTrue((ex.getMessage()).contains(expectedErrorMsg)); - } - } - - /** - * Try to change monitoring exporter configuration with invalid username. - * - * @throws Exception if the expected exception message does not match - */ - private void changeConfigInvalidUser() throws Exception { - changeConfigNegativeAuth( - "replace", - RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", - "401 Unauthorized for " + exporterUrl, - "invaliduser", - ADMIN_PASSWORD_DEFAULT); - } - - /** - * Try to change monitoring exporter configuration with invalid password. - * - * @throws Exception if the expected exception message does not match - */ - private void changeConfigInvalidPass() throws Exception { - changeConfigNegativeAuth( - "replace", - RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", - "401 Unauthorized for " + exporterUrl, - ADMIN_USERNAME_DEFAULT, - "invalidpass"); - } - - /** - * Try to change monitoring exporter configuration with empty username. - * - * @throws Exception if the expected exception message does not match - */ - private void changeConfigEmptyUser() throws Exception { - changeConfigNegativeAuth( - "replace", - RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", - "401 Unauthorized for " + exporterUrl, - "", - ADMIN_PASSWORD_DEFAULT); - } - - /** - * Try to change monitoring exporter configuration with empty pass. - * - * @throws Exception if the expected exception message does not match - */ - private void changeConfigEmptyPass() throws Exception { - changeConfigNegativeAuth( - "replace", - RESOURCE_DIR + "/exporter/rest_snakecasetrue.yaml", - "401 Unauthorized for " + exporterUrl, - ADMIN_USERNAME_DEFAULT, - ""); - } - - private boolean changeListenPort(String domainUid, String domainNS, String setListenPortEnabled) throws Exception { - // copy changeListenPort.py and callpyscript.sh to Admin Server pod - String adminServerPodName = domainUid + "-" + ADMIN_SERVER_NAME_BASE; - V1Pod adminPod = Kubernetes.getPod(domainNS, null, adminServerPodName); - if (adminPod == null) { - logger.info("The admin pod {0} does not exist in namespace {1}!", adminServerPodName, domainNS); - return false; - } - - logger.info("Copying changeListenPort.py and callpyscript.sh to admin server pod"); - try { - copyFileToPod(domainNS, adminServerPodName, null, - Paths.get(RESOURCE_DIR, "python-scripts", "changeListenPort.py"), - Paths.get("/u01/oracle/changeListenPort.py")); - - copyFileToPod(domainNS, adminServerPodName, null, - Paths.get(RESOURCE_DIR, "bash-scripts", "callpyscript.sh"), - Paths.get("/u01/oracle/callpyscript.sh")); - } catch (ApiException apex) { - logger.severe("Got ApiException while copying file to admin pod {0}", apex.getResponseBody()); - return false; - } catch (IOException ioex) { - logger.severe("Got IOException while copying file to admin pod {0}", ioex.getStackTrace()); - return false; - } - - logger.info("Adding execute mode for callpyscript.sh"); - ExecResult result = exec(adminPod, null, true, - "/bin/sh", "-c", "chmod +x /u01/oracle/callpyscript.sh"); - if (result.exitValue() != 0) { - return false; - } - logger.info("Changing ListenPortEnabled"); - String command = new StringBuffer("/u01/oracle/callpyscript.sh /u01/oracle/changeListenPort.py ") - .append(ADMIN_USERNAME_DEFAULT) - .append(" ") - .append(ADMIN_PASSWORD_DEFAULT) - .append(" t3://") - .append(adminServerPodName) - .append(":7001 ") - .append(setListenPortEnabled) - .append(" ") - .append("managed-server1") - .toString(); - - result = exec(adminPod, null, true, "/bin/sh", "-c", command); - if (result.exitValue() != 0) { - return false; - } - return true; - } - - private static String convertToJson(String yaml) { - final Object loadedYaml = new Yaml().load(yaml); - return new Gson().toJson(loadedYaml, LinkedHashMap.class); - } - -} \ No newline at end of file From 8e30a018b0397e1bd822106572606b31a878eaf3 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Wed, 10 Nov 2021 23:53:39 +0000 Subject: [PATCH 04/10] added check for webapp download --- .../kubernetes/utils/MonitoringUtils.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/MonitoringUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/MonitoringUtils.java index 6712af60fe3..94468244941 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/MonitoringUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/MonitoringUtils.java @@ -134,20 +134,28 @@ public static void downloadMonitoringExporterApp(String configFile, String appli .command(command)) .execute(), "Failed to download monitoring exporter webapp"); - command = String.format("cd %s && %s %s", + String command1 = String.format("cd %s && %s %s", applicationDir, monitoringExporterBuildFile, configFile); - assertTrue(new Command() - .withParams(new CommandParams() - .command(command)) - .execute(), "Failed to build monitoring exporter webapp"); + + testUntil( + (() -> new Command() + .withParams( + new CommandParams() + .verbose(true) + .command(command1)) + .executeAndVerify("adding: config.yml") + ), + logger, + "Downloading monitoring exporter webapp"); + assertDoesNotThrow(() -> checkFile(applicationDir + "/wls-exporter.war"), "Monitoring Exporter web application file was not found"); } /** - * Build monitoring exporter web applicaiont wls-exporter.war with provided configuration + * Build monitoring exporter web applicaiont wls-exporter.war with provided configuration * @param monitoringExporterSrcDir directory containing github monitoring exporter * @param configFile configuration file for weblogic domain monitoring * @param appDir directory where war file will be created From 2fc9a28c4643aad1dc86dd4ebc47301cb3963323 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Thu, 11 Nov 2021 00:25:49 +0000 Subject: [PATCH 05/10] fixed intermitent failure for service account creation --- .../ItUsabilityOperatorHelmChart.java | 25 ++++++++++++------- .../kubernetes/assertions/TestAssertions.java | 14 +++++++++++ .../kubernetes/utils/OperatorUtils.java | 16 +++++++++--- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java index a8f92e5b799..323b067b4af 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java @@ -49,7 +49,6 @@ import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_RELEASE_NAME; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_SERVICE_NAME; import static oracle.weblogic.kubernetes.TestConstants.WLS_DOMAIN_TYPE; -import static oracle.weblogic.kubernetes.actions.TestActions.createServiceAccount; import static oracle.weblogic.kubernetes.actions.TestActions.deleteDomainCustomResource; import static oracle.weblogic.kubernetes.actions.TestActions.deleteSecret; import static oracle.weblogic.kubernetes.actions.TestActions.deleteServiceAccount; @@ -65,6 +64,7 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorIsReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorRestServiceRunning; import static oracle.weblogic.kubernetes.assertions.TestAssertions.podStateNotChanged; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceAccountIsCreated; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkServiceDoesNotExist; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkServiceExists; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getHostAndPort; @@ -713,10 +713,14 @@ void testNotPreexistedOpServiceAccountCreateOperatorNegativeInstall() { } // Create a service account for the unique op2Namespace logger.info("Creating service account"); - assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(op2Namespace) - .name(opServiceAccount)))); + testUntil( + assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(op2Namespace) + .name(opServiceAccount))), "failed to create ServiceAccount"), + logger, + "creating operator service account"); + logger.info("Created service account: {0}", opServiceAccount); logger.info("Installing operator %s in namespace %s again", opReleaseName, op2Namespace); @@ -993,10 +997,13 @@ private static HelmParams installOperatorHelmChart(String operNamespace, if (createOpSA) { // Create a service account for the unique operNamespace logger.info("Creating service account"); - assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(operNamespace) - .name(opServiceAccount)))); + testUntil( + assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(operNamespace) + .name(opServiceAccount))), "failed to create ServiceAccount"), + logger, + "creating operator service account"); logger.info("Created service account: {0}", opServiceAccount); } diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java index 6649db44493..d34894a8818 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java @@ -12,8 +12,10 @@ import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.models.V1Pod; import io.kubernetes.client.openapi.models.V1Secret; +import io.kubernetes.client.openapi.models.V1ServiceAccount; import oracle.weblogic.domain.DomainCondition; import oracle.weblogic.kubernetes.actions.impl.LoggingExporter; +import oracle.weblogic.kubernetes.actions.impl.ServiceAccount; import oracle.weblogic.kubernetes.assertions.impl.Apache; import oracle.weblogic.kubernetes.assertions.impl.Application; import oracle.weblogic.kubernetes.assertions.impl.ClusterRole; @@ -56,6 +58,18 @@ public static Callable operatorIsReady(String namespace) { return Operator.isReady(namespace); } + /** + * Check if ServiceAccount is created. + * + * @param serviceAccount object + * @return true if created false otherwise + */ + public static Callable serviceAccountIsCreated(V1ServiceAccount serviceAccount) { + return () -> { + return ServiceAccount.create(serviceAccount); + }; + } + /** * Check if NGINX is running. * diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java index a9ea5797aea..fb57d4f345b 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java @@ -32,6 +32,7 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.isHelmReleaseDeployed; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorIsReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorRestServiceRunning; +import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceAccountIsCreated; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.testUntil; import static oracle.weblogic.kubernetes.utils.ImageUtils.createOcirRepoSecret; import static oracle.weblogic.kubernetes.utils.OKDUtils.createRouteForOKD; @@ -255,9 +256,18 @@ public static OperatorParams installAndVerifyOperator(String opNamespace, // Create a service account for the unique opNamespace logger.info("Creating service account"); assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(opNamespace) - .name(opServiceAccount)))); + .metadata(new V1ObjectMeta() + .namespace(opNamespace) + .name(opServiceAccount))), "failed to create ServiceAccount"); + + testUntil( + assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(opNamespace) + .name(opServiceAccount))), "failed to create ServiceAccount"), + logger, + "creating operator service account"); + logger.info("Created service account: {0}", opServiceAccount); From 49ef510e7e76c1e8f1af72332b387586fb737857 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Thu, 11 Nov 2021 01:11:59 +0000 Subject: [PATCH 06/10] fixed logic --- .../oracle/weblogic/kubernetes/utils/OperatorUtils.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java index fb57d4f345b..5bf0357a9e2 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java @@ -22,7 +22,6 @@ import static oracle.weblogic.kubernetes.TestConstants.OKD; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_CHART_DIR; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_RELEASE_NAME; -import static oracle.weblogic.kubernetes.actions.TestActions.createServiceAccount; import static oracle.weblogic.kubernetes.actions.TestActions.getOperatorImageName; import static oracle.weblogic.kubernetes.actions.TestActions.getOperatorPodName; import static oracle.weblogic.kubernetes.actions.TestActions.installOperator; @@ -255,11 +254,6 @@ public static OperatorParams installAndVerifyOperator(String opNamespace, // Create a service account for the unique opNamespace logger.info("Creating service account"); - assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(opNamespace) - .name(opServiceAccount))), "failed to create ServiceAccount"); - testUntil( assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() .metadata(new V1ObjectMeta() From c1d65dbd9240615bc3c5b80ffcccb34e36503d55 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Thu, 11 Nov 2021 04:07:05 +0000 Subject: [PATCH 07/10] corrected logic --- .../java/oracle/weblogic/kubernetes/utils/OperatorUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java index 5bf0357a9e2..8074f73bd7a 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java @@ -255,10 +255,10 @@ public static OperatorParams installAndVerifyOperator(String opNamespace, // Create a service account for the unique opNamespace logger.info("Creating service account"); testUntil( - assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + serviceAccountIsCreated(new V1ServiceAccount() .metadata(new V1ObjectMeta() .namespace(opNamespace) - .name(opServiceAccount))), "failed to create ServiceAccount"), + .name(opServiceAccount))), logger, "creating operator service account"); From 6b55626cda06071a23f88f224e5615c84e050d44 Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Thu, 11 Nov 2021 04:10:51 +0000 Subject: [PATCH 08/10] fixed logic --- .../weblogic/kubernetes/ItUsabilityOperatorHelmChart.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java index 323b067b4af..f10964d9f83 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java @@ -714,10 +714,10 @@ void testNotPreexistedOpServiceAccountCreateOperatorNegativeInstall() { // Create a service account for the unique op2Namespace logger.info("Creating service account"); testUntil( - assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + serviceAccountIsCreated(new V1ServiceAccount() .metadata(new V1ObjectMeta() .namespace(op2Namespace) - .name(opServiceAccount))), "failed to create ServiceAccount"), + .name(opServiceAccount))), logger, "creating operator service account"); @@ -998,10 +998,10 @@ private static HelmParams installOperatorHelmChart(String operNamespace, // Create a service account for the unique operNamespace logger.info("Creating service account"); testUntil( - assertDoesNotThrow(() -> serviceAccountIsCreated(new V1ServiceAccount() + serviceAccountIsCreated(new V1ServiceAccount() .metadata(new V1ObjectMeta() .namespace(operNamespace) - .name(opServiceAccount))), "failed to create ServiceAccount"), + .name(opServiceAccount))), logger, "creating operator service account"); logger.info("Created service account: {0}", opServiceAccount); From d3f55bd8c8880ee36efd054563f5d6d4bda760fc Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Fri, 12 Nov 2021 20:37:15 +0000 Subject: [PATCH 09/10] reset --- .../ItUsabilityOperatorHelmChart.java | 25 +++++++------------ .../kubernetes/assertions/TestAssertions.java | 14 ----------- .../kubernetes/utils/OperatorUtils.java | 14 ++++------- 3 files changed, 14 insertions(+), 39 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java index f10964d9f83..a8f92e5b799 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/ItUsabilityOperatorHelmChart.java @@ -49,6 +49,7 @@ import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_RELEASE_NAME; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_SERVICE_NAME; import static oracle.weblogic.kubernetes.TestConstants.WLS_DOMAIN_TYPE; +import static oracle.weblogic.kubernetes.actions.TestActions.createServiceAccount; import static oracle.weblogic.kubernetes.actions.TestActions.deleteDomainCustomResource; import static oracle.weblogic.kubernetes.actions.TestActions.deleteSecret; import static oracle.weblogic.kubernetes.actions.TestActions.deleteServiceAccount; @@ -64,7 +65,6 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorIsReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorRestServiceRunning; import static oracle.weblogic.kubernetes.assertions.TestAssertions.podStateNotChanged; -import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceAccountIsCreated; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkServiceDoesNotExist; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.checkServiceExists; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.getHostAndPort; @@ -713,14 +713,10 @@ void testNotPreexistedOpServiceAccountCreateOperatorNegativeInstall() { } // Create a service account for the unique op2Namespace logger.info("Creating service account"); - testUntil( - serviceAccountIsCreated(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(op2Namespace) - .name(opServiceAccount))), - logger, - "creating operator service account"); - + assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(op2Namespace) + .name(opServiceAccount)))); logger.info("Created service account: {0}", opServiceAccount); logger.info("Installing operator %s in namespace %s again", opReleaseName, op2Namespace); @@ -997,13 +993,10 @@ private static HelmParams installOperatorHelmChart(String operNamespace, if (createOpSA) { // Create a service account for the unique operNamespace logger.info("Creating service account"); - testUntil( - serviceAccountIsCreated(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(operNamespace) - .name(opServiceAccount))), - logger, - "creating operator service account"); + assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(operNamespace) + .name(opServiceAccount)))); logger.info("Created service account: {0}", opServiceAccount); } diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java index d34894a8818..6649db44493 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/TestAssertions.java @@ -12,10 +12,8 @@ import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.models.V1Pod; import io.kubernetes.client.openapi.models.V1Secret; -import io.kubernetes.client.openapi.models.V1ServiceAccount; import oracle.weblogic.domain.DomainCondition; import oracle.weblogic.kubernetes.actions.impl.LoggingExporter; -import oracle.weblogic.kubernetes.actions.impl.ServiceAccount; import oracle.weblogic.kubernetes.assertions.impl.Apache; import oracle.weblogic.kubernetes.assertions.impl.Application; import oracle.weblogic.kubernetes.assertions.impl.ClusterRole; @@ -58,18 +56,6 @@ public static Callable operatorIsReady(String namespace) { return Operator.isReady(namespace); } - /** - * Check if ServiceAccount is created. - * - * @param serviceAccount object - * @return true if created false otherwise - */ - public static Callable serviceAccountIsCreated(V1ServiceAccount serviceAccount) { - return () -> { - return ServiceAccount.create(serviceAccount); - }; - } - /** * Check if NGINX is running. * diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java index 8074f73bd7a..a9ea5797aea 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/OperatorUtils.java @@ -22,6 +22,7 @@ import static oracle.weblogic.kubernetes.TestConstants.OKD; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_CHART_DIR; import static oracle.weblogic.kubernetes.TestConstants.OPERATOR_RELEASE_NAME; +import static oracle.weblogic.kubernetes.actions.TestActions.createServiceAccount; import static oracle.weblogic.kubernetes.actions.TestActions.getOperatorImageName; import static oracle.weblogic.kubernetes.actions.TestActions.getOperatorPodName; import static oracle.weblogic.kubernetes.actions.TestActions.installOperator; @@ -31,7 +32,6 @@ import static oracle.weblogic.kubernetes.assertions.TestAssertions.isHelmReleaseDeployed; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorIsReady; import static oracle.weblogic.kubernetes.assertions.TestAssertions.operatorRestServiceRunning; -import static oracle.weblogic.kubernetes.assertions.TestAssertions.serviceAccountIsCreated; import static oracle.weblogic.kubernetes.utils.CommonTestUtils.testUntil; import static oracle.weblogic.kubernetes.utils.ImageUtils.createOcirRepoSecret; import static oracle.weblogic.kubernetes.utils.OKDUtils.createRouteForOKD; @@ -254,14 +254,10 @@ public static OperatorParams installAndVerifyOperator(String opNamespace, // Create a service account for the unique opNamespace logger.info("Creating service account"); - testUntil( - serviceAccountIsCreated(new V1ServiceAccount() - .metadata(new V1ObjectMeta() - .namespace(opNamespace) - .name(opServiceAccount))), - logger, - "creating operator service account"); - + assertDoesNotThrow(() -> createServiceAccount(new V1ServiceAccount() + .metadata(new V1ObjectMeta() + .namespace(opNamespace) + .name(opServiceAccount)))); logger.info("Created service account: {0}", opServiceAccount); From bee37f740401e10881d7019e641a748a6a6e756e Mon Sep 17 00:00:00 2001 From: Marina Kogan Date: Mon, 15 Nov 2021 19:01:28 +0000 Subject: [PATCH 10/10] fixed npe --- .../assertions/impl/Kubernetes.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java index e9583783e38..9881dfaa5f6 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/assertions/impl/Kubernetes.java @@ -664,16 +664,20 @@ public static boolean isDeploymentReady(String deploymentName, boolean status = false; V1Deployment deployment = getDeployment(deploymentName, label, namespace); - V1DeploymentCondition v1DeploymentRunningCondition = Optional.ofNullable(deployment) + List deplList = Optional.ofNullable(deployment) .map(V1Deployment::getStatus).map(V1DeploymentStatus::getConditions) - .orElse(null).stream() - .filter(v1DeploymentCondition -> "Available".equals(v1DeploymentCondition.getType())) - .findAny() .orElse(null); - if (v1DeploymentRunningCondition != null) { - status = v1DeploymentRunningCondition.getStatus().equalsIgnoreCase("true"); - } else { - getLogger().info("Can't check deployment status"); + if (deplList != null) { + V1DeploymentCondition v1DeploymentRunningCondition = deplList.stream() + .filter(v1DeploymentCondition -> "Available".equals(v1DeploymentCondition.getType())) + .findAny() + .orElse(null); + + if (v1DeploymentRunningCondition != null) { + status = v1DeploymentRunningCondition.getStatus().equalsIgnoreCase("true"); + } else { + getLogger().info("Can't check deployment status"); + } } return status; }