github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/multicluster/examples/sock-shop/sock_shop_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 sock_shop
     5  
     6  import (
     7  	"fmt"
     8  	dump "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/clusterdump"
     9  	"os"
    10  	"strconv"
    11  	"time"
    12  
    13  	"github.com/verrazzano/verrazzano/pkg/k8s/resource"
    14  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework"
    15  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework/metrics"
    16  
    17  	. "github.com/onsi/ginkgo/v2"
    18  	. "github.com/onsi/gomega"
    19  	"github.com/verrazzano/verrazzano/tests/e2e/pkg"
    20  )
    21  
    22  const (
    23  	longPollingInterval  = 20 * time.Second
    24  	longWaitTimeout      = 10 * time.Minute
    25  	pollingInterval      = 5 * time.Second
    26  	waitTimeout          = 5 * time.Minute
    27  	consistentlyDuration = 1 * time.Minute
    28  	sourceDir            = "sock-shop"
    29  	testNamespace        = "mc-sockshop"
    30  	testProjectName      = "sockshop"
    31  	testCluster          = "SockShop"
    32  	testApp              = "carts-coh"
    33  )
    34  
    35  var clusterName = os.Getenv("MANAGED_CLUSTER_NAME")
    36  var adminKubeconfig = os.Getenv("ADMIN_KUBECONFIG")
    37  var managedKubeconfig = os.Getenv("MANAGED_KUBECONFIG")
    38  var metricsTest pkg.MetricsTest
    39  
    40  // failed indicates whether any of the tests has failed
    41  var failed = false
    42  var beforeSuitePassed = false
    43  
    44  var t = framework.NewTestFramework("sock_shop")
    45  
    46  var _ = t.AfterEach(func() {
    47  	// set failed to true if any of the tests has failed
    48  	failed = failed || CurrentSpecReport().Failed()
    49  })
    50  
    51  // set the kubeconfig to use the admin cluster kubeconfig and deploy the example resources
    52  var beforeSuite = t.BeforeSuiteFunc(func() {
    53  	// deploy the VerrazzanoProject
    54  	start := time.Now()
    55  	Eventually(func() error {
    56  		return DeploySockShopProject(adminKubeconfig, sourceDir)
    57  	}, waitTimeout, pollingInterval).ShouldNot(HaveOccurred())
    58  
    59  	// wait for the namespace to be created on the cluster before deploying app
    60  	Eventually(func() bool {
    61  		return SockShopNamespaceExists(adminKubeconfig, testNamespace)
    62  	}, waitTimeout, pollingInterval).Should(BeTrue())
    63  
    64  	Eventually(func() error {
    65  		return DeploySockShopApp(adminKubeconfig, sourceDir)
    66  	}, waitTimeout, pollingInterval).ShouldNot(HaveOccurred())
    67  
    68  	var err error
    69  	metricsTest, err = pkg.NewMetricsTest(adminKubeconfig, map[string]string{}, managedKubeconfig)
    70  	if err != nil {
    71  		AbortSuite(fmt.Sprintf("Failed to create the Metrics test object: %v", err))
    72  	}
    73  
    74  	beforeSuitePassed = true
    75  	metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds()))
    76  })
    77  
    78  var _ = BeforeSuite(beforeSuite)
    79  
    80  var _ = t.Describe("In Multi-cluster, verify sock-shop", Label("f:multicluster.mc-app-lcm"), func() {
    81  	t.Context("Admin Cluster", func() {
    82  		// GIVEN an admin cluster and at least one managed cluster
    83  		// WHEN the example application has been deployed to the admin cluster
    84  		// THEN expect that the multi-cluster resources have been created on the admin cluster
    85  		t.It("Has multi cluster resources", func() {
    86  			Eventually(func() bool {
    87  				return VerifyMCResources(adminKubeconfig, true, false, testNamespace)
    88  			}, waitTimeout, pollingInterval).Should(BeTrue())
    89  		})
    90  		// GIVEN an admin cluster
    91  		// WHEN the multi-cluster example application has been created on admin cluster but not placed there
    92  		// THEN expect that the app is not deployed to the admin cluster consistently for some length of time
    93  		t.It("Does not have application placed", func() {
    94  			Consistently(func() bool {
    95  				result, err := VerifySockShopInCluster(adminKubeconfig, true, false, testProjectName, testNamespace)
    96  				if err != nil {
    97  					AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err))
    98  				}
    99  				return result
   100  			}, consistentlyDuration, pollingInterval).Should(BeTrue())
   101  		})
   102  	})
   103  
   104  	t.Context("Managed Cluster", func() {
   105  		// GIVEN an admin cluster and at least one managed cluster
   106  		// WHEN the example application has been deployed to the admin cluster
   107  		// THEN expect that the multi-cluster resources have been created on the managed cluster
   108  		t.It("Has multi cluster resources", func() {
   109  			Eventually(func() bool {
   110  				return VerifyMCResources(managedKubeconfig, false, true, testNamespace)
   111  			}, waitTimeout, pollingInterval).Should(BeTrue())
   112  		})
   113  		// GIVEN an admin cluster and at least one managed cluster
   114  		// WHEN the multi-cluster example application has been created on admin cluster and placed in managed cluster
   115  		// THEN expect that the app is deployed to the managed cluster
   116  		t.It("Has application placed", func() {
   117  			Eventually(func() bool {
   118  				result, err := VerifySockShopInCluster(managedKubeconfig, false, true, testProjectName, testNamespace)
   119  				if err != nil {
   120  					AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err))
   121  				}
   122  				return result
   123  			}, waitTimeout, pollingInterval).Should(BeTrue())
   124  		})
   125  	})
   126  
   127  	t.Context("Remaining Managed Clusters", func() {
   128  		clusterCountStr := os.Getenv("CLUSTER_COUNT")
   129  		if clusterCountStr == "" {
   130  			// skip tests
   131  			return
   132  		}
   133  		clusterCount, err := strconv.Atoi(clusterCountStr)
   134  		if err != nil {
   135  			// skip tests
   136  			return
   137  		}
   138  
   139  		kubeconfigDir := os.Getenv("KUBECONFIG_DIR")
   140  		for i := 3; i <= clusterCount; i++ {
   141  			kubeconfig := kubeconfigDir + "/" + fmt.Sprintf("%d", i) + "/kube_config"
   142  			t.It("Does not have multi cluster resources", func() {
   143  				Eventually(func() bool {
   144  					return VerifyMCResources(kubeconfig, false, false, testNamespace)
   145  				}, waitTimeout, pollingInterval).Should(BeTrue())
   146  			})
   147  			t.It("Does not have application placed", func() {
   148  				Eventually(func() bool {
   149  					result, err := VerifySockShopInCluster(kubeconfig, false, false, testProjectName, testNamespace)
   150  					if err != nil {
   151  						AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", testNamespace, err))
   152  					}
   153  					return result
   154  				}, waitTimeout, pollingInterval).Should(BeTrue())
   155  			})
   156  		}
   157  	})
   158  
   159  	t.Context("for Logging", Label("f:observability.logging.es"), func() {
   160  		indexName, err := pkg.GetOpenSearchAppIndexWithKC(testNamespace, adminKubeconfig)
   161  		Expect(err).To(BeNil())
   162  		// GIVEN an admin cluster and at least one managed cluster
   163  		// WHEN the example application has been deployed to the admin cluster
   164  		// THEN expect the Opensearch index for the app exists on the admin cluster Opensearch
   165  		t.It("Verify Opensearch index exists on admin cluster", func() {
   166  			Eventually(func() bool {
   167  				return pkg.LogIndexFoundInCluster(indexName, adminKubeconfig)
   168  			}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find log index for sock-shop")
   169  		})
   170  	})
   171  
   172  	// GIVEN an admin cluster and at least one managed cluster
   173  	// WHEN the example application has been deployed to the admin cluster
   174  	// THEN expect Prometheus metrics for the app to exist in Prometheus on the admin cluster
   175  	t.Context("for Prometheus Metrics", Label("f:observability.monitoring.prom"), func() {
   176  
   177  		// Coherence metric fix available only from 1.3.0
   178  		if ok, _ := pkg.IsVerrazzanoMinVersion("1.3.0", adminKubeconfig); ok {
   179  			t.It("Verify base_jvm_uptime_seconds metrics exist for managed cluster", func() {
   180  				clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig)
   181  				Eventually(func() bool {
   182  					m := make(map[string]string)
   183  					m["app"] = testApp
   184  					m[clusterNameMetricsLabel] = clusterName
   185  					return metricsTest.MetricsExist("base_jvm_uptime_seconds", m)
   186  				}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find base_jvm_uptime_seconds metric")
   187  			})
   188  
   189  			t.It("Verify DNE base_jvm_uptime_seconds metrics does not exist for managed cluster", func() {
   190  				clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig)
   191  				Eventually(func() bool {
   192  					m := make(map[string]string)
   193  					m["app"] = testApp
   194  					m[clusterNameMetricsLabel] = "DNE"
   195  					return metricsTest.MetricsExist("base_jvm_uptime_seconds", m)
   196  				}, longWaitTimeout, longPollingInterval).Should(BeFalse(), "Not expected to find base_jvm_uptime_seconds metric")
   197  			})
   198  
   199  			t.It("Verify vendor_requests_count_total metrics exist for managed cluster", func() {
   200  				clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig)
   201  				Eventually(func() bool {
   202  					m := make(map[string]string)
   203  					m["app"] = testApp
   204  					m[clusterNameMetricsLabel] = clusterName
   205  					return metricsTest.MetricsExist("vendor_requests_count_total", m)
   206  				}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find vendor_requests_count_total metric")
   207  			})
   208  
   209  			t.It("Verify container_cpu_cfs_periods_total metrics exist for managed cluster", func() {
   210  				clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig)
   211  				Eventually(func() bool {
   212  					m := make(map[string]string)
   213  					m["namespace"] = testNamespace
   214  					m[clusterNameMetricsLabel] = clusterName
   215  					return metricsTest.MetricsExist("container_cpu_cfs_periods_total", m)
   216  				}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find container_cpu_cfs_periods_total metric")
   217  			})
   218  
   219  			t.It("Verify coherence metrics exist for managed cluster", func() {
   220  				clusterNameMetricsLabel, _ := pkg.GetClusterNameMetricLabel(adminKubeconfig)
   221  				Eventually(func() bool {
   222  					m := make(map[string]string)
   223  					m["cluster"] = testCluster
   224  					m[clusterNameMetricsLabel] = clusterName
   225  					return metricsTest.MetricsExist("vendor:coherence_service_messages_local", m)
   226  				}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find coherence metric")
   227  			})
   228  		}
   229  	})
   230  
   231  	t.Context("Delete resources", func() {
   232  		t.It("on admin cluster", func() {
   233  			Eventually(func() error {
   234  				return cleanUp(adminKubeconfig)
   235  			}, waitTimeout, pollingInterval).ShouldNot(HaveOccurred())
   236  		})
   237  
   238  		t.It("Verify deletion on admin cluster", func() {
   239  			Eventually(func() bool {
   240  				return VerifySockShopDeleteOnAdminCluster(adminKubeconfig, false, testNamespace, testProjectName)
   241  			}, waitTimeout, pollingInterval).Should(BeTrue())
   242  		})
   243  
   244  		t.It("Verify automatic deletion on managed cluster", func() {
   245  			Eventually(func() bool {
   246  				return VerifySockShopDeleteOnManagedCluster(managedKubeconfig, testNamespace, testProjectName)
   247  			}, waitTimeout, pollingInterval).Should(BeTrue())
   248  		})
   249  
   250  		t.It("Delete test namespace on managed cluster", func() {
   251  			Eventually(func() error {
   252  				return pkg.DeleteNamespaceInCluster(testNamespace, managedKubeconfig)
   253  			}, waitTimeout, pollingInterval).ShouldNot(HaveOccurred())
   254  		})
   255  
   256  		t.It("Delete test namespace on admin cluster", func() {
   257  			Eventually(func() error {
   258  				return pkg.DeleteNamespaceInCluster(testNamespace, adminKubeconfig)
   259  			}, waitTimeout, pollingInterval).ShouldNot(HaveOccurred())
   260  		})
   261  	})
   262  })
   263  
   264  var afterSuite = t.AfterSuiteFunc(func() {
   265  	if failed || !beforeSuitePassed {
   266  		err := dump.ExecuteBugReport(testNamespace)
   267  		if err != nil {
   268  			return
   269  		}
   270  	}
   271  })
   272  
   273  var _ = AfterSuite(afterSuite)
   274  
   275  func cleanUp(kubeconfigPath string) error {
   276  	start := time.Now()
   277  	file, err := pkg.FindTestDataFile(fmt.Sprintf("examples/multicluster/%s/sock-shop-app.yaml", sourceDir))
   278  	if err != nil {
   279  		return err
   280  	}
   281  	if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil {
   282  		return fmt.Errorf("failed to delete multi-cluster sock-shop application resource: %v", err)
   283  	}
   284  
   285  	file, err = pkg.FindTestDataFile(fmt.Sprintf("examples/multicluster/%s/sock-shop-comp.yaml", sourceDir))
   286  	if err != nil {
   287  		return err
   288  	}
   289  	if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil {
   290  		return fmt.Errorf("failed to delete multi-cluster sock-shop component resources: %v", err)
   291  	}
   292  
   293  	file, err = pkg.FindTestDataFile(fmt.Sprintf("examples/multicluster/%s/verrazzano-project.yaml", sourceDir))
   294  	if err != nil {
   295  		return err
   296  	}
   297  	if err := resource.DeleteResourceFromFileInCluster(file, kubeconfigPath); err != nil {
   298  		return fmt.Errorf("failed to delete sock-shop project resource: %v", err)
   299  	}
   300  	metrics.Emit(t.Metrics.With("undeployment_elapsed_time", time.Since(start).Milliseconds()))
   301  	return nil
   302  }