k8s.io/kubernetes@v1.29.3/test/e2e/common/node/lease.go (about)

     1  /*
     2  Copyright 2019 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 node
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"time"
    24  
    25  	coordinationv1 "k8s.io/api/coordination/v1"
    26  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    27  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/labels"
    30  	"k8s.io/apimachinery/pkg/types"
    31  	"k8s.io/apimachinery/pkg/util/strategicpatch"
    32  	"k8s.io/kubernetes/test/e2e/framework"
    33  	admissionapi "k8s.io/pod-security-admission/api"
    34  	"k8s.io/utils/pointer"
    35  
    36  	"github.com/google/go-cmp/cmp"
    37  	"github.com/onsi/gomega"
    38  )
    39  
    40  func getPatchBytes(oldLease, newLease *coordinationv1.Lease) ([]byte, error) {
    41  	oldData, err := json.Marshal(oldLease)
    42  	if err != nil {
    43  		return nil, fmt.Errorf("failed to Marshal oldData: %w", err)
    44  	}
    45  	newData, err := json.Marshal(newLease)
    46  	if err != nil {
    47  		return nil, fmt.Errorf("failed to Marshal newData: %w", err)
    48  	}
    49  	patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, coordinationv1.Lease{})
    50  	if err != nil {
    51  		return nil, fmt.Errorf("failed to CreateTwoWayMergePatch: %w", err)
    52  	}
    53  	return patchBytes, nil
    54  }
    55  
    56  var _ = SIGDescribe("Lease", func() {
    57  	f := framework.NewDefaultFramework("lease-test")
    58  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    59  
    60  	/*
    61  		Release: v1.17
    62  		Testname: lease API should be available
    63  		Description: Create Lease object, and get it; create and get MUST be successful and Spec of the
    64  		read Lease MUST match Spec of original Lease. Update the Lease and get it; update and get MUST
    65  		be successful	and Spec of the read Lease MUST match Spec of updated Lease. Patch the Lease and
    66  		get it; patch and get MUST be successful and Spec of the read Lease MUST match Spec of patched
    67  		Lease. Create a second Lease with labels and list Leases; create and list MUST be successful and
    68  		list MUST return both leases. Delete the labels lease via delete collection; the delete MUST be
    69  		successful and MUST delete only the labels lease. List leases; list MUST be successful and MUST
    70  		return just the remaining lease. Delete the lease; delete MUST be successful. Get the lease; get
    71  		MUST return not found error.
    72  	*/
    73  	framework.ConformanceIt("lease API should be available", func(ctx context.Context) {
    74  		leaseClient := f.ClientSet.CoordinationV1().Leases(f.Namespace.Name)
    75  
    76  		name := "lease"
    77  		lease := &coordinationv1.Lease{
    78  			ObjectMeta: metav1.ObjectMeta{
    79  				Name: name,
    80  			},
    81  			Spec: coordinationv1.LeaseSpec{
    82  				HolderIdentity:       pointer.String("holder"),
    83  				LeaseDurationSeconds: pointer.Int32(30),
    84  				AcquireTime:          &metav1.MicroTime{Time: time.Time{}.Add(2 * time.Second)},
    85  				RenewTime:            &metav1.MicroTime{Time: time.Time{}.Add(5 * time.Second)},
    86  				LeaseTransitions:     pointer.Int32(0),
    87  			},
    88  		}
    89  
    90  		createdLease, err := leaseClient.Create(ctx, lease, metav1.CreateOptions{})
    91  		framework.ExpectNoError(err, "creating Lease failed")
    92  
    93  		readLease, err := leaseClient.Get(ctx, name, metav1.GetOptions{})
    94  		framework.ExpectNoError(err, "couldn't read Lease")
    95  		if !apiequality.Semantic.DeepEqual(lease.Spec, readLease.Spec) {
    96  			framework.Failf("Leases don't match. Diff (- for expected, + for actual):\n%s", cmp.Diff(lease.Spec, readLease.Spec))
    97  		}
    98  
    99  		createdLease.Spec = coordinationv1.LeaseSpec{
   100  			HolderIdentity:       pointer.String("holder2"),
   101  			LeaseDurationSeconds: pointer.Int32(30),
   102  			AcquireTime:          &metav1.MicroTime{Time: time.Time{}.Add(20 * time.Second)},
   103  			RenewTime:            &metav1.MicroTime{Time: time.Time{}.Add(50 * time.Second)},
   104  			LeaseTransitions:     pointer.Int32(1),
   105  		}
   106  
   107  		_, err = leaseClient.Update(ctx, createdLease, metav1.UpdateOptions{})
   108  		framework.ExpectNoError(err, "updating Lease failed")
   109  
   110  		readLease, err = leaseClient.Get(ctx, name, metav1.GetOptions{})
   111  		framework.ExpectNoError(err, "couldn't read Lease")
   112  		if !apiequality.Semantic.DeepEqual(createdLease.Spec, readLease.Spec) {
   113  			framework.Failf("Leases don't match. Diff (- for expected, + for actual):\n%s", cmp.Diff(createdLease.Spec, readLease.Spec))
   114  		}
   115  
   116  		patchedLease := readLease.DeepCopy()
   117  		patchedLease.Spec = coordinationv1.LeaseSpec{
   118  			HolderIdentity:       pointer.String("holder3"),
   119  			LeaseDurationSeconds: pointer.Int32(60),
   120  			AcquireTime:          &metav1.MicroTime{Time: time.Time{}.Add(50 * time.Second)},
   121  			RenewTime:            &metav1.MicroTime{Time: time.Time{}.Add(70 * time.Second)},
   122  			LeaseTransitions:     pointer.Int32(2),
   123  		}
   124  		patchBytes, err := getPatchBytes(readLease, patchedLease)
   125  		framework.ExpectNoError(err, "creating patch failed")
   126  
   127  		_, err = leaseClient.Patch(ctx, name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
   128  		framework.ExpectNoError(err, "patching Lease failed")
   129  
   130  		readLease, err = leaseClient.Get(ctx, name, metav1.GetOptions{})
   131  		framework.ExpectNoError(err, "couldn't read Lease")
   132  		if !apiequality.Semantic.DeepEqual(patchedLease.Spec, readLease.Spec) {
   133  			framework.Failf("Leases don't match. Diff (- for expected, + for actual):\n%s", cmp.Diff(patchedLease.Spec, readLease.Spec))
   134  		}
   135  
   136  		name2 := "lease2"
   137  		lease2 := &coordinationv1.Lease{
   138  			ObjectMeta: metav1.ObjectMeta{
   139  				Name:   name2,
   140  				Labels: map[string]string{"deletecollection": "true"},
   141  			},
   142  			Spec: coordinationv1.LeaseSpec{
   143  				HolderIdentity:       pointer.String("holder"),
   144  				LeaseDurationSeconds: pointer.Int32(30),
   145  				AcquireTime:          &metav1.MicroTime{Time: time.Time{}.Add(2 * time.Second)},
   146  				RenewTime:            &metav1.MicroTime{Time: time.Time{}.Add(5 * time.Second)},
   147  				LeaseTransitions:     pointer.Int32(0),
   148  			},
   149  		}
   150  		_, err = leaseClient.Create(ctx, lease2, metav1.CreateOptions{})
   151  		framework.ExpectNoError(err, "creating Lease failed")
   152  
   153  		leases, err := leaseClient.List(ctx, metav1.ListOptions{})
   154  		framework.ExpectNoError(err, "couldn't list Leases")
   155  		gomega.Expect(leases.Items).To(gomega.HaveLen(2))
   156  
   157  		selector := labels.Set(map[string]string{"deletecollection": "true"}).AsSelector()
   158  		err = leaseClient.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: selector.String()})
   159  		framework.ExpectNoError(err, "couldn't delete collection")
   160  
   161  		leases, err = leaseClient.List(ctx, metav1.ListOptions{})
   162  		framework.ExpectNoError(err, "couldn't list Leases")
   163  		gomega.Expect(leases.Items).To(gomega.HaveLen(1))
   164  
   165  		err = leaseClient.Delete(ctx, name, metav1.DeleteOptions{})
   166  		framework.ExpectNoError(err, "deleting Lease failed")
   167  
   168  		_, err = leaseClient.Get(ctx, name, metav1.GetOptions{})
   169  		if !apierrors.IsNotFound(err) {
   170  			framework.Failf("expected IsNotFound error, got %#v", err)
   171  		}
   172  
   173  		leaseClient = f.ClientSet.CoordinationV1().Leases(metav1.NamespaceAll)
   174  		// Number of leases may be high in large clusters, as Lease object is
   175  		// created for every node by the corresponding Kubelet.
   176  		// That said, the objects themselves are small (~300B), so even with 5000
   177  		// of them, that gives ~1.5MB, which is acceptable.
   178  		_, err = leaseClient.List(ctx, metav1.ListOptions{})
   179  		framework.ExpectNoError(err, "couldn't list Leases from all namespace")
   180  	})
   181  })