k8s.io/client-go@v0.31.1/tools/leaderelection/leasecandidate_test.go (about) 1 /* 2 Copyright 2024 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 leaderelection 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 v1 "k8s.io/api/coordination/v1" 25 "k8s.io/apimachinery/pkg/api/errors" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/util/wait" 28 "k8s.io/client-go/kubernetes/fake" 29 ) 30 31 type testcase struct { 32 candidateName, candidateNamespace, leaseName string 33 binaryVersion, emulationVersion string 34 } 35 36 func TestLeaseCandidateCreation(t *testing.T) { 37 tc := testcase{ 38 candidateName: "foo", 39 candidateNamespace: "default", 40 leaseName: "lease", 41 binaryVersion: "1.30.0", 42 emulationVersion: "1.30.0", 43 } 44 45 ctx, cancel := context.WithTimeout(context.Background(), time.Minute) 46 defer cancel() 47 48 client := fake.NewSimpleClientset() 49 candidate, _, err := NewCandidate( 50 client, 51 tc.candidateNamespace, 52 tc.candidateName, 53 tc.leaseName, 54 tc.binaryVersion, 55 tc.emulationVersion, 56 []v1.CoordinatedLeaseStrategy{v1.OldestEmulationVersion}, 57 ) 58 if err != nil { 59 t.Fatal(err) 60 } 61 62 go candidate.Run(ctx) 63 err = pollForLease(ctx, tc, client, nil) 64 if err != nil { 65 t.Fatal(err) 66 } 67 } 68 69 func TestLeaseCandidateAck(t *testing.T) { 70 tc := testcase{ 71 candidateName: "foo", 72 candidateNamespace: "default", 73 leaseName: "lease", 74 binaryVersion: "1.30.0", 75 emulationVersion: "1.30.0", 76 } 77 78 ctx, cancel := context.WithTimeout(context.Background(), time.Minute) 79 defer cancel() 80 81 client := fake.NewSimpleClientset() 82 83 candidate, _, err := NewCandidate( 84 client, 85 tc.candidateNamespace, 86 tc.candidateName, 87 tc.leaseName, 88 tc.binaryVersion, 89 tc.emulationVersion, 90 []v1.CoordinatedLeaseStrategy{v1.OldestEmulationVersion}, 91 ) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 go candidate.Run(ctx) 97 err = pollForLease(ctx, tc, client, nil) 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 // Update PingTime and verify that the client renews 103 ensureAfter := &metav1.MicroTime{Time: time.Now()} 104 lc, err := client.CoordinationV1alpha1().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{}) 105 if err == nil { 106 if lc.Spec.PingTime == nil { 107 c := lc.DeepCopy() 108 c.Spec.PingTime = &metav1.MicroTime{Time: time.Now()} 109 _, err = client.CoordinationV1alpha1().LeaseCandidates(tc.candidateNamespace).Update(ctx, c, metav1.UpdateOptions{}) 110 if err != nil { 111 t.Error(err) 112 } 113 } 114 } 115 err = pollForLease(ctx, tc, client, ensureAfter) 116 if err != nil { 117 t.Fatal(err) 118 } 119 } 120 121 func pollForLease(ctx context.Context, tc testcase, client *fake.Clientset, t *metav1.MicroTime) error { 122 return wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 10*time.Second, true, func(ctx context.Context) (done bool, err error) { 123 lc, err := client.CoordinationV1alpha1().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{}) 124 if err != nil { 125 if errors.IsNotFound(err) { 126 return false, nil 127 } 128 return true, err 129 } 130 if lc.Spec.BinaryVersion == tc.binaryVersion && 131 lc.Spec.EmulationVersion == tc.emulationVersion && 132 lc.Spec.LeaseName == tc.leaseName && 133 lc.Spec.RenewTime != nil { 134 // Ensure that if a time is provided, the renewTime occurred after the provided time. 135 if t != nil && t.After(lc.Spec.RenewTime.Time) { 136 return false, nil 137 } 138 return true, nil 139 } 140 return false, nil 141 }) 142 }