#!/usr/bin/env python3 import json from pathlib import Path import socket import subprocess import sys import tempfile import threading ROOT = Path(__file__).resolve().parents[1] CLIENT = ( ROOT / "ocf" / "loxthelion" / "managed-container.d" / "proxy_client.py" ) def require(condition, message): if not condition: raise SystemExit("FAIL: " + message) def run_exchange(response, action="promote"): with tempfile.TemporaryDirectory() as temp_dir: socket_path = str( Path(temp_dir) / "managed-containerd.sock" ) listener = socket.socket( socket.AF_UNIX, socket.SOCK_STREAM, ) listener.bind(socket_path) listener.listen(1) captured = {} errors = [] def serve_once(): try: conn, _ = listener.accept() with conn: raw = b"" while b"\n" not in raw: chunk = conn.recv(65536) if not chunk: break raw += chunk captured["request"] = json.loads( raw.decode("utf-8").strip() ) conn.sendall( json.dumps(response).encode("utf-8") + b"\n" ) except Exception as exc: errors.append(exc) finally: listener.close() thread = threading.Thread( target=serve_once, daemon=True, ) thread.start() completed = subprocess.run( [ sys.executable, str(CLIENT), socket_path, "postgresql-ha", action, "10", "11", ], text=True, capture_output=True, check=False, ) thread.join(timeout=5) require( not thread.is_alive(), "test server did not finish", ) require( not errors, f"test server failed: {errors}", ) return completed, captured["request"] print("===== GENERIC PROXY CLIENT ACTIONS =====") valid_response = { "protocol_version": 1, "ok": True, "resource": "postgresql-ha", "action": "promote", "result": { "state": "promoted", "changed": True, }, } completed, request = run_exchange( valid_response, action="promote", ) require(completed.returncode == 0, "generic action failed") require( completed.stdout.strip() == '{"changed":true,"state":"promoted"}', "generic result was not emitted as canonical JSON", ) require( request == { "protocol_version": 1, "action": "promote", "resource": "postgresql-ha", }, "generic request envelope is incorrect", ) print("generic_action expected=0 actual=0") wrong_action_response = dict(valid_response) wrong_action_response["action"] = "demote" completed, _ = run_exchange( wrong_action_response, action="promote", ) require( completed.returncode == 11, "mismatched action was not a protocol failure", ) print("wrong_action_echo expected=11 actual=11") with tempfile.TemporaryDirectory() as temp_dir: missing_socket = str( Path(temp_dir) / "missing.sock" ) completed = subprocess.run( [ sys.executable, str(CLIENT), missing_socket, "postgresql-ha", "promote", "10", "11", ], text=True, capture_output=True, check=False, ) require( completed.returncode == 10, "missing socket was not a transport failure", ) print("generic_transport expected=10 actual=10") print() print("PROXY_CLIENT_ACTION_TEST_PASS=1")