diff --git a/execute-script-via-k8s-job/README.md b/execute-script-via-k8s-job/README.md index d0b1683..a69ca1b 100644 --- a/execute-script-via-k8s-job/README.md +++ b/execute-script-via-k8s-job/README.md @@ -16,6 +16,7 @@ This example demonstrates how to execute a custom bash script within a Kubernete * **Resource Management**: Utilize the resources of your Kubernetes cluster to execute scripts that require more CPU, memory, or storage than what is available in the default `ExecuteScript` command. * **Custom Images**: Use your own container images from private registries to tailor the execution environment to your needs. * **Timeout Configuration**: Set higher timeouts for script execution, ensuring that long-running scripts can complete without being interrupted. +* **Event Logging**: Retrieve all Kubernetes events related to the script execution for better debugging and monitoring. ### Use Cases @@ -58,13 +59,15 @@ To use this example you'll need the following: 3. **Monitor the Execution**: -* The command will create a Kubernetes Job to execute the script, wait for it to finish, and at the end will retrieve the exit code and the script output. -* After the execution finishes, you can see the script output and exit code: +* The command will create a Kubernetes Job to execute the script, wait for it to finish, and at the end will retrieve the exit code, the script output, and all related Kubernetes events. +* After the execution finishes, you can see the script output, exit code, and related events: ![Successful Execution](./assets/successful-execution.png) ![Script Output](./assets/script-output.png) +![Kubernetes Events](./assets/kubernetes-events.png) + :information_source: The Kubernetes Job will be automatically cleaned up after execution, ensuring that no resources are left behind. The job is configured with [ttlSecondsAfterFinished](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/) which automatically deletes the job after 3 minutes. ## Setup Pull Secret diff --git a/execute-script-via-k8s-job/assets/kubernetes-events.png b/execute-script-via-k8s-job/assets/kubernetes-events.png new file mode 100644 index 0000000..11f03b3 Binary files /dev/null and b/execute-script-via-k8s-job/assets/kubernetes-events.png differ diff --git a/execute-script-via-k8s-job/assets/script-output.png b/execute-script-via-k8s-job/assets/script-output.png index 25f5b10..9159418 100644 Binary files a/execute-script-via-k8s-job/assets/script-output.png and b/execute-script-via-k8s-job/assets/script-output.png differ diff --git a/execute-script-via-k8s-job/assets/successful-execution.png b/execute-script-via-k8s-job/assets/successful-execution.png index 939a7a8..e062326 100644 Binary files a/execute-script-via-k8s-job/assets/successful-execution.png and b/execute-script-via-k8s-job/assets/successful-execution.png differ diff --git a/execute-script-via-k8s-job/catalog.json b/execute-script-via-k8s-job/catalog.json index eb8f494..2181f59 100644 --- a/execute-script-via-k8s-job/catalog.json +++ b/execute-script-via-k8s-job/catalog.json @@ -122,7 +122,8 @@ "values": [], "output": { "output": "$(.FetchScriptLogs.output.log | split(\"\\n\"))", - "exitCode": "$(.GetScriptPod.output.resources[0].status.containerStatuses[0].state.terminated.exitCode // -1)" + "exitCode": "$(.GetScriptPod.output.resources[0].status.containerStatuses[0].state.terminated.exitCode // -1)", + "events": "$(.FetchScriptEvents.output.resources | filter(.involvedObject.name | startswith($.GenerateScriptName.output.message)) | map({ involvedObject, reason, message, eventTime, type, reportingComponent, reportingInstance }))" }, "executors": [ { @@ -145,7 +146,7 @@ { "execute": "kubernetes-sapcp:CreateK8sResource:1", "input": { - "resource": "{ \"apiVersion\": \"batch/v1\", \"kind\": \"Job\", \"metadata\": { \"name\": \"$(.GenerateScriptName.output.message)\", \"namespace\": \"$(.execution.input.namespace)\", \"labels\": { \"app\": \"$(.GenerateScriptName.output.message)\" } }, \"spec\": { \"ttlSecondsAfterFinished\": 180, \"activeDeadlineSeconds\": $(.execution.input.timeout + 60), \"completions\": 1, \"backoffLimit\": 0, \"template\": { \"spec\": { \"terminationGracePeriodSeconds\": 0, \"restartPolicy\": \"Never\", \"imagePullSecrets\": [ $(.execution.input.imagePullSecretName | if . != null then {name: .} else . end) ], \"containers\": [ { \"name\": \"script-executor\", \"image\": \"$(.execution.input.image)\", \"command\": [ \"bash\", \"-c\", \"--\" ], \"args\": [ \"$(.execution.input.script | fromBase64 | toEscapedJson)\" ], \"env\": $(.execution.input.environment | to_entries | map({name: .key, value: .value})) } ] } } } }", + "resource": "{ \"apiVersion\": \"batch/v1\", \"kind\": \"Job\", \"metadata\": { \"name\": \"$(.GenerateScriptName.output.message)\", \"namespace\": \"$(.execution.input.namespace)\", \"labels\": { \"app\": \"$(.GenerateScriptName.output.message)\" }}, \"spec\": { \"ttlSecondsAfterFinished\": 180, \"activeDeadlineSeconds\": $(.execution.input.timeout + 60), \"completions\": 1, \"backoffLimit\": 0, \"template\": { \"spec\": { \"terminationGracePeriodSeconds\": 0, \"restartPolicy\": \"Never\", \"imagePullSecrets\": [ $(.execution.input.imagePullSecretName | if . != null then {name: .} else . end)], \"containers\": [{ \"name\": \"script-executor\", \"image\": \"$(.execution.input.image)\", \"command\": [ \"bash\", \"-c\", \"--\" ], \"args\": [ \"$(.execution.input.script | fromBase64 | toEscapedJson)\" ], \"env\": $(.execution.input.environment | to_entries | map({name: .key, value: .value}))}]}}}}", "kubeconfig": "$(.execution.input.kubeconfig)", "resourceType": "jobs" }, @@ -243,7 +244,27 @@ "initialDelay": null, "pause": null, "when": null, - "validate": { + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "kubernetes-sapcp:GetKubernetesPodLog:1", + "input": { + "tailLines": "$(.execution.input.outputLines)", + "pod": "$(.GetScriptPod.output.resources[0].metadata.name)", + "namespace": "$(.execution.input.namespace)", + "sinceSeconds": "3600", + "kubeconfig": "$(.execution.input.kubeconfig)" + }, + "alias": "FetchScriptLogs", + "description": "Fetch the script logs from the pod", + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { "semantic": "OR", "conditions": [ { @@ -261,22 +282,23 @@ } ] }, + "validate": null, "autoRetry": null, "repeat": null, "errorMessages": [], "dryRun": null }, { - "execute": "kubernetes-sapcp:GetKubernetesPodLog:1", + "execute": "kubernetes-sapcp:ListK8sResources:1", "input": { - "tailLines": "$(.execution.input.outputLines)", - "pod": "$(.GetScriptPod.output.resources[0].metadata.name)", + "apiVersion": "v1", "namespace": "$(.execution.input.namespace)", - "sinceSeconds": "3600", - "kubeconfig": "$(.execution.input.kubeconfig)" + "pageSize": "100", + "kubeconfig": "$(.execution.input.kubeconfig)", + "resourceType": "events" }, - "alias": "FetchScriptLogs", - "description": "Fetch the script logs from the pod", + "alias": "FetchScriptEvents", + "description": "Fetch all Kubernetes events related to the script execution", "progressMessage": null, "initialDelay": null, "pause": null, @@ -435,6 +457,11 @@ "type": "number", "sensitive": false, "description": "Exit code returned from the script execution" + }, + "events": { + "type": "array", + "sensitive": false, + "description": "Kubernetes events produced by the script execution" } }, "tags": {}