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 }