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  }