Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / sigs.k8s.io / controller-runtime / pkg / leaderelection / leader_election.go
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 leaderelection
18
19 import (
20         "fmt"
21         "io/ioutil"
22         "os"
23
24         "k8s.io/apimachinery/pkg/util/uuid"
25         "k8s.io/client-go/kubernetes"
26         "k8s.io/client-go/rest"
27         "k8s.io/client-go/tools/leaderelection/resourcelock"
28         "sigs.k8s.io/controller-runtime/pkg/recorder"
29 )
30
31 const inClusterNamespacePath = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
32
33 // Options provides the required configuration to create a new resource lock
34 type Options struct {
35         // LeaderElection determines whether or not to use leader election when
36         // starting the manager.
37         LeaderElection bool
38
39         // LeaderElectionNamespace determines the namespace in which the leader
40         // election configmap will be created.
41         LeaderElectionNamespace string
42
43         // LeaderElectionID determines the name of the configmap that leader election
44         // will use for holding the leader lock.
45         LeaderElectionID string
46 }
47
48 // NewResourceLock creates a new config map resource lock for use in a leader
49 // election loop
50 func NewResourceLock(config *rest.Config, recorderProvider recorder.Provider, options Options) (resourcelock.Interface, error) {
51         if !options.LeaderElection {
52                 return nil, nil
53         }
54
55         // Default the LeaderElectionID
56         if options.LeaderElectionID == "" {
57                 options.LeaderElectionID = "controller-leader-election-helper"
58         }
59
60         // Default the namespace (if running in cluster)
61         if options.LeaderElectionNamespace == "" {
62                 var err error
63                 options.LeaderElectionNamespace, err = getInClusterNamespace()
64                 if err != nil {
65                         return nil, fmt.Errorf("unable to find leader election namespace: %v", err)
66                 }
67         }
68
69         // Leader id, needs to be unique
70         id, err := os.Hostname()
71         if err != nil {
72                 return nil, err
73         }
74         id = id + "_" + string(uuid.NewUUID())
75
76         // Construct client for leader election
77         client, err := kubernetes.NewForConfig(config)
78         if err != nil {
79                 return nil, err
80         }
81
82         // TODO(JoelSpeed): switch to leaderelection object in 1.12
83         return resourcelock.New(resourcelock.ConfigMapsResourceLock,
84                 options.LeaderElectionNamespace,
85                 options.LeaderElectionID,
86                 client.CoreV1(),
87                 resourcelock.ResourceLockConfig{
88                         Identity:      id,
89                         EventRecorder: recorderProvider.GetEventRecorderFor(id),
90                 })
91 }
92
93 func getInClusterNamespace() (string, error) {
94         // Check whether the namespace file exists.
95         // If not, we are not running in cluster so can't guess the namespace.
96         _, err := os.Stat(inClusterNamespacePath)
97         if os.IsNotExist(err) {
98                 return "", fmt.Errorf("not running in-cluster, please specify LeaderElectionNamespace")
99         } else if err != nil {
100                 return "", fmt.Errorf("error checking namespace file: %v", err)
101         }
102
103         // Load the namespace file and return itss content
104         namespace, err := ioutil.ReadFile(inClusterNamespacePath)
105         if err != nil {
106                 return "", fmt.Errorf("error reading namespace file: %v", err)
107         }
108         return string(namespace), nil
109 }