diff --git a/src/containerizer/verify.py b/src/containerizer/verify.py new file mode 100644 index 0000000..a34e151 --- /dev/null +++ b/src/containerizer/verify.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +import subprocess +import time +import urllib.request +from pathlib import Path +from typing import Any + + +def _run(command: list[str], root: Path, timeout: int = 300) -> dict[str, Any]: + completed = subprocess.run(command, cwd=root, text=True, capture_output=True, + timeout=timeout, check=False) + return {"command": " ".join(command), "exit_code": completed.returncode, + "output": (completed.stdout + completed.stderr)[-4000:]} + + +def verify_with_docker(root: str | Path, port: int, health: str | None) -> dict[str, Any]: + root = Path(root) + evidence: dict[str, Any] = {"executed": True, "steps": []} + build = _run(["docker", "compose", "build", "--pull"], root) + evidence["steps"].append(build) + if build["exit_code"]: + evidence["passed"] = False + return evidence + start = _run(["docker", "compose", "up", "--detach", "--wait"], root) + evidence["steps"].append(start) + try: + if not start["exit_code"] and health: + time.sleep(1) + with urllib.request.urlopen(f"http://127.0.0.1:{port}{health}", timeout=5) as response: + evidence["http_status"] = response.status + evidence["passed"] = start["exit_code"] == 0 and ( + not health or evidence.get("http_status", 500) < 400) + finally: + evidence["steps"].append(_run(["docker", "compose", "down", "--volumes"], root)) + return evidence