|
| 1 | +import logging |
| 2 | +import os |
| 3 | +import uuid |
| 4 | + |
| 5 | +from hikaru.model.rel_1_26 import Container, PodSpec |
| 6 | +from robusta.api import ( |
| 7 | + RUNNER_SERVICE_ACCOUNT, |
| 8 | + ExecutionBaseEvent, |
| 9 | + FileBlock, |
| 10 | + MarkdownBlock, |
| 11 | + PodRunningParams, |
| 12 | + RobustaJob, |
| 13 | + action, |
| 14 | +) |
| 15 | +from robusta.utils.parsing import format_event_templated_string |
| 16 | + |
| 17 | +IMAGE: str = os.getenv("KUBECTL_IMAGE_OVERRIDE", f"bitnami/kubectl:latest") |
| 18 | + |
| 19 | + |
| 20 | +class KubectlParams(PodRunningParams): |
| 21 | + """ |
| 22 | + :var kubectl_command: The full kubectl command to run, formatted as a shell command string. |
| 23 | + :var description: A description of the command ran. |
| 24 | + :var timeout: The maximum time (in seconds) to wait for the kubectl command to complete. Default is 3600 seconds. |
| 25 | + """ |
| 26 | + |
| 27 | + command: str = None |
| 28 | + description: str = None |
| 29 | + timeout: int = 3600 |
| 30 | + |
| 31 | + |
| 32 | +@action |
| 33 | +def kubectl_command(event: ExecutionBaseEvent, params: KubectlParams): |
| 34 | + """ |
| 35 | + Runs a custom kubectl command inside a Kubernetes pod using a Job. |
| 36 | + """ |
| 37 | + |
| 38 | + subject = event.get_subject() |
| 39 | + formatted_kubectl_command = format_event_templated_string(subject, params.command) |
| 40 | + logging.info(f"kubectl_command running '{params.description}'") |
| 41 | + logging.debug(f"kubectl_command: '{formatted_kubectl_command}'") |
| 42 | + |
| 43 | + spec = PodSpec( |
| 44 | + serviceAccountName=RUNNER_SERVICE_ACCOUNT, |
| 45 | + containers=[ |
| 46 | + Container( |
| 47 | + name="kubectl", |
| 48 | + image=IMAGE, |
| 49 | + imagePullPolicy="Always", |
| 50 | + command=["/bin/sh", "-c"], |
| 51 | + args=[formatted_kubectl_command] |
| 52 | + ) |
| 53 | + ], |
| 54 | + restartPolicy="Never", |
| 55 | + ) |
| 56 | + |
| 57 | + try: |
| 58 | + kubectl_response = RobustaJob.run_simple_job_spec( |
| 59 | + spec, |
| 60 | + f"robusta-kubectl-command-{str(uuid.uuid4())}", |
| 61 | + params.timeout, |
| 62 | + custom_annotations=params.custom_annotations, |
| 63 | + ttl_seconds_after_finished=43200, # 12 hours |
| 64 | + delete_job_post_execution=True, |
| 65 | + process_name=False, |
| 66 | + ) |
| 67 | + descriptiont_text = params.description if params.description else "Kubectl Command" |
| 68 | + event.add_enrichment( |
| 69 | + [ |
| 70 | + MarkdownBlock(f"*{formatted_kubectl_command}*"), |
| 71 | + FileBlock(f"kubectl.txt", kubectl_response.encode()), |
| 72 | + ], title=descriptiont_text |
| 73 | + ) |
| 74 | + except Exception: |
| 75 | + logging.exception("Error running kubectl command") |
| 76 | + |
| 77 | + |
0 commit comments