1
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
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
175
176
177
178 _, err = leaseClient.List(ctx, metav1.ListOptions{})
179 framework.ExpectNoError(err, "couldn't list Leases from all namespace")
180 })
181 })
182
View as plain text