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

     1  /*
     2  Copyright 2016 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  	"fmt"
    22  	clientset "k8s.io/client-go/kubernetes"
    23  	restclient "k8s.io/client-go/rest"
    24  	"time"
    25  
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/runtime"
    28  	coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
    29  	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
    30  )
    31  
    32  const (
    33  	LeaderElectionRecordAnnotationKey = "control-plane.alpha.kubernetes.io/leader"
    34  	EndpointsResourceLock             = "endpoints"
    35  	ConfigMapsResourceLock            = "configmaps"
    36  	LeasesResourceLock                = "leases"
    37  	EndpointsLeasesResourceLock       = "endpointsleases"
    38  	ConfigMapsLeasesResourceLock      = "configmapsleases"
    39  )
    40  
    41  // LeaderElectionRecord is the record that is stored in the leader election annotation.
    42  // This information should be used for observational purposes only and could be replaced
    43  // with a random string (e.g. UUID) with only slight modification of this code.
    44  // TODO(mikedanese): this should potentially be versioned
    45  type LeaderElectionRecord struct {
    46  	// HolderIdentity is the ID that owns the lease. If empty, no one owns this lease and
    47  	// all callers may acquire. Versions of this library prior to Kubernetes 1.14 will not
    48  	// attempt to acquire leases with empty identities and will wait for the full lease
    49  	// interval to expire before attempting to reacquire. This value is set to empty when
    50  	// a client voluntarily steps down.
    51  	HolderIdentity       string      `json:"holderIdentity"`
    52  	LeaseDurationSeconds int         `json:"leaseDurationSeconds"`
    53  	AcquireTime          metav1.Time `json:"acquireTime"`
    54  	RenewTime            metav1.Time `json:"renewTime"`
    55  	LeaderTransitions    int         `json:"leaderTransitions"`
    56  }
    57  
    58  // EventRecorder records a change in the ResourceLock.
    59  type EventRecorder interface {
    60  	Eventf(obj runtime.Object, eventType, reason, message string, args ...interface{})
    61  }
    62  
    63  // ResourceLockConfig common data that exists across different
    64  // resource locks
    65  type ResourceLockConfig struct {
    66  	// Identity is the unique string identifying a lease holder across
    67  	// all participants in an election.
    68  	Identity string
    69  	// EventRecorder is optional.
    70  	EventRecorder EventRecorder
    71  }
    72  
    73  // Interface offers a common interface for locking on arbitrary
    74  // resources used in leader election.  The Interface is used
    75  // to hide the details on specific implementations in order to allow
    76  // them to change over time.  This interface is strictly for use
    77  // by the leaderelection code.
    78  type Interface interface {
    79  	// Get returns the LeaderElectionRecord
    80  	Get(ctx context.Context) (*LeaderElectionRecord, []byte, error)
    81  
    82  	// Create attempts to create a LeaderElectionRecord
    83  	Create(ctx context.Context, ler LeaderElectionRecord) error
    84  
    85  	// Update will update and existing LeaderElectionRecord
    86  	Update(ctx context.Context, ler LeaderElectionRecord) error
    87  
    88  	// RecordEvent is used to record events
    89  	RecordEvent(string)
    90  
    91  	// Identity will return the locks Identity
    92  	Identity() string
    93  
    94  	// Describe is used to convert details on current resource lock
    95  	// into a string
    96  	Describe() string
    97  }
    98  
    99  // Manufacture will create a lock of a given type according to the input parameters
   100  func New(lockType string, ns string, name string, coreClient corev1.CoreV1Interface, coordinationClient coordinationv1.CoordinationV1Interface, rlc ResourceLockConfig) (Interface, error) {
   101  	endpointsLock := &EndpointsLock{
   102  		EndpointsMeta: metav1.ObjectMeta{
   103  			Namespace: ns,
   104  			Name:      name,
   105  		},
   106  		Client:     coreClient,
   107  		LockConfig: rlc,
   108  	}
   109  	configmapLock := &ConfigMapLock{
   110  		ConfigMapMeta: metav1.ObjectMeta{
   111  			Namespace: ns,
   112  			Name:      name,
   113  		},
   114  		Client:     coreClient,
   115  		LockConfig: rlc,
   116  	}
   117  	leaseLock := &LeaseLock{
   118  		LeaseMeta: metav1.ObjectMeta{
   119  			Namespace: ns,
   120  			Name:      name,
   121  		},
   122  		Client:     coordinationClient,
   123  		LockConfig: rlc,
   124  	}
   125  	switch lockType {
   126  	case EndpointsResourceLock:
   127  		return endpointsLock, nil
   128  	case ConfigMapsResourceLock:
   129  		return configmapLock, nil
   130  	case LeasesResourceLock:
   131  		return leaseLock, nil
   132  	case EndpointsLeasesResourceLock:
   133  		return &MultiLock{
   134  			Primary:   endpointsLock,
   135  			Secondary: leaseLock,
   136  		}, nil
   137  	case ConfigMapsLeasesResourceLock:
   138  		return &MultiLock{
   139  			Primary:   configmapLock,
   140  			Secondary: leaseLock,
   141  		}, nil
   142  	default:
   143  		return nil, fmt.Errorf("Invalid lock-type %s", lockType)
   144  	}
   145  }
   146  
   147  // NewFromKubeconfig will create a lock of a given type according to the input parameters.
   148  // Timeout set for a client used to contact to Kubernetes should be lower than
   149  // RenewDeadline to keep a single hung request from forcing a leader loss.
   150  // Setting it to max(time.Second, RenewDeadline/2) as a reasonable heuristic.
   151  func NewFromKubeconfig(lockType string, ns string, name string, rlc ResourceLockConfig, kubeconfig *restclient.Config, renewDeadline time.Duration) (Interface, error) {
   152  	// shallow copy, do not modify the kubeconfig
   153  	config := *kubeconfig
   154  	timeout := renewDeadline / 2
   155  	if timeout < time.Second {
   156  		timeout = time.Second
   157  	}
   158  	config.Timeout = timeout
   159  	leaderElectionClient := clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "leader-election"))
   160  	return New(lockType, ns, name, leaderElectionClient.CoreV1(), leaderElectionClient.CoordinationV1(), rlc)
   161  }