github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/multicluster/examples/helidon-deprecated/helidon_example_test.go (about) 1 // Copyright (c) 2021, 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 mchelidon 5 6 import ( 7 "fmt" 8 "os" 9 "strconv" 10 "time" 11 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 "github.com/verrazzano/verrazzano/pkg/k8s/resource" 15 "github.com/verrazzano/verrazzano/pkg/k8sutil" 16 "github.com/verrazzano/verrazzano/tests/e2e/multicluster/examples" 17 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 18 dump "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/clusterdump" 19 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 20 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework/metrics" 21 ) 22 23 const ( 24 longPollingInterval = 20 * time.Second 25 longWaitTimeout = 20 * time.Minute 26 pollingInterval = 5 * time.Second 27 waitTimeout = 5 * time.Minute 28 consistentlyDuration = 1 * time.Minute 29 projectfile = "tests/e2e/multicluster/examples/helidon-deprecated/testdata/verrazzano-project.yaml" 30 compFile = "tests/e2e/multicluster/examples/helidon-deprecated/testdata/mc-hello-helidon-comp.yaml" 31 appFile = "tests/e2e/multicluster/examples/helidon-deprecated/testdata/mc-hello-helidon-app.yaml" 32 changePlacementToAdminFile = "tests/e2e/multicluster/examples/helidon-deprecated/testdata/patch-change-placement-to-admin.yaml" 33 changePlacementToManagedFile = "tests/e2e/multicluster/examples/helidon-deprecated/testdata/patch-return-placement-to-managed1.yaml" 34 testNamespace = "hello-helidon-dep" 35 testProjectName = "hello-helidon-dep" 36 ) 37 38 var clusterName = os.Getenv("MANAGED_CLUSTER_NAME") 39 var adminKubeconfig = os.Getenv("ADMIN_KUBECONFIG") 40 var managedKubeconfig = os.Getenv("MANAGED_KUBECONFIG") 41 var metricsTest pkg.MetricsTest 42 43 // failed indicates whether any of the tests has failed 44 var failed = false 45 var beforeSuitePassed = false 46 47 var t = framework.NewTestFramework("mchelidon") 48 49 var _ = t.AfterEach(func() { 50 // set failed to true if any of the tests has failed 51 failed = failed || CurrentSpecReport().Failed() 52 }) 53 54 // set the kubeconfig to use the admin cluster kubeconfig and deploy the example resources 55 var beforeSuite = t.BeforeSuiteFunc(func() { 56 // deploy the VerrazzanoProject 57 start := time.Now() 58 Eventually(func() error { 59 file, err := pkg.FindTestDataFile(projectfile) 60 if err != nil { 61 return err 62 } 63 return resource.CreateOrUpdateResourceFromFileInCluster(file, adminKubeconfig) 64 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 65 66 // wait for the namespace to be created on the cluster before deploying app 67 Eventually(func() bool { 68 return examples.HelidonNamespaceExists(adminKubeconfig, testNamespace) 69 }, waitTimeout, pollingInterval).Should(BeTrue()) 70 71 // deploy the multicluster components 72 Eventually(func() error { 73 file, err := pkg.FindTestDataFile(compFile) 74 if err != nil { 75 return err 76 } 77 return resource.CreateOrUpdateResourceFromFileInCluster(file, adminKubeconfig) 78 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 79 80 // deploy the multicluster app 81 Eventually(func() error { 82 file, err := pkg.FindTestDataFile(appFile) 83 if err != nil { 84 return err 85 } 86 return resource.CreateOrUpdateResourceFromFileInCluster(file, adminKubeconfig) 87 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 88 89 var err error 90 metricsTest, err = pkg.NewMetricsTest(adminKubeconfig, map[string]string{}, managedKubeconfig) 91 if err != nil { 92 AbortSuite(fmt.Sprintf("Failed to create the Metrics test object: %v", err)) 93 } 94 95 beforeSuitePassed = true 96 metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds())) 97 }) 98 99 var _ = BeforeSuite(beforeSuite) 100 101 var _ = t.AfterEach(func() {}) 102 103 var _ = t.Describe("Multi-cluster verify hello-helidon", func() { 104 t.BeforeEach(func() { 105 Expect(os.Setenv(k8sutil.EnvVarTestKubeConfig, adminKubeconfig)).To(BeNil()) 106 }) 107 t.Context("Admin Cluster", func() { 108 // GIVEN an admin cluster and at least one managed cluster 109 // WHEN the example application has been deployed to the admin cluster 110 // THEN expect that the multi-cluster resources have been created on the admin cluster 111 t.It("Has multi cluster resources", func() { 112 Eventually(func() bool { 113 return examples.VerifyMCResourcesV100(adminKubeconfig, true, false, testNamespace) 114 }, waitTimeout, pollingInterval).Should(BeTrue()) 115 }) 116 // GIVEN an admin cluster 117 // WHEN the multi-cluster example application has been created on admin cluster but not placed there 118 // THEN expect that the app is not deployed to the admin cluster consistently for some length of time 119 t.It("Does not have application placed", func() { 120 Consistently(func() bool { 121 result, err := examples.VerifyHelloHelidonInCluster(adminKubeconfig, true, false, testProjectName, testNamespace) 122 if err != nil { 123 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 124 } 125 return result 126 }, consistentlyDuration, pollingInterval).Should(BeTrue()) 127 }) 128 }) 129 130 t.Context("Managed Cluster", func() { 131 // GIVEN an admin cluster and at least one managed cluster 132 // WHEN the example application has been deployed to the admin cluster 133 // THEN expect that the multi-cluster resources have been created on the managed cluster 134 t.It("Has multi cluster resources", func() { 135 Eventually(func() bool { 136 return examples.VerifyMCResourcesV100(managedKubeconfig, false, true, testNamespace) 137 }, waitTimeout, pollingInterval).Should(BeTrue()) 138 }) 139 // GIVEN an admin cluster and at least one managed cluster 140 // WHEN the multi-cluster example application has been created on admin cluster and placed in managed cluster 141 // THEN expect that the app is deployed to the managed cluster 142 t.It("Has application placed", func() { 143 Eventually(func() bool { 144 result, err := examples.VerifyHelloHelidonInCluster(managedKubeconfig, false, true, testProjectName, testNamespace) 145 if err != nil { 146 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 147 } 148 return result 149 }, waitTimeout, pollingInterval).Should(BeTrue()) 150 }) 151 }) 152 153 t.Context("Remaining Managed Clusters", func() { 154 clusterCountStr := os.Getenv("CLUSTER_COUNT") 155 if clusterCountStr == "" { 156 // skip tests 157 return 158 } 159 clusterCount, err := strconv.Atoi(clusterCountStr) 160 if err != nil { 161 // skip tests 162 return 163 } 164 165 kubeconfigDir := os.Getenv("KUBECONFIG_DIR") 166 for i := 3; i <= clusterCount; i++ { 167 kubeconfig := kubeconfigDir + "/" + fmt.Sprintf("%d", i) + "/kube_config" 168 t.It("Does not have multi cluster resources", func() { 169 Eventually(func() bool { 170 return examples.VerifyMCResourcesV100(kubeconfig, false, false, testNamespace) 171 }, waitTimeout, pollingInterval).Should(BeTrue()) 172 }) 173 t.It("Does not have application placed", func() { 174 Eventually(func() bool { 175 result, err := examples.VerifyHelloHelidonInCluster(kubeconfig, false, false, testProjectName, testNamespace) 176 if err != nil { 177 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 178 } 179 return result 180 }, waitTimeout, pollingInterval).Should(BeTrue()) 181 }) 182 } 183 }) 184 185 t.Context("Logging", func() { 186 indexName, err := pkg.GetOpenSearchAppIndexWithKC(testNamespace, adminKubeconfig) 187 Expect(err).To(BeNil()) 188 // GIVEN an admin cluster and at least one managed cluster 189 // WHEN the example application has been deployed to the admin cluster 190 // THEN expect the Elasticsearch index for the app exists on the admin cluster Elasticsearch 191 t.It("Verify Elasticsearch index exists on admin cluster", func() { 192 Eventually(func() bool { 193 return pkg.LogIndexFoundInCluster(indexName, adminKubeconfig) 194 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find log index for hello helidon") 195 }) 196 197 // GIVEN an admin cluster and at least one managed cluster 198 // WHEN the example application has been deployed to the admin cluster 199 // THEN expect recent Elasticsearch logs for the app exist on the admin cluster Elasticsearch 200 t.It("Verify recent Elasticsearch log record exists on admin cluster", func() { 201 Eventually(func() bool { 202 return pkg.LogRecordFoundInCluster(indexName, time.Now().Add(-24*time.Hour), map[string]string{ 203 "kubernetes.labels.app_oam_dev\\/component": "hello-helidon-component", 204 "kubernetes.labels.app_oam_dev\\/name": "hello-helidon", 205 "kubernetes.container_name": "hello-helidon-container", 206 }, adminKubeconfig) 207 }, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record") 208 }) 209 }) 210 211 // GIVEN an admin cluster and at least one managed cluster 212 // WHEN the example application has been deployed to the admin cluster 213 // THEN expect Prometheus metrics for the app to exist in Prometheus on the admin cluster 214 t.Context("Metrics", func() { 215 t.It("Verify Prometheus metrics exist on admin cluster", func() { 216 clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig) 217 Eventually(func() bool { 218 var m = map[string]string{clusterNameMetricsLabel: clusterName} 219 return metricsTest.MetricsExist("base_jvm_uptime_seconds", m) 220 }, longWaitTimeout, longPollingInterval).Should(BeTrue()) 221 }) 222 }) 223 224 t.Context("Change Placement of app to Admin Cluster", func() { 225 t.It("Apply patch to change placement to admin cluster", func() { 226 Eventually(func() error { 227 return examples.ChangePlacementV100(adminKubeconfig, changePlacementToAdminFile, testNamespace, testProjectName) 228 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 229 }) 230 231 t.It("MC Resources should be removed from managed cluster", func() { 232 Eventually(func() bool { 233 // app should not be placed in the managed cluster 234 return examples.VerifyMCResourcesV100(managedKubeconfig, false, false, testNamespace) 235 }, waitTimeout, pollingInterval).Should(BeTrue()) 236 }) 237 238 t.It("App should be removed from managed cluster", func() { 239 Eventually(func() bool { 240 // app should not be placed in the managed cluster 241 result, err := examples.VerifyHelloHelidonInCluster(managedKubeconfig, false, false, testProjectName, testNamespace) 242 if err != nil { 243 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 244 } 245 return result 246 }, waitTimeout, pollingInterval).Should(BeTrue()) 247 }) 248 249 t.It("App should be placed in admin cluster", func() { 250 Eventually(func() bool { 251 // app should be placed in the admin cluster 252 result, err := examples.VerifyHelloHelidonInCluster(adminKubeconfig, true, true, testProjectName, testProjectName) 253 if err != nil { 254 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 255 } 256 return result 257 }, waitTimeout, pollingInterval).Should(BeTrue()) 258 }) 259 }) 260 261 // Ensure that if we change placement again, back to the original managed cluster, everything functions 262 // as expected. This is needed because the change of placement to admin cluster and the change of placement to 263 // a managed cluster are different, and we want to ensure we test the case where the destination cluster is 264 // each of the 2 types - admin and managed 265 t.Context("Return the app to Managed Cluster", func() { 266 t.It("Apply patch to change placement back to managed cluster", func() { 267 Eventually(func() error { 268 return examples.ChangePlacementV100(adminKubeconfig, changePlacementToManagedFile, testNamespace, testProjectName) 269 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 270 }) 271 272 // GIVEN an admin cluster 273 // WHEN the multi-cluster example application has changed placement from admin back to managed cluster 274 // THEN expect that the app is not deployed to the admin cluster 275 t.It("Admin cluster does not have application placed", func() { 276 Eventually(func() bool { 277 result, err := examples.VerifyHelloHelidonInCluster(adminKubeconfig, true, false, testProjectName, testNamespace) 278 if err != nil { 279 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 280 } 281 return result 282 }, waitTimeout, pollingInterval).Should(BeTrue()) 283 }) 284 285 // GIVEN a managed cluster 286 // WHEN the multi-cluster example application has changed placement to this managed cluster 287 // THEN expect that the app is now deployed to the cluster 288 t.It("Managed cluster again has application placed", func() { 289 Eventually(func() bool { 290 result, err := examples.VerifyHelloHelidonInCluster(managedKubeconfig, false, true, testProjectName, testNamespace) 291 if err != nil { 292 AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err)) 293 } 294 return result 295 }, waitTimeout, pollingInterval).Should(BeTrue()) 296 }) 297 }) 298 299 t.Context("Delete resources", func() { 300 t.It("Delete resources on admin cluster", func() { 301 Eventually(func() error { 302 return cleanUp(adminKubeconfig) 303 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 304 }) 305 306 t.It("Verify deletion on admin cluster", func() { 307 Eventually(func() bool { 308 return examples.VerifyHelloHelidonDeletedAdminCluster(adminKubeconfig, false, testNamespace, testProjectName) 309 }, waitTimeout, pollingInterval).Should(BeTrue()) 310 }) 311 312 t.It("Verify automatic deletion on managed cluster", func() { 313 Eventually(func() bool { 314 return examples.VerifyHelloHelidonDeletedInManagedCluster(managedKubeconfig, testNamespace, testProjectName) 315 }, waitTimeout, pollingInterval).Should(BeTrue()) 316 }) 317 318 t.It("Delete test namespace on managed cluster", func() { 319 Eventually(func() error { 320 return pkg.DeleteNamespaceInCluster(testNamespace, managedKubeconfig) 321 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 322 }) 323 324 t.It("Delete test namespace on admin cluster", func() { 325 Eventually(func() error { 326 return pkg.DeleteNamespaceInCluster(testNamespace, adminKubeconfig) 327 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 328 }) 329 }) 330 }) 331 332 var afterSuite = t.AfterSuiteFunc(func() { 333 if failed || !beforeSuitePassed { 334 dump.ExecuteBugReport(testNamespace) 335 } 336 }) 337 338 var _ = AfterSuite(afterSuite) 339 340 func cleanUp(kubeconfigPath string) error { 341 start := time.Now() 342 file, err := pkg.FindTestDataFile(projectfile) 343 if err != nil { 344 return err 345 } 346 if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil { 347 return fmt.Errorf("failed to delete multi-cluster hello-helidon application resource: %v", err) 348 } 349 350 file, err = pkg.FindTestDataFile(compFile) 351 if err != nil { 352 return err 353 } 354 if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil { 355 return fmt.Errorf("failed to delete multi-cluster hello-helidon component resources: %v", err) 356 } 357 358 file, err = pkg.FindTestDataFile(appFile) 359 if err != nil { 360 return err 361 } 362 if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil { 363 return fmt.Errorf("failed to delete hello-helidon project resource: %v", err) 364 } 365 metrics.Emit(t.Metrics.With("undeployment_elapsed_time", time.Since(start).Milliseconds())) 366 return nil 367 }