github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/grafana-db/grafana_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 grafanadb
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net/http"
    11  	"os"
    12  	"time"
    13  
    14  	"github.com/verrazzano/verrazzano/pkg/constants"
    15  	"github.com/verrazzano/verrazzano/pkg/k8sutil"
    16  	corev1 "k8s.io/api/core/v1"
    17  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    18  
    19  	. "github.com/onsi/ginkgo/v2"
    20  	. "github.com/onsi/gomega"
    21  	"github.com/verrazzano/verrazzano/tests/e2e/pkg"
    22  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework"
    23  )
    24  
    25  const (
    26  	waitTimeout     = 3 * time.Minute
    27  	pollingInterval = 10 * time.Second
    28  	documentFile    = "testdata/upgrade/grafana/dashboard.json"
    29  )
    30  
    31  var clientset = k8sutil.GetKubernetesClientsetOrDie()
    32  var testDashboard pkg.DashboardMetadata
    33  var t = framework.NewTestFramework("grafana")
    34  
    35  var beforeSuite = t.BeforeSuiteFunc(func() {
    36  	kubeconfigPath, err := k8sutil.GetKubeConfigLocation()
    37  	if err != nil {
    38  		Fail(fmt.Sprintf(pkg.KubeConfigErrorFmt, err))
    39  	}
    40  	supported := pkg.IsGrafanaEnabled(kubeconfigPath)
    41  	// Only run tests if Grafana component is enabled in Verrazzano CR
    42  	if !supported {
    43  		Skip("Grafana component is not enabled")
    44  	}
    45  	// Create the test Grafana dashboard
    46  	file, err := pkg.FindTestDataFile(documentFile)
    47  	if err != nil {
    48  		pkg.Log(pkg.Error, fmt.Sprintf("failed to find test data file: %v", err))
    49  		Fail(err.Error())
    50  	}
    51  	data, err := os.ReadFile(file)
    52  	if err != nil {
    53  		pkg.Log(pkg.Error, fmt.Sprintf("failed to read test data file: %v", err))
    54  		Fail(err.Error())
    55  	}
    56  	Eventually(func() bool {
    57  		resp, err := pkg.CreateGrafanaDashboard(string(data))
    58  		if err != nil {
    59  			pkg.Log(pkg.Error, fmt.Sprintf("Failed to create Grafana testDashboard: %v", err))
    60  			return false
    61  		}
    62  		if resp.StatusCode != http.StatusOK {
    63  			pkg.Log(pkg.Error, fmt.Sprintf("Failed to create Grafana testDashboard: status=%d: body=%s", resp.StatusCode, string(resp.Body)))
    64  			return false
    65  		}
    66  		json.Unmarshal(resp.Body, &testDashboard)
    67  		return true
    68  	}).WithPolling(pollingInterval).WithTimeout(waitTimeout).Should(BeTrue(),
    69  		"It should be possible to create a Grafana dashboard and persist it.")
    70  })
    71  
    72  var _ = BeforeSuite(beforeSuite)
    73  
    74  var _ = t.Describe("Test Grafana Dashboard Persistence", Label("f:observability.logging.es"), func() {
    75  
    76  	// GIVEN a running grafana instance,
    77  	// WHEN a GET call is made  to Grafana with the UID of the newly created testDashboard,
    78  	// THEN the testDashboard metadata of the corresponding testDashboard is returned.
    79  	It("Get details of the test Grafana Dashboard", func() {
    80  		pkg.TestGrafanaTestDashboard(testDashboard, pollingInterval, waitTimeout)
    81  	})
    82  
    83  	// GIVEN a running Grafana instance,
    84  	// WHEN a search is done based on the dashboard title,
    85  	// THEN the details of the dashboards matching the search query is returned.
    86  	It("Search the test Grafana Dashboard using its title", func() {
    87  		pkg.TestSearchGrafanaDashboard(pollingInterval, waitTimeout)
    88  	})
    89  
    90  	// GIVEN a running grafana instance,
    91  	// WHEN a GET call is made  to Grafana with the system dashboard UID,
    92  	// THEN the dashboard metadata of the corresponding testDashboard is returned.
    93  	It("Get details of the system Grafana Dashboard", func() {
    94  		pkg.TestSystemHealthGrafanaDashboard(pollingInterval, waitTimeout)
    95  	})
    96  
    97  	kubeconfigPath, err := k8sutil.GetKubeConfigLocation()
    98  	if err != nil {
    99  		Expect(err).To(BeNil(), fmt.Sprintf(pkg.KubeConfigErrorFmt, err))
   100  	}
   101  
   102  	// GIVEN a running grafana instance
   103  	// WHEN a call is made to Grafana Dashboard with UID corresponding to OpenSearch Summary Dashboard
   104  	// THEN the dashboard metadata of the corresponding dashboard is returned
   105  	if ok, _ := pkg.IsVerrazzanoMinVersion("1.3.0", kubeconfigPath); ok {
   106  		t.It("Get details of the OpenSearch Grafana Dashboard", func() {
   107  			pkg.TestOpenSearchGrafanaDashBoard(pollingInterval, waitTimeout)
   108  		})
   109  	}
   110  
   111  	// GIVEN a running grafana instance,
   112  	// WHEN the pod is deleted,
   113  	// THEN pod eventually comes back up.
   114  	It("Delete and wait for the pod to come back up", func() {
   115  		// delete grafana pods
   116  		Eventually(func() error {
   117  			pods, err := clientset.CoreV1().Pods(constants.VerrazzanoSystemNamespace).List(context.TODO(), metav1.ListOptions{
   118  				LabelSelector: "app=system-grafana",
   119  			})
   120  			if err != nil {
   121  				pkg.Log(pkg.Error, "Failed to find grafana pod")
   122  				return err
   123  			}
   124  
   125  			for i := range pods.Items {
   126  				pod := &pods.Items[i]
   127  				if err := clientset.CoreV1().Pods(pod.Namespace).Delete(context.TODO(), pod.Name, metav1.DeleteOptions{}); err != nil {
   128  					pkg.Log(pkg.Error, "Failed to delete grafana pod")
   129  					return err
   130  				}
   131  			}
   132  
   133  			return nil
   134  		}).WithPolling(pollingInterval).WithTimeout(waitTimeout).ShouldNot(HaveOccurred())
   135  
   136  		// wait for pods to come back up
   137  		Eventually(func() (bool, error) {
   138  			pods, err := clientset.CoreV1().Pods(constants.VerrazzanoSystemNamespace).List(context.TODO(), metav1.ListOptions{})
   139  			if err != nil {
   140  				pkg.Log(pkg.Info, "Failed to get grafana pod")
   141  				return false, err
   142  			}
   143  
   144  			if pods == nil || len(pods.Items) == 0 {
   145  				return false, nil
   146  			}
   147  			for _, pod := range pods.Items {
   148  				if !IsPodReadyOrCompleted(pod) {
   149  					return false, nil
   150  				}
   151  			}
   152  
   153  			return true, nil
   154  		}).WithPolling(pollingInterval).WithTimeout(waitTimeout).Should(BeTrue(), "Expected Grafana pods to restart")
   155  	})
   156  
   157  	// GIVEN a running Grafana instance,
   158  	// WHEN a search is made for the dashboard using its title,
   159  	// THEN the dashboard metadata is returned.
   160  	It("Search the test Grafana Dashboard using its title", func() {
   161  		pkg.TestSearchGrafanaDashboard(pollingInterval, waitTimeout)
   162  	})
   163  
   164  	// GIVEN a running grafana instance,
   165  	// WHEN a GET call is made  to Grafana with the UID of the system dashboard,
   166  	// THEN the dashboard metadata of the corresponding System dashboard is returned.
   167  	It("Get details of the system Grafana dashboard", func() {
   168  		pkg.TestSystemHealthGrafanaDashboard(pollingInterval, waitTimeout)
   169  	})
   170  
   171  	kubeconfigPath, err = k8sutil.GetKubeConfigLocation()
   172  	if err != nil {
   173  		Expect(err).To(BeNil(), fmt.Sprintf(pkg.KubeConfigErrorFmt, err))
   174  	}
   175  
   176  	// GIVEN a running grafana instance
   177  	// WHEN a call is made to Grafana Dashboard with UID corresponding to OpenSearch Summary Dashboard
   178  	// THEN the dashboard metadata of the corresponding dashboard is returned
   179  	if ok, _ := pkg.IsVerrazzanoMinVersion("1.3.0", kubeconfigPath); ok {
   180  		t.It("Get details of the OpenSearch Grafana Dashboard", func() {
   181  			pkg.TestOpenSearchGrafanaDashBoard(pollingInterval, waitTimeout)
   182  		})
   183  	}
   184  })
   185  
   186  func IsPodReadyOrCompleted(pod corev1.Pod) bool {
   187  	switch pod.Status.Phase {
   188  	case corev1.PodSucceeded:
   189  		return true
   190  	case corev1.PodRunning:
   191  		for _, c := range pod.Status.ContainerStatuses {
   192  			if !c.Ready {
   193  				return false
   194  			}
   195  		}
   196  		return true
   197  	default:
   198  		return false
   199  	}
   200  }