Merge pull request #84801 from mikedanese/lebug

Fix panic on configmap and lease lock implementations
This commit is contained in:
Kubernetes Prow Robot
2019-11-05 22:18:54 -08:00
committed by GitHub
3 changed files with 72 additions and 49 deletions

View File

@@ -37,26 +37,27 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
) )
func createLockObject(t *testing.T, objectType, namespace, name string, record rl.LeaderElectionRecord) (obj runtime.Object) { func createLockObject(t *testing.T, objectType, namespace, name string, record *rl.LeaderElectionRecord) (obj runtime.Object) {
objectMeta := metav1.ObjectMeta{ objectMeta := metav1.ObjectMeta{
Namespace: namespace, Namespace: namespace,
Name: name, Name: name,
} }
if record != nil {
recordBytes, _ := json.Marshal(record)
objectMeta.Annotations = map[string]string{
rl.LeaderElectionRecordAnnotationKey: string(recordBytes),
}
}
switch objectType { switch objectType {
case "endpoints": case "endpoints":
recordBytes, _ := json.Marshal(record)
objectMeta.Annotations = map[string]string{
rl.LeaderElectionRecordAnnotationKey: string(recordBytes),
}
obj = &corev1.Endpoints{ObjectMeta: objectMeta} obj = &corev1.Endpoints{ObjectMeta: objectMeta}
case "configmaps": case "configmaps":
recordBytes, _ := json.Marshal(record)
objectMeta.Annotations = map[string]string{
rl.LeaderElectionRecordAnnotationKey: string(recordBytes),
}
obj = &corev1.ConfigMap{ObjectMeta: objectMeta} obj = &corev1.ConfigMap{ObjectMeta: objectMeta}
case "leases": case "leases":
spec := rl.LeaderElectionRecordToLeaseSpec(&record) var spec coordinationv1.LeaseSpec
if record != nil {
spec = rl.LeaderElectionRecordToLeaseSpec(record)
}
obj = &coordinationv1.Lease{ObjectMeta: objectMeta, Spec: spec} obj = &coordinationv1.Lease{ObjectMeta: objectMeta, Spec: spec}
default: default:
t.Fatal("unexpected objType:" + objectType) t.Fatal("unexpected objType:" + objectType)
@@ -108,13 +109,33 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
expectSuccess: true, expectSuccess: true,
outHolder: "baz", outHolder: "baz",
}, },
{
name: "acquire from object without annotations",
reactors: []Reactor{
{
verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), nil), nil
},
},
{
verb: "update",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, action.(fakeclient.CreateAction).GetObject(), nil
},
},
},
expectSuccess: true,
transitionLeader: true,
outHolder: "baz",
},
{ {
name: "acquire from unled object", name: "acquire from unled object",
reactors: []Reactor{ reactors: []Reactor{
{ {
verb: "get", verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{}), nil return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{}), nil
}, },
}, },
{ {
@@ -135,7 +156,7 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
{ {
verb: "get", verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -158,7 +179,7 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
{ {
verb: "get", verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: ""}), nil return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: ""}), nil
}, },
}, },
{ {
@@ -180,7 +201,7 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
{ {
verb: "get", verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
}, },
@@ -195,7 +216,7 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
{ {
verb: "get", verb: "get",
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, objectType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
{ {
@@ -421,7 +442,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{}), nil
}, },
}, },
{ {
@@ -464,14 +485,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{}), nil
}, },
}, },
{ {
@@ -485,7 +506,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{}), nil
}, },
}, },
{ {
@@ -507,7 +528,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -528,7 +549,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -554,14 +575,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -575,7 +596,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -601,14 +622,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
}, },
@@ -626,14 +647,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil
}, },
}, },
{ {
@@ -647,7 +668,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: rl.UnknownLeader}), nil
}, },
}, },
{ {
@@ -673,7 +694,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
@@ -698,14 +719,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
}, },
@@ -723,14 +744,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "bing"}), nil
}, },
}, },
}, },
@@ -748,14 +769,14 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: primaryType, objectType: primaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, primaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
{ {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
{ {
@@ -769,7 +790,7 @@ func testTryAcquireOrRenewMultiLock(t *testing.T, objectType string) {
verb: "get", verb: "get",
objectType: secondaryType, objectType: secondaryType,
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) { reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil return true, createLockObject(t, secondaryType, action.GetNamespace(), action.(fakeclient.GetAction).GetName(), &rl.LeaderElectionRecord{HolderIdentity: "baz"}), nil
}, },
}, },
{ {

View File

@@ -82,6 +82,9 @@ func (el *EndpointsLock) Update(ler LeaderElectionRecord) error {
if err != nil { if err != nil {
return err return err
} }
if el.e.Annotations == nil {
el.e.Annotations = make(map[string]string)
}
el.e.Annotations[LeaderElectionRecordAnnotationKey] = string(recordBytes) el.e.Annotations[LeaderElectionRecordAnnotationKey] = string(recordBytes)
el.e, err = el.Client.Endpoints(el.EndpointsMeta.Namespace).Update(el.e) el.e, err = el.Client.Endpoints(el.EndpointsMeta.Namespace).Update(el.e)
return err return err

View File

@@ -96,25 +96,24 @@ func (ll *LeaseLock) Identity() string {
} }
func LeaseSpecToLeaderElectionRecord(spec *coordinationv1.LeaseSpec) *LeaderElectionRecord { func LeaseSpecToLeaderElectionRecord(spec *coordinationv1.LeaseSpec) *LeaderElectionRecord {
holderIdentity := "" var r LeaderElectionRecord
if spec.HolderIdentity != nil { if spec.HolderIdentity != nil {
holderIdentity = *spec.HolderIdentity r.HolderIdentity = *spec.HolderIdentity
} }
leaseDurationSeconds := 0
if spec.LeaseDurationSeconds != nil { if spec.LeaseDurationSeconds != nil {
leaseDurationSeconds = int(*spec.LeaseDurationSeconds) r.LeaseDurationSeconds = int(*spec.LeaseDurationSeconds)
} }
leaseTransitions := 0
if spec.LeaseTransitions != nil { if spec.LeaseTransitions != nil {
leaseTransitions = int(*spec.LeaseTransitions) r.LeaderTransitions = int(*spec.LeaseTransitions)
} }
return &LeaderElectionRecord{ if spec.AcquireTime != nil {
HolderIdentity: holderIdentity, r.AcquireTime = metav1.Time{spec.AcquireTime.Time}
LeaseDurationSeconds: leaseDurationSeconds,
AcquireTime: metav1.Time{spec.AcquireTime.Time},
RenewTime: metav1.Time{spec.RenewTime.Time},
LeaderTransitions: leaseTransitions,
} }
if spec.RenewTime != nil {
r.RenewTime = metav1.Time{spec.RenewTime.Time}
}
return &r
} }
func LeaderElectionRecordToLeaseSpec(ler *LeaderElectionRecord) coordinationv1.LeaseSpec { func LeaderElectionRecordToLeaseSpec(ler *LeaderElectionRecord) coordinationv1.LeaseSpec {