github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/logging/weblogic/weblogic_logging_test.go (about) 1 // Copyright (c) 2022, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package weblogic 5 6 import ( 7 "fmt" 8 dump "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/clusterdump" 9 "time" 10 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 "github.com/verrazzano/verrazzano/pkg/k8s/resource" 14 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 15 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 16 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework/metrics" 17 pkgweblogic "github.com/verrazzano/verrazzano/tests/e2e/pkg/weblogic" 18 v1 "k8s.io/api/core/v1" 19 "k8s.io/apimachinery/pkg/api/errors" 20 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 21 ) 22 23 const ( 24 longWaitTimeout = 20 * time.Minute 25 longPollingInterval = 20 * time.Second 26 shortWaitTimeout = 5 * time.Minute 27 shortPollingInterval = 10 * time.Second 28 imagePullWaitTimeout = 30 * time.Minute 29 imagePullPollingInterval = 30 * time.Second 30 ) 31 32 var ( 33 t = framework.NewTestFramework("weblogic-logging") 34 generatedNamespace = pkg.GenerateNamespace("weblogic-logging") 35 36 failed = false 37 beforeSuitePassed = false 38 39 expectedPods = []string{"weblogicloggingdomain-adminserver"} 40 ) 41 42 var _ = t.AfterEach(func() { 43 failed = failed || CurrentSpecReport().Failed() 44 }) 45 46 // Create all of the resources to deploy the application and wait for the pods to run 47 var beforeSuite = t.BeforeSuiteFunc(func() { 48 start := time.Now() 49 50 t.Logs.Info("Deploy WebLogic logging application") 51 wlsUser := "weblogic" 52 wlsPass := pkg.GetRequiredEnvVarOrFail("WEBLOGIC_PSW") 53 regServ := pkg.GetRequiredEnvVarOrFail("OCR_REPO") 54 regUser := pkg.GetRequiredEnvVarOrFail("OCR_CREDS_USR") 55 regPass := pkg.GetRequiredEnvVarOrFail("OCR_CREDS_PSW") 56 57 t.Logs.Info("Create namespace") 58 Eventually(func() (*v1.Namespace, error) { 59 nsLabels := map[string]string{ 60 "verrazzano-managed": "true", 61 "istio-injection": istioInjection} 62 return pkg.CreateNamespace(namespace, nsLabels) 63 }, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil()) 64 65 t.Logs.Info("Create repository secret") 66 Eventually(func() (*v1.Secret, error) { 67 return pkg.CreateDockerSecret(namespace, "weblogicloggingdomain-repo-credentials", regServ, regUser, regPass) 68 }, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil()) 69 70 t.Logs.Info("Create WebLogic credentials secret") 71 Eventually(func() (*v1.Secret, error) { 72 return pkg.CreateCredentialsSecret(namespace, "weblogicloggingdomain-weblogic-credentials", wlsUser, wlsPass, nil) 73 }, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil()) 74 75 t.Logs.Info("Create persistent volume claim") 76 Eventually(func() error { 77 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/pvc.yaml") 78 if err != nil { 79 return err 80 } 81 return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace) 82 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 83 84 t.Logs.Info("Create component resources") 85 Eventually(func() error { 86 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/weblogic-logging-comp.yaml") 87 if err != nil { 88 return err 89 } 90 return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace) 91 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 92 93 t.Logs.Info("Create application resources") 94 Eventually(func() error { 95 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/weblogic-logging-app.yaml") 96 if err != nil { 97 return err 98 } 99 return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace) 100 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 101 102 t.Logs.Info("Wait for image pulls") 103 Eventually(func() bool { 104 return pkg.ContainerImagePullWait(namespace, expectedPods) 105 }, imagePullWaitTimeout, imagePullPollingInterval).Should(BeTrue()) 106 107 t.Logs.Info("Wait for running pods") 108 Eventually(func() bool { 109 result, err := pkg.PodsRunning(namespace, expectedPods) 110 if err != nil { 111 AbortSuite(fmt.Sprintf("One or more pods are not running in namespace: %v, error: %v", namespace, err)) 112 } 113 return result 114 }, longWaitTimeout, longPollingInterval).Should(BeTrue()) 115 116 beforeSuitePassed = true 117 metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds())) 118 }) 119 120 var _ = BeforeSuite(beforeSuite) 121 122 // Delete all of the resources to undeploy the application 123 var afterSuite = t.AfterSuiteFunc(func() { 124 if failed || !beforeSuitePassed { 125 dump.ExecuteBugReport(namespace) 126 } 127 start := time.Now() 128 129 t.Logs.Info("Delete component resources") 130 Eventually(func() error { 131 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/weblogic-logging-app.yaml") 132 if err != nil { 133 return err 134 } 135 return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace) 136 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 137 138 t.Logs.Info("Delete application resources") 139 Eventually(func() error { 140 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/weblogic-logging-comp.yaml") 141 if err != nil { 142 return err 143 } 144 return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace) 145 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 146 147 t.Logs.Info("Wait for application pods to terminate") 148 Eventually(func() bool { 149 podsTerminated, _ := pkg.PodsNotRunning(namespace, expectedPods) 150 return podsTerminated 151 }, shortWaitTimeout, shortPollingInterval).Should(BeTrue()) 152 153 t.Logs.Info("Delete persistent volume claim") 154 Eventually(func() error { 155 file, err := pkg.FindTestDataFile("testdata/logging/weblogic/pvc.yaml") 156 if err != nil { 157 return err 158 } 159 return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace) 160 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 161 162 t.Logs.Info("Delete namespace") 163 Eventually(func() error { 164 return pkg.DeleteNamespace(namespace) 165 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 166 167 t.Logs.Info("Wait for namespace to be deleted") 168 Eventually(func() bool { 169 _, err := pkg.GetNamespace(namespace) 170 return err != nil && errors.IsNotFound(err) 171 }, shortWaitTimeout, shortPollingInterval).Should(BeTrue()) 172 173 metrics.Emit(t.Metrics.With("undeployment_elapsed_time", time.Since(start).Milliseconds())) 174 }) 175 176 var _ = AfterSuite(afterSuite) 177 178 var _ = t.Describe("WebLogic logging test", Label("f:app-lcm.oam", "f:app-lcm.weblogic-workload"), func() { 179 180 t.Context("WebLogic domain is configured properly.", func() { 181 // GIVEN the WebLogic domain resource has been created by the Verrazzano Application Operator 182 // WHEN we fetch the domain 183 // THEN the logHome in the spec has not been overwritten with a /scratch directory 184 t.It("logHome has not been overwritten", func() { 185 domain, err := pkgweblogic.GetDomain(namespace, "weblogic-logging-domain") 186 Expect(domain, err).ShouldNot(BeNil()) 187 188 logHome, _, err := unstructured.NestedString(domain.Object, "spec", "logHome") 189 Expect(logHome, err).To(Equal("/mnt/shared/logs")) 190 }) 191 }) 192 193 t.Context("Logging.", Label("f:observability.logging.es"), func() { 194 var indexName string 195 var err error 196 Eventually(func() error { 197 indexName, err = pkg.GetOpenSearchAppIndex(namespace) 198 return err 199 }, shortWaitTimeout, shortPollingInterval).Should(BeNil(), "Expected to get OpenSearch App Index") 200 201 // GIVEN a WebLogic application with logging enabled 202 // WHEN the Opensearch index is retrieved 203 // THEN verify that it is found 204 t.It("Verify Opensearch index exists", func() { 205 Eventually(func() bool { 206 return pkg.LogIndexFound(indexName) 207 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find log index") 208 }) 209 210 // GIVEN a WebLogic application with logging enabled 211 // WHEN the log records are retrieved from the Opensearch index 212 // THEN verify that at least one recent log record is found 213 const k8sContainerNameKeyword = "kubernetes.container_name.keyword" 214 const fluentdStdoutSidecarName = "fluentd-stdout-sidecar" 215 216 pkg.Concurrently( 217 func() { 218 t.It("Verify recent adminserver log record exists", func() { 219 Eventually(func() bool { 220 return pkg.LogRecordFound(indexName, time.Now().Add(-24*time.Hour), map[string]string{ 221 "kubernetes.labels.weblogic_domainUID": "weblogicloggingdomain", 222 "kubernetes.labels.app_oam_dev\\/name": "weblogicloggingdomain-appconf", 223 "kubernetes.labels.weblogic_serverName": "AdminServer", 224 "kubernetes.container_name": "weblogic-server", 225 }) 226 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent adminserver log record") 227 }) 228 }, 229 func() { 230 t.It("Verify recent pattern-matched AdminServer log record exists", func() { 231 Eventually(func() bool { 232 return pkg.FindLog(indexName, 233 []pkg.Match{ 234 {Key: k8sContainerNameKeyword, Value: fluentdStdoutSidecarName}, 235 {Key: "messageID", Value: "BEA-"}, 236 {Key: "serverName", Value: "weblogicloggingdomain-adminserver"}, 237 {Key: "serverName2", Value: "AdminServer"}}, 238 []pkg.Match{}) 239 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent pattern-matched adminserver log record") 240 }) 241 }, 242 func() { 243 t.It("Verify recent pattern-matched WebLogic Server log record exists", func() { 244 Eventually(func() bool { 245 return pkg.FindLog(indexName, 246 []pkg.Match{ 247 {Key: k8sContainerNameKeyword, Value: fluentdStdoutSidecarName}, 248 {Key: "messageID", Value: "BEA-"}, 249 {Key: "message", Value: "WebLogic Server"}, 250 {Key: "subSystem", Value: "WebLogicServer"}}, 251 []pkg.Match{}) 252 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent pattern-matched WebLogic Server log record") 253 }) 254 }, 255 func() { 256 t.It("Verify recent fluentd-stdout-sidecar server log record exists", func() { 257 Eventually(func() bool { 258 return pkg.FindLog(indexName, 259 []pkg.Match{ 260 {Key: k8sContainerNameKeyword, Value: fluentdStdoutSidecarName}, 261 {Key: "wls_log_stream", Value: "server_log"}, 262 {Key: "stream", Value: "stdout"}}, 263 []pkg.Match{}) 264 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent fluentd-stdout-sidecar server log record") 265 }) 266 }, 267 func() { 268 t.It("Verify recent fluentd-stdout-sidecar domain log record exists", func() { 269 Eventually(func() bool { 270 return pkg.FindLog(indexName, 271 []pkg.Match{ 272 {Key: k8sContainerNameKeyword, Value: fluentdStdoutSidecarName}, 273 {Key: "wls_log_stream", Value: "domain_log"}, 274 {Key: "stream", Value: "stdout"}}, 275 []pkg.Match{}) 276 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent fluentd-stdout-sidecar domain log record") 277 }) 278 }, 279 func() { 280 t.It("Verify recent fluentd-stdout-sidecar nodemanager log record exists", func() { 281 Eventually(func() bool { 282 return pkg.FindLog(indexName, 283 []pkg.Match{ 284 {Key: "kubernetes.container_name.keyword", Value: fluentdStdoutSidecarName}, 285 {Key: "wls_log_stream", Value: "server_nodemanager_log"}, 286 {Key: "stream", Value: "stdout"}}, 287 []pkg.Match{}) 288 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent server fluentd-stdout-sidecar nodemanager log record") 289 }) 290 }, 291 ) 292 }) 293 })