k8s.io/client-go@v0.22.2/tools/leaderelection/resourcelock/leaselock.go (about)

     1  /*
     2  Copyright 2018 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 resourcelock
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  
    25  	coordinationv1 "k8s.io/api/coordination/v1"
    26  	corev1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	coordinationv1client "k8s.io/client-go/kubernetes/typed/coordination/v1"
    29  )
    30  
    31  type LeaseLock struct {
    32  	// LeaseMeta should contain a Name and a Namespace of a
    33  	// LeaseMeta object that the LeaderElector will attempt to lead.
    34  	LeaseMeta  metav1.ObjectMeta
    35  	Client     coordinationv1client.LeasesGetter
    36  	LockConfig ResourceLockConfig
    37  	lease      *coordinationv1.Lease
    38  }
    39  
    40  // Get returns the election record from a Lease spec
    41  func (ll *LeaseLock) Get(ctx context.Context) (*LeaderElectionRecord, []byte, error) {
    42  	var err error
    43  	ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Get(ctx, ll.LeaseMeta.Name, metav1.GetOptions{})
    44  	if err != nil {
    45  		return nil, nil, err
    46  	}
    47  	record := LeaseSpecToLeaderElectionRecord(&ll.lease.Spec)
    48  	recordByte, err := json.Marshal(*record)
    49  	if err != nil {
    50  		return nil, nil, err
    51  	}
    52  	return record, recordByte, nil
    53  }
    54  
    55  // Create attempts to create a Lease
    56  func (ll *LeaseLock) Create(ctx context.Context, ler LeaderElectionRecord) error {
    57  	var err error
    58  	ll.lease, err = ll.Client.Leases(ll.LeaseMeta.Namespace).Create(ctx, &coordinationv1.Lease{
    59  		ObjectMeta: metav1.ObjectMeta{
    60  			Name:      ll.LeaseMeta.Name,
    61  			Namespace: ll.LeaseMeta.Namespace,
    62  		},
    63  		Spec: LeaderElectionRecordToLeaseSpec(&ler),
    64  	}, metav1.CreateOptions{})
    65  	return err
    66  }
    67  
    68  // Update will update an existing Lease spec.
    69  func (ll *LeaseLock) Update(ctx context.Context, ler LeaderElectionRecord) error {
    70  	if ll.lease == nil {
    71  		return errors.New("lease not initialized, call get or create first")
    72  	}
    73  	ll.lease.Spec = LeaderElectionRecordToLeaseSpec(&ler)
    74  
    75  	lease, err := ll.Client.Leases(ll.LeaseMeta.Namespace).Update(ctx, ll.lease, metav1.UpdateOptions{})
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	ll.lease = lease
    81  	return nil
    82  }
    83  
    84  // RecordEvent in leader election while adding meta-data
    85  func (ll *LeaseLock) RecordEvent(s string) {
    86  	if ll.LockConfig.EventRecorder == nil {
    87  		return
    88  	}
    89  	events := fmt.Sprintf("%v %v", ll.LockConfig.Identity, s)
    90  	ll.LockConfig.EventRecorder.Eventf(&coordinationv1.Lease{ObjectMeta: ll.lease.ObjectMeta}, corev1.EventTypeNormal, "LeaderElection", events)
    91  }
    92  
    93  // Describe is used to convert details on current resource lock
    94  // into a string
    95  func (ll *LeaseLock) Describe() string {
    96  	return fmt.Sprintf("%v/%v", ll.LeaseMeta.Namespace, ll.LeaseMeta.Name)
    97  }
    98  
    99  // Identity returns the Identity of the lock
   100  func (ll *LeaseLock) Identity() string {
   101  	return ll.LockConfig.Identity
   102  }
   103  
   104  func LeaseSpecToLeaderElectionRecord(spec *coordinationv1.LeaseSpec) *LeaderElectionRecord {
   105  	var r LeaderElectionRecord
   106  	if spec.HolderIdentity != nil {
   107  		r.HolderIdentity = *spec.HolderIdentity
   108  	}
   109  	if spec.LeaseDurationSeconds != nil {
   110  		r.LeaseDurationSeconds = int(*spec.LeaseDurationSeconds)
   111  	}
   112  	if spec.LeaseTransitions != nil {
   113  		r.LeaderTransitions = int(*spec.LeaseTransitions)
   114  	}
   115  	if spec.AcquireTime != nil {
   116  		r.AcquireTime = metav1.Time{spec.AcquireTime.Time}
   117  	}
   118  	if spec.RenewTime != nil {
   119  		r.RenewTime = metav1.Time{spec.RenewTime.Time}
   120  	}
   121  	return &r
   122  
   123  }
   124  
   125  func LeaderElectionRecordToLeaseSpec(ler *LeaderElectionRecord) coordinationv1.LeaseSpec {
   126  	leaseDurationSeconds := int32(ler.LeaseDurationSeconds)
   127  	leaseTransitions := int32(ler.LeaderTransitions)
   128  	return coordinationv1.LeaseSpec{
   129  		HolderIdentity:       &ler.HolderIdentity,
   130  		LeaseDurationSeconds: &leaseDurationSeconds,
   131  		AcquireTime:          &metav1.MicroTime{ler.AcquireTime.Time},
   132  		RenewTime:            &metav1.MicroTime{ler.RenewTime.Time},
   133  		LeaseTransitions:     &leaseTransitions,
   134  	}
   135  }