Add LeaseCandidate v1beta1

This commit is contained in:
Jefftree 2025-02-19 21:43:35 +00:00
parent caf541857f
commit 5ba4a90fda
19 changed files with 331 additions and 220 deletions

View File

@ -108,6 +108,8 @@ type LeaseCandidate struct {
// LeaseCandidateSpec is a specification of a Lease.
type LeaseCandidateSpec struct {
// LeaseName is the name of the lease for which this candidate is contending.
// The limits on this field are the same as on Lease.name. Multiple lease candidates
// may reference the same Lease.name.
// This field is immutable.
// +required
LeaseName string

View File

@ -285,6 +285,7 @@ func DefaultGenericAPIServicePriorities() map[schema.GroupVersion]APIServicePrio
{Group: "admissionregistration.k8s.io", Version: "v1beta1"}: {Group: 16700, Version: 12},
{Group: "admissionregistration.k8s.io", Version: "v1alpha1"}: {Group: 16700, Version: 9},
{Group: "coordination.k8s.io", Version: "v1"}: {Group: 16500, Version: 15},
{Group: "coordination.k8s.io", Version: "v1beta1"}: {Group: 16500, Version: 13},
{Group: "coordination.k8s.io", Version: "v1alpha2"}: {Group: 16500, Version: 12},
{Group: "discovery.k8s.io", Version: "v1"}: {Group: 16200, Version: 15},
{Group: "discovery.k8s.io", Version: "v1beta1"}: {Group: 16200, Version: 12},

View File

@ -166,7 +166,7 @@ func (c completedConfig) New(name string, delegationTarget genericapiserver.Dele
if utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.CoordinatedLeaderElection) {
leaseInformer := s.VersionedInformers.Coordination().V1().Leases()
lcInformer := s.VersionedInformers.Coordination().V1alpha2().LeaseCandidates()
lcInformer := s.VersionedInformers.Coordination().V1beta1().LeaseCandidates()
// Ensure that informers are registered before starting. Coordinated Leader Election leader-elected
// and may register informer handlers after they are started.
_ = leaseInformer.Informer()
@ -177,7 +177,7 @@ func (c completedConfig) New(name string, delegationTarget genericapiserver.Dele
leaseInformer,
lcInformer,
client.CoordinationV1(),
client.CoordinationV1alpha2(),
client.CoordinationV1beta1(),
)
gccontroller := leaderelection.NewLeaseCandidateGC(
client,

View File

@ -22,12 +22,12 @@ import (
"github.com/blang/semver/v4"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
"k8s.io/utils/clock"
)
func pickBestLeaderOldestEmulationVersion(candidates []*v1alpha2.LeaseCandidate) *v1alpha2.LeaseCandidate {
var electee *v1alpha2.LeaseCandidate
func pickBestLeaderOldestEmulationVersion(candidates []*v1beta1.LeaseCandidate) *v1beta1.LeaseCandidate {
var electee *v1beta1.LeaseCandidate
for _, c := range candidates {
if !validLeaseCandidateForOldestEmulationVersion(c) {
continue
@ -39,7 +39,7 @@ func pickBestLeaderOldestEmulationVersion(candidates []*v1alpha2.LeaseCandidate)
return electee
}
func pickBestStrategy(candidates []*v1alpha2.LeaseCandidate) (v1.CoordinatedLeaseStrategy, error) {
func pickBestStrategy(candidates []*v1beta1.LeaseCandidate) (v1.CoordinatedLeaseStrategy, error) {
nilStrategy := v1.CoordinatedLeaseStrategy("")
if len(candidates) == 0 {
return nilStrategy, fmt.Errorf("no candidates")
@ -62,7 +62,7 @@ func pickBestStrategy(candidates []*v1alpha2.LeaseCandidate) (v1.CoordinatedLeas
return strategy, nil
}
func validLeaseCandidateForOldestEmulationVersion(l *v1alpha2.LeaseCandidate) bool {
func validLeaseCandidateForOldestEmulationVersion(l *v1beta1.LeaseCandidate) bool {
_, err := semver.ParseTolerant(l.Spec.EmulationVersion)
if err != nil {
return false
@ -71,7 +71,7 @@ func validLeaseCandidateForOldestEmulationVersion(l *v1alpha2.LeaseCandidate) bo
return err == nil
}
func getEmulationVersionOrZero(l *v1alpha2.LeaseCandidate) semver.Version {
func getEmulationVersionOrZero(l *v1beta1.LeaseCandidate) semver.Version {
value := l.Spec.EmulationVersion
v, err := semver.ParseTolerant(value)
if err != nil {
@ -80,7 +80,7 @@ func getEmulationVersionOrZero(l *v1alpha2.LeaseCandidate) semver.Version {
return v
}
func getBinaryVersionOrZero(l *v1alpha2.LeaseCandidate) semver.Version {
func getBinaryVersionOrZero(l *v1beta1.LeaseCandidate) semver.Version {
value := l.Spec.BinaryVersion
v, err := semver.ParseTolerant(value)
if err != nil {
@ -90,7 +90,7 @@ func getBinaryVersionOrZero(l *v1alpha2.LeaseCandidate) semver.Version {
}
// -1: lhs better, 1: rhs better
func compare(lhs, rhs *v1alpha2.LeaseCandidate) int {
func compare(lhs, rhs *v1beta1.LeaseCandidate) int {
l := getEmulationVersionOrZero(lhs)
r := getEmulationVersionOrZero(rhs)
result := l.Compare(r)
@ -115,7 +115,7 @@ func isLeaseExpired(clock clock.Clock, lease *v1.Lease) bool {
lease.Spec.RenewTime.Add(time.Duration(*lease.Spec.LeaseDurationSeconds)*time.Second).Before(currentTime)
}
func isLeaseCandidateExpired(clock clock.Clock, lease *v1alpha2.LeaseCandidate) bool {
func isLeaseCandidateExpired(clock clock.Clock, lease *v1beta1.LeaseCandidate) bool {
currentTime := clock.Now()
return lease.Spec.RenewTime == nil ||
lease.Spec.RenewTime.Add(leaseCandidateValidDuration).Before(currentTime)

View File

@ -22,42 +22,42 @@ import (
"github.com/blang/semver/v4"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
tests := []struct {
name string
candidates []*v1alpha2.LeaseCandidate
want *v1alpha2.LeaseCandidate
candidates []*v1beta1.LeaseCandidate
want *v1beta1.LeaseCandidate
}{
{
name: "empty",
candidates: []*v1alpha2.LeaseCandidate{},
candidates: []*v1beta1.LeaseCandidate{},
want: nil,
},
{
name: "single candidate",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
},
},
want: &v1alpha2.LeaseCandidate{
want: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -65,14 +65,14 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
},
{
name: "multiple candidates, different emulation versions",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now().Add(-1 * time.Hour)},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -83,18 +83,18 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.2.0",
BinaryVersion: "0.2.0",
},
},
},
want: &v1alpha2.LeaseCandidate{
want: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "v1",
BinaryVersion: "v1",
},
@ -102,14 +102,14 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
},
{
name: "multiple candidates, same emulation versions, different binary versions",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now().Add(-1 * time.Hour)},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -120,18 +120,18 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.2.0",
},
},
},
want: &v1alpha2.LeaseCandidate{
want: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -139,14 +139,14 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
},
{
name: "multiple candidates, same emulation versions, same binary versions, different creation timestamps",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now().Add(-1 * time.Hour)},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -157,18 +157,18 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
},
},
want: &v1alpha2.LeaseCandidate{
want: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -192,13 +192,13 @@ func TestPickBestLeaderOldestEmulationVersion(t *testing.T) {
func TestValidLeaseCandidateForOldestEmulationVersion(t *testing.T) {
tests := []struct {
name string
candidate *v1alpha2.LeaseCandidate
candidate *v1beta1.LeaseCandidate
want bool
}{
{
name: "valid emulation and binary versions",
candidate: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
candidate: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "0.1.0",
},
@ -207,8 +207,8 @@ func TestValidLeaseCandidateForOldestEmulationVersion(t *testing.T) {
},
{
name: "invalid emulation version",
candidate: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
candidate: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "invalid",
BinaryVersion: "0.1.0",
},
@ -217,8 +217,8 @@ func TestValidLeaseCandidateForOldestEmulationVersion(t *testing.T) {
},
{
name: "invalid binary version",
candidate: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
candidate: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
BinaryVersion: "invalid",
},
@ -239,13 +239,13 @@ func TestValidLeaseCandidateForOldestEmulationVersion(t *testing.T) {
func TestGetEmulationVersion(t *testing.T) {
tests := []struct {
name string
candidate *v1alpha2.LeaseCandidate
candidate *v1beta1.LeaseCandidate
want semver.Version
}{
{
name: "valid emulation version",
candidate: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
candidate: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "0.1.0",
},
},
@ -265,13 +265,13 @@ func TestGetEmulationVersion(t *testing.T) {
func TestGetBinaryVersion(t *testing.T) {
tests := []struct {
name string
candidate *v1alpha2.LeaseCandidate
candidate *v1beta1.LeaseCandidate
want semver.Version
}{
{
name: "valid binary version",
candidate: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
candidate: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
BinaryVersion: "0.3.0",
},
},
@ -292,14 +292,14 @@ func TestCompare(t *testing.T) {
nowTime := time.Now()
cases := []struct {
name string
lhs *v1alpha2.LeaseCandidate
rhs *v1alpha2.LeaseCandidate
lhs *v1beta1.LeaseCandidate
rhs *v1beta1.LeaseCandidate
expectedResult int
}{
{
name: "identical versions earlier timestamp",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
@ -307,8 +307,8 @@ func TestCompare(t *testing.T) {
CreationTimestamp: metav1.Time{Time: nowTime.Add(time.Duration(1))},
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
@ -320,9 +320,9 @@ func TestCompare(t *testing.T) {
},
{
name: "no lhs version",
lhs: &v1alpha2.LeaseCandidate{},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{},
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
@ -331,25 +331,25 @@ func TestCompare(t *testing.T) {
},
{
name: "no rhs version",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
},
rhs: &v1alpha2.LeaseCandidate{},
rhs: &v1beta1.LeaseCandidate{},
expectedResult: 1,
},
{
name: "invalid lhs version",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "xyz",
BinaryVersion: "xyz",
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
@ -358,14 +358,14 @@ func TestCompare(t *testing.T) {
},
{
name: "invalid rhs version",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.21.0",
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "xyz",
BinaryVersion: "xyz",
},
@ -374,14 +374,14 @@ func TestCompare(t *testing.T) {
},
{
name: "lhs less than rhs",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.20.0",
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.20.0",
},
@ -390,14 +390,14 @@ func TestCompare(t *testing.T) {
},
{
name: "rhs less than lhs",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.20.0",
BinaryVersion: "1.20.0",
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.20.0",
},
@ -406,14 +406,14 @@ func TestCompare(t *testing.T) {
},
{
name: "lhs less than rhs, lexographical order check",
lhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
lhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.2.0",
BinaryVersion: "1.20.0",
},
},
rhs: &v1alpha2.LeaseCandidate{
Spec: v1alpha2.LeaseCandidateSpec{
rhs: &v1beta1.LeaseCandidate{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.20.0",
},
@ -434,18 +434,18 @@ func TestCompare(t *testing.T) {
func TestShouldReelect(t *testing.T) {
cases := []struct {
name string
candidates []*v1alpha2.LeaseCandidate
currentLeader *v1alpha2.LeaseCandidate
candidates []*v1beta1.LeaseCandidate
currentLeader *v1beta1.LeaseCandidate
expectResult bool
}{
{
name: "candidate with newer binary version",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
@ -455,18 +455,18 @@ func TestShouldReelect(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.20.0",
Strategy: v1.OldestEmulationVersion,
},
},
},
currentLeader: &v1alpha2.LeaseCandidate{
currentLeader: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
@ -476,12 +476,12 @@ func TestShouldReelect(t *testing.T) {
},
{
name: "no newer candidates",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
@ -491,18 +491,18 @@ func TestShouldReelect(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
},
},
},
currentLeader: &v1alpha2.LeaseCandidate{
currentLeader: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
@ -512,12 +512,12 @@ func TestShouldReelect(t *testing.T) {
},
{
name: "no candidates",
candidates: []*v1alpha2.LeaseCandidate{},
currentLeader: &v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{},
currentLeader: &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
Strategy: v1.OldestEmulationVersion,
@ -539,19 +539,19 @@ func TestShouldReelect(t *testing.T) {
func TestPickBestStrategy(t *testing.T) {
tests := []struct {
name string
candidates []*v1alpha2.LeaseCandidate
candidates []*v1beta1.LeaseCandidate
wantStrategy v1.CoordinatedLeaseStrategy
wantError bool
}{
{
name: "single candidate, single preferred strategy",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
Strategy: v1.OldestEmulationVersion,
},
@ -562,13 +562,13 @@ func TestPickBestStrategy(t *testing.T) {
},
{
name: "multiple candidates, different preferred strategies should fail",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
Strategy: v1.OldestEmulationVersion,
},
@ -578,7 +578,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
Strategy: v1.CoordinatedLeaseStrategy("foo.com/bar"),
},
@ -588,13 +588,13 @@ func TestPickBestStrategy(t *testing.T) {
},
{
name: "multiple candidates, different preferred strategy different binary version should resolve",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.32.0",
Strategy: v1.OldestEmulationVersion,
@ -605,7 +605,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.CoordinatedLeaseStrategy("foo.com/bar"),
@ -617,13 +617,13 @@ func TestPickBestStrategy(t *testing.T) {
},
{
name: "multiple candidates, different preferred strategy different binary version should resolve, order agnostic",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.CoordinatedLeaseStrategy("foo.com/bar"),
@ -634,7 +634,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.32.0",
Strategy: v1.OldestEmulationVersion,
@ -646,13 +646,13 @@ func TestPickBestStrategy(t *testing.T) {
},
{
name: "multiple candidates, different preferred strategy different binary version string comparison check",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.1.10",
Strategy: v1.OldestEmulationVersion,
@ -663,7 +663,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.1.2",
Strategy: v1.CoordinatedLeaseStrategy("foo.com/bar"),
@ -676,13 +676,13 @@ func TestPickBestStrategy(t *testing.T) {
{
name: "multiple candidates, same preferred strategy",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.OldestEmulationVersion,
@ -693,7 +693,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.OldestEmulationVersion,
@ -705,13 +705,13 @@ func TestPickBestStrategy(t *testing.T) {
},
{
name: "multiple candidates, conflicting preferred strategy",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.OldestEmulationVersion,
@ -722,7 +722,7 @@ func TestPickBestStrategy(t *testing.T) {
Name: "candidate2",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
BinaryVersion: "1.31.0",
Strategy: v1.CoordinatedLeaseStrategy("foo.com/bar"),
@ -748,7 +748,7 @@ func TestPickBestStrategy(t *testing.T) {
}
}
func shouldReelect(candidates []*v1alpha2.LeaseCandidate, currentLeader *v1alpha2.LeaseCandidate) bool {
func shouldReelect(candidates []*v1beta1.LeaseCandidate, currentLeader *v1beta1.LeaseCandidate) bool {
pickedLeader := pickBestLeaderOldestEmulationVersion(candidates)
if pickedLeader == nil {
return false

View File

@ -24,7 +24,7 @@ import (
"golang.org/x/sync/errgroup"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
@ -32,9 +32,9 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
coordinationv1informers "k8s.io/client-go/informers/coordination/v1"
coordinationv1alpha2 "k8s.io/client-go/informers/coordination/v1alpha2"
coordinationv1beta1 "k8s.io/client-go/informers/coordination/v1beta1"
coordinationv1client "k8s.io/client-go/kubernetes/typed/coordination/v1"
coordinationv1alpha2client "k8s.io/client-go/kubernetes/typed/coordination/v1alpha2"
coordinationv1beta1client "k8s.io/client-go/kubernetes/typed/coordination/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
@ -65,8 +65,8 @@ type Controller struct {
leaseClient coordinationv1client.CoordinationV1Interface
leaseRegistration cache.ResourceEventHandlerRegistration
leaseCandidateInformer coordinationv1alpha2.LeaseCandidateInformer
leaseCandidateClient coordinationv1alpha2client.CoordinationV1alpha2Interface
leaseCandidateInformer coordinationv1beta1.LeaseCandidateInformer
leaseCandidateClient coordinationv1beta1client.CoordinationV1beta1Interface
leaseCandidateRegistration cache.ResourceEventHandlerRegistration
queue workqueue.TypedRateLimitingInterface[types.NamespacedName]
@ -110,7 +110,7 @@ func (c *Controller) Run(ctx context.Context, workers int) {
<-ctx.Done()
}
func NewController(leaseInformer coordinationv1informers.LeaseInformer, leaseCandidateInformer coordinationv1alpha2.LeaseCandidateInformer, leaseClient coordinationv1client.CoordinationV1Interface, leaseCandidateClient coordinationv1alpha2client.CoordinationV1alpha2Interface) (*Controller, error) {
func NewController(leaseInformer coordinationv1informers.LeaseInformer, leaseCandidateInformer coordinationv1beta1.LeaseCandidateInformer, leaseClient coordinationv1client.CoordinationV1Interface, leaseCandidateClient coordinationv1beta1client.CoordinationV1beta1Interface) (*Controller, error) {
c := &Controller{
leaseInformer: leaseInformer,
leaseCandidateInformer: leaseCandidateInformer,
@ -175,7 +175,7 @@ func (c *Controller) processNextElectionItem(ctx context.Context) bool {
}
func (c *Controller) enqueueCandidate(obj any) {
lc, ok := obj.(*v1alpha2.LeaseCandidate)
lc, ok := obj.(*v1beta1.LeaseCandidate)
if !ok {
return
}
@ -197,7 +197,7 @@ func (c *Controller) enqueueLease(obj any) {
c.queue.Add(types.NamespacedName{Namespace: lease.Namespace, Name: lease.Name})
}
func (c *Controller) electionNeeded(candidates []*v1alpha2.LeaseCandidate, leaseNN types.NamespacedName) (bool, error) {
func (c *Controller) electionNeeded(candidates []*v1beta1.LeaseCandidate, leaseNN types.NamespacedName) (bool, error) {
lease, err := c.leaseInformer.Lister().Leases(leaseNN.Namespace).Get(leaseNN.Name)
if err != nil && !apierrors.IsNotFound(err) {
return false, fmt.Errorf("error reading lease: %w", err)
@ -316,7 +316,7 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
}
}
var ackedCandidates []*v1alpha2.LeaseCandidate
var ackedCandidates []*v1beta1.LeaseCandidate
for _, candidate := range candidates {
if candidate.Spec.RenewTime.Add(electionDuration).After(now) {
ackedCandidates = append(ackedCandidates, candidate)
@ -422,12 +422,12 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
return defaultRequeueInterval, nil
}
func (c *Controller) listAdmissableCandidates(leaseNN types.NamespacedName) ([]*v1alpha2.LeaseCandidate, error) {
func (c *Controller) listAdmissableCandidates(leaseNN types.NamespacedName) ([]*v1beta1.LeaseCandidate, error) {
leases, err := c.leaseCandidateInformer.Lister().LeaseCandidates(leaseNN.Namespace).List(labels.Everything())
if err != nil {
return nil, err
}
var results []*v1alpha2.LeaseCandidate
var results []*v1beta1.LeaseCandidate
for _, l := range leases {
if l.Spec.LeaseName != leaseNN.Name {
continue

View File

@ -25,7 +25,7 @@ import (
"time"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
@ -42,7 +42,7 @@ func TestReconcileElectionStep(t *testing.T) {
tests := []struct {
name string
leaseNN types.NamespacedName
candidates []*v1alpha2.LeaseCandidate
candidates []*v1beta1.LeaseCandidate
existingLease *v1.Lease
expectLease bool
expectedHolderIdentity *string
@ -55,7 +55,7 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "no candidates, no lease, noop",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{},
candidates: []*v1beta1.LeaseCandidate{},
existingLease: nil,
expectLease: false,
expectedHolderIdentity: nil,
@ -66,7 +66,7 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "no candidates, lease exists. noop, not managed by CLE",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{},
candidates: []*v1beta1.LeaseCandidate{},
existingLease: &v1.Lease{},
expectLease: false,
expectedHolderIdentity: nil,
@ -77,13 +77,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, no existing lease should create lease",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -102,13 +102,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, lease exists, unoptimal should set preferredHolder",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -121,7 +121,7 @@ func TestReconcileElectionStep(t *testing.T) {
Namespace: "default",
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.18.0",
BinaryVersion: "1.18.0",
@ -151,13 +151,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, should only elect leader from acked candidates",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -171,7 +171,7 @@ func TestReconcileElectionStep(t *testing.T) {
Namespace: "default",
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.20.0",
BinaryVersion: "1.20.0",
@ -191,13 +191,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, lease exists, lease expired",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -226,13 +226,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, no acked candidates should return error",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -251,13 +251,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, should ping on election",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -277,13 +277,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidate exist, pinged candidate should have until electionDuration until election decision is made",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -302,13 +302,13 @@ func TestReconcileElectionStep(t *testing.T) {
{
name: "candidates exist, lease exists, lease expired, 3rdparty strategy",
leaseNN: types.NamespacedName{Namespace: "default", Name: "component-A"},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -344,9 +344,9 @@ func TestReconcileElectionStep(t *testing.T) {
controller, err := NewController(
informerFactory.Coordination().V1().Leases(),
informerFactory.Coordination().V1alpha2().LeaseCandidates(),
informerFactory.Coordination().V1beta1().LeaseCandidates(),
client.CoordinationV1(),
client.CoordinationV1alpha2(),
client.CoordinationV1beta1(),
)
controller.clock = fakeClock
if err != nil {
@ -363,7 +363,7 @@ func TestReconcileElectionStep(t *testing.T) {
// Set up the fake client with the candidates
for _, candidate := range tc.candidates {
_, err = client.CoordinationV1alpha2().LeaseCandidates(candidate.Namespace).Create(ctx, candidate, metav1.CreateOptions{})
_, err = client.CoordinationV1beta1().LeaseCandidates(candidate.Namespace).Create(ctx, candidate, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
@ -414,11 +414,11 @@ func TestReconcileElectionStep(t *testing.T) {
// Verify that ping to candidate was issued
if tc.candidatesPinged {
pinged := false
candidatesList, err := client.CoordinationV1alpha2().LeaseCandidates(tc.leaseNN.Namespace).List(ctx, metav1.ListOptions{})
candidatesList, err := client.CoordinationV1beta1().LeaseCandidates(tc.leaseNN.Namespace).List(ctx, metav1.ListOptions{})
if err != nil {
t.Fatal(err)
}
oldCandidateMap := make(map[string]*v1alpha2.LeaseCandidate)
oldCandidateMap := make(map[string]*v1beta1.LeaseCandidate)
for _, candidate := range tc.candidates {
oldCandidateMap[candidate.Name] = candidate
}
@ -443,20 +443,20 @@ func TestController(t *testing.T) {
cases := []struct {
name string
leases []*v1.Lease
candidates []*v1alpha2.LeaseCandidate
createAfterControllerStart []*v1alpha2.LeaseCandidate
candidates []*v1beta1.LeaseCandidate
createAfterControllerStart []*v1beta1.LeaseCandidate
deleteLeaseAfterControllerStart []types.NamespacedName
expectedLeaderLeases []*v1.Lease
}{
{
name: "single candidate leader election",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -479,13 +479,13 @@ func TestController(t *testing.T) {
},
{
name: "multiple candidate leader election",
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -498,7 +498,7 @@ func TestController(t *testing.T) {
Namespace: "kube-system",
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.20.0",
@ -511,7 +511,7 @@ func TestController(t *testing.T) {
Namespace: "kube-system",
Name: "component-identity-3",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.20.0",
BinaryVersion: "1.20.0",
@ -547,13 +547,13 @@ func TestController(t *testing.T) {
},
},
},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -593,13 +593,13 @@ func TestController(t *testing.T) {
},
},
},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -636,13 +636,13 @@ func TestController(t *testing.T) {
},
},
},
candidates: []*v1alpha2.LeaseCandidate{
candidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-1",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.20.0",
BinaryVersion: "1.20.0",
@ -651,13 +651,13 @@ func TestController(t *testing.T) {
},
},
},
createAfterControllerStart: []*v1alpha2.LeaseCandidate{
createAfterControllerStart: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Namespace: "kube-system",
Name: "component-identity-2",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -693,9 +693,9 @@ func TestController(t *testing.T) {
informerFactory := informers.NewSharedInformerFactory(client, 0)
controller, err := NewController(
informerFactory.Coordination().V1().Leases(),
informerFactory.Coordination().V1alpha2().LeaseCandidates(),
informerFactory.Coordination().V1beta1().LeaseCandidates(),
client.CoordinationV1(),
client.CoordinationV1alpha2(),
client.CoordinationV1beta1(),
)
if err != nil {
t.Fatal(err)
@ -710,7 +710,7 @@ func TestController(t *testing.T) {
}
for _, obj := range tc.candidates {
t.Logf("Pre-creating lease candidate %s/%s", obj.Namespace, obj.Name)
_, err := client.CoordinationV1alpha2().LeaseCandidates(obj.Namespace).Create(ctx, obj, metav1.CreateOptions{})
_, err := client.CoordinationV1beta1().LeaseCandidates(obj.Namespace).Create(ctx, obj, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Error pre-creating lease candidate %s/%s: %v", obj.Namespace, obj.Name, err)
}
@ -748,7 +748,7 @@ func TestController(t *testing.T) {
if *ph == *l.Spec.HolderIdentity {
continue
}
if _, err := client.CoordinationV1alpha2().LeaseCandidates(expectedLease.Namespace).Get(ctx, *l.Spec.HolderIdentity, metav1.GetOptions{}); err != nil {
if _, err := client.CoordinationV1beta1().LeaseCandidates(expectedLease.Namespace).Get(ctx, *l.Spec.HolderIdentity, metav1.GetOptions{}); err != nil {
continue // only candidate-aware controllers will follow preferredHolder
}
@ -772,7 +772,7 @@ func TestController(t *testing.T) {
case <-ctx.Done():
return
case <-ticker.C:
cs, err := client.CoordinationV1alpha2().LeaseCandidates("").List(ctx, metav1.ListOptions{})
cs, err := client.CoordinationV1beta1().LeaseCandidates("").List(ctx, metav1.ListOptions{})
if err != nil {
t.Logf("Error listing lease candidates: %v", err)
continue
@ -781,7 +781,7 @@ func TestController(t *testing.T) {
if c.Spec.PingTime != nil && (c.Spec.RenewTime == nil || c.Spec.PingTime.Time.After(c.Spec.RenewTime.Time)) {
t.Logf("Answering ping for %s/%s", c.Namespace, c.Name)
c.Spec.RenewTime = &metav1.MicroTime{Time: time.Now()}
_, err = client.CoordinationV1alpha2().LeaseCandidates(c.Namespace).Update(ctx, &c, metav1.UpdateOptions{})
_, err = client.CoordinationV1beta1().LeaseCandidates(c.Namespace).Update(ctx, &c, metav1.UpdateOptions{})
if err != nil {
t.Logf("Error updating lease candidate %s/%s: %v", c.Namespace, c.Name, err)
}
@ -793,7 +793,7 @@ func TestController(t *testing.T) {
for _, obj := range tc.createAfterControllerStart {
t.Logf("Post-creating lease candidate %s/%s", obj.Namespace, obj.Name)
_, err := client.CoordinationV1alpha2().LeaseCandidates(obj.Namespace).Create(ctx, obj, metav1.CreateOptions{})
_, err := client.CoordinationV1beta1().LeaseCandidates(obj.Namespace).Create(ctx, obj, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Error post-creating lease candidate %s/%s: %v", obj.Namespace, obj.Name, err)
}

View File

@ -26,9 +26,9 @@ import (
"k8s.io/apimachinery/pkg/labels"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
coordinationv1alpha2informers "k8s.io/client-go/informers/coordination/v1alpha2"
coordinationv1beta1informers "k8s.io/client-go/informers/coordination/v1beta1"
"k8s.io/client-go/kubernetes"
listers "k8s.io/client-go/listers/coordination/v1alpha2"
listers "k8s.io/client-go/listers/coordination/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/utils/clock"
@ -39,7 +39,7 @@ type LeaseCandidateGCController struct {
kubeclientset kubernetes.Interface
leaseCandidateLister listers.LeaseCandidateLister
leaseCandidateInformer coordinationv1alpha2informers.LeaseCandidateInformer
leaseCandidateInformer coordinationv1beta1informers.LeaseCandidateInformer
leaseCandidatesSynced cache.InformerSynced
gcCheckPeriod time.Duration
@ -48,7 +48,7 @@ type LeaseCandidateGCController struct {
}
// NewLeaseCandidateGC creates a new LeaseCandidateGCController.
func NewLeaseCandidateGC(clientset kubernetes.Interface, gcCheckPeriod time.Duration, leaseCandidateInformer coordinationv1alpha2informers.LeaseCandidateInformer) *LeaseCandidateGCController {
func NewLeaseCandidateGC(clientset kubernetes.Interface, gcCheckPeriod time.Duration, leaseCandidateInformer coordinationv1beta1informers.LeaseCandidateInformer) *LeaseCandidateGCController {
return &LeaseCandidateGCController{
kubeclientset: clientset,
leaseCandidateLister: leaseCandidateInformer.Lister(),
@ -87,7 +87,7 @@ func (c *LeaseCandidateGCController) gc(ctx context.Context) {
if !isLeaseCandidateExpired(c.clock, leaseCandidate) {
continue
}
lc, err := c.kubeclientset.CoordinationV1alpha2().LeaseCandidates(leaseCandidate.Namespace).Get(ctx, leaseCandidate.Name, metav1.GetOptions{})
lc, err := c.kubeclientset.CoordinationV1beta1().LeaseCandidates(leaseCandidate.Namespace).Get(ctx, leaseCandidate.Name, metav1.GetOptions{})
if err != nil {
klog.ErrorS(err, "Error getting lc")
continue
@ -96,7 +96,7 @@ func (c *LeaseCandidateGCController) gc(ctx context.Context) {
if !isLeaseCandidateExpired(c.clock, lc) {
continue
}
if err := c.kubeclientset.CoordinationV1alpha2().LeaseCandidates(lc.Namespace).Delete(
if err := c.kubeclientset.CoordinationV1beta1().LeaseCandidates(lc.Namespace).Delete(
ctx, lc.Name, metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) {
klog.ErrorS(err, "Error deleting lease")
}

View File

@ -22,7 +22,7 @@ import (
"time"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/informers"
@ -33,19 +33,19 @@ import (
func TestLeaseCandidateGCController(t *testing.T) {
tests := []struct {
name string
leaseCandidates []*v1alpha2.LeaseCandidate
leaseCandidates []*v1beta1.LeaseCandidate
expectedDeletedCount int
}{
{
name: "delete expired lease candidates",
leaseCandidates: []*v1alpha2.LeaseCandidate{
leaseCandidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now().Add(-1 * leaseCandidateValidDuration)},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -59,7 +59,7 @@ func TestLeaseCandidateGCController(t *testing.T) {
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now().Add(-1 * leaseCandidateValidDuration)},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-B",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -73,7 +73,7 @@ func TestLeaseCandidateGCController(t *testing.T) {
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-C",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -86,14 +86,14 @@ func TestLeaseCandidateGCController(t *testing.T) {
},
{
name: "no expired lease candidates",
leaseCandidates: []*v1alpha2.LeaseCandidate{
leaseCandidates: []*v1beta1.LeaseCandidate{
{
ObjectMeta: metav1.ObjectMeta{
Name: "candidate1",
Namespace: "default",
CreationTimestamp: metav1.Time{Time: time.Now()},
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "component-A",
EmulationVersion: "1.19.0",
BinaryVersion: "1.19.0",
@ -111,12 +111,12 @@ func TestLeaseCandidateGCController(t *testing.T) {
ctx := context.Background()
client := fake.NewSimpleClientset()
informerFactory := informers.NewSharedInformerFactory(client, 0)
leaseCandidateInformer := informerFactory.Coordination().V1alpha2().LeaseCandidates()
leaseCandidateInformer := informerFactory.Coordination().V1beta1().LeaseCandidates()
controller := NewLeaseCandidateGC(client, 10*time.Millisecond, leaseCandidateInformer)
// Create lease candidates
for _, lc := range tc.leaseCandidates {
_, err := client.CoordinationV1alpha2().LeaseCandidates(lc.Namespace).Create(ctx, lc, metav1.CreateOptions{})
_, err := client.CoordinationV1beta1().LeaseCandidates(lc.Namespace).Create(ctx, lc, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
@ -127,7 +127,7 @@ func TestLeaseCandidateGCController(t *testing.T) {
go controller.Run(ctx)
err := wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 600*time.Second, true, func(ctx context.Context) (done bool, err error) {
lcs, err := client.CoordinationV1alpha2().LeaseCandidates("default").List(ctx, metav1.ListOptions{})
lcs, err := client.CoordinationV1beta1().LeaseCandidates("default").List(ctx, metav1.ListOptions{})
if err != nil {
return true, err
}

View File

@ -40,6 +40,7 @@ import (
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
coordinationapiv1 "k8s.io/api/coordination/v1"
coordinationv1alpha2 "k8s.io/api/coordination/v1alpha2"
coordinationv1beta1 "k8s.io/api/coordination/v1beta1"
apiv1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
eventsv1 "k8s.io/api/events/v1"
@ -459,6 +460,7 @@ var (
admissionregistrationv1beta1.SchemeGroupVersion,
authenticationv1beta1.SchemeGroupVersion,
certificatesv1beta1.SchemeGroupVersion,
coordinationv1beta1.SchemeGroupVersion,
storageapiv1beta1.SchemeGroupVersion,
flowcontrolv1beta1.SchemeGroupVersion,
flowcontrolv1beta2.SchemeGroupVersion,

View File

@ -79,7 +79,7 @@ func NewStorageFactoryConfigEffectiveVersion(effectiveVersion basecompatibility.
//
// TODO (https://github.com/kubernetes/kubernetes/issues/108451): remove the override in 1.25.
// apisstorage.Resource("csistoragecapacities").WithVersion("v1beta1"),
coordination.Resource("leasecandidates").WithVersion("v1alpha2"),
coordination.Resource("leasecandidates").WithVersion("v1beta1"),
// TODO(aojea) ipaddresses and servicecidrs are v1 in 1.33
// remove them in 1.34 when all apiserver understand the v1 version.
networking.Resource("ipaddresses").WithVersion("v1beta1"),

View File

@ -19,6 +19,7 @@ package rest
import (
coordinationv1 "k8s.io/api/coordination/v1"
coordinationv1alpha2 "k8s.io/api/coordination/v1alpha2"
coordinationv1beta1 "k8s.io/api/coordination/v1beta1"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
@ -42,6 +43,12 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1.SchemeGroupVersion.Version] = storageMap
}
if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, err
} else if len(storageMap) > 0 {
apiGroupInfo.VersionedResourcesStorageMap[coordinationv1beta1.SchemeGroupVersion.Version] = storageMap
}
if storageMap, err := p.v1alpha2Storage(apiResourceConfigSource, restOptionsGetter); err != nil {
return genericapiserver.APIGroupInfo{}, err
} else if len(storageMap) > 0 {
@ -65,6 +72,20 @@ func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.API
return storage, nil
}
func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{}
// identity
if resource := "leasecandidates"; apiResourceConfigSource.ResourceEnabled(coordinationv1beta1.SchemeGroupVersion.WithResource(resource)) {
leaseCandidateStorage, err := leasecandidatestorage.NewREST(restOptionsGetter)
if err != nil {
return storage, err
}
storage[resource] = leaseCandidateStorage
}
return storage, nil
}
func (p RESTStorageProvider) v1alpha2Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) {
storage := map[string]rest.Storage{}

View File

@ -46,6 +46,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Lease{},
&LeaseList{},
&LeaseCandidate{},
&LeaseCandidateList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)

View File

@ -91,3 +91,76 @@ type LeaseList struct {
// items is a list of schema objects.
Items []Lease `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.33
// LeaseCandidate defines a candidate for a Lease object.
// Candidates are created such that coordinated leader election will pick the best leader from the list of candidates.
type LeaseCandidate struct {
metav1.TypeMeta `json:",inline"`
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// spec contains the specification of the Lease.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec LeaseCandidateSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
}
// LeaseCandidateSpec is a specification of a Lease.
type LeaseCandidateSpec struct {
// LeaseName is the name of the lease for which this candidate is contending.
// The limits on this field are the same as on Lease.name. Multiple lease candidates
// may reference the same Lease.name.
// This field is immutable.
// +required
LeaseName string `json:"leaseName" protobuf:"bytes,1,name=leaseName"`
// PingTime is the last time that the server has requested the LeaseCandidate
// to renew. It is only done during leader election to check if any
// LeaseCandidates have become ineligible. When PingTime is updated, the
// LeaseCandidate will respond by updating RenewTime.
// +optional
PingTime *metav1.MicroTime `json:"pingTime,omitempty" protobuf:"bytes,2,opt,name=pingTime"`
// RenewTime is the time that the LeaseCandidate was last updated.
// Any time a Lease needs to do leader election, the PingTime field
// is updated to signal to the LeaseCandidate that they should update
// the RenewTime.
// Old LeaseCandidate objects are also garbage collected if it has been hours
// since the last renew. The PingTime field is updated regularly to prevent
// garbage collection for still active LeaseCandidates.
// +optional
RenewTime *metav1.MicroTime `json:"renewTime,omitempty" protobuf:"bytes,3,opt,name=renewTime"`
// BinaryVersion is the binary version. It must be in a semver format without leading `v`.
// This field is required.
// +required
BinaryVersion string `json:"binaryVersion" protobuf:"bytes,4,name=binaryVersion"`
// EmulationVersion is the emulation version. It must be in a semver format without leading `v`.
// EmulationVersion must be less than or equal to BinaryVersion.
// This field is required when strategy is "OldestEmulationVersion"
// +optional
EmulationVersion string `json:"emulationVersion,omitempty" protobuf:"bytes,5,opt,name=emulationVersion"`
// Strategy is the strategy that coordinated leader election will use for picking the leader.
// If multiple candidates for the same Lease return different strategies, the strategy provided
// by the candidate with the latest BinaryVersion will be used. If there is still conflict,
// this is a user error and coordinated leader election will not operate the Lease until resolved.
// +required
Strategy v1.CoordinatedLeaseStrategy `json:"strategy,omitempty" protobuf:"bytes,6,opt,name=strategy"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.33
// LeaseCandidateList is a list of Lease objects.
type LeaseCandidateList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is a list of schema objects.
Items []LeaseCandidate `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View File

@ -22,14 +22,14 @@ import (
"time"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
coordinationv1alpha2client "k8s.io/client-go/kubernetes/typed/coordination/v1alpha2"
coordinationv1beta1client "k8s.io/client-go/kubernetes/typed/coordination/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
@ -43,7 +43,7 @@ type CacheSyncWaiter interface {
}
type LeaseCandidate struct {
leaseClient coordinationv1alpha2client.LeaseCandidateInterface
leaseClient coordinationv1beta1client.LeaseCandidateInterface
leaseCandidateInformer cache.SharedIndexInformer
informerFactory informers.SharedInformerFactory
hasSynced cache.InformerSynced
@ -84,10 +84,10 @@ func NewCandidate(clientset kubernetes.Interface,
options.FieldSelector = fieldSelector
}),
)
leaseCandidateInformer := informerFactory.Coordination().V1alpha2().LeaseCandidates().Informer()
leaseCandidateInformer := informerFactory.Coordination().V1beta1().LeaseCandidates().Informer()
lc := &LeaseCandidate{
leaseClient: clientset.CoordinationV1alpha2().LeaseCandidates(candidateNamespace),
leaseClient: clientset.CoordinationV1beta1().LeaseCandidates(candidateNamespace),
leaseCandidateInformer: leaseCandidateInformer,
informerFactory: informerFactory,
name: candidateName,
@ -102,7 +102,7 @@ func NewCandidate(clientset kubernetes.Interface,
h, err := leaseCandidateInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
UpdateFunc: func(oldObj, newObj interface{}) {
if leasecandidate, ok := newObj.(*v1alpha2.LeaseCandidate); ok {
if leasecandidate, ok := newObj.(*v1beta1.LeaseCandidate); ok {
if leasecandidate.Spec.PingTime != nil && leasecandidate.Spec.PingTime.After(leasecandidate.Spec.RenewTime.Time) {
lc.enqueueLease()
}
@ -184,13 +184,13 @@ func (c *LeaseCandidate) ensureLease(ctx context.Context) error {
return nil
}
func (c *LeaseCandidate) newLeaseCandidate() *v1alpha2.LeaseCandidate {
lc := &v1alpha2.LeaseCandidate{
func (c *LeaseCandidate) newLeaseCandidate() *v1beta1.LeaseCandidate {
lc := &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: c.name,
Namespace: c.namespace,
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: c.leaseName,
BinaryVersion: c.binaryVersion,
EmulationVersion: c.emulationVersion,

View File

@ -101,12 +101,12 @@ func TestLeaseCandidateAck(t *testing.T) {
// Update PingTime and verify that the client renews
ensureAfter := &metav1.MicroTime{Time: time.Now()}
lc, err := client.CoordinationV1alpha2().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{})
lc, err := client.CoordinationV1beta1().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{})
if err == nil {
if lc.Spec.PingTime == nil {
c := lc.DeepCopy()
c.Spec.PingTime = &metav1.MicroTime{Time: time.Now()}
_, err = client.CoordinationV1alpha2().LeaseCandidates(tc.candidateNamespace).Update(ctx, c, metav1.UpdateOptions{})
_, err = client.CoordinationV1beta1().LeaseCandidates(tc.candidateNamespace).Update(ctx, c, metav1.UpdateOptions{})
if err != nil {
t.Error(err)
}
@ -120,7 +120,7 @@ func TestLeaseCandidateAck(t *testing.T) {
func pollForLease(ctx context.Context, tc testcase, client *fake.Clientset, t *metav1.MicroTime) error {
return wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, 10*time.Second, true, func(ctx context.Context) (done bool, err error) {
lc, err := client.CoordinationV1alpha2().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{})
lc, err := client.CoordinationV1beta1().LeaseCandidates(tc.candidateNamespace).Get(ctx, tc.candidateName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return false, nil

View File

@ -58,7 +58,7 @@ var _ = SIGDescribe("CoordinatedLeaderElection", feature.CoordinatedLeaderElecti
_ = clientset.CoordinationV1().Leases(ns).Delete(ctx, "baz", metav1.DeleteOptions{})
_ = clientset.CoordinationV1().Leases(ns).Delete(ctx, "bar", metav1.DeleteOptions{})
_ = clientset.CoordinationV1().Leases(ns).Delete(ctx, "foobar", metav1.DeleteOptions{})
_ = clientset.CoordinationV1alpha2().LeaseCandidates(ns).DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{})
_ = clientset.CoordinationV1beta1().LeaseCandidates(ns).DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{})
})
/*

View File

@ -24,7 +24,7 @@ import (
"time"
v1 "k8s.io/api/coordination/v1"
v1alpha2 "k8s.io/api/coordination/v1alpha2"
v1beta1 "k8s.io/api/coordination/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
@ -56,7 +56,7 @@ func TestSingleLeaseCandidate(t *testing.T) {
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -95,7 +95,7 @@ func TestSingleLeaseCandidateUsingThirdPartyStrategy(t *testing.T) {
},
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -133,7 +133,7 @@ func TestMultipleLeaseCandidate(t *testing.T) {
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -175,7 +175,7 @@ func TestMultipleLeaseCandidateUsingThirdPartyStrategy(t *testing.T) {
},
}
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
@ -204,7 +204,7 @@ func TestMultipleLeaseCandidateUsingThirdPartyStrategy(t *testing.T) {
func TestLeaseSwapIfBetterAvailable(t *testing.T) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -227,7 +227,7 @@ func TestLeaseSwapIfBetterAvailable(t *testing.T) {
func TestUpgradeSkew(t *testing.T) {
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.CoordinatedLeaderElection, true)
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -257,7 +257,7 @@ func TestLeaseCandidateCleanup(t *testing.T) {
apiserver.LeaseCandidateGCPeriod = 30 * time.Minute
}()
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha2.SchemeGroupVersion)}
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), flags, framework.SharedEtcd())
if err != nil {
t.Fatal(err)
@ -268,12 +268,12 @@ func TestLeaseCandidateCleanup(t *testing.T) {
if err != nil {
t.Fatal(err)
}
expiredLC := &v1alpha2.LeaseCandidate{
expiredLC := &v1beta1.LeaseCandidate{
ObjectMeta: metav1.ObjectMeta{
Name: "expired",
Namespace: "default",
},
Spec: v1alpha2.LeaseCandidateSpec{
Spec: v1beta1.LeaseCandidateSpec{
LeaseName: "foobaz",
BinaryVersion: "0.1.0",
EmulationVersion: "0.1.0",
@ -283,13 +283,13 @@ func TestLeaseCandidateCleanup(t *testing.T) {
},
}
ctx := context.Background()
_, err = clientset.CoordinationV1alpha2().LeaseCandidates("default").Create(ctx, expiredLC, metav1.CreateOptions{})
_, err = clientset.CoordinationV1beta1().LeaseCandidates("default").Create(ctx, expiredLC, metav1.CreateOptions{})
if err != nil {
t.Fatal(err)
}
err = wait.PollUntilContextTimeout(ctx, 1000*time.Millisecond, 5*time.Second, true, func(ctx context.Context) (done bool, err error) {
_, err = clientset.CoordinationV1alpha2().LeaseCandidates("default").Get(ctx, "expired", metav1.GetOptions{})
_, err = clientset.CoordinationV1beta1().LeaseCandidates("default").Get(ctx, "expired", metav1.GetOptions{})
if apierrors.IsNotFound(err) {
return true, nil
}

View File

@ -241,10 +241,20 @@ func GetEtcdStorageDataForNamespaceServedAt(namespace string, v string, removeAl
},
// --
// k8s.io/kubernetes/pkg/apis/coordination/v1beta1
gvr("coordination.k8s.io", "v1beta1", "leasecandidates"): {
Stub: `{"metadata": {"name": "leasecandidatev1beta1"}, "spec": {"leaseName": "lease", "binaryVersion": "0.1.0", "emulationVersion": "0.1.0", "strategy": "OldestEmulationVersion"}}`,
ExpectedEtcdPath: "/registry/leasecandidates/" + namespace + "/leasecandidatev1beta1",
IntroducedVersion: "1.33",
RemovedVersion: "1.39",
},
// --
// k8s.io/kubernetes/pkg/apis/coordination/v1alpha2
gvr("coordination.k8s.io", "v1alpha2", "leasecandidates"): {
Stub: `{"metadata": {"name": "leasecandidatev1alpha2"}, "spec": {"leaseName": "lease", "binaryVersion": "0.1.0", "emulationVersion": "0.1.0", "strategy": "OldestEmulationVersion"}}`,
ExpectedEtcdPath: "/registry/leasecandidates/" + namespace + "/leasecandidatev1alpha2",
ExpectedGVK: gvkP("coordination.k8s.io", "v1beta1", "LeaseCandidate"),
IntroducedVersion: "1.32",
RemovedVersion: "1.38",
},