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 }