From 0c75deb3008af3286ccd060c809500e6f830e7a5 Mon Sep 17 00:00:00 2001 From: humoflife Date: Mon, 22 Apr 2024 17:38:50 -0700 Subject: [PATCH] deprecate config map support Signed-off-by: humoflife --- Makefile | 8 +- README.md | 44 ++-------- example/{out-of-cluster => }/composition.yaml | 0 .../function-shell-grant-read-secrets.sh | 0 example/{out-of-cluster => }/functions.yaml | 0 example/in-cluster/composition.yaml | 37 -------- example/in-cluster/configmap.yaml | 17 ---- example/in-cluster/definition.yaml | 30 ------- example/in-cluster/functions.yaml | 8 -- example/in-cluster/shell-claim.yaml | 6 -- example/{out-of-cluster => }/xr.yaml | 0 fn.go | 25 +----- input/v1alpha1/parameters.go | 14 --- input/v1alpha1/zz_generated.deepcopy.go | 27 ------ .../template.fn.crossplane.io_parameters.yaml | 21 +---- script.go | 85 ------------------- 16 files changed, 12 insertions(+), 310 deletions(-) rename example/{out-of-cluster => }/composition.yaml (100%) rename example/{in-cluster => }/function-shell-grant-read-secrets.sh (100%) rename example/{out-of-cluster => }/functions.yaml (100%) delete mode 100644 example/in-cluster/composition.yaml delete mode 100644 example/in-cluster/configmap.yaml delete mode 100644 example/in-cluster/definition.yaml delete mode 100644 example/in-cluster/functions.yaml delete mode 100644 example/in-cluster/shell-claim.yaml rename example/{out-of-cluster => }/xr.yaml (100%) delete mode 100644 script.go diff --git a/Makefile b/Makefile index 72a9be2..4b7ebf2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ REPO_URL="xpkg.upbound.io/crossplane-contrib/function-shell" -VERSION_TAG="v0.0.6" +VERSION_TAG="v0.1.0" #PACKAGE_FILES="function-amd64.xpkg,function-arm64.xpkg" PACKAGE_FILES="function-arm64.xpkg" @@ -45,9 +45,9 @@ test: ## Run Code Tests render: ## Render Examples, Requires make debug first crossplane beta render \ - example/out-of-cluster/xr.yaml \ - example/out-of-cluster/composition.yaml \ - example/out-of-cluster/functions.yaml + example/xr.yaml \ + example/composition.yaml \ + example/functions.yaml debug: ## Run Shell Function For Rendering Examples go run . --insecure --debug diff --git a/README.md b/README.md index b8b526e..b01200e 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,6 @@ is expected to follow the above pattern. The `function-shell` accepts commands to run in a shell and it returns the output to specified fields. It accepts the following parameters: -- `shellScriptsConfigMapsRef` - referencing at least one Kubernetes -[`ConfigMap`](https://kubernetes.io/docs/concepts/configuration/configmap/) -with at least one shell script. This script can be written in an arbitrary -shell language, for example bash or python3. - `shellEnvVarsSecretRef` - referencing environment variables in a Kubernetes secret. `shellEnvVarsSecretRef` requires a `name`, a `namespace` and a `key` for the secret. Inside of it, the shell @@ -76,32 +72,6 @@ kubectl create clusterrolebinding function-shell-admin-binding \ --serviceaccount="${SA}" ``` -The composition reads a `ConfigMap` that contains 2 example scripts. -When you experiment with scripts in ConfigMaps, apply the yaml to the -desired namespace, e.g. `kubectl -n crossplane-system apply -f -example/in-cluster/configmap.yaml`. It is recommended to use -the namespace where the `function-shell` pod is running. - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: function-shell-script -data: - hello-from-python.py: | - #!/usr/bin/python3 - - print ( "hello from python" ) - get-datadog-dashboard-ids.sh: | - #!/bin/bash - - curl -X GET "${DATADOG_API_URL}" \ - -H "Accept: application/json" \ - -H "DD-API-KEY: ${DATADOG_API_KEY}" \ - -H "DD-APPLICATION-KEY: ${DATADOG_APP_KEY}"|\ - jq '.dashboards[] .id'; -``` - The composition reads a datadog secret that looks like below. Replace `YOUR_API_KEY` and `YOUR_APP_KEY` with your respective keys. @@ -130,13 +100,6 @@ spec: input: apiVersion: shell.fn.crossplane.io/v1beta1 kind: Parameters - - shellScriptsConfigMapsRef: - - scriptNames: - - hello-from-python.py - - get-datadog-dashboard-ids.sh - name: function-shell-script - namespace: upbound-system shellEnvVarsSecretRef: name: datadog-secret namespace: upbound-system @@ -145,8 +108,11 @@ spec: - key: DATADOG_API_URL value: "https://api.datadoghq.com/api/v1/dashboard" shellCommand: | - /scripts/get-datadog-dashboard-ids.sh - python3 /scripts/hello-from-python.py|awk '{print $3}'|tr "p" "P" + curl -X GET "${DATADOG_API_URL}" \ + -H "Accept: application/json" \ + -H "DD-API-KEY: ${DATADOG_API_KEY}" \ + -H "DD-APPLICATION-KEY: ${DATADOG_APP_KEY}"|\ + jq '.dashboards[] .id'; stdoutField: status.atFunction.shell.stdout stderrField: status.atFunction.shell.stderr ``` diff --git a/example/out-of-cluster/composition.yaml b/example/composition.yaml similarity index 100% rename from example/out-of-cluster/composition.yaml rename to example/composition.yaml diff --git a/example/in-cluster/function-shell-grant-read-secrets.sh b/example/function-shell-grant-read-secrets.sh similarity index 100% rename from example/in-cluster/function-shell-grant-read-secrets.sh rename to example/function-shell-grant-read-secrets.sh diff --git a/example/out-of-cluster/functions.yaml b/example/functions.yaml similarity index 100% rename from example/out-of-cluster/functions.yaml rename to example/functions.yaml diff --git a/example/in-cluster/composition.yaml b/example/in-cluster/composition.yaml deleted file mode 100644 index b8ee448..0000000 --- a/example/in-cluster/composition.yaml +++ /dev/null @@ -1,37 +0,0 @@ ---- -apiVersion: apiextensions.crossplane.io/v1 -kind: Composition -metadata: - name: shell.upbound.io -spec: - compositeTypeRef: - apiVersion: upbound.io/v1alpha1 - kind: XShell - mode: Pipeline - pipeline: - - step: shell - functionRef: - # When installed through a package manager, use - # name: crossplane-contrib-function-shell - name: function-shell - input: - apiVersion: shell.fn.crossplane.io/v1alpha1 - kind: Parameters - shellScriptsConfigMapsRef: - - scriptNames: - - hello-from-python.py - - get-datadog-dashboard-ids.sh - name: function-shell-script - namespace: upbound-system - shellEnvVarsSecretRef: - key: credentials - name: datadog-secret - namespace: upbound-system - shellEnvVars: - - key: DATADOG_API_URL - value: "https://api.datadoghq.com/api/v1/dashboard" - shellCommand: | - /scripts/get-datadog-dashboard-ids.sh - python3 /scripts/hello-from-python.py|awk '{print $3}'|tr "p" "P" - stdoutField: status.atFunction.shell.stdout - stderrField: status.atFunction.shell.stderr \ No newline at end of file diff --git a/example/in-cluster/configmap.yaml b/example/in-cluster/configmap.yaml deleted file mode 100644 index c02c353..0000000 --- a/example/in-cluster/configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: function-shell-script -data: - hello-from-python.py: | - #!/usr/bin/python3 - - print ( "hello from python" ) - get-datadog-dashboard-ids.sh: | - #!/bin/bash - - curl -X GET "${DATADOG_API_URL}" \ - -H "Accept: application/json" \ - -H "DD-API-KEY: ${DATADOG_API_KEY}" \ - -H "DD-APPLICATION-KEY: ${DATADOG_APP_KEY}"|\ - jq '.dashboards[] .id'; diff --git a/example/in-cluster/definition.yaml b/example/in-cluster/definition.yaml deleted file mode 100644 index 62d97b1..0000000 --- a/example/in-cluster/definition.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: apiextensions.crossplane.io/v1 -kind: CompositeResourceDefinition -metadata: - name: xshells.upbound.io -spec: - group: upbound.io - names: - kind: XShell - plural: xshells - claimNames: - kind: Shell - plural: shells - defaultCompositionRef: - name: shell.upbound.io - versions: - - name: v1alpha1 - served: true - referenceable: true - schema: - openAPIV3Schema: - properties: - spec: - properties: - cmd: - type: string - status: - properties: - atFunction: - type: object - x-kubernetes-preserve-unknown-fields: true diff --git a/example/in-cluster/functions.yaml b/example/in-cluster/functions.yaml deleted file mode 100644 index e781c0a..0000000 --- a/example/in-cluster/functions.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: pkg.crossplane.io/v1beta1 -kind: Function -metadata: - name: function-shell -spec: - package: xpkg.upbound.io/crossplane-contrib/function-shell:v0.0.6 - packagePullPolicy: Always diff --git a/example/in-cluster/shell-claim.yaml b/example/in-cluster/shell-claim.yaml deleted file mode 100644 index 4f508dc..0000000 --- a/example/in-cluster/shell-claim.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -apiVersion: upbound.io/v1alpha1 -kind: Shell -metadata: - name: shell-1 -spec: {} diff --git a/example/out-of-cluster/xr.yaml b/example/xr.yaml similarity index 100% rename from example/out-of-cluster/xr.yaml rename to example/xr.yaml diff --git a/fn.go b/fn.go index 93c946f..d36204e 100644 --- a/fn.go +++ b/fn.go @@ -70,27 +70,6 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ stderrField = "status.atFunction.shell.stderr" } - var shellScripts map[string][]string - if in.ShellScriptsConfigMapsRef != nil { - shellScripts, err = loadShellScripts(log, in.ShellScriptsConfigMapsRef) - if err != nil { - response.Fatal(rsp, errors.Wrapf(err, "cannot process shell script ConfigMaps")) - return rsp, nil - } - } - - copyShellScripts := "" - if len(shellScripts) > 0 { - for shellScriptName, shellScript := range shellScripts { - copyShellScripts = "rm -f ./scripts/" + shellScriptName + ";" - for _, line := range shellScript { - escapedLine := strings.ReplaceAll(line, "'", "\"'\"") - copyShellScripts = copyShellScripts + "echo '" + escapedLine + "'>> ./scripts/" + shellScriptName + ";" - } - copyShellScripts = copyShellScripts + "/bin/chmod +x ./scripts/" + shellScriptName + ";" - } - } - shellCmd := "" if len(in.ShellCommand) == 0 && len(in.ShellCommandField) == 0 { log.Info("no shell command in in.ShellCommand nor in.ShellCommandField") @@ -128,7 +107,7 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ log.Info(shellCmd) var stdout, stderr bytes.Buffer - cmd := shell.Commandf(exportCmds + copyShellScripts + shellCmd) + cmd := shell.Commandf(exportCmds + shellCmd) cmd.Stdout = &stdout cmd.Stderr = &stderr err = cmd.Run() @@ -153,4 +132,4 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ } return rsp, nil -} \ No newline at end of file +} diff --git a/input/v1alpha1/parameters.go b/input/v1alpha1/parameters.go index c2994c7..f5d4d6c 100644 --- a/input/v1alpha1/parameters.go +++ b/input/v1alpha1/parameters.go @@ -27,10 +27,6 @@ type Parameters struct { // +optional ShellEnvVars []ShellEnvVar `json:"shellEnvVars,omitempty"` - // shellScriptFiles - // +optional - ShellScriptsConfigMapsRef []ShellScriptsConfigMapRef `json:"shellScriptsConfigMapsRef"` - // shellCmd // +optional ShellCommand string `json:"shellCommand,omitempty"` @@ -61,13 +57,3 @@ type ShellEnvVarsSecretRef struct { // Namespace where Kubernetes secret resides Namespace string `json:"namespace,omitempty"` } - -type ShellScriptsConfigMapRef struct { - // The name of the script entries in a ConfigMap - // Each ConfigMap can contain multiple scripts - ScriptNames []string `json:"scriptNames,omitempty"` - // Name of Kubernetes ConfigMap - Name string `json:"name,omitempty"` - // Namespace where Kubernetes ConfigMap resides - Namespace string `json:"namespace,omitempty"` -} diff --git a/input/v1alpha1/zz_generated.deepcopy.go b/input/v1alpha1/zz_generated.deepcopy.go index dbe1bb2..0c205cf 100644 --- a/input/v1alpha1/zz_generated.deepcopy.go +++ b/input/v1alpha1/zz_generated.deepcopy.go @@ -19,13 +19,6 @@ func (in *Parameters) DeepCopyInto(out *Parameters) { *out = make([]ShellEnvVar, len(*in)) copy(*out, *in) } - if in.ShellScriptsConfigMapsRef != nil { - in, out := &in.ShellScriptsConfigMapsRef, &out.ShellScriptsConfigMapsRef - *out = make([]ShellScriptsConfigMapRef, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parameters. @@ -75,23 +68,3 @@ func (in *ShellEnvVarsSecretRef) DeepCopy() *ShellEnvVarsSecretRef { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ShellScriptsConfigMapRef) DeepCopyInto(out *ShellScriptsConfigMapRef) { - *out = *in - if in.ScriptNames != nil { - in, out := &in.ScriptNames, &out.ScriptNames - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShellScriptsConfigMapRef. -func (in *ShellScriptsConfigMapRef) DeepCopy() *ShellScriptsConfigMapRef { - if in == nil { - return nil - } - out := new(ShellScriptsConfigMapRef) - in.DeepCopyInto(out) - return out -} diff --git a/package/input/template.fn.crossplane.io_parameters.yaml b/package/input/template.fn.crossplane.io_parameters.yaml index 6be41c6..b85aeba 100644 --- a/package/input/template.fn.crossplane.io_parameters.yaml +++ b/package/input/template.fn.crossplane.io_parameters.yaml @@ -67,25 +67,6 @@ spec: description: Namespace where Kubernetes secret resides type: string type: object - shellScriptsConfigMapsRef: - description: shellScriptFiles - items: - properties: - name: - description: Name of Kubernetes ConfigMap - type: string - namespace: - description: Namespace where Kubernetes ConfigMap resides - type: string - scriptNames: - description: |- - The name of the script entries in a ConfigMap - Each ConfigMap can contain multiple scripts - items: - type: string - type: array - type: object - type: array stderrField: description: stderrField type: string @@ -94,4 +75,4 @@ spec: type: string type: object served: true - storage: true \ No newline at end of file + storage: true diff --git a/script.go b/script.go deleted file mode 100644 index 8137b5d..0000000 --- a/script.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "context" - "fmt" - "maps" - "os" - "strings" - - "github.com/crossplane-contrib/function-shell/input/v1alpha1" - "github.com/crossplane/crossplane-runtime/pkg/logging" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - _ "k8s.io/client-go/plugin/pkg/client/auth" -) - -func loadShellScripts(log logging.Logger, shellScriptsConfigMapsRef []v1alpha1.ShellScriptsConfigMapRef) (map[string][]string, error) { - shellScripts := make(map[string][]string) - - for _, shellScriptsConfigMapRef := range shellScriptsConfigMapsRef { - newShellScripts, err := getShellScriptsFromConfigMap(shellScriptsConfigMapRef) - if err != nil { - log.Info("unable to get shell scripts from ", shellScriptsConfigMapRef.Name) - continue - } - maps.Copy(shellScripts, newShellScripts) - } - - return shellScripts, nil -} - -func getShellScriptsFromConfigMap(shellScriptsConfigMapRef v1alpha1.ShellScriptsConfigMapRef) (map[string][]string, error) { - var clientset *kubernetes.Clientset - scripts := make(map[string][]string) - - _, err := os.OpenFile("/var/run/secrets/kubernetes.io", os.O_RDWR, 0666) - if os.IsNotExist(err) { - clientset, err = outOfClusterClient() - if err != nil { - return scripts, err - } - } else { - clientset, err = inClusterClient() - if err != nil { - return scripts, err - } - } - - scripts, err = getScripts(clientset, shellScriptsConfigMapRef) - if err != nil { - return scripts, err - } - - return scripts, nil -} - -func getScripts(clientset *kubernetes.Clientset, shellScriptsConfigMapRef v1alpha1.ShellScriptsConfigMapRef) (map[string][]string, error) { - scripts := make(map[string][]string) - scriptNames := shellScriptsConfigMapRef.ScriptNames - name := shellScriptsConfigMapRef.Name - namespace := shellScriptsConfigMapRef.Namespace - - scriptConfigMap, err := clientset.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metav1.GetOptions{}) - if errors.IsNotFound(err) { - err = fmt.Errorf("Script ConfigMap %s in namespace %s not found\n", name, namespace) - return scripts, err - } - - if statusError, isStatus := err.(*errors.StatusError); isStatus { - err = fmt.Errorf("Error getting script in ConfigMap %s in namespace %s: %v\n", - name, namespace, statusError.ErrStatus.Message) - return scripts, err - } - - if err != nil { - return scripts, err - } - - for _, scriptName := range scriptNames { - scripts[scriptName] = append(scripts[scriptName], strings.Split(scriptConfigMap.Data[scriptName], "\n")...) - } - - return scripts, nil -}