github.com/cilium/cilium@v1.16.2/test/k8s/assertion_helpers.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package k8sTest 5 6 import ( 7 "fmt" 8 "time" 9 10 . "github.com/onsi/gomega" 11 12 . "github.com/cilium/cilium/test/ginkgo-ext" 13 "github.com/cilium/cilium/test/helpers" 14 ) 15 16 var longTimeout = 10 * time.Minute 17 18 // ExpectKubeDNSReady is a wrapper around helpers/WaitKubeDNS. It asserts that 19 // the error returned by that function is nil. 20 func ExpectKubeDNSReady(vm *helpers.Kubectl) { 21 By("Waiting for kube-dns to be ready") 22 err := vm.WaitKubeDNS() 23 ExpectWithOffset(1, err).Should(BeNil(), "kube-dns was not able to get into ready state") 24 25 By("Running kube-dns preflight check") 26 err = vm.KubeDNSPreFlightCheck() 27 ExpectWithOffset(1, err).Should(BeNil(), "kube-dns service not ready") 28 } 29 30 // ExpectCiliumReady is a wrapper around helpers/WaitForPods. It asserts that 31 // the error returned by that function is nil. 32 func ExpectCiliumReady(vm *helpers.Kubectl) { 33 vm.WaitForCiliumReadiness(0, "Timeout while waiting for Cilium to become ready") 34 35 err := vm.CiliumPreFlightCheck() 36 ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed") 37 } 38 39 // ExpectCiliumOperatorReady is a wrapper around helpers/WaitForPods. It asserts that 40 // the error returned by that function is nil. 41 func ExpectCiliumOperatorReady(vm *helpers.Kubectl) { 42 By("Waiting for cilium-operator to be ready") 43 var err error 44 if vm.NumNodes() < 2 { 45 err = vm.WaitforNPods(helpers.CiliumNamespace, "-l name=cilium-operator", 1, longTimeout) 46 } else { 47 err = vm.WaitforPods(helpers.CiliumNamespace, "-l name=cilium-operator", longTimeout) 48 } 49 ExpectWithOffset(1, err).Should(BeNil(), "Cilium operator was not able to get into ready state") 50 } 51 52 // ExpectHubbleCLIReady is a wrapper around helpers/WaitForPods. It asserts 53 // that the error returned by that function is nil. 54 func ExpectHubbleCLIReady(vm *helpers.Kubectl, ns string) { 55 By("Waiting for hubble-cli to be ready") 56 err := vm.WaitforPods(ns, "-l k8s-app=hubble-cli", longTimeout) 57 ExpectWithOffset(1, err).Should(BeNil(), "hubble-cli was not able to get into ready state") 58 } 59 60 // ExpectHubbleRelayReady is a wrapper around helpers/WaitForPods. It asserts 61 // that the error returned by that function is nil. 62 func ExpectHubbleRelayReady(vm *helpers.Kubectl, ns string) { 63 By("Waiting for hubble-relay to be ready") 64 err := vm.WaitforPods(ns, "-l k8s-app=hubble-relay", longTimeout) 65 ExpectWithOffset(1, err).Should(BeNil(), "hubble-relay was not able to get into ready state") 66 } 67 68 // ExpectAllPodsTerminated is a wrapper around helpers/WaitTerminatingPods. 69 // It asserts that the error returned by that function is nil. 70 func ExpectAllPodsTerminated(vm *helpers.Kubectl) { 71 err := vm.WaitTerminatingPods(helpers.HelperTimeout) 72 ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout") 73 } 74 75 // ExpectAllPodsInNsTerminated is a wrapper around helpers/WaitTerminatingPods. 76 // It asserts that the error returned by that function is nil. 77 func ExpectAllPodsInNsTerminated(vm *helpers.Kubectl, ns string) { 78 err := vm.WaitTerminatingPodsInNs(ns, helpers.HelperTimeout) 79 ExpectWithOffset(1, err).To(BeNil(), "terminating containers are not deleted after timeout") 80 } 81 82 // ExpectCiliumPreFlightInstallReady is a wrapper around helpers/WaitForNPods. 83 // It asserts the error returned by that function is nil. 84 func ExpectCiliumPreFlightInstallReady(vm *helpers.Kubectl) { 85 By("Waiting for all cilium pre-flight pods to be ready") 86 87 err := vm.WaitforPods(helpers.CiliumNamespace, "-l k8s-app=cilium-pre-flight-check", longTimeout) 88 warningMessage := "" 89 if err != nil { 90 res := vm.Exec(fmt.Sprintf( 91 "%s -n %s get pods -l k8s-app=cilium-pre-flight-check", 92 helpers.KubectlCmd, helpers.CiliumNamespace)) 93 warningMessage = res.Stdout() 94 } 95 Expect(err).To(BeNil(), "cilium pre-flight check is not ready after timeout, pods status:\n %s", warningMessage) 96 } 97 98 // DeployCiliumAndDNS deploys DNS and cilium into the kubernetes cluster 99 func DeployCiliumAndDNS(vm *helpers.Kubectl, ciliumFilename string) { 100 DeployCiliumOptionsAndDNS(vm, ciliumFilename, map[string]string{}) 101 } 102 103 func redeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) { 104 By("Installing Cilium") 105 err := vm.CiliumInstall(ciliumFilename, options) 106 Expect(err).To(BeNil(), "Cilium cannot be installed") 107 108 vm.WaitForCiliumReadiness(0, "Timeout while waiting for Cilium to become ready") 109 } 110 111 // RedeployCilium reinstantiates the Cilium DS and ensures it is running. 112 // 113 // This helper is only appropriate for reconfiguring Cilium in the middle of 114 // an existing testsuite that calls DeployCiliumAndDNS(...). 115 func RedeployCilium(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) { 116 redeployCilium(vm, ciliumFilename, options) 117 err := vm.CiliumPreFlightCheck() 118 ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed") 119 ExpectCiliumOperatorReady(vm) 120 } 121 122 // UninstallCiliumFromManifest uninstall a deployed Cilium configuration from the 123 // provided manifest file. 124 // Treat this as a cleanup function for RedeployCilium/Redeploy/DeployCiliumAndDNS/CiliumInstall. 125 func UninstallCiliumFromManifest(vm *helpers.Kubectl, ciliumFilename string) { 126 By("Removing Cilium installation using generated helm manifest") 127 128 Expect(vm.DeleteAndWait(ciliumFilename, true).GetError()). 129 To(BeNil(), "Error removing cilium from installed manifest") 130 } 131 132 // RedeployCiliumWithMerge merges the configuration passed as "from" into 133 // "options", allowing the caller to preserve the previous Cilium 134 // configuration, along with passing new configuration. This function behaves 135 // equivalently to RedeployCilium. Note that "options" is deep copied, meaning 136 // it will NOT be modified. Any modifications will be local to this function. 137 func RedeployCiliumWithMerge(vm *helpers.Kubectl, 138 ciliumFilename string, 139 from, options map[string]string) { 140 141 // Merge configuration 142 newOpts := make(map[string]string, len(options)) 143 for k, v := range from { 144 newOpts[k] = v 145 } 146 for k, v := range options { 147 newOpts[k] = v 148 } 149 150 RedeployCilium(vm, ciliumFilename, newOpts) 151 } 152 153 // optionChangeRequiresPodRedeploy returns true if the difference between the 154 // specified options requires redeployment of all pods to ensure that the 155 // datapath is operating consistently. 156 func optionChangeRequiresPodRedeploy(prev, next map[string]string) bool { 157 // See GH-16717, as of v1.10.x Cilium does not support migrating 158 // between endpointRoutes modes without restarting pods. 159 // Also, the default setting for endpointRoutes is disabled. 160 // If either of these properties change, this logic needs updating! 161 a := "false" 162 if opt, ok := prev["endpointRoutes.enabled"]; ok { 163 a = opt 164 } 165 b := "false" 166 if opt, ok := next["endpointRoutes.enabled"]; ok { 167 b = opt 168 } 169 170 if a != b { 171 return true 172 } 173 174 // Switching on and off KPR affects who is handling service traffic. 175 // E.g., off => on some traffic might be handled by iptables. For existing 176 // connections it might not have enough of state information which could 177 // lead to connection interruptions. To avoid it, restart the pods to restart 178 // such connections. 179 a = "disabled" 180 if opt, ok := prev["kubeProxyReplacement"]; ok { 181 a = opt 182 } 183 b = "disabled" 184 if opt, ok := next["kubeProxyReplacement"]; ok { 185 b = opt 186 } 187 188 if a != b { 189 return true 190 } 191 192 return false 193 } 194 195 // DeployCiliumOptionsAndDNS deploys DNS and cilium with options into the kubernetes cluster 196 func DeployCiliumOptionsAndDNS(vm *helpers.Kubectl, ciliumFilename string, options map[string]string) { 197 prevOptions := vm.CiliumOptions() 198 199 redeployCilium(vm, ciliumFilename, options) 200 201 vm.RestartUnmanagedPodsInNamespace(helpers.LogGathererNamespace) 202 203 forceDNSRedeploy := optionChangeRequiresPodRedeploy(prevOptions, options) 204 vm.RedeployKubernetesDnsIfNecessary(forceDNSRedeploy) 205 206 switch helpers.GetCurrentIntegration() { 207 case helpers.CIIntegrationGKE: 208 if helpers.LogGathererNamespace != helpers.KubeSystemNamespace { 209 vm.RestartUnmanagedPodsInNamespace(helpers.KubeSystemNamespace) 210 } 211 } 212 213 err := vm.CiliumPreFlightCheck() 214 ExpectWithOffset(1, err).Should(BeNil(), "cilium pre-flight checks failed") 215 ExpectCiliumOperatorReady(vm) 216 217 switch helpers.GetCurrentIntegration() { 218 case helpers.CIIntegrationGKE: 219 err := vm.WaitforPods(helpers.KubeSystemNamespace, "", longTimeout) 220 ExpectWithOffset(1, err).Should(BeNil(), "kube-system pods were not able to get into ready state after restart") 221 } 222 } 223 224 // SkipIfIntegration will skip a test if it's running with any of the specified 225 // integration. 226 func SkipIfIntegration(integration string) { 227 if helpers.IsIntegration(integration) { 228 Skip(fmt.Sprintf( 229 "This feature is not supported in Cilium %q mode. Skipping test.", 230 integration)) 231 } 232 }