github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/examples/todo/todo_list_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 todo
     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  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/weblogic"
    20  	v1 "k8s.io/api/core/v1"
    21  	"k8s.io/apimachinery/pkg/api/errors"
    22  )
    23  
    24  const (
    25  	shortWaitTimeout         = 10 * time.Minute
    26  	shortPollingInterval     = 10 * time.Second
    27  	longWaitTimeout          = 20 * time.Minute
    28  	longPollingInterval      = 20 * time.Second
    29  	imagePullWaitTimeout     = 40 * time.Minute
    30  	imagePullPollingInterval = 30 * time.Second
    31  
    32  	mysqlService = "mysql"
    33  	ingress      = "todo-domain-ingress"
    34  	repoCreds    = "tododomain-repo-credentials"
    35  )
    36  
    37  var (
    38  	t                  = framework.NewTestFramework("todo")
    39  	generatedNamespace = pkg.GenerateNamespace("todo-list")
    40  	clusterDump        = dump.NewClusterDumpWrapper(t, generatedNamespace)
    41  	expectedPods       = []string{"mysql",
    42  		"tododomain-adminserver"}
    43  	host        = ""
    44  	metricsTest pkg.MetricsTest
    45  )
    46  
    47  var beforeSuite = clusterDump.BeforeSuiteFunc(func() {
    48  	if !skipDeploy {
    49  		start := time.Now()
    50  		deployToDoListExample(namespace)
    51  		metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds()))
    52  	}
    53  
    54  	t.Logs.Info("Container image pull check")
    55  	Eventually(func() bool {
    56  		return pkg.ContainerImagePullWait(namespace, expectedPods)
    57  	}, imagePullWaitTimeout, imagePullPollingInterval).Should(BeTrue())
    58  
    59  	// GIVEN the ToDoList app is deployed
    60  	// WHEN the running pods are checked
    61  	// THEN the tododomain-adminserver and mysql pods should be found running
    62  	t.Logs.Info("Todo List Application: check expected pods are running")
    63  	Eventually(func() bool {
    64  		result, err := pkg.PodsRunning(namespace, expectedPods)
    65  		if err != nil {
    66  			AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", namespace, err))
    67  		}
    68  		return result
    69  	}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Todo List Application Failed to Deploy: Pods are not ready")
    70  
    71  	t.Logs.Info("Todo List Application: check expected Service is running")
    72  	Eventually(func() bool {
    73  		result, err := pkg.DoesServiceExist(namespace, mysqlService)
    74  		if err != nil {
    75  			AbortSuite(fmt.Sprintf("App Service %s is not running in the namespace: %v, error: %v", mysqlService, namespace, err))
    76  		}
    77  		return result
    78  	}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Todo List Application Failed to Deploy: Service is not ready")
    79  
    80  	t.Logs.Info("Todo List Application: check expected VirtualService is ready")
    81  	Eventually(func() bool {
    82  		result, err := pkg.DoesVirtualServiceExist(namespace, ingress)
    83  		if err != nil {
    84  			AbortSuite(fmt.Sprintf("App VirtualService %s is not running in the namespace: %v, error: %v", ingress, namespace, err))
    85  		}
    86  		return result
    87  	}, shortWaitTimeout, longPollingInterval).Should(BeTrue(), "Todo List Application Failed to Deploy: VirtualService is not ready")
    88  
    89  	t.Logs.Info("Todo List Application: check expected Secret exists")
    90  	Eventually(func() bool {
    91  		result, err := pkg.DoesSecretExist(namespace, repoCreds)
    92  		if err != nil {
    93  			AbortSuite(fmt.Sprintf("App Secret %s does not exist in the namespace: %v, error: %v", repoCreds, namespace, err))
    94  		}
    95  		return result
    96  	}, shortWaitTimeout, longPollingInterval).Should(BeTrue(), "Todo List Application Failed to Deploy: Secret does not exist")
    97  
    98  	var err error
    99  	// Get the host from the Istio gateway resource.
   100  	start := time.Now()
   101  	t.Logs.Info("Todo List Application: check expected Gateway is ready")
   102  	Eventually(func() (string, error) {
   103  		host, err = k8sutil.GetHostnameFromGateway(namespace, "")
   104  		return host, err
   105  	}, shortWaitTimeout, shortPollingInterval).Should(Not(BeEmpty()), "Todo List Application Failed to Deploy: Gateway is not ready")
   106  
   107  	kubeconfig, err := k8sutil.GetKubeConfigLocation()
   108  	if err != nil {
   109  		AbortSuite(fmt.Sprintf("Failed to get the Kubeconfig location for the cluster: %v", err))
   110  	}
   111  	metricsTest, err = pkg.NewMetricsTest(kubeconfig, map[string]string{})
   112  	if err != nil {
   113  		AbortSuite(fmt.Sprintf("Failed to create the Metrics test object: %v", err))
   114  	}
   115  
   116  	metrics.Emit(t.Metrics.With("get_host_name_elapsed_time", time.Since(start).Milliseconds()))
   117  
   118  })
   119  
   120  var _ = clusterDump.AfterEach(func() {})             // Dump cluster if spec fails
   121  var afterSuite = clusterDump.AfterSuiteFunc(func() { // Dump cluster if aftersuite fails
   122  	if !skipUndeploy {
   123  		undeployToDoListExample()
   124  	}
   125  })
   126  
   127  var _ = BeforeSuite(beforeSuite)
   128  var _ = AfterSuite(afterSuite)
   129  
   130  func deployToDoListExample(namespace string) {
   131  	t.Logs.Info("Deploy ToDoList example")
   132  	wlsUser := "weblogic"
   133  	wlsPass := pkg.GetRequiredEnvVarOrFail("WEBLOGIC_PSW")
   134  	dbPass := pkg.GetRequiredEnvVarOrFail("DATABASE_PSW")
   135  	regServ := pkg.GetRequiredEnvVarOrFail("OCR_REPO")
   136  	regUser := pkg.GetRequiredEnvVarOrFail("OCR_CREDS_USR")
   137  	regPass := pkg.GetRequiredEnvVarOrFail("OCR_CREDS_PSW")
   138  
   139  	t.Logs.Info("Create namespace")
   140  	start := time.Now()
   141  	Eventually(func() (*v1.Namespace, error) {
   142  		nsLabels := map[string]string{
   143  			"verrazzano-managed": "true",
   144  			"istio-injection":    istioInjection}
   145  		return pkg.CreateNamespace(namespace, nsLabels)
   146  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil())
   147  
   148  	t.Logs.Info("Create Docker repository secret")
   149  	Eventually(func() (*v1.Secret, error) {
   150  		return pkg.CreateDockerSecret(namespace, "tododomain-repo-credentials", regServ, regUser, regPass)
   151  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil())
   152  
   153  	t.Logs.Info("Create WebLogic credentials secret")
   154  	Eventually(func() (*v1.Secret, error) {
   155  		return pkg.CreateCredentialsSecret(namespace, "tododomain-weblogic-credentials", wlsUser, wlsPass, nil)
   156  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil())
   157  
   158  	t.Logs.Info("Create database credentials secret")
   159  	Eventually(func() (*v1.Secret, error) {
   160  		return pkg.CreateCredentialsSecret(namespace, "tododomain-jdbc-tododb", wlsUser, dbPass, map[string]string{"weblogic.domainUID": "tododomain"})
   161  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(BeNil())
   162  
   163  	t.Logs.Info("Create component resources")
   164  	Eventually(func() error {
   165  		file, err := pkg.FindTestDataFile("examples/todo-list/todo-list-components.yaml")
   166  		if err != nil {
   167  			return err
   168  		}
   169  		return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace)
   170  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred())
   171  
   172  	t.Logs.Info("Create application resources")
   173  	Eventually(func() error {
   174  		file, err := pkg.FindTestDataFile("examples/todo-list/todo-list-application.yaml")
   175  		if err != nil {
   176  			return err
   177  		}
   178  		return resource.CreateOrUpdateResourceFromFileInGeneratedNamespace(file, namespace)
   179  	}, shortWaitTimeout, shortPollingInterval, "Failed to create application resource").ShouldNot(HaveOccurred())
   180  	metrics.Emit(t.Metrics.With("deployment_elapsed_time", time.Since(start).Milliseconds()))
   181  }
   182  
   183  func undeployToDoListExample() {
   184  	t.Logs.Info("Undeploy ToDoList example")
   185  	t.Logs.Info("Delete application")
   186  	start := time.Now()
   187  	Eventually(func() error {
   188  		file, err := pkg.FindTestDataFile("examples/todo-list/todo-list-application.yaml")
   189  		if err != nil {
   190  			return err
   191  		}
   192  		return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace)
   193  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred(), "deleting todo-list-application")
   194  
   195  	t.Logs.Info("Delete components")
   196  	Eventually(func() error {
   197  		file, err := pkg.FindTestDataFile("examples/todo-list/todo-list-components.yaml")
   198  		if err != nil {
   199  			return err
   200  		}
   201  		return resource.DeleteResourceFromFileInGeneratedNamespace(file, namespace)
   202  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred(), "deleting todo-list-components")
   203  
   204  	t.Logs.Info("Wait for pods to terminate")
   205  	Eventually(func() bool {
   206  		podsNotRunning, _ := pkg.PodsNotRunning(namespace, []string{"mysql", "tododomain-adminserver"})
   207  		return podsNotRunning
   208  	}, shortWaitTimeout, shortPollingInterval).Should(BeTrue(), "pods deleted")
   209  
   210  	t.Logs.Info("Delete namespace")
   211  	Eventually(func() error {
   212  		return pkg.DeleteNamespace(namespace)
   213  	}, shortWaitTimeout, shortPollingInterval).ShouldNot(HaveOccurred(), "deleting namespace")
   214  
   215  	t.Logs.Info("Wait for finalizer to be removed")
   216  	Eventually(func() bool {
   217  		return pkg.CheckNamespaceFinalizerRemoved(namespace)
   218  	}, shortWaitTimeout, shortPollingInterval).Should(BeTrue(), "namespace finalizer deleted")
   219  
   220  	t.Logs.Info("Deleted namespace check")
   221  	Eventually(func() bool {
   222  		_, err := pkg.GetNamespace(namespace)
   223  		return err != nil && errors.IsNotFound(err)
   224  	}, shortWaitTimeout, shortPollingInterval).Should(BeTrue(), "namespace deleted")
   225  
   226  	// GIVEN the ToDoList app is undeployed
   227  	// WHEN the app config certificate generated to support secure gateways is fetched
   228  	// THEN the certificate should have been cleaned up
   229  	t.Logs.Info("Deleted certificate check")
   230  	Eventually(func() bool {
   231  		_, err := pkg.GetCertificate("istio-system", namespace+"-todo-domain-ingress-cert")
   232  		return err != nil && errors.IsNotFound(err)
   233  	}, shortWaitTimeout, shortPollingInterval).Should(BeTrue(), "ingress trait cert deleted")
   234  
   235  	// GIVEN the ToDoList app is undeployed
   236  	// WHEN the app config secret generated to support secure gateways is fetched
   237  	// THEN the secret should have been cleaned up
   238  	t.Logs.Info("Waiting for secret containing certificate to be deleted")
   239  	Eventually(func() bool {
   240  		_, err := pkg.GetSecret("istio-system", namespace+"-todo-domain-ingress-cert-secret")
   241  		if err != nil && errors.IsNotFound(err) {
   242  			t.Logs.Info("Secret deleted")
   243  			return true
   244  		}
   245  		if err != nil {
   246  			t.Logs.Errorf("Error attempting to get secret: %v", err)
   247  		}
   248  		return false
   249  	}, shortWaitTimeout, shortPollingInterval).Should(BeTrue(), "ingress trait cert secret deleted")
   250  	metrics.Emit(t.Metrics.With("undeployment_elapsed_time", time.Since(start).Milliseconds()))
   251  }
   252  
   253  var _ = t.AfterEach(func() {})
   254  
   255  var _ = t.Describe("ToDo List test", Label("f:app-lcm.oam",
   256  	"f:app-lcm.weblogic-workload"), func() {
   257  
   258  	t.Context("application Deployment.", func() {
   259  		// GIVEN the ToDoList app is deployed
   260  		// WHEN the app config secret generated to support secure gateways is fetched
   261  		// THEN the secret should exist
   262  		t.It("Verify cert secret for todo-list has been created", Label("f:cert-mgmt"), func() {
   263  			Eventually(func() (*v1.Secret, error) {
   264  				return pkg.GetSecret("istio-system", namespace+"-todo-domain-ingress-cert-secret")
   265  			}, longWaitTimeout, longPollingInterval).ShouldNot(BeNil())
   266  		})
   267  		// GIVEN the ToDoList app is deployed
   268  		// WHEN the servers in the WebLogic domain is ready
   269  		// THEN the domain.servers.status.health.overallHeath fields should be ok
   270  		t.It("Verify 'todo-domain' overall health is ok", func() {
   271  			Eventually(func() bool {
   272  				domain, err := weblogic.GetDomain(namespace, "todo-domain")
   273  				if err != nil {
   274  					t.Logs.Errorf("Error attempting to get domain: %v", err)
   275  					return false
   276  				}
   277  				healths, err := weblogic.GetHealthOfServers(domain)
   278  				if err != nil {
   279  					t.Logs.Errorf("Error attempting to get health of servers: %v", err)
   280  					return false
   281  				}
   282  
   283  				if healths[0] != weblogic.Healthy {
   284  					t.Logs.Errorf("server not healthy")
   285  					return false
   286  				}
   287  				return true
   288  			}, longWaitTimeout, longPollingInterval).Should(BeTrue())
   289  		})
   290  
   291  	})
   292  
   293  	t.Context("Ingress.", Label("f:mesh.ingress"), func() {
   294  		var host = ""
   295  		var err error
   296  		// Get the host from the Istio gateway resource.
   297  		// GIVEN the Istio gateway for the todo-list namespace
   298  		// WHEN GetHostnameFromGateway is called
   299  		// THEN return the host name found in the gateway.
   300  		t.BeforeEach(func() {
   301  			Eventually(func() (string, error) {
   302  				host, err = k8sutil.GetHostnameFromGateway(namespace, "")
   303  				return host, err
   304  			}, shortWaitTimeout, shortPollingInterval).Should(Not(BeEmpty()))
   305  		})
   306  
   307  		// Verify the application REST endpoint is working.
   308  		// GIVEN the ToDoList app is deployed
   309  		// WHEN the UI is accessed
   310  		// THEN the expected returned page should contain an expected value.
   311  		t.It("Verify '/todo' UI endpoint is working.", func() {
   312  			Eventually(func() (*pkg.HTTPResponse, error) {
   313  				url := fmt.Sprintf("https://%s/todo/", host)
   314  				return pkg.GetWebPage(url, host)
   315  			}, shortWaitTimeout, shortPollingInterval).Should(And(pkg.HasStatus(http.StatusOK), pkg.BodyContains("Derek")))
   316  		})
   317  
   318  		// Verify the application REST endpoint is working.
   319  		// GIVEN the ToDoList app is deployed
   320  		// WHEN the REST endpoint is accessed
   321  		// THEN the expected results should be returned
   322  		t.It("Verify '/todo/rest/items' REST endpoint is working.", func() {
   323  			task := fmt.Sprintf("test-task-%s", time.Now().Format("20060102150405.0000"))
   324  			Eventually(func() (*pkg.HTTPResponse, error) {
   325  				url := fmt.Sprintf("https://%s/todo/rest/items", host)
   326  				return pkg.GetWebPage(url, host)
   327  			}, shortWaitTimeout, shortPollingInterval).Should(And(pkg.HasStatus(http.StatusOK), pkg.BodyContains("[")))
   328  			Eventually(func() bool {
   329  				return putGetTodoTask(host, task)
   330  
   331  			}, shortWaitTimeout, shortPollingInterval).Should(BeTrue())
   332  		})
   333  	})
   334  
   335  	t.Context("Metrics.", Label("f:observability.monitoring.prom"), func() {
   336  		// Verify Prometheus scraped metrics
   337  		// GIVEN a deployed WebLogic application
   338  		// WHEN the application configuration uses a default metrics trait
   339  		// THEN confirm that metrics are being collected
   340  		t.It("Retrieve Prometheus scraped metrics", func() {
   341  			pkg.Concurrently(
   342  				func() {
   343  					Eventually(func() bool {
   344  						return metricsTest.MetricsExist("wls_jvm_process_cpu_load", map[string]string{"app_oam_dev_name": "todo-appconf"})
   345  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find metrics for todo-list")
   346  				},
   347  				func() {
   348  					Eventually(func() bool {
   349  						return metricsTest.MetricsExist("wls_scrape_mbeans_count_total", map[string]string{"app_oam_dev_name": "todo-appconf"})
   350  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find metrics for todo-list")
   351  				},
   352  			)
   353  		})
   354  	})
   355  
   356  	t.Context("Logging.", Label("f:observability.logging.es"), func() {
   357  		var indexName string
   358  		var err error
   359  		Eventually(func() error {
   360  			indexName, err = pkg.GetOpenSearchAppIndex(namespace)
   361  			return err
   362  		}, shortWaitTimeout, shortPollingInterval).Should(BeNil(), "Expected to get OpenSearch App Index")
   363  
   364  		// GIVEN a WebLogic application with logging enabled
   365  		// WHEN the Opensearch index is retrieved
   366  		// THEN verify that it is found
   367  		It("Verify Opensearch index exists", func() {
   368  			Eventually(func() bool {
   369  				return pkg.LogIndexFound(indexName)
   370  			}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find log index for todo-list")
   371  		})
   372  
   373  		// GIVEN a WebLogic application with logging enabled
   374  		// WHEN the log records are retrieved from the Opensearch index
   375  		// THEN verify that at least one recent log record is found
   376  		pkg.Concurrently(
   377  			func() {
   378  				t.It("Verify recent adminserver log record exists", func() {
   379  					Eventually(func() bool {
   380  						return pkg.LogRecordFound(indexName, time.Now().Add(-24*time.Hour), map[string]string{
   381  							"kubernetes.labels.weblogic_domainUID":  "tododomain",
   382  							"kubernetes.labels.app_oam_dev\\/name":  "todo-appconf",
   383  							"kubernetes.labels.weblogic_serverName": "AdminServer",
   384  							"kubernetes.container_name":             "weblogic-server",
   385  						})
   386  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   387  				})
   388  			},
   389  			func() {
   390  				t.It("Verify recent pattern-matched AdminServer log record exists", func() {
   391  					Eventually(func() bool {
   392  						return pkg.FindLog(indexName,
   393  							[]pkg.Match{
   394  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   395  								{Key: "messageID", Value: "BEA-"}, //matches BEA-*
   396  								{Key: "serverName", Value: "tododomain-adminserver"},
   397  								{Key: "serverName2", Value: "AdminServer"}},
   398  							[]pkg.Match{})
   399  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   400  				})
   401  			},
   402  			func() {
   403  				t.It("Verify recent pattern-matched WebLogic Server log record exists", func() {
   404  					Eventually(func() bool {
   405  						return pkg.FindLog(indexName,
   406  							[]pkg.Match{
   407  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   408  								{Key: "messageID", Value: "BEA-"},          //matches BEA-*
   409  								{Key: "message", Value: "WebLogic Server"}, //contains WebLogic Server
   410  								{Key: "subSystem", Value: "WebLogicServer"}},
   411  							[]pkg.Match{})
   412  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   413  				})
   414  			},
   415  			func() {
   416  				t.It("Verify recent pattern-matched Security log record exists", func() {
   417  					Eventually(func() bool {
   418  						return pkg.FindLog(indexName,
   419  							[]pkg.Match{
   420  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   421  								{Key: "messageID", Value: "BEA-"}, //matches BEA-*
   422  								{Key: "serverName", Value: "tododomain-adminserver"},
   423  								{Key: "subSystem.keyword", Value: "Security"}},
   424  							[]pkg.Match{})
   425  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   426  				})
   427  			},
   428  			func() {
   429  				t.It("Verify recent pattern-matched multi-lines log record exists", func() {
   430  					Eventually(func() bool {
   431  						return pkg.FindLog(indexName,
   432  							[]pkg.Match{
   433  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   434  								{Key: "messageID", Value: "BEA-"},         //matches BEA-*
   435  								{Key: "message", Value: "Tunneling Ping"}, //"Tunneling Ping" in last line
   436  								{Key: "serverName", Value: "tododomain-adminserver"},
   437  								{Key: "subSystem.keyword", Value: "RJVM"}},
   438  							[]pkg.Match{})
   439  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   440  				})
   441  			},
   442  			func() {
   443  				pkg.MinVersionSpec("Verify recent fluentd-stdout-sidecar server log record exists", "1.1.0",
   444  					func() {
   445  						Eventually(func() bool {
   446  							return pkg.FindLog(indexName,
   447  								[]pkg.Match{
   448  									{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   449  									{Key: "wls_log_stream", Value: "server_log"},
   450  									{Key: "stream", Value: "stdout"}},
   451  								[]pkg.Match{})
   452  						}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent server log record")
   453  					})
   454  			},
   455  			func() {
   456  				pkg.MinVersionSpec("Verify recent fluentd-stdout-sidecar domain log record exists", "1.1.0",
   457  					func() {
   458  						Eventually(func() bool {
   459  							return pkg.FindLog(indexName,
   460  								[]pkg.Match{
   461  									{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   462  									{Key: "wls_log_stream", Value: "domain_log"},
   463  									{Key: "stream", Value: "stdout"}},
   464  								[]pkg.Match{})
   465  						}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent domain log record")
   466  					})
   467  			},
   468  			func() {
   469  				pkg.MinVersionSpec("Verify recent fluentd-stdout-sidecar nodemanager log record exists", "1.1.0",
   470  					func() {
   471  						Eventually(func() bool {
   472  							return pkg.FindLog(indexName,
   473  								[]pkg.Match{
   474  									{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   475  									{Key: "wls_log_stream", Value: "server_nodemanager_log"},
   476  									{Key: "stream", Value: "stdout"}},
   477  								[]pkg.Match{})
   478  						}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent server nodemanager log record")
   479  					})
   480  			},
   481  			// GIVEN a WebLogic application with logging enabled
   482  			// WHEN the log records are retrieved from the Opensearch index
   483  			// THEN verify that a recent pattern-matched log record of tododomain-adminserver stdout is found
   484  			func() {
   485  				t.It("Verify recent pattern-matched AdminServer log record exists", func() {
   486  					Eventually(func() bool {
   487  						return pkg.FindLog(indexName,
   488  							[]pkg.Match{
   489  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   490  								{Key: "subSystem.keyword", Value: "WorkManager"},
   491  								{Key: "serverName.keyword", Value: "tododomain-adminserver"},
   492  								{Key: "serverName2.keyword", Value: "AdminServer"},
   493  								{Key: "message", Value: "standby threads"}},
   494  							[]pkg.Match{})
   495  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   496  				})
   497  			},
   498  			// GIVEN a WebLogic application with logging enabled
   499  			// WHEN the log records are retrieved from the Opensearch index
   500  			// THEN verify that a recent pattern-matched log record of tododomain-adminserver stdout is found
   501  			func() {
   502  				t.It("Verify recent pattern-matched AdminServer log record exists", func() {
   503  					Eventually(func() bool {
   504  						return pkg.FindLog(indexName,
   505  							[]pkg.Match{
   506  								{Key: "kubernetes.container_name.keyword", Value: "fluentd-stdout-sidecar"},
   507  								{Key: "subSystem", Value: "WorkManager"},
   508  								{Key: "serverName", Value: "tododomain-adminserver"},
   509  								{Key: "serverName2", Value: "AdminServer"},
   510  								{Key: "message", Value: "Self-tuning"}},
   511  							[]pkg.Match{})
   512  					}, longWaitTimeout, longPollingInterval).Should(BeTrue(), "Expected to find a recent log record")
   513  				})
   514  			},
   515  		)
   516  	})
   517  })
   518  
   519  // function to pair a put and get for a given task item
   520  func putGetTodoTask(host string, task string) bool {
   521  	url := fmt.Sprintf("https://%s/todo/rest/item/%s", host, task)
   522  	resp, err := pkg.PutWithHostHeader(url, "application/json", host, nil)
   523  	if err != nil {
   524  		t.Logs.Errorf("PUT failed with error: %v", err)
   525  		return false
   526  	}
   527  	if resp.StatusCode != http.StatusNoContent {
   528  		t.Logs.Errorf("Put status code is: %d", resp.StatusCode)
   529  		return false
   530  	}
   531  	url = fmt.Sprintf("https://%s/todo/rest/items", host)
   532  	resp, err = pkg.GetWebPage(url, host)
   533  	if err != nil {
   534  		t.Logs.Errorf("GET failed with error: %v", err)
   535  		return false
   536  	}
   537  	if resp.StatusCode == http.StatusOK && resp.Body != nil {
   538  		return true
   539  	}
   540  	t.Logs.Errorf("Get status code is: %d", resp.StatusCode)
   541  	return false
   542  }