Skip to content

Commit afef0fa

Browse files
committed
Remove reliance on k8sutil
1 parent 505a98a commit afef0fa

File tree

1 file changed

+83
-5
lines changed

1 file changed

+83
-5
lines changed

leader/leader.go

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ package leader
1616

1717
import (
1818
"context"
19+
"fmt"
20+
"io/ioutil"
21+
"os"
22+
"strings"
1923
"time"
2024

21-
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
22-
2325
corev1 "k8s.io/api/core/v1"
2426
apierrors "k8s.io/apimachinery/pkg/api/errors"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -29,6 +31,29 @@ import (
2931
logf "sigs.k8s.io/controller-runtime/pkg/log"
3032
)
3133

34+
type runModeType string
35+
36+
const (
37+
localRunMode runModeType = "local"
38+
clusterRunMode runModeType = "cluster"
39+
)
40+
41+
// forceRunModeEnv indicates if the operator should be forced to run in either local
42+
// or cluster mode (currently only used for local mode)
43+
var forceRunModeEnv = "OSDK_FORCE_RUN_MODE"
44+
45+
// errNoNamespace indicates that a namespace could not be found for the current
46+
// environment
47+
var errNoNamespace = fmt.Errorf("namespace not found for current environment")
48+
49+
// errRunLocal indicates that the operator is set to run in local mode (this error
50+
// is returned by functions that only work on operators running in cluster mode)
51+
var errRunLocal = fmt.Errorf("operator run mode forced to local")
52+
53+
// podNameEnvVar is the constant for env variable POD_NAME
54+
// which is the name of the current pod.
55+
const podNameEnvVar = "POD_NAME"
56+
3257
var log = logf.Log.WithName("leader")
3358

3459
// maxBackoffInterval defines the maximum amount of time to wait between
@@ -45,9 +70,9 @@ const maxBackoffInterval = time.Second * 16
4570
func Become(ctx context.Context, lockName string) error {
4671
log.Info("Trying to become the leader.")
4772

48-
ns, err := k8sutil.GetOperatorNamespace()
73+
ns, err := getOperatorNamespace()
4974
if err != nil {
50-
if err == k8sutil.ErrNoNamespace || err == k8sutil.ErrRunLocal {
75+
if err == errNoNamespace || err == errRunLocal {
5176
log.Info("Skipping leader election; not running in a cluster.")
5277
return nil
5378
}
@@ -164,7 +189,7 @@ func Become(ctx context.Context, lockName string) error {
164189
// this code is currently running.
165190
// It expects the environment variable POD_NAME to be set by the downwards API
166191
func myOwnerRef(ctx context.Context, client crclient.Client, ns string) (*metav1.OwnerReference, error) {
167-
myPod, err := k8sutil.GetPod(ctx, client, ns)
192+
myPod, err := getPod(ctx, client, ns)
168193
if err != nil {
169194
return nil, err
170195
}
@@ -183,3 +208,56 @@ func isPodEvicted(pod corev1.Pod) bool {
183208
podEvicted := pod.Status.Reason == "Evicted"
184209
return podFailed && podEvicted
185210
}
211+
212+
// getOperatorNamespace returns the namespace the operator should be running in.
213+
func getOperatorNamespace() (string, error) {
214+
if isRunModeLocal() {
215+
return "", errRunLocal
216+
}
217+
nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
218+
if err != nil {
219+
if os.IsNotExist(err) {
220+
return "", errNoNamespace
221+
}
222+
return "", err
223+
}
224+
ns := strings.TrimSpace(string(nsBytes))
225+
log.V(1).Info("Found namespace", "Namespace", ns)
226+
return ns, nil
227+
}
228+
229+
func isRunModeLocal() bool {
230+
return os.Getenv(forceRunModeEnv) == string(localRunMode)
231+
}
232+
233+
// getPod returns a Pod object that corresponds to the pod in which the code
234+
// is currently running.
235+
// It expects the environment variable POD_NAME to be set by the downwards API.
236+
func getPod(ctx context.Context, client crclient.Client, ns string) (*corev1.Pod, error) {
237+
if isRunModeLocal() {
238+
return nil, errRunLocal
239+
}
240+
podName := os.Getenv(podNameEnvVar)
241+
if podName == "" {
242+
return nil, fmt.Errorf("required env %s not set, please configure downward API", podNameEnvVar)
243+
}
244+
245+
log.V(1).Info("Found podname", "Pod.Name", podName)
246+
247+
pod := &corev1.Pod{}
248+
key := crclient.ObjectKey{Namespace: ns, Name: podName}
249+
err := client.Get(ctx, key, pod)
250+
if err != nil {
251+
log.Error(err, "Failed to get Pod", "Pod.Namespace", ns, "Pod.Name", podName)
252+
return nil, err
253+
}
254+
255+
// .Get() clears the APIVersion and Kind,
256+
// so we need to set them before returning the object.
257+
pod.TypeMeta.APIVersion = "v1"
258+
pod.TypeMeta.Kind = "Pod"
259+
260+
log.V(1).Info("Found Pod", "Pod.Namespace", ns, "Pod.Name", pod.Name)
261+
262+
return pod, nil
263+
}

0 commit comments

Comments
 (0)