...

Source file src/k8s.io/kubernetes/test/e2e/upgrades/network/services.go

Documentation: k8s.io/kubernetes/test/e2e/upgrades/network

     1  /*
     2  Copyright 2017 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 network
    18  
    19  import (
    20  	"context"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/util/wait"
    24  	"k8s.io/kubernetes/test/e2e/framework"
    25  	e2eservice "k8s.io/kubernetes/test/e2e/framework/service"
    26  	"k8s.io/kubernetes/test/e2e/upgrades"
    27  
    28  	"github.com/onsi/ginkgo/v2"
    29  )
    30  
    31  // ServiceUpgradeTest tests that a service is available before and
    32  // after a cluster upgrade. During a master-only upgrade, it will test
    33  // that a service remains available during the upgrade.
    34  type ServiceUpgradeTest struct {
    35  	jig          *e2eservice.TestJig
    36  	tcpService   *v1.Service
    37  	tcpIngressIP string
    38  	svcPort      int
    39  }
    40  
    41  // Name returns the tracking name of the test.
    42  func (ServiceUpgradeTest) Name() string { return "service-upgrade" }
    43  
    44  // Setup creates a service with a load balancer and makes sure it's reachable.
    45  func (t *ServiceUpgradeTest) Setup(ctx context.Context, f *framework.Framework) {
    46  	serviceName := "service-test"
    47  	jig := e2eservice.NewTestJig(f.ClientSet, f.Namespace.Name, serviceName)
    48  
    49  	ns := f.Namespace
    50  	cs := f.ClientSet
    51  
    52  	ginkgo.By("creating a TCP service " + serviceName + " with type=LoadBalancer in namespace " + ns.Name)
    53  	_, err := jig.CreateTCPService(ctx, func(s *v1.Service) {
    54  		s.Spec.Type = v1.ServiceTypeLoadBalancer
    55  	})
    56  	framework.ExpectNoError(err)
    57  	tcpService, err := jig.WaitForLoadBalancer(ctx, e2eservice.GetServiceLoadBalancerCreationTimeout(ctx, cs))
    58  	framework.ExpectNoError(err)
    59  
    60  	// Get info to hit it with
    61  	tcpIngressIP := e2eservice.GetIngressPoint(&tcpService.Status.LoadBalancer.Ingress[0])
    62  	svcPort := int(tcpService.Spec.Ports[0].Port)
    63  
    64  	ginkgo.By("creating pod to be part of service " + serviceName)
    65  	rc, err := jig.Run(ctx, jig.AddRCAntiAffinity)
    66  	framework.ExpectNoError(err)
    67  
    68  	ginkgo.By("creating a PodDisruptionBudget to cover the ReplicationController")
    69  	_, err = jig.CreatePDB(ctx, rc)
    70  	framework.ExpectNoError(err)
    71  
    72  	// Hit it once before considering ourselves ready
    73  	ginkgo.By("hitting the pod through the service's LoadBalancer")
    74  	timeout := e2eservice.LoadBalancerLagTimeoutDefault
    75  	if framework.ProviderIs("aws") {
    76  		timeout = e2eservice.LoadBalancerLagTimeoutAWS
    77  	}
    78  	e2eservice.TestReachableHTTP(ctx, tcpIngressIP, svcPort, timeout)
    79  
    80  	t.jig = jig
    81  	t.tcpService = tcpService
    82  	t.tcpIngressIP = tcpIngressIP
    83  	t.svcPort = svcPort
    84  }
    85  
    86  // Test runs a connectivity check to the service.
    87  func (t *ServiceUpgradeTest) Test(ctx context.Context, f *framework.Framework, done <-chan struct{}, upgrade upgrades.UpgradeType) {
    88  	switch upgrade {
    89  	case upgrades.MasterUpgrade, upgrades.ClusterUpgrade:
    90  		t.test(ctx, f, done, true, true)
    91  	case upgrades.NodeUpgrade:
    92  		t.test(ctx, f, done, true, false)
    93  	default:
    94  		t.test(ctx, f, done, false, false)
    95  	}
    96  }
    97  
    98  // Teardown cleans up any remaining resources.
    99  func (t *ServiceUpgradeTest) Teardown(ctx context.Context, f *framework.Framework) {
   100  	// rely on the namespace deletion to clean up everything
   101  }
   102  
   103  func (t *ServiceUpgradeTest) test(ctx context.Context, f *framework.Framework, done <-chan struct{}, testDuringDisruption, testFinalizer bool) {
   104  	if testDuringDisruption {
   105  		// Continuous validation
   106  		ginkgo.By("continuously hitting the pod through the service's LoadBalancer")
   107  		// TODO (pohly): add context support
   108  		wait.Until(func() {
   109  			e2eservice.TestReachableHTTP(ctx, t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
   110  		}, framework.Poll, done)
   111  	} else {
   112  		// Block until upgrade is done
   113  		ginkgo.By("waiting for upgrade to finish without checking if service remains up")
   114  		<-done
   115  	}
   116  
   117  	// Hit it once more
   118  	ginkgo.By("hitting the pod through the service's LoadBalancer")
   119  	e2eservice.TestReachableHTTP(ctx, t.tcpIngressIP, t.svcPort, e2eservice.LoadBalancerLagTimeoutDefault)
   120  	if testFinalizer {
   121  		defer func() {
   122  			ginkgo.By("Check that service can be deleted with finalizer")
   123  			e2eservice.WaitForServiceDeletedWithFinalizer(ctx, t.jig.Client, t.tcpService.Namespace, t.tcpService.Name)
   124  		}()
   125  		ginkgo.By("Check that finalizer is present on loadBalancer type service")
   126  		e2eservice.WaitForServiceUpdatedWithFinalizer(ctx, t.jig.Client, t.tcpService.Namespace, t.tcpService.Name, true)
   127  	}
   128  }
   129  

View as plain text