github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/verify-install/kubernetes/kubernetes_test.go (about)

     1  // Copyright (c) 2020, 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 kubernetes_test
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/verrazzano/verrazzano/pkg/constants"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  	"github.com/verrazzano/verrazzano/pkg/k8sutil"
    15  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    16  	"github.com/verrazzano/verrazzano/pkg/nginxutil"
    17  	"github.com/verrazzano/verrazzano/tests/e2e/pkg"
    18  	"github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework"
    19  	v1 "k8s.io/api/core/v1"
    20  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    21  )
    22  
    23  const waitTimeout = 15 * time.Minute
    24  const pollingInterval = 30 * time.Second
    25  const shortTimeout = 5 * time.Minute
    26  
    27  var t = framework.NewTestFramework("kubernetes")
    28  
    29  var expectedPodsCattleSystem = []string{
    30  	"rancher"}
    31  
    32  var expectedPodsKeycloak = []string{
    33  	"mysql",
    34  	"keycloak"}
    35  
    36  var expectedPodsCertManager = []string{
    37  	"cert-manager"}
    38  
    39  var expectedPodsIngressNginx = []string{
    40  	"ingress-controller-ingress-nginx-controller",
    41  	"ingress-controller-ingress-nginx-defaultbackend"}
    42  
    43  var expectedVMOPod = "verrazzano-monitoring-operator"
    44  
    45  // comment out while debugging, so it does not break master
    46  // "vmi-system-prometheus",
    47  // "vmi-system-prometheus-gw"}
    48  
    49  var _ = t.AfterEach(func() {})
    50  
    51  var _ = t.Describe("In the Kubernetes Cluster", Label("f:platform-lcm.install"),
    52  	func() {
    53  		isManagedClusterProfile := pkg.IsManagedClusterProfile()
    54  		isProdProfile := pkg.IsProdProfile()
    55  		ingressNGINXNamespace, err := nginxutil.DetermineNamespaceForIngressNGINX(vzlog.DefaultLogger())
    56  		if err != nil {
    57  			Fail("Error determining ingress-nginx namespace")
    58  		}
    59  
    60  		t.It("the expected number of nodes exist", func() {
    61  			Eventually(func() (bool, error) {
    62  				nodes, err := pkg.ListNodes()
    63  				return nodes != nil && len(nodes.Items) >= 1, err
    64  			}, shortTimeout, pollingInterval).Should(BeTrue())
    65  		})
    66  
    67  		t.DescribeTable("the expected namespaces exist",
    68  			func(namespace string, expected bool) {
    69  				Eventually(func() (bool, error) {
    70  					var err error
    71  					var namespaces *v1.NamespaceList
    72  					namespaces, err = pkg.ListNamespaces(metav1.ListOptions{})
    73  					if err != nil {
    74  						return false, err
    75  					}
    76  					return nsListContains(namespaces.Items, namespace) == expected, nil
    77  				}, shortTimeout, pollingInterval).Should(BeTrue())
    78  			},
    79  			t.Entry("cattle-global-data", "cattle-global-data", !isManagedClusterProfile),
    80  			t.Entry("cattle-global-nt", "cattle-global-nt", !isManagedClusterProfile),
    81  			// Even though we do not install Rancher on managed clusters, we do create the namespace
    82  			// so we can create network policies. Rancher will run pods in this namespace once
    83  			// the managed cluster manifest YAML is applied to the managed cluster. So expect cattle-system
    84  			// to exist on all clusters
    85  			t.Entry(constants.RancherSystemNamespace, constants.RancherSystemNamespace, true),
    86  			t.Entry("istio-system", "istio-system", true),
    87  			t.Entry("gitlab", "gitlab", false),
    88  			t.Entry("keycloak", "keycloak", !isManagedClusterProfile),
    89  			t.Entry("verrazzano-system", "verrazzano-system", true),
    90  			t.Entry("verrazzano-mc", "verrazzano-mc", true),
    91  			t.Entry("cert-manager", "cert-manager", true),
    92  			t.Entry(ingressNGINXNamespace, ingressNGINXNamespace, true),
    93  			t.Entry("verrazzano-logging", "verrazzano-logging", !isManagedClusterProfile),
    94  		)
    95  
    96  		kubeconfigPath, _ := k8sutil.GetKubeConfigLocation()
    97  		componentsArgs := []interface{}{
    98  			func(name string, expected bool) {
    99  				Eventually(func() (bool, error) {
   100  					return vzComponentPresent(name, "verrazzano-system")
   101  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   102  			},
   103  			t.Entry("does not include verrazzano-web", "verrazzano-web", false),
   104  			t.Entry("includes verrazzano-console", "verrazzano-console", !isManagedClusterProfile),
   105  			t.Entry("does not include verrazzano-ldap", "verrazzano-ldap", false),
   106  			t.Entry("includes verrazzano-cluster-operator", "verrazzano-cluster-operator", true),
   107  			t.Entry("includes verrazzano-monitoring-operator", "verrazzano-monitoring-operator", isVMOExpected(kubeconfigPath)),
   108  			t.Entry("Check weblogic-operator deployment", "weblogic-operator", pkg.IsWebLogicOperatorEnabled(kubeconfigPath)),
   109  			t.Entry("Check coherence-operator deployment", "coherence-operator", pkg.IsCoherenceOperatorEnabled(kubeconfigPath)),
   110  			// t.Entry("Check external-dns deployment", "external-dns", pkg.IsOCIDNSEnabled(kubeconfigPath)),
   111  			// t.Entry("Check verrazzano-cert-manager-oci-dns-webhook deployment", "cert-manager-ocidns-provider", pkg.IsOCIDNSWebhookEnabled(kubeconfigPath)),
   112  		}
   113  
   114  		t.DescribeTable("Verrazzano components are deployed,",
   115  			componentsArgs...,
   116  		)
   117  
   118  		t.DescribeTable("cert-manager components are deployed,",
   119  			func(name string, expected bool) {
   120  				Eventually(func() (bool, error) {
   121  					return vzComponentPresent(name, "cert-manager")
   122  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   123  			},
   124  			t.Entry("includes cert-manager", "cert-manager", true),
   125  			t.Entry("does include cert-manager-cainjector", "cert-manager-cainjector", true),
   126  		)
   127  
   128  		t.DescribeTable("ingress components are deployed,",
   129  			func(name string, expected bool) {
   130  				Eventually(func() (bool, error) {
   131  					return vzComponentPresent(name, ingressNGINXNamespace)
   132  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   133  			},
   134  			t.Entry("includes ingress-controller-ingress-nginx-controller", "ingress-controller-ingress-nginx-controller", true),
   135  		)
   136  
   137  		t.DescribeTable("keycloak components are not deployed,",
   138  			func(name string, expected bool) {
   139  				Eventually(func() (bool, error) {
   140  					return vzComponentPresent(name, "keycloak")
   141  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   142  			},
   143  			t.Entry("includes ssoproxycontroller", "ssoproxycontroller", false),
   144  		)
   145  
   146  		isMinVersion169, _ := pkg.IsVerrazzanoMinVersion("1.6.9", kubeconfigPath)
   147  		if isManagedClusterProfile {
   148  			// Only expect rancher-webhook if the cattle-cluster-agent is deployed, and
   149  			// installed on a minimum of v1.6.9.
   150  			registered, err := pkg.DoesDeploymentExist(constants.RancherSystemNamespace, "cattle-cluster-agent")
   151  			if err != nil {
   152  				Fail(fmt.Sprintf("failed to check deployment %s/%s: %v", constants.RancherSystemNamespace, "cattle-cluster-agent", err))
   153  			}
   154  			expectWebhook := isMinVersion169
   155  			if !registered {
   156  				expectWebhook = false
   157  			}
   158  			t.DescribeTable("rancher components are not deployed,",
   159  				func(name string, expected bool) {
   160  					Eventually(func() (bool, error) {
   161  						return vzComponentPresent(name, constants.RancherSystemNamespace)
   162  					}, waitTimeout, pollingInterval).Should(Equal(expected))
   163  				},
   164  				// Starting with Rancher 2.7.8, rancher-webhook is installed on all downstream clusters
   165  				t.Entry("includes rancher-webhook", "rancher-webhook", expectWebhook),
   166  			)
   167  		} else {
   168  			t.DescribeTable("rancher components are deployed,",
   169  				func(name string, expected bool) {
   170  					Eventually(func() (bool, error) {
   171  						return vzComponentPresent(name, constants.RancherSystemNamespace)
   172  					}, waitTimeout, pollingInterval).Should(Equal(expected))
   173  				},
   174  				t.Entry("includes rancher", "rancher", true),
   175  				t.Entry("includes rancher-webhook", "rancher-webhook", true),
   176  			)
   177  		}
   178  
   179  		ok, _ := pkg.IsVerrazzanoMinVersion("1.7.0", kubeconfigPath)
   180  		t.DescribeTable("VMI components are deployed,",
   181  			func(name string, expected bool) {
   182  				Eventually(func() (bool, error) {
   183  					return vzComponentPresent(name, "verrazzano-system")
   184  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   185  			},
   186  			t.Entry("includes es-ingest", "vmi-system-es-ingest", isProdProfile && !ok),
   187  			t.Entry("includes es-data", "vmi-system-es-data", isProdProfile && !ok),
   188  			t.Entry("includes es-master", "vmi-system-es-master", !isManagedClusterProfile && !ok),
   189  			t.Entry("includes es-kibana", "vmi-system-osd", !isManagedClusterProfile && !ok),
   190  			t.Entry("includes es-grafana", "vmi-system-grafana", !isManagedClusterProfile),
   191  			t.Entry("includes verrazzano-console", "verrazzano-console", !isManagedClusterProfile),
   192  		)
   193  
   194  		// If version is >= 1.7.0, check for opensearch in verrazzano-logging namespace
   195  		if ok {
   196  			t.DescribeTable("Logging components are deployed,",
   197  				func(name string, expected bool) {
   198  					Eventually(func() (bool, error) {
   199  						return vzComponentPresent(name, "verrazzano-logging")
   200  					}, waitTimeout, pollingInterval).Should(Equal(expected))
   201  				},
   202  				t.Entry("includes opensearch-operator", "opensearch-operator-controller-manager", !isManagedClusterProfile),
   203  				t.Entry("includes es-master", "opensearch-es-master", !isManagedClusterProfile),
   204  				t.Entry("includes es-data", "opensearch-es-data", isProdProfile),
   205  				t.Entry("includes es-ingest", "opensearch-es-ingest", isProdProfile),
   206  				t.Entry("includes opensearch-dashboards", "opensearch-dashboards", !isManagedClusterProfile),
   207  			)
   208  		}
   209  
   210  		t.DescribeTable("Prometheus components are deployed,",
   211  			func(name string) {
   212  				Eventually(func() (bool, error) {
   213  					return vzComponentPresent(name, "verrazzano-monitoring")
   214  				}, waitTimeout, pollingInterval).Should(Equal(true))
   215  			},
   216  			t.Entry("includes prometheus-operator-kube-p-operator", "prometheus-operator-kube-p-operator"),
   217  			t.Entry("includes prometheus-prometheus-operator-kube-p-prometheus", "prometheus-prometheus-operator-kube-p-prometheus"),
   218  		)
   219  
   220  		// Test components that may not exist for older versions
   221  		t.DescribeTable("VMI components that don't exist in older versions are deployed,",
   222  			func(name string, expected bool) {
   223  				Eventually(func() (bool, error) {
   224  					ok, _ := pkg.IsVerrazzanoMinVersion("1.1.0", kubeconfigPath)
   225  					if !ok {
   226  						// skip test
   227  						fmt.Printf("Skipping Kiali check since version < 1.1.0")
   228  						return expected, nil
   229  					}
   230  					return vzComponentPresent(name, "verrazzano-system")
   231  				}, waitTimeout, pollingInterval).Should(Equal(expected))
   232  			},
   233  			t.Entry("includes kiali", "vmi-system-kiali", !isManagedClusterProfile),
   234  		)
   235  
   236  		t.It("the expected pods are running", func() {
   237  			assertions := []func(){
   238  				func() {
   239  					// Rancher pods do not run on the managed cluster at install time (they do get started later when the managed
   240  					// cluster is registered)
   241  					if !isManagedClusterProfile {
   242  						Eventually(func() bool { return checkPodsRunning(constants.RancherSystemNamespace, expectedPodsCattleSystem) }, waitTimeout, pollingInterval).
   243  							Should(BeTrue())
   244  					}
   245  				},
   246  				func() {
   247  					if !isManagedClusterProfile {
   248  						Eventually(func() bool {
   249  							return checkPodsRunning("keycloak", expectedPodsKeycloak)
   250  						}, waitTimeout, pollingInterval).Should(BeTrue())
   251  					}
   252  				},
   253  				func() {
   254  					Eventually(func() bool { return checkPodsRunning("cert-manager", expectedPodsCertManager) }, waitTimeout, pollingInterval).
   255  						Should(BeTrue())
   256  				},
   257  				func() {
   258  					Eventually(func() bool { return checkPodsRunning(ingressNGINXNamespace, expectedPodsIngressNginx) }, waitTimeout, pollingInterval).
   259  						Should(BeTrue())
   260  				},
   261  				func() {
   262  					if isVMOExpected(kubeconfigPath) {
   263  						Eventually(func() bool { return checkPodsRunning("verrazzano-system", []string{expectedVMOPod}) }, waitTimeout, pollingInterval).
   264  							Should(BeTrue())
   265  					} else {
   266  						// skip test
   267  						fmt.Printf("Skipping VMO pod check in managed cluster profile for VZ >= 1.6.0")
   268  					}
   269  				},
   270  			}
   271  
   272  			pkg.Concurrently(
   273  				assertions...,
   274  			)
   275  		})
   276  	})
   277  
   278  // isVMOExpected - is the VMO pod expected to exist in the given cluster
   279  func isVMOExpected(kubeconfigPath string) bool {
   280  	// in v1.6.0 and later, the VMO pod is not part of managed cluster profile
   281  	noVMOPodInManagedCluster, _ := pkg.IsVerrazzanoMinVersion("1.6.0", kubeconfigPath)
   282  	isManagedClusterProfile := pkg.IsManagedClusterProfile()
   283  	if isManagedClusterProfile && noVMOPodInManagedCluster {
   284  		return false
   285  	}
   286  	return true
   287  }
   288  
   289  func nsListContains(list []v1.Namespace, target string) bool {
   290  	for i := range list {
   291  		if list[i].Name == target {
   292  			return true
   293  		}
   294  	}
   295  	return false
   296  }
   297  
   298  func vzComponentPresent(name string, namespace string) (bool, error) {
   299  	return pkg.DoesPodExist(namespace, name)
   300  }
   301  
   302  func checkPodsRunning(namespace string, expectedPods []string) bool {
   303  	result, err := pkg.PodsRunning(namespace, expectedPods)
   304  	if err != nil {
   305  		AbortSuite(fmt.Sprintf("One or more pods are not running in the namespace: %v, error: %v", namespace, err))
   306  	}
   307  	return result
   308  }