github.xiaoq7.com/operator-framework/operator-sdk@v0.8.2/pkg/k8sutil/k8sutil.go (about) 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 discovery "k8s.io/client-go/discovery" 26 crclient "sigs.k8s.io/controller-runtime/pkg/client" 27 logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" 28 ) 29 30 var log = logf.Log.WithName("k8sutil") 31 32 // GetWatchNamespace returns the namespace the operator should be watching for changes 33 func GetWatchNamespace() (string, error) { 34 ns, found := os.LookupEnv(WatchNamespaceEnvVar) 35 if !found { 36 return "", fmt.Errorf("%s must be set", WatchNamespaceEnvVar) 37 } 38 return ns, nil 39 } 40 41 // errNoNS indicates that a namespace could not be found for the current 42 // environment 43 var ErrNoNamespace = fmt.Errorf("namespace not found for current environment") 44 45 // GetOperatorNamespace returns the namespace the operator should be running in. 46 func GetOperatorNamespace() (string, error) { 47 nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") 48 if err != nil { 49 if os.IsNotExist(err) { 50 return "", ErrNoNamespace 51 } 52 return "", err 53 } 54 ns := strings.TrimSpace(string(nsBytes)) 55 log.V(1).Info("Found namespace", "Namespace", ns) 56 return ns, nil 57 } 58 59 // GetOperatorName return the operator name 60 func GetOperatorName() (string, error) { 61 operatorName, found := os.LookupEnv(OperatorNameEnvVar) 62 if !found { 63 return "", fmt.Errorf("%s must be set", OperatorNameEnvVar) 64 } 65 if len(operatorName) == 0 { 66 return "", fmt.Errorf("%s must not be empty", OperatorNameEnvVar) 67 } 68 return operatorName, nil 69 } 70 71 // ResourceExists returns true if the given resource kind exists 72 // in the given api groupversion 73 func ResourceExists(dc discovery.DiscoveryInterface, apiGroupVersion, kind string) (bool, error) { 74 apiLists, err := dc.ServerResources() 75 if err != nil { 76 return false, err 77 } 78 for _, apiList := range apiLists { 79 if apiList.GroupVersion == apiGroupVersion { 80 for _, r := range apiList.APIResources { 81 if r.Kind == kind { 82 return true, nil 83 } 84 } 85 } 86 } 87 return false, nil 88 } 89 90 // GetPod returns a Pod object that corresponds to the pod in which the code 91 // is currently running. 92 // It expects the environment variable POD_NAME to be set by the downwards API. 93 func GetPod(ctx context.Context, client crclient.Client, ns string) (*corev1.Pod, error) { 94 podName := os.Getenv(PodNameEnvVar) 95 if podName == "" { 96 return nil, fmt.Errorf("required env %s not set, please configure downward API", PodNameEnvVar) 97 } 98 99 log.V(1).Info("Found podname", "Pod.Name", podName) 100 101 pod := &corev1.Pod{} 102 key := crclient.ObjectKey{Namespace: ns, Name: podName} 103 err := client.Get(ctx, key, pod) 104 if err != nil { 105 log.Error(err, "Failed to get Pod", "Pod.Namespace", ns, "Pod.Name", podName) 106 return nil, err 107 } 108 109 // .Get() clears the APIVersion and Kind, 110 // so we need to set them before returning the object. 111 pod.TypeMeta.APIVersion = "v1" 112 pod.TypeMeta.Kind = "Pod" 113 114 log.V(1).Info("Found Pod", "Pod.Namespace", ns, "Pod.Name", pod.Name) 115 116 return pod, nil 117 }