github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/workloads/coherence/coherence_workload_test.go (about) 1 // Copyright (c) 2022, 2023, 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 coherence 5 6 import ( 7 "fmt" 8 "net/http" 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/pkg/k8sutil" 15 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 16 dump "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/clusterdump" 17 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 18 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework/metrics" 19 v1 "k8s.io/api/core/v1" 20 "k8s.io/apimachinery/pkg/api/errors" 21 ) 22 23 const ( 24 shortWaitTimeout = 10 * time.Minute 25 shortPollingInterval = 10 * time.Second 26 longWaitTimeout = 20 * time.Minute 27 longPollingInterval = 20 * time.Second 28 imagePullWaitTimeout = 40 * time.Minute 29 imagePullPollingInterval = 30 * time.Second 30 31 appConfiguration = "tests/testdata/test-applications/coherence/hello-coherence/hello-coherence-app.yaml" 32 compConfiguration = "tests/testdata/test-applications/coherence/hello-coherence/hello-coherence-comp.yaml" 33 34 appEndPoint = "catalogue" 35 expectedResponse = "A perfect example of a swivel chair trained calf" 36 skipVerifications = "Skip Verifications" 37 38 ingress = "hello-ingress-rule" 39 coherenceService = "hello-coh-http" 40 helloCreds = "hello-coh" 41 ) 42 43 var ( 44 t = framework.NewTestFramework("coherence") 45 generatedNamespace = pkg.GenerateNamespace("hello-coherence") 46 expectedPods = []string{"hello-coh-"} 47 host = "" 48 metricsTest pkg.MetricsTest 49 ) 50 51 var beforeSuite = t.BeforeSuiteFunc(func() { 52 if !skipDeploy { 53 start := time.Now() 54 deployCoherenceApp(namespace) 55 metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds())) 56 57 t.Logs.Info("Container image pull check") 58 Eventually(func() bool { 59 return pkg.ContainerImagePullWait(namespace, expectedPods) 60 }, imagePullWaitTimeout, imagePullPollingInterval).Should(BeTrue()) 61 } 62 if !skipVerify { 63 t.Logs.Info("Coherence Application: check expected pod is running") 64 Eventually(func() bool { 65 result, err := pkg.PodsRunning(namespace, expectedPods) 66 if err != nil { 67 AbortSuite(fmt.Sprintf("Coherence application pod is not running in the namespace: %v, error: %v", namespace, err)) 68 } 69 return result 70 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Coherence Application Failed to Deploy: Pods are not ready\"") 71 72 t.Logs.Info("Coherence Application: check expected Services are running") 73 Eventually(func() bool { 74 result, err := pkg.DoesServiceExist(namespace, coherenceService) 75 if err != nil { 76 AbortSuite(fmt.Sprintf("App Service %s is not running in the namespace: %v, error: %v", coherenceService, namespace, err)) 77 } 78 return result 79 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Coherence Application Failed to Deploy: Services are not ready") 80 81 t.Logs.Info("Coherence Application: check expected VirtualService is ready") 82 Eventually(func() bool { 83 result, err := pkg.DoesVirtualServiceExist(namespace, ingress) 84 if err != nil { 85 AbortSuite(fmt.Sprintf("App VirtualService %s is not running in the namespace: %v, error: %v", ingress, namespace, err)) 86 } 87 return result 88 }, shortWaitTimeout, longPollingInterval).Should(BeTrue(), "Coherence Application Failed to Deploy: VirtualService is not ready") 89 90 t.Logs.Info("Coherence Application: check expected Secret exists") 91 Eventually(func() bool { 92 result, err := pkg.DoesSecretExist(namespace, helloCreds) 93 if err != nil { 94 AbortSuite(fmt.Sprintf("App Secret %s does not exist in the namespace: %v, error: %v", helloCreds, namespace, err)) 95 } 96 return result 97 }, shortWaitTimeout, longPollingInterval).Should(BeTrue(), "Coherence Application Failed to Deploy: Secret does not exist") 98 99 var err error 100 // Get the host from the Istio gateway resource. 101 start := time.Now() 102 t.Logs.Info("Coherence Application: check expected Gateway is ready") 103 Eventually(func() (string, error) { 104 host, err = k8sutil.GetHostnameFromGateway(namespace, "") 105 return host, err 106 }, shortWaitTimeout, shortPollingInterval).Should(Not(BeEmpty()), "Coherence Application Failed to Deploy: Gateway is not ready") 107 metrics.Emit(t.Metrics.With("get_host_name_elapsed_time", time.Since(start).Milliseconds())) 108 } 109 110 kubeconfigPath, err := k8sutil.GetKubeConfigLocation() 111 if err != nil { 112 AbortSuite(fmt.Sprintf("Failed to find Kubeconfig location: %v", err)) 113 } 114 metricsTest, err = pkg.NewMetricsTest(kubeconfigPath, map[string]string{}) 115 if err != nil { 116 AbortSuite(fmt.Sprintf("Failed to create the Metrics test object: %v", err)) 117 } 118 119 beforeSuitePassed = true 120 }) 121 122 var _ = BeforeSuite(beforeSuite) 123 124 var failed = false 125 var beforeSuitePassed = false 126 var _ = t.AfterEach(func() { 127 failed = failed || CurrentSpecReport().Failed() 128 }) 129 130 var afterSuite = t.AfterSuiteFunc(func() { 131 if failed || !beforeSuitePassed { 132 dump.ExecuteBugReport(namespace) 133 } 134 if !skipUndeploy { 135 undeployCoherenceApp() 136 } 137 }) 138 139 var _ = AfterSuite(afterSuite) 140 141 var _ = t.Describe("Validate deployment of VerrazzanoCoherenceWorkload", Label("f:app-lcm.oam", "f:app-lcm.coherence-workload"), func() { 142 143 t.Context("Ingress", Label("f:mesh.ingress"), func() { 144 // Verify the application endpoints 145 t.It("Verify '/catalogue' UI endpoint is working", func() { 146 if skipVerify { 147 Skip(skipVerifications) 148 } 149 Eventually(func() (*pkg.HTTPResponse, error) { 150 url := fmt.Sprintf("https://%s/%s", host, appEndPoint) 151 return pkg.GetWebPage(url, host) 152 }, shortWaitTimeout, shortPollingInterval).Should(And(pkg.HasStatus(http.StatusOK), pkg.BodyContains(expectedResponse))) 153 }) 154 }) 155 156 t.Context("Logging.", Label("f:observability.logging.es"), func() { 157 var indexName string 158 var err error 159 Eventually(func() error { 160 indexName, err = pkg.GetOpenSearchAppIndex(namespace) 161 return err 162 }, shortWaitTimeout, shortPollingInterval).Should(BeNil(), "Expected to get OpenSearch App Index") 163 164 t.It("Verify Opensearch index exists", func() { 165 if skipVerify { 166 Skip(skipVerifications) 167 } 168 Eventually(func() bool { 169 return pkg.LogIndexFound(indexName) 170 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find Opensearch index for Coherence application.") 171 }) 172 173 t.It("Verify recent Opensearch log record exists", func() { 174 if skipVerify { 175 Skip(skipVerifications) 176 } 177 Eventually(func() bool { 178 return pkg.LogRecordFound(indexName, time.Now().Add(-24*time.Hour), map[string]string{ 179 "kubernetes.labels.app_oam_dev\\/component": "hello-coherence", 180 "kubernetes.labels.app_oam_dev\\/name": "hello-appconf", 181 "kubernetes.container_name": "hello-coherence", 182 }) 183 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record.") 184 }) 185 186 t.It("Verify Coherence log records", func() { 187 if skipVerify { 188 Skip(skipVerifications) 189 } 190 Eventually(func() bool { 191 return pkg.LogRecordFound(indexName, time.Now().Add(-24*time.Hour), map[string]string{ 192 "kubernetes.labels.coherenceCluster": "HelloCoherence", 193 "kubernetes.labels.app_oam_dev\\/component.keyword": "hello-coherence", 194 "kubernetes.pod_name": "hello-coh-0", 195 "kubernetes.container_name.keyword": "coherence", 196 }) 197 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record.") 198 }) 199 }) 200 201 t.Context("Metrics", Label("f:observability.monitoring.prom"), func() { 202 // Verify Coherence metrics 203 t.It("Retrieve Coherence metrics", func() { 204 if skipVerify { 205 Skip(skipVerifications) 206 } 207 kubeConfig, err := k8sutil.GetKubeConfigLocation() 208 if err != nil { 209 Expect(err).To(BeNil(), fmt.Sprintf("Failed to get default kubeconfig path: %s", err.Error())) 210 } 211 // Coherence metric fix available only from 1.3.0 212 if ok, _ := pkg.IsVerrazzanoMinVersion("1.3.0", kubeConfig); ok { 213 Eventually(func() bool { 214 return metricsTest.MetricsExist("vendor:coherence_service_messages_local", map[string]string{"role": "HelloCoherenceRole"}) 215 }, longWaitTimeout, longPollingInterval).Should(BeTrue()) 216 } 217 }) 218 219 t.It("Retrieve application metrics", func() { 220 if skipVerify { 221 Skip(skipVerifications) 222 } 223 pkg.Concurrently( 224 func() { 225 Eventually(func() bool { 226 return metricsTest.MetricsExist("base_jvm_uptime_seconds", map[string]string{"app_oam_dev_name": "hello-appconf"}) 227 }, longWaitTimeout, longPollingInterval).Should(BeTrue()) 228 }, 229 func() { 230 Eventually(func() bool { 231 return metricsTest.MetricsExist("vendor_requests_count_total", map[string]string{"app_oam_dev_name": "hello-appconf"}) 232 }, longWaitTimeout, longPollingInterval).Should(BeTrue()) 233 }, 234 ) 235 }) 236 }) 237 }) 238 239 func deployCoherenceApp(namespace string) { 240 t.Logs.Info("Deploy Coherence application") 241 242 t.Logs.Info("Create namespace") 243 Eventually(func() (*v1.Namespace, error) { 244 nsLabels := map[string]string{ 245 "verrazzano-managed": "true"} 246 return pkg.CreateNamespace(namespace, nsLabels) 247 }, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil()) 248 249 t.Logs.Info("Create component resources") 250 Eventually(func() error { 251 file, err := pkg.FindTestDataFile(compConfiguration) 252 if err != nil { 253 return err 254 } 255 return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace) 256 }, shortWaitTimeout, shortPollingInterval, "Failed to create component resources for Coherence application").ShouldNot(HaveOccurred()) 257 258 t.Logs.Info("Create application resources") 259 Eventually(func() error { 260 file, err := pkg.FindTestDataFile(appConfiguration) 261 if err != nil { 262 return err 263 } 264 return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace) 265 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 266 } 267 268 func undeployCoherenceApp() { 269 t.Logs.Info("Undeploy Coherence application") 270 t.Logs.Info("Delete application") 271 start := time.Now() 272 Eventually(func() error { 273 file, err := pkg.FindTestDataFile(appConfiguration) 274 if err != nil { 275 return err 276 } 277 return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace) 278 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 279 280 t.Logs.Info("Delete component") 281 Eventually(func() error { 282 file, err := pkg.FindTestDataFile(compConfiguration) 283 if err != nil { 284 return err 285 } 286 return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace) 287 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 288 289 t.Logs.Info("Wait for pod to terminate") 290 Eventually(func() bool { 291 podsTerminated, _ := pkg.PodsNotRunning(namespace, expectedPods) 292 return podsTerminated 293 }, shortWaitTimeout, shortPollingInterval).Should(BeTrue()) 294 295 t.Logs.Info("Delete namespace") 296 Eventually(func() error { 297 return pkg.DeleteNamespace(namespace) 298 }, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred()) 299 300 t.Logs.Info("Wait for namespace finalizer to be removed") 301 Eventually(func() bool { 302 return pkg.CheckNamespaceFinalizerRemoved(namespace) 303 }, shortWaitTimeout, shortPollingInterval).Should(BeTrue()) 304 305 t.Logs.Info("Wait for namespace deletion") 306 Eventually(func() bool { 307 _, err := pkg.GetNamespace(namespace) 308 return err != nil && errors.IsNotFound(err) 309 }, shortWaitTimeout, shortPollingInterval).Should(BeTrue()) 310 311 metrics.Emit(t.Metrics.With("undeployment_elapsed_time", time.Since(start).Milliseconds())) 312 }