github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/verify-install/istio/istio_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 istio 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/Jeffail/gabs/v2" 11 . "github.com/onsi/ginkgo/v2" 12 . "github.com/onsi/gomega" 13 "github.com/verrazzano/verrazzano/pkg/k8sutil" 14 vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1" 15 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 16 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 17 appsv1 "k8s.io/api/apps/v1" 18 corev1 "k8s.io/api/core/v1" 19 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 20 "k8s.io/apimachinery/pkg/labels" 21 "k8s.io/apimachinery/pkg/types" 22 ) 23 24 const ( 25 waitTimeout = 3 * time.Minute 26 pollingInterval = 10 * time.Second 27 ) 28 29 var t = framework.NewTestFramework("istio") 30 31 var _ = t.AfterEach(func() {}) 32 33 var _ = t.Describe("Istio", Label("f:platform-lcm.install"), func() { 34 const istioNamespace = "istio-system" 35 36 t.It("has affinity configured on istiod pods", func() { 37 var pods []corev1.Pod 38 var err error 39 Eventually(func() bool { 40 pods, err = pkg.GetPodsFromSelector(&metav1.LabelSelector{MatchLabels: map[string]string{"app": "istiod"}}, istioNamespace) 41 if err != nil { 42 t.Logs.Error("Failed to get Istiod pods: %v", err) 43 return false 44 } 45 if len(pods) < 1 { 46 return false 47 } 48 return true 49 }, waitTimeout, pollingInterval).Should(BeTrue()) 50 for _, pod := range pods { 51 affinity := pod.Spec.Affinity 52 Expect(affinity).ToNot(BeNil()) 53 Expect(affinity.PodAffinity).To(BeNil()) 54 Expect(affinity.NodeAffinity).To(BeNil()) 55 Expect(affinity.PodAntiAffinity).ToNot(BeNil()) 56 Expect(len(affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution)).To(Equal(1)) 57 } 58 }) 59 60 t.DescribeTable("namespace", 61 func(name string) { 62 Eventually(func() (bool, error) { 63 return pkg.DoesNamespaceExist(name) 64 }, waitTimeout, pollingInterval).Should(BeTrue()) 65 }, 66 t.Entry(fmt.Sprintf("%s namespace should exist", istioNamespace), istioNamespace), 67 ) 68 69 expectedDeployments := []string{ 70 "istio-egressgateway", 71 "istio-ingressgateway", 72 "istiod", 73 } 74 75 t.DescribeTable("deployments", 76 func(namespace string) { 77 78 deploymentNames := func(deploymentList *appsv1.DeploymentList) []string { 79 var deploymentNames []string 80 for _, deployment := range deploymentList.Items { 81 deploymentNames = append(deploymentNames, deployment.Name) 82 } 83 return deploymentNames 84 } 85 86 var deployments *appsv1.DeploymentList 87 Eventually(func() (*appsv1.DeploymentList, error) { 88 var err error 89 deployments, err = pkg.ListDeployments(namespace) 90 return deployments, err 91 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 92 93 Expect(deployments).Should(WithTransform(deploymentNames, ContainElements(expectedDeployments))) 94 }, 95 t.Entry(fmt.Sprintf("%s namespace should contain expected list of deployments", istioNamespace), istioNamespace), 96 ) 97 98 t.DescribeTable("Verify expected replica counts", 99 func(namespace string) { 100 101 // Verify the correct number of pods for each deployment based on the profile & any overrides 102 103 kubeconfigPath, err := k8sutil.GetKubeConfigLocation() 104 if err != nil { 105 Fail(err.Error()) 106 } 107 108 vz, err := pkg.GetVerrazzanoInstallResourceInClusterV1beta1(kubeconfigPath) 109 if err != nil { 110 Fail(err.Error()) 111 } 112 113 deployments := []types.NamespacedName{ 114 {Name: "istio-egressgateway", Namespace: namespace}, 115 {Name: "istio-ingressgateway", Namespace: namespace}, 116 {Name: "istiod", Namespace: namespace}, 117 } 118 expectedPods := map[string]uint32{ 119 deployments[0].String(): getEgressReplicaCount(vz), 120 deployments[1].String(): getIngressReplicaCount(vz), 121 deployments[2].String(): getPilotReplicaCount(vz), 122 } 123 t.Logs.Infof("Expected replica counts: %v", expectedPods) 124 125 Eventually(func() (map[string]uint32, error) { 126 return pkg.GetReplicaCounts(deployments, buildListOpts) 127 }, waitTimeout, pollingInterval).Should(Equal(expectedPods)) 128 }, 129 t.Entry(fmt.Sprintf("%s namespace should contain expected pod counts", istioNamespace), istioNamespace), 130 ) 131 }) 132 133 func buildListOpts(name types.NamespacedName) (metav1.ListOptions, error) { 134 selector := metav1.LabelSelector{ 135 MatchLabels: map[string]string{ 136 "app": name.Name, 137 }, 138 } 139 labelMap, err := metav1.LabelSelectorAsMap(&selector) 140 if err != nil { 141 return metav1.ListOptions{}, err 142 } 143 listOpts := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()} 144 return listOpts, nil 145 } 146 147 func getIngressReplicaCount(vz *vzapi.Verrazzano) uint32 { 148 istio := vz.Spec.Components.Istio 149 if istio != nil { 150 if !isIstioEnabled(istio) { 151 return 0 152 } 153 return extractIstioSubComponentReplicas(istio.ValueOverrides, "spec.components.egressGateways.0.k8s.replicaCount") 154 } 155 return 1 156 } 157 158 func getEgressReplicaCount(vz *vzapi.Verrazzano) uint32 { 159 istio := vz.Spec.Components.Istio 160 if istio != nil { 161 if !isIstioEnabled(istio) { 162 return 0 163 } 164 return extractIstioSubComponentReplicas(istio.ValueOverrides, "spec.components.ingressGateways.0.k8s.replicaCount") 165 } 166 return 1 167 } 168 169 func getPilotReplicaCount(vz *vzapi.Verrazzano) uint32 { 170 istio := vz.Spec.Components.Istio 171 if istio != nil { 172 if !isIstioEnabled(istio) { 173 return 0 174 } 175 return extractIstioSubComponentReplicas(istio.ValueOverrides, "spec.components.pilot.k8s.replicaCount") 176 } 177 return 1 178 } 179 180 func extractIstioSubComponentReplicas(overrides []vzapi.Overrides, jsonPath string) uint32 { 181 for _, override := range overrides { 182 if override.Values != nil { 183 jsonString, err := gabs.ParseJSON(override.Values.Raw) 184 if err != nil { 185 return 1 186 } 187 if container := jsonString.Path(jsonPath); container != nil { 188 if val, ok := container.Data().(float64); ok { 189 return uint32(val) 190 } 191 } 192 } 193 } 194 return 1 195 } 196 197 func isIstioEnabled(istio *vzapi.IstioComponent) bool { 198 if istio.Enabled != nil { 199 return *istio.Enabled 200 } 201 return true 202 }