refactor(orchestrator): rename in-guest core Orchestrator -> OrchestratorCore

Free the `Orchestrator` name for the incoming host-side control-plane service
ABC (parallel to `Gateway`). The in-guest control-plane core (registry + broker,
in orchestrator/service.py) becomes `OrchestratorCore`; server.py, __main__.py,
the lazy facade, and the two service/server tests updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 14:29:32 -04:00
parent 07c975636d
commit 57d32d2c5c
9 changed files with 29 additions and 29 deletions
+4 -4
View File
@@ -14,7 +14,7 @@ backend-neutral "consolidation core" that needs no VM packaging:
lifecycle contract (idempotent singleton). One
gateway shared by all bottles instead of one per
bottle; backend impls live under `backend/*/gateway`.
* `service` — the `Orchestrator`: owns the registry, brokers the
* `service` — the `OrchestratorCore`: owns the registry, brokers the
launch lifecycle (launch/teardown), manages the
shared gateway, attributes.
* `server` — the HTTP control-plane RPC (launch / teardown /
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
)
from .docker_broker import DockerBroker, DockerBrokerError
from ..gateway import Gateway, GatewayError
from .service import Orchestrator
from .service import OrchestratorCore
from .server import OrchestratorServer, dispatch, make_server
@@ -64,7 +64,7 @@ _LAZY: dict[str, str] = {
"DockerBrokerError": ".docker_broker",
"Gateway": "..gateway",
"GatewayError": "..gateway",
"Orchestrator": ".service",
"OrchestratorCore": ".service",
"OrchestratorServer": ".server",
"dispatch": ".server",
"make_server": ".server",
@@ -96,7 +96,7 @@ __all__ = [
"DockerBrokerError",
"Gateway",
"GatewayError",
"Orchestrator",
"OrchestratorCore",
"OrchestratorServer",
"dispatch",
"make_server",
+2 -2
View File
@@ -21,7 +21,7 @@ from .broker import LaunchBroker, StubBroker
from .server import make_server
from .docker_broker import DockerBroker
from .store.registry_store import RegistryStore, default_db_path
from .service import Orchestrator
from .service import OrchestratorCore
def main(argv: list[str] | None = None) -> int:
@@ -52,7 +52,7 @@ def main(argv: list[str] | None = None) -> int:
# anything; 'docker' runs real containers (firecracker drops in later).
secret = secrets.token_bytes(32)
broker: LaunchBroker = DockerBroker(secret) if args.broker == "docker" else StubBroker(secret)
orchestrator = Orchestrator(registry, broker, secret)
orchestrator = OrchestratorCore(registry, broker, secret)
server = make_server(orchestrator, host=args.host, port=args.port)
bound_host, bound_port = server.server_address[0], server.server_address[1]
+2 -2
View File
@@ -2,7 +2,7 @@
Bridges the existing per-bottle `prepare` output to the consolidated
registry: turns a prepared bottle's egress plan into the backend-neutral
inputs `Orchestrator.launch_bottle` takes — the egress **policy** blob and
inputs `OrchestratorCore.launch_bottle` takes — the egress **policy** blob and
launch **metadata**.
The policy blob is the exact routes YAML the per-bottle egress daemon used
@@ -26,7 +26,7 @@ from ..egress import EgressPlan, egress_render_routes
@dataclass(frozen=True)
class RegistrationInputs:
"""What `Orchestrator.launch_bottle` needs to register a bottle, derived
"""What `OrchestratorCore.launch_bottle` needs to register a bottle, derived
from its prepared plan. `policy` is served verbatim by the gateway's
`/resolve`; `metadata` is opaque forward-compat state — it carries the
human slug so the console / supervise can show a name, not just the
+5 -5
View File
@@ -45,7 +45,7 @@ Both attribute the caller by `(source_ip, identity_token)` exactly like
`POST /bottles` / `DELETE` drive the full launch lifecycle: they mint (or
tear down) the bottle in the registry AND broker the backend-native launch
via the orchestrator. Register/deregister without a launch are internal to
`Orchestrator`, not exposed here.
`OrchestratorCore`, not exposed here.
Routing/handling is the pure function `dispatch()` so it is unit-testable
without a socket; `Handler` / `OrchestratorServer` / `make_server` are a
@@ -66,7 +66,7 @@ from urllib.parse import urlsplit
from ..orchestrator_auth import ROLE_CLI, ROLES, verify
from ..paths import ORCHESTRATOR_TOKEN_ENV
from ..supervisor.types import TOOLS
from .service import Orchestrator
from .service import OrchestratorCore
# JSON body payload type (parsed request / rendered response).
Json = dict[str, object]
@@ -109,7 +109,7 @@ def _parse_json_object(body: bytes) -> Json:
def dispatch( # pylint: disable=too-many-return-statements,too-many-branches
orch: Orchestrator, method: str, path: str, body: bytes, *, role: str | None = ROLE_CLI,
orch: OrchestratorCore, method: str, path: str, body: bytes, *, role: str | None = ROLE_CLI,
) -> tuple[int, Json]:
"""Route one control-plane request to a (status, payload) pair. Pure —
no I/O beyond the orchestrator — so it is fully testable without a socket.
@@ -411,7 +411,7 @@ class OrchestratorServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
daemon_threads = True
allow_reuse_address = True
def __init__(self, address: tuple[str, int], orchestrator: Orchestrator) -> None:
def __init__(self, address: tuple[str, int], orchestrator: OrchestratorCore) -> None:
self.orchestrator = orchestrator
self._signing_key = os.environ.get(ORCHESTRATOR_TOKEN_ENV, "").strip()
if not self._signing_key:
@@ -437,7 +437,7 @@ class OrchestratorServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
def make_server(
orchestrator: Orchestrator, host: str = "127.0.0.1", port: int = 0
orchestrator: OrchestratorCore, host: str = "127.0.0.1", port: int = 0
) -> OrchestratorServer:
"""Build (but do not start) a control-plane server. `port=0` binds an
ephemeral port — read `server.server_address` for the actual one."""
+3 -3
View File
@@ -1,6 +1,6 @@
"""The per-host orchestrator core (PRD 0070).
`Orchestrator` is the single backend-neutral object the control plane talks
`OrchestratorCore` is the single backend-neutral object the control plane talks
to: it owns the registry (runtime state) and brokers agent launches. It
never branches on backend — the `LaunchBroker` abstracts the backend-native
launch, so this same object drives docker / firecracker / apple once a real
@@ -54,7 +54,7 @@ _RESPOND_STATUS = {
_APPLY_TOOLS = (TOOL_EGRESS_ALLOW, TOOL_EGRESS_BLOCK)
class Orchestrator:
class OrchestratorCore:
"""Owns the registry + brokers launches, and manages the single
consolidated per-host gateway. Backend-neutral (broker and gateway
abstract the backend-native pieces)."""
@@ -390,4 +390,4 @@ class Orchestrator:
return {"configured": False}
__all__ = ["Orchestrator"]
__all__ = ["OrchestratorCore"]
+1 -1
View File
@@ -1,6 +1,6 @@
"""The orchestrator's supervise service.
`Supervisor` is the service object the `Orchestrator` owns and calls: it wraps
`Supervisor` is the service object the `OrchestratorCore` owns and calls: it wraps
the supervise queue + audit stores (queue proposals, record operator responses,
write audit entries, stage the DB at launch). Binding those operations to one
object — optionally scoped to a `db_path` — makes the orchestrator's supervise