diff --git a/internal/util/k8sutil/k8sutil.go b/internal/util/k8sutil/k8sutil.go index 1be8ea2525..a6eb649189 100644 --- a/internal/util/k8sutil/k8sutil.go +++ b/internal/util/k8sutil/k8sutil.go @@ -16,30 +16,22 @@ package k8sutil import ( "bytes" - "context" "errors" "fmt" "io" - "io/ioutil" - "os" "regexp" "strings" "unicode" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/client-go/discovery" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" - crclient "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) // GetKubeconfigAndNamespace returns the *rest.Config and default namespace defined in the @@ -148,161 +140,6 @@ func TrimDNS1123Label(label string) string { return label } -// ForceRunModeEnv indicates if the operator should be forced to run in either local -// or cluster mode (currently only used for local mode) -var ForceRunModeEnv = "OSDK_FORCE_RUN_MODE" - -type RunModeType string - -const ( - LocalRunMode RunModeType = "local" - ClusterRunMode RunModeType = "cluster" -) - -var logk8sutil = logf.Log.WithName("k8sutil") - -// GetWatchNamespace returns the namespace the operator should be watching for changes -func GetWatchNamespace() (string, error) { - ns, found := os.LookupEnv(WatchNamespaceEnvVar) - if !found { - return "", fmt.Errorf("%s must be set", WatchNamespaceEnvVar) - } - return ns, nil -} - -// ErrNoNamespace indicates that a namespace could not be found for the current -// environment -var ErrNoNamespace = fmt.Errorf("namespace not found for current environment") - -// ErrRunLocal indicates that the operator is set to run in local mode (this error -// is returned by functions that only work on operators running in cluster mode) -var ErrRunLocal = fmt.Errorf("operator run mode forced to local") - -// GetOperatorNamespace returns the namespace the operator should be running in. -func GetOperatorNamespace() (string, error) { - if isRunModeLocal() { - return "", ErrRunLocal - } - nsBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") - if err != nil { - if os.IsNotExist(err) { - return "", ErrNoNamespace - } - return "", err - } - ns := strings.TrimSpace(string(nsBytes)) - logk8sutil.V(1).Info("Found namespace", "Namespace", ns) - return ns, nil -} - -// GetOperatorName return the operator name -func GetOperatorName() (string, error) { - operatorName, found := os.LookupEnv(OperatorNameEnvVar) - if !found { - return "", fmt.Errorf("%s must be set", OperatorNameEnvVar) - } - if len(operatorName) == 0 { - return "", fmt.Errorf("%s must not be empty", OperatorNameEnvVar) - } - return operatorName, nil -} - -// ResourceExists returns true if the given resource kind exists -// in the given api groupversion -func ResourceExists(dc discovery.DiscoveryInterface, apiGroupVersion, kind string) (bool, error) { - - _, apiLists, err := dc.ServerGroupsAndResources() - if err != nil { - return false, err - } - for _, apiList := range apiLists { - if apiList.GroupVersion == apiGroupVersion { - for _, r := range apiList.APIResources { - if r.Kind == kind { - return true, nil - } - } - } - } - return false, nil -} - -// GetPod returns a Pod object that corresponds to the pod in which the code -// is currently running. -// It expects the environment variable POD_NAME to be set by the downwards API. -func GetPod(ctx context.Context, client crclient.Client, ns string) (*corev1.Pod, error) { - if isRunModeLocal() { - return nil, ErrRunLocal - } - podName := os.Getenv(PodNameEnvVar) - if podName == "" { - return nil, fmt.Errorf("required env %s not set, please configure downward API", PodNameEnvVar) - } - - logk8sutil.V(1).Info("Found podname", "Pod.Name", podName) - - pod := &corev1.Pod{} - key := crclient.ObjectKey{Namespace: ns, Name: podName} - err := client.Get(ctx, key, pod) - if err != nil { - logk8sutil.Error(err, "Failed to get Pod", "Pod.Namespace", ns, "Pod.Name", podName) - return nil, err - } - - // .Get() clears the APIVersion and Kind, - // so we need to set them before returning the object. - pod.TypeMeta.APIVersion = "v1" - pod.TypeMeta.Kind = "Pod" - - logk8sutil.V(1).Info("Found Pod", "Pod.Namespace", ns, "Pod.Name", pod.Name) - - return pod, nil -} - -// GetGVKsFromAddToScheme takes in the runtime scheme and filters out all generic apimachinery meta types. -// It returns just the GVK specific to this scheme. -func GetGVKsFromAddToScheme(addToSchemeFunc func(*runtime.Scheme) error) ([]schema.GroupVersionKind, error) { - s := runtime.NewScheme() - err := addToSchemeFunc(s) - if err != nil { - return nil, err - } - schemeAllKnownTypes := s.AllKnownTypes() - ownGVKs := []schema.GroupVersionKind{} - for gvk := range schemeAllKnownTypes { - if !isKubeMetaKind(gvk.Kind) { - ownGVKs = append(ownGVKs, gvk) - } - } - - return ownGVKs, nil -} - -func isKubeMetaKind(kind string) bool { - if strings.HasSuffix(kind, "List") || - kind == "PatchOptions" || - kind == "GetOptions" || - kind == "DeleteOptions" || - kind == "ExportOptions" || - kind == "APIVersions" || - kind == "APIGroupList" || - kind == "APIResourceList" || - kind == "UpdateOptions" || - kind == "CreateOptions" || - kind == "Status" || - kind == "WatchEvent" || - kind == "ListOptions" || - kind == "APIGroup" { - return true - } - - return false -} - -func isRunModeLocal() bool { - return os.Getenv(ForceRunModeEnv) == string(LocalRunMode) -} - // SupportsOwnerReference checks whether a given dependent supports owner references, based on the owner. // This function performs following checks: // -- True: Owner is cluster-scoped. diff --git a/internal/util/k8sutil/k8sutil_test.go b/internal/util/k8sutil/k8sutil_test.go index 125d486d85..9fcdcbaadc 100644 --- a/internal/util/k8sutil/k8sutil_test.go +++ b/internal/util/k8sutil/k8sutil_test.go @@ -15,9 +15,6 @@ package k8sutil import ( - "fmt" - "os" - "reflect" "testing" "github.com/stretchr/testify/assert" @@ -54,60 +51,6 @@ func TestGetDisplayName(t *testing.T) { } } -func TestGetOperatorName(t *testing.T) { - type Output struct { - operatorName string - err error - } - - type Scenario struct { - name string - envVarKey string - envVarValue string - expectedOutput Output - } - - tests := []Scenario{ - { - name: "Simple case", - envVarKey: OperatorNameEnvVar, - envVarValue: "myoperator", - expectedOutput: Output{ - operatorName: "myoperator", - err: nil, - }, - }, - { - name: "Unset env var", - envVarKey: "", - envVarValue: "", - expectedOutput: Output{ - operatorName: "", - err: fmt.Errorf("%s must be set", OperatorNameEnvVar), - }, - }, - { - name: "Empty env var", - envVarKey: OperatorNameEnvVar, - envVarValue: "", - expectedOutput: Output{ - operatorName: "", - err: fmt.Errorf("%s must not be empty", OperatorNameEnvVar), - }, - }, - } - - for _, test := range tests { - _ = os.Setenv(test.envVarKey, test.envVarValue) - operatorName, err := GetOperatorName() - if !(operatorName == test.expectedOutput.operatorName && reflect.DeepEqual(err, test.expectedOutput.err)) { - t.Errorf("Test %s failed, expected output: %s,%v; got: %s,%v", test.name, - test.expectedOutput.operatorName, test.expectedOutput.err, operatorName, err) - } - _ = os.Unsetenv(test.envVarKey) - } -} - func TestSupportsOwnerReference(t *testing.T) { type testcase struct { name string