diff --git a/playbooks/robusta_playbooks/event_enrichments.py b/playbooks/robusta_playbooks/event_enrichments.py index e4d3d47b6..d68d90551 100644 --- a/playbooks/robusta_playbooks/event_enrichments.py +++ b/playbooks/robusta_playbooks/event_enrichments.py @@ -134,7 +134,7 @@ def event_resource_events(event: EventChangeEvent): return obj = event.obj.regarding events_table = get_resource_events_table( - "*Related Events*", + "Related Events", obj.kind, obj.name, obj.namespace, @@ -245,7 +245,7 @@ def resource_events_enricher(event: KubernetesResourceEvent, params: ExtendedEve [ EventsBlock( events=events_row, - table_name=f"*{kind} events:*", + table_name=f"{kind} Events", column_renderers={"time": RendererType.DATETIME}, headers=["reason", "type", "time", "kind", "name", "message"], rows=rows, @@ -269,7 +269,7 @@ def pod_events_enricher(event: PodEvent, params: EventEnricherParams): return events_table_block = get_resource_events_table( - "*Pod events:*", + "Pod Events", pod.kind, pod.metadata.name, pod.metadata.namespace, @@ -292,7 +292,7 @@ def enrich_pod_with_node_events(event: PodEvent, params: EventEnricherParams): """ pod = event.get_pod() events_table_block = get_resource_events_table( - "*Node events:*", + "Node Events", kind="Node", name=pod.spec.nodeName, included_types=params.included_types, @@ -325,7 +325,7 @@ def deployment_events_enricher(event: DeploymentEvent, params: ExtendedEventEnri selected_pods = pods if len(pods) <= params.max_pods else pods[: params.max_pods] for pod in selected_pods: events_table_block = get_resource_events_table( - f"*Pod events for {pod.metadata.name}:*", + f"Pod events for {pod.metadata.name}", "Pod", pod.metadata.name, pod.metadata.namespace, @@ -341,7 +341,7 @@ def deployment_events_enricher(event: DeploymentEvent, params: ExtendedEventEnri ) else: events_table_block = get_resource_events_table( - "*Deployment events:*", + "Deployment Events", dep.kind, dep.metadata.name, dep.metadata.namespace, diff --git a/playbooks/robusta_playbooks/kubectl_enrichments.py b/playbooks/robusta_playbooks/kubectl_enrichments.py new file mode 100644 index 000000000..a7b8fd60d --- /dev/null +++ b/playbooks/robusta_playbooks/kubectl_enrichments.py @@ -0,0 +1,77 @@ +import logging +import os +import uuid + +from hikaru.model.rel_1_26 import Container, PodSpec +from robusta.api import ( + RUNNER_SERVICE_ACCOUNT, + ExecutionBaseEvent, + FileBlock, + MarkdownBlock, + PodRunningParams, + RobustaJob, + action, +) +from robusta.utils.parsing import format_event_templated_string + +IMAGE: str = os.getenv("KUBECTL_IMAGE_OVERRIDE", f"bitnami/kubectl:latest") + + +class KubectlParams(PodRunningParams): + """ + :var kubectl_command: The full kubectl command to run, formatted as a shell command string. + :var description: A description of the command ran. + :var timeout: The maximum time (in seconds) to wait for the kubectl command to complete. Default is 3600 seconds. + """ + + command: str = None + description: str = None + timeout: int = 3600 + + +@action +def kubectl_command(event: ExecutionBaseEvent, params: KubectlParams): + """ + Runs a custom kubectl command inside a Kubernetes pod using a Job. + """ + + subject = event.get_subject() + formatted_kubectl_command = format_event_templated_string(subject, params.command) + logging.info(f"kubectl_command running '{params.description}'") + logging.debug(f"kubectl_command: '{formatted_kubectl_command}'") + + spec = PodSpec( + serviceAccountName=RUNNER_SERVICE_ACCOUNT, + containers=[ + Container( + name="kubectl", + image=IMAGE, + imagePullPolicy="Always", + command=["/bin/sh", "-c"], + args=[formatted_kubectl_command] + ) + ], + restartPolicy="Never", + ) + + try: + kubectl_response = RobustaJob.run_simple_job_spec( + spec, + f"robusta-kubectl-command-{str(uuid.uuid4())}", + params.timeout, + custom_annotations=params.custom_annotations, + ttl_seconds_after_finished=43200, # 12 hours + delete_job_post_execution=True, + process_name=False, + ) + descriptiont_text = params.description if params.description else "Kubectl Command" + event.add_enrichment( + [ + MarkdownBlock(f"*{formatted_kubectl_command}*"), + FileBlock(f"kubectl.txt", kubectl_response.encode()), + ], title=descriptiont_text + ) + except Exception: + logging.exception("Error running kubectl command") + +