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  }