...

Source file src/k8s.io/kubernetes/test/e2e/framework/skipper/skipper.go

Documentation: k8s.io/kubernetes/test/e2e/framework/skipper

     1  /*
     2  Copyright 2014 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package skipper
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/onsi/ginkgo/v2"
    24  
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/labels"
    27  	utilversion "k8s.io/apimachinery/pkg/util/version"
    28  	"k8s.io/client-go/discovery"
    29  	clientset "k8s.io/client-go/kubernetes"
    30  	"k8s.io/component-base/featuregate"
    31  	"k8s.io/kubernetes/test/e2e/framework"
    32  	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
    33  	e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
    34  )
    35  
    36  func skipInternalf(caller int, format string, args ...interface{}) {
    37  	msg := fmt.Sprintf(format, args...)
    38  	ginkgo.Skip(msg, caller+1)
    39  	panic("unreachable")
    40  }
    41  
    42  // Skipf skips with information about why the test is being skipped.
    43  // The direct caller is recorded in the callstack.
    44  func Skipf(format string, args ...interface{}) {
    45  	skipInternalf(1, format, args...)
    46  	panic("unreachable")
    47  }
    48  
    49  // SkipUnlessAtLeast skips if the value is less than the minValue.
    50  func SkipUnlessAtLeast(value int, minValue int, message string) {
    51  	if value < minValue {
    52  		skipInternalf(1, message)
    53  	}
    54  }
    55  
    56  var featureGate featuregate.FeatureGate
    57  
    58  // InitFeatureGates must be called in test suites that have a --feature-gates parameter.
    59  // If not called, SkipUnlessFeatureGateEnabled and SkipIfFeatureGateEnabled will
    60  // record a test failure.
    61  func InitFeatureGates(defaults featuregate.FeatureGate, overrides map[string]bool) error {
    62  	clone := defaults.DeepCopy()
    63  	if err := clone.SetFromMap(overrides); err != nil {
    64  		return err
    65  	}
    66  	featureGate = clone
    67  	return nil
    68  }
    69  
    70  // SkipUnlessFeatureGateEnabled skips if the feature is disabled.
    71  //
    72  // Beware that this only works in test suites that have a --feature-gate
    73  // parameter and call InitFeatureGates. In test/e2e, the `Feature: XYZ` tag
    74  // has to be used instead and invocations have to make sure that they
    75  // only run tests that work with the given test cluster.
    76  func SkipUnlessFeatureGateEnabled(gate featuregate.Feature) {
    77  	if featureGate == nil {
    78  		framework.Failf("Feature gate checking is not enabled, don't use SkipUnlessFeatureGateEnabled(%v). Instead use the Feature tag.", gate)
    79  	}
    80  	if !featureGate.Enabled(gate) {
    81  		skipInternalf(1, "Only supported when %v feature is enabled", gate)
    82  	}
    83  }
    84  
    85  // SkipUnlessNodeCountIsAtLeast skips if the number of nodes is less than the minNodeCount.
    86  func SkipUnlessNodeCountIsAtLeast(minNodeCount int) {
    87  	if framework.TestContext.CloudConfig.NumNodes < minNodeCount {
    88  		skipInternalf(1, "Requires at least %d nodes (not %d)", minNodeCount, framework.TestContext.CloudConfig.NumNodes)
    89  	}
    90  }
    91  
    92  // SkipUnlessNodeCountIsAtMost skips if the number of nodes is greater than the maxNodeCount.
    93  func SkipUnlessNodeCountIsAtMost(maxNodeCount int) {
    94  	if framework.TestContext.CloudConfig.NumNodes > maxNodeCount {
    95  		skipInternalf(1, "Requires at most %d nodes (not %d)", maxNodeCount, framework.TestContext.CloudConfig.NumNodes)
    96  	}
    97  }
    98  
    99  // SkipIfProviderIs skips if the provider is included in the unsupportedProviders.
   100  func SkipIfProviderIs(unsupportedProviders ...string) {
   101  	if framework.ProviderIs(unsupportedProviders...) {
   102  		skipInternalf(1, "Not supported for providers %v (found %s)", unsupportedProviders, framework.TestContext.Provider)
   103  	}
   104  }
   105  
   106  // SkipUnlessProviderIs skips if the provider is not included in the supportedProviders.
   107  func SkipUnlessProviderIs(supportedProviders ...string) {
   108  	if !framework.ProviderIs(supportedProviders...) {
   109  		skipInternalf(1, "Only supported for providers %v (not %s)", supportedProviders, framework.TestContext.Provider)
   110  	}
   111  }
   112  
   113  // SkipUnlessMultizone skips if the cluster does not have multizone.
   114  func SkipUnlessMultizone(ctx context.Context, c clientset.Interface) {
   115  	zones, err := e2enode.GetClusterZones(ctx, c)
   116  	if err != nil {
   117  		skipInternalf(1, "Error listing cluster zones")
   118  	}
   119  	if zones.Len() <= 1 {
   120  		skipInternalf(1, "Requires more than one zone")
   121  	}
   122  }
   123  
   124  // SkipIfMultizone skips if the cluster has multizone.
   125  func SkipIfMultizone(ctx context.Context, c clientset.Interface) {
   126  	zones, err := e2enode.GetClusterZones(ctx, c)
   127  	if err != nil {
   128  		skipInternalf(1, "Error listing cluster zones")
   129  	}
   130  	if zones.Len() > 1 {
   131  		skipInternalf(1, "Requires at most one zone")
   132  	}
   133  }
   134  
   135  // SkipUnlessMasterOSDistroIs skips if the master OS distro is not included in the supportedMasterOsDistros.
   136  func SkipUnlessMasterOSDistroIs(supportedMasterOsDistros ...string) {
   137  	if !framework.MasterOSDistroIs(supportedMasterOsDistros...) {
   138  		skipInternalf(1, "Only supported for master OS distro %v (not %s)", supportedMasterOsDistros, framework.TestContext.MasterOSDistro)
   139  	}
   140  }
   141  
   142  // SkipUnlessNodeOSDistroIs skips if the node OS distro is not included in the supportedNodeOsDistros.
   143  func SkipUnlessNodeOSDistroIs(supportedNodeOsDistros ...string) {
   144  	if !framework.NodeOSDistroIs(supportedNodeOsDistros...) {
   145  		skipInternalf(1, "Only supported for node OS distro %v (not %s)", supportedNodeOsDistros, framework.TestContext.NodeOSDistro)
   146  	}
   147  }
   148  
   149  // SkipUnlessNodeOSArchIs skips if the node OS distro is not included in the supportedNodeOsArchs.
   150  func SkipUnlessNodeOSArchIs(supportedNodeOsArchs ...string) {
   151  	if !framework.NodeOSArchIs(supportedNodeOsArchs...) {
   152  		skipInternalf(1, "Only supported for node OS arch %v (not %s)", supportedNodeOsArchs, framework.TestContext.NodeOSArch)
   153  	}
   154  }
   155  
   156  // SkipIfNodeOSDistroIs skips if the node OS distro is included in the unsupportedNodeOsDistros.
   157  func SkipIfNodeOSDistroIs(unsupportedNodeOsDistros ...string) {
   158  	if framework.NodeOSDistroIs(unsupportedNodeOsDistros...) {
   159  		skipInternalf(1, "Not supported for node OS distro %v (is %s)", unsupportedNodeOsDistros, framework.TestContext.NodeOSDistro)
   160  	}
   161  }
   162  
   163  // SkipUnlessServerVersionGTE skips if the server version is less than v.
   164  func SkipUnlessServerVersionGTE(v *utilversion.Version, c discovery.ServerVersionInterface) {
   165  	gte, err := serverVersionGTE(v, c)
   166  	if err != nil {
   167  		framework.Failf("Failed to get server version: %v", err)
   168  	}
   169  	if !gte {
   170  		skipInternalf(1, "Not supported for server versions before %q", v)
   171  	}
   172  }
   173  
   174  // SkipUnlessSSHKeyPresent skips if no SSH key is found.
   175  func SkipUnlessSSHKeyPresent() {
   176  	if _, err := e2essh.GetSigner(framework.TestContext.Provider); err != nil {
   177  		skipInternalf(1, "No SSH Key for provider %s: '%v'", framework.TestContext.Provider, err)
   178  	}
   179  }
   180  
   181  // serverVersionGTE returns true if v is greater than or equal to the server version.
   182  func serverVersionGTE(v *utilversion.Version, c discovery.ServerVersionInterface) (bool, error) {
   183  	serverVersion, err := c.ServerVersion()
   184  	if err != nil {
   185  		return false, fmt.Errorf("Unable to get server version: %w", err)
   186  	}
   187  	sv, err := utilversion.ParseSemantic(serverVersion.GitVersion)
   188  	if err != nil {
   189  		return false, fmt.Errorf("Unable to parse server version %q: %w", serverVersion.GitVersion, err)
   190  	}
   191  	return sv.AtLeast(v), nil
   192  }
   193  
   194  // AppArmorDistros are distros with AppArmor support
   195  var AppArmorDistros = []string{"gci", "ubuntu"}
   196  
   197  // SkipIfAppArmorNotSupported skips if the AppArmor is not supported by the node OS distro.
   198  func SkipIfAppArmorNotSupported() {
   199  	SkipUnlessNodeOSDistroIs(AppArmorDistros...)
   200  }
   201  
   202  // SkipUnlessComponentRunsAsPodsAndClientCanDeleteThem run if the component run as pods and client can delete them
   203  func SkipUnlessComponentRunsAsPodsAndClientCanDeleteThem(ctx context.Context, componentName string, c clientset.Interface, ns string, labelSet labels.Set) {
   204  	// verify if component run as pod
   205  	label := labels.SelectorFromSet(labelSet)
   206  	listOpts := metav1.ListOptions{LabelSelector: label.String()}
   207  	pods, err := c.CoreV1().Pods(ns).List(ctx, listOpts)
   208  	framework.Logf("SkipUnlessComponentRunsAsPodsAndClientCanDeleteThem: %v, %v", pods, err)
   209  	if err != nil {
   210  		skipInternalf(1, "Skipped because client failed to get component:%s pod err:%v", componentName, err)
   211  	}
   212  
   213  	if len(pods.Items) == 0 {
   214  		skipInternalf(1, "Skipped because component:%s is not running as pod.", componentName)
   215  	}
   216  
   217  	// verify if client can delete pod
   218  	pod := pods.Items[0]
   219  	if err := c.CoreV1().Pods(ns).Delete(ctx, pod.Name, metav1.DeleteOptions{DryRun: []string{metav1.DryRunAll}}); err != nil {
   220  		skipInternalf(1, "Skipped because client failed to delete component:%s pod, err:%v", componentName, err)
   221  	}
   222  }
   223  
   224  // SkipIfIPv6 skips if the cluster IP family is IPv6 and the provider is included in the unsupportedProviders.
   225  func SkipIfIPv6(unsupportedProviders ...string) {
   226  	if framework.TestContext.ClusterIsIPv6() && framework.ProviderIs(unsupportedProviders...) {
   227  		skipInternalf(1, "Not supported for IPv6 clusters and providers %v (found %s)", unsupportedProviders, framework.TestContext.Provider)
   228  	}
   229  }
   230  

View as plain text