1 // Copyright 2018 The Operator-SDK Authors
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
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"
32 var log = logf.Log.WithName("k8sutil")
34 // GetWatchNamespace returns the namespace the operator should be watching for changes
35 func GetWatchNamespace() (string, error) {
36 ns, found := os.LookupEnv(WatchNamespaceEnvVar)
38 return "", fmt.Errorf("%s must be set", WatchNamespaceEnvVar)
43 // errNoNS indicates that a namespace could not be found for the current
45 var ErrNoNamespace = fmt.Errorf("namespace not found for current environment")
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")
51 if os.IsNotExist(err) {
52 return "", ErrNoNamespace
56 ns := strings.TrimSpace(string(nsBytes))
57 log.V(1).Info("Found namespace", "Namespace", ns)
61 // GetOperatorName return the operator name
62 func GetOperatorName() (string, error) {
63 operatorName, found := os.LookupEnv(OperatorNameEnvVar)
65 return "", fmt.Errorf("%s must be set", OperatorNameEnvVar)
67 if len(operatorName) == 0 {
68 return "", fmt.Errorf("%s must not be empty", OperatorNameEnvVar)
70 return operatorName, nil
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()
80 for _, apiList := range apiLists {
81 if apiList.GroupVersion == apiGroupVersion {
82 for _, r := range apiList.APIResources {
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)
98 return nil, fmt.Errorf("required env %s not set, please configure downward API", PodNameEnvVar)
101 log.V(1).Info("Found podname", "Pod.Name", podName)
104 key := crclient.ObjectKey{Namespace: ns, Name: podName}
105 err := client.Get(ctx, key, pod)
107 log.Error(err, "Failed to get Pod", "Pod.Namespace", ns, "Pod.Name", podName)
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"
116 log.V(1).Info("Found Pod", "Pod.Namespace", ns, "Pod.Name", pod.Name)
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)
129 schemeAllKnownTypes := s.AllKnownTypes()
130 ownGVKs := []schema.GroupVersionKind{}
131 for gvk, _ := range schemeAllKnownTypes {
132 if !isKubeMetaKind(gvk.Kind) {
133 ownGVKs = append(ownGVKs, gvk)
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" ||
151 kind == "WatchEvent" ||
152 kind == "ListOptions" ||