diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea0deb3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ + +# Python +__pycache__/ +*.py[cod] + +# Development backups +*.pre-* +*.bak +*.orig +*.rej + +# Accidental test-output files +/-INFINITY +/100 diff --git a/daemon/server.py b/daemon/server.py index 7102df3..ef38cb8 100644 --- a/daemon/server.py +++ b/daemon/server.py @@ -17,34 +17,76 @@ SOCKET_PATH = os.environ.get( server_socket = None registry = None +PROTOCOL_VERSION = 1 + + +def protocol_response(payload): + """ + Return a daemon response carrying the wire-protocol version. + + protocol_version is daemon-owned metadata and cannot be overridden by + registry or plugin output. + """ + response = dict(payload) + response["protocol_version"] = PROTOCOL_VERSION + return response + def handle_request(req): + if not isinstance(req, dict): + return protocol_response({ + "ok": False, + "error_code": "invalid_request", + "error": "request must be a JSON object", + }) + + requested_version = req.get("protocol_version") + + # Backward compatibility for the pre-versioned proxy: + # absence is accepted during the rolling upgrade, but an explicitly + # incompatible version is rejected. + if ( + requested_version is not None + and requested_version != PROTOCOL_VERSION + ): + return protocol_response({ + "ok": False, + "error_code": "unsupported_protocol_version", + "error": ( + "unsupported protocol version: " + f"{requested_version}; " + f"supported={PROTOCOL_VERSION}" + ), + }) + action = req.get("action") if action == "ping": - return { + return protocol_response({ "ok": True, "daemon": "managed-containerd", - "protocol_version": 1, - } + }) if action == "registry.list": - return { + return protocol_response({ "ok": True, "resources": registry.list_resources(), - } + }) resource = req.get("resource") if not resource: - return { + return protocol_response({ "ok": False, + "error_code": "invalid_request", "error": "resource is required", - } + }) - return registry.execute( - resource, - action, + return protocol_response( + registry.execute( + resource, + action, + ) ) @@ -136,18 +178,20 @@ def serve(): ValueError, KeyError, ) as exc: - response = { + response = protocol_response({ "ok": False, + "error_code": "request_error", "error": str(exc), - } + }) except Exception as exc: traceback.print_exc() - response = { + response = protocol_response({ "ok": False, + "error_code": "internal_error", "error": str(exc), - } + }) conn.sendall( json.dumps(