fix(orchestrator): poll for the gateway CA (fresh-start readiness race)
lint / lint (push) Successful in 2m5s
test / unit (pull_request) Successful in 1m4s
test / integration (pull_request) Successful in 23s
test / coverage (pull_request) Successful in 1m13s

On a fresh gateway container, mitmproxy writes mitmproxy-ca-cert.pem a beat
after mitmdump boots, so ca_cert_pem() read it too early and launch died with
'gateway CA cert not available'. It now polls (up to 30s) until mitmproxy has
generated it. Surfaced running the docker backend locally on a cold gateway.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
2026-07-14 01:38:22 -04:00
parent dcf81ee2ce
commit 4132b09ebc
2 changed files with 31 additions and 11 deletions
+9 -1
View File
@@ -81,9 +81,17 @@ class TestDockerGateway(unittest.TestCase):
self.assertEqual(["docker", "exec", self.sc.name, "cat", GATEWAY_CA_CERT], argv)
def test_ca_cert_pem_raises_when_absent(self) -> None:
# timeout=0 → one probe then give up (no polling delay in the test).
with patch(_RUN_DOCKER, return_value=_proc(returncode=1, stderr="No such file")):
with self.assertRaises(GatewayError):
self.sc.ca_cert_pem()
self.sc.ca_cert_pem(timeout=0)
def test_ca_cert_pem_polls_until_mitmproxy_writes_it(self) -> None:
# First read: CA not there yet; second read: present.
seq = [_proc(returncode=1, stderr="No such file"), _proc(stdout=_CA_PEM)]
with patch(_RUN_DOCKER, side_effect=seq), \
patch("bot_bottle.orchestrator.gateway.time.sleep"):
self.assertEqual(_CA_PEM, self.sc.ca_cert_pem(timeout=5))
def test_ensure_running_reuses_existing_network(self) -> None:
calls: list[list[str]] = []