#!/usr/bin/env python3 """A fake `docker` CLI for tgit-runner tests: records every call, keeps containers in a JSON file. Behaviour knobs (env): FAKE_HEALTH (healthy|unhealthy|none), FAKE_STATUS (running|exited), FAKE_RESTARTS, FAKE_BUILD_FAIL=1. State: $FAKE_DOCKER_STATE (json), calls: $FAKE_DOCKER_LOG (one json array per line). """ import json import os import sys state_path = os.environ["FAKE_DOCKER_STATE"] args = sys.argv[1:] with open(os.environ["FAKE_DOCKER_LOG"], "a") as log: log.write(json.dumps(args) + "\n") try: with open(state_path) as f: state = json.load(f) except FileNotFoundError: state = {"containers": {}, "images": []} def save() -> None: with open(state_path, "w") as f: json.dump(state, f) def done(code: int = 0, out: str = "") -> None: if out: print(out) save() sys.exit(code) cmd = args[0] if args else "" if cmd == "container" and args[1] == "inspect": done(0 if args[2] in state["containers"] else 1) if cmd == "inspect": fmt, name = args[2], args[3] if name not in state["containers"]: done(1) if "Health" in fmt: done(0, os.environ.get("FAKE_HEALTH", "healthy")) if "RestartCount" in fmt: done(0, os.environ.get("FAKE_RESTARTS", "0")) done(0, os.environ.get("FAKE_STATUS", "running")) if cmd == "ps": done(0, "\n".join(n for n in state["containers"])) if cmd == "build": if os.environ.get("FAKE_BUILD_FAIL"): done(1, "ERROR: could not install requirements") tag = args[args.index("-t") + 1] ctx = args[-1] with open(os.path.join(ctx, "Dockerfile")) as f: state.setdefault("dockerfiles", {})[tag] = f.read() state["images"].append(tag) done(0, "sha256:feed") if cmd == "run": name = args[args.index("--name") + 1] state["containers"][name] = {"image": args[-1], "args": args} done(0, "cid") if cmd == "rm": for name in args[2:]: state["containers"].pop(name, None) done(0) if cmd == "rename": state["containers"][args[2]] = state["containers"].pop(args[1]) done(0) if cmd == "restart": done(0) if cmd == "logs": done(0, "Traceback: boom") if cmd == "image" and args[1] == "ls": repo = args[2] tags = [t.split(":", 1)[1] for t in reversed(state["images"]) if t.split(":", 1)[0] == repo] full = "{{.Repository}}" in args[-1] done(0, "\n".join(f"{repo}:{t}" if full else t for t in tags)) if cmd == "image" and args[1] == "rm": state["images"] = [t for t in state["images"] if t != args[2]] done(0) if cmd == "network": done(0) done(2, f"fake docker: unsupported {args}")