Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / operator-framework / operator-sdk / pkg / k8sutil / k8sutil.go
1 // Copyright 2018 The Operator-SDK Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package k8sutil
16
17 import (
18         "context"
19         "fmt"
20         "io/ioutil"
21         "os"
22         "strings"
23
24         corev1 "k8s.io/api/core/v1"
25         "k8s.io/apimachinery/pkg/runtime"
26         "k8s.io/apimachinery/pkg/runtime/schema"
27         discovery "k8s.io/client-go/discovery"
28         crclient "sigs.k8s.io/controller-runtime/pkg/client"
29         logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
30 )
31
32 var log = logf.Log.WithName("k8sutil")
33
34 // GetWatchNamespace returns the namespace the operator should be watching for changes
35 func GetWatchNamespace() (string, error) {
36         ns, found := os.LookupEnv(WatchNamespaceEnvVar)
37         if !found {
38                 return "", fmt.Errorf("%s must be set", WatchNamespaceEnvVar)
39         }
40         return ns, nil
41 }
42
43 // errNoNS indicates that a namespace could not be found for the current
44 // environment
45 var ErrNoNamespace = fmt.Errorf("namespace not found for current environment")
46
47 // GetOperatorNamespace returns the namespace the operator should be running in.
48 func GetOperatorNamespace() (string, error) {
49         nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
50         if err != nil {
51                 if os.IsNotExist(err) {
52                         return "", ErrNoNamespace
53                 }
54                 return "", err
55         }
56         ns := strings.TrimSpace(string(nsBytes))
57         log.V(1).Info("Found namespace", "Namespace", ns)
58         return ns, nil
59 }
60
61 // GetOperatorName return the operator name
62 func GetOperatorName() (string, error) {
63         operatorName, found := os.LookupEnv(OperatorNameEnvVar)
64         if !found {
65                 return "", fmt.Errorf("%s must be set", OperatorNameEnvVar)
66         }
67         if len(operatorName) == 0 {
68                 return "", fmt.Errorf("%s must not be empty", OperatorNameEnvVar)
69         }
70         return operatorName, nil
71 }
72
73 // ResourceExists returns true if the given resource kind exists
74 // in the given api groupversion
75 func ResourceExists(dc discovery.DiscoveryInterface, apiGroupVersion, kind string) (bool, error) {
76         apiLists, err := dc.ServerResources()
77         if err != nil {
78                 return false, err
79         }
80         for _, apiList := range apiLists {
81                 if apiList.GroupVersion == apiGroupVersion {
82                         for _, r := range apiList.APIResources {
83                                 if r.Kind == kind {
84                                         return true, nil
85                                 }
86                         }
87                 }
88         }
89         return false, nil
90 }
91
92 // GetPod returns a Pod object that corresponds to the pod in which the code
93 // is currently running.
94 // It expects the environment variable POD_NAME to be set by the downwards API.
95 func GetPod(ctx context.Context, client crclient.Client, ns string) (*corev1.Pod, error) {
96         podName := os.Getenv(PodNameEnvVar)
97         if podName == "" {
98                 return nil, fmt.Errorf("required env %s not set, please configure downward API", PodNameEnvVar)
99         }
100
101         log.V(1).Info("Found podname", "Pod.Name", podName)
102
103         pod := &corev1.Pod{}
104         key := crclient.ObjectKey{Namespace: ns, Name: podName}
105         err := client.Get(ctx, key, pod)
106         if err != nil {
107                 log.Error(err, "Failed to get Pod", "Pod.Namespace", ns, "Pod.Name", podName)
108                 return nil, err
109         }
110
111         // .Get() clears the APIVersion and Kind,
112         // so we need to set them before returning the object.
113         pod.TypeMeta.APIVersion = "v1"
114         pod.TypeMeta.Kind = "Pod"
115
116         log.V(1).Info("Found Pod", "Pod.Namespace", ns, "Pod.Name", pod.Name)
117
118         return pod, nil
119 }
120
121 // GetGVKsFromAddToScheme takes in the runtime scheme and filters out all generic apimachinery meta types.
122 // It returns just the GVK specific to this scheme.
123 func GetGVKsFromAddToScheme(addToSchemeFunc func(*runtime.Scheme) error) ([]schema.GroupVersionKind, error) {
124         s := runtime.NewScheme()
125         err := addToSchemeFunc(s)
126         if err != nil {
127                 return nil, err
128         }
129         schemeAllKnownTypes := s.AllKnownTypes()
130         ownGVKs := []schema.GroupVersionKind{}
131         for gvk, _ := range schemeAllKnownTypes {
132                 if !isKubeMetaKind(gvk.Kind) {
133                         ownGVKs = append(ownGVKs, gvk)
134                 }
135         }
136
137         return ownGVKs, nil
138 }
139
140 func isKubeMetaKind(kind string) bool {
141         if strings.HasSuffix(kind, "List") ||
142                 kind == "GetOptions" ||
143                 kind == "DeleteOptions" ||
144                 kind == "ExportOptions" ||
145                 kind == "APIVersions" ||
146                 kind == "APIGroupList" ||
147                 kind == "APIResourceList" ||
148                 kind == "UpdateOptions" ||
149                 kind == "CreateOptions" ||
150                 kind == "Status" ||
151                 kind == "WatchEvent" ||
152                 kind == "ListOptions" ||
153                 kind == "APIGroup" {
154                 return true
155         }
156
157         return false
158 }