from os import error from yaml import dump from playbook import models from playbook.action_registry import ActionRegistry from playbook.models import ContextChecker from playbook.logging_models import StepLogModel import sys import json import docker import subprocess dockeractions = ActionRegistry(name="docker_actions_reg") @dockeractions.register(name="get_service_container_name", version="") @ContextChecker.requires("service_name") def get_service_container_name(ctx, name) -> StepLogModel: client = docker.from_env() filters: dict[str, object]= { "label": [f"com.docker.compose.service={ctx["service_name"]}"] } containers = client.containers.list(filters=filters, all=True) if not containers: return StepLogModel.fail(name, [{ "status": "failed", "output": f"no container found for service {ctx["service_name"]}"} ]) new_data = {"container": containers[0].id} return StepLogModel.ok(name, f"found container {containers[0].id}", pipe_ctx=new_data) @dockeractions.register(name="dump_container_pg_db", version="") @ContextChecker.requires("container", "dump_path", "db_user", "database") def dump_container_pg_db(ctx, name) -> StepLogModel: client = docker.from_env() container = client.containers.get(ctx["container"]) res = container.exec_run( cmd=f"pg_dump -U {ctx["db_user"]} {ctx["database"]}", stream=False, # change to True to stream directly to host file (need to check) demux=True, ) stdout, stderr = res.output if stderr: if not isinstance(stderr, bytes): return StepLogModel.fail(name, [{"status": "failed", "output": "stderr is not bytes"}]) if res.exit_code != 0: error_msg = stderr.decode("utf-8") if stderr else "dump failed with no output" return StepLogModel.fail(name, [{"status": "failed", "output": error_msg}]) if not isinstance(stdout, bytes): return StepLogModel.fail(name, [{"status": "failed", "output": "stdout is not bytes"}]) with open(ctx["dump_path"], "wb") as f: f.write(stdout) return StepLogModel.ok(name, "database dump successful")