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  }