a401310865
test / image-input-builds (pull_request) Successful in 59s
test / integration-docker (pull_request) Successful in 1m3s
lint / lint (push) Successful in 3m32s
test / unit (pull_request) Successful in 2m47s
test / coverage (pull_request) Successful in 49s
tracker-policy-pr / check-pr (pull_request) Successful in 13s
Follows the base branch back to 0081. 0083 was already claimed by feat/pinned-infra-artifacts (docs/prds/0083-packaged-infra-artifacts.md), so the two PRDs would have collided on whichever merged second; 0081 is free. 29 references across 21 files — the "PRD 0083" prose in the backends, the shared gateway_attach flow, the tests, and the ADR — plus the PRD filename in the ADR's reference link, which now resolves again. requirements.gateway.lock matches "0083" inside a sha256 hash and is deliberately untouched. Unit suite unchanged: same 13 pre-existing failures as main (test_cli_start_selector, test_firecracker_cleanup).
55 lines
2.1 KiB
Python
55 lines
2.1 KiB
Python
"""The shared gateway-attach reconcile flow (PRD 0081).
|
|
|
|
`BottleBackend.attach_bottled_agents_to_gateway()` delegates here so every
|
|
backend reconciles running bottles against a freshly-booted gateway *the same
|
|
way* — the control flow + fail-hard policy live in one place and backends
|
|
override only the primitives (see ADR 0006). Kept out of `backend/base.py` so
|
|
the backend contract module stays lean (the base.py size guardrail).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from .base import InfraLaunchError
|
|
|
|
if TYPE_CHECKING:
|
|
from .base import BottleBackend
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class GatewayAttachResources:
|
|
"""Everything a running bottle needs to (re)attach to the current gateway on
|
|
a cold boot (PRD 0081). Gathered once per reconcile and handed to every
|
|
bottle. The CA now; egress secrets and git-gate state join as the reconcile
|
|
grows (#516)."""
|
|
|
|
ca_pem: str
|
|
|
|
|
|
def reconcile_running_bottles(backend: "BottleBackend[Any, Any, Any]") -> None:
|
|
"""Reconcile every already-running bottle against the freshly-(re)booted
|
|
gateway: gather the attach resources once, then attach every live bottle.
|
|
|
|
Fail hard, never skip: a bottle that silently can't reach the fresh gateway
|
|
(its egress just starts failing TLS) is worse than a loud bring-up failure,
|
|
so any attach failure aborts bring-up. Every bottle is attempted first and
|
|
the failures are raised together, so one bring-up surfaces the full blast
|
|
radius rather than one bottle at a time."""
|
|
resources = backend._gateway_attach_resources()
|
|
failures: list[str] = []
|
|
for bottle in backend._running_bottles():
|
|
try:
|
|
backend._attach_bottle_to_gateway(bottle, resources)
|
|
except InfraLaunchError as exc:
|
|
failures.append(str(exc))
|
|
if failures:
|
|
raise InfraLaunchError(
|
|
f"could not attach {len(failures)} running bottle(s) to the "
|
|
f"freshly-booted gateway:\n " + "\n ".join(failures)
|
|
)
|
|
|
|
|
|
__all__ = ["GatewayAttachResources", "reconcile_running_bottles"]
|