NK-WP-0056-T10: wait for OpenBao reachability before the first login
First live journey Job was refused at setup (URLError). netcheck showed every connection refused at 0 s and open from 3 s: k3s applies NetworkPolicy to a new pod a moment late. Both CLI modes now poll OpenBao's unauthenticated sys/health for up to 30 s before logging in; only connection errors retry. 48 executor tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5502@bnt-lap001 Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
This commit is contained in:
parent
110eb63058
commit
15c9cdbef8
5 changed files with 76 additions and 0 deletions
|
|
@ -120,6 +120,9 @@ class CliTests(unittest.TestCase):
|
|||
(root / "cfg.json").write_text(json.dumps(cfg))
|
||||
admission = CLI.X.REPO / "examples/bounded-execution-admission/bind-rotation-svc-authelia.yaml"
|
||||
import contextlib, io
|
||||
wait = CLI.OPS.wait_reachable
|
||||
self.addCleanup(setattr, CLI.OPS, "wait_reachable", wait)
|
||||
CLI.OPS.wait_reachable = lambda addr, **kw: wait(addr, **{**kw, "timeout": 0.2, "interval": 0.1})
|
||||
with contextlib.redirect_stdout(io.StringIO()) as out:
|
||||
code = CLI.main(["--admission", str(admission), "--approval-id", "apr-1", "--config", str(root / "cfg.json")])
|
||||
self.assertEqual(code, 4)
|
||||
|
|
|
|||
|
|
@ -162,6 +162,39 @@ class JourneyOnly(Base):
|
|||
self.run_cli(self.cfg(), "--approval-id", "apr-1")
|
||||
|
||||
|
||||
class WaitReachable(unittest.TestCase):
|
||||
"""k3s applies NetworkPolicy to a new pod a moment late: early connections are refused (live, 2026-10-31)."""
|
||||
|
||||
def fake(self, outcomes):
|
||||
self.now, self.slept, calls = 0.0, [], list(outcomes)
|
||||
|
||||
def open_(request, timeout):
|
||||
outcome = calls.pop(0)
|
||||
if isinstance(outcome, BaseException):
|
||||
raise outcome
|
||||
return contextlib.nullcontext()
|
||||
|
||||
def sleep(seconds):
|
||||
self.slept.append(seconds)
|
||||
self.now += seconds
|
||||
return dict(opener=open_, clock=lambda: self.now, sleep=sleep)
|
||||
|
||||
def test_refused_then_reachable(self):
|
||||
refused = OPS.urllib.error.URLError(ConnectionRefusedError())
|
||||
waited = OPS.wait_reachable("http://bao:8200", **self.fake([refused, refused, "ok"]))
|
||||
self.assertEqual((waited, self.slept), (2.0, [1, 1]))
|
||||
|
||||
def test_any_http_answer_is_reachable(self):
|
||||
sealed = OPS.urllib.error.HTTPError("http://bao/v1/sys/health", 503, "sealed", {}, io.BytesIO(b""))
|
||||
self.assertEqual(OPS.wait_reachable("http://bao:8200", **self.fake([sealed])), 0.0)
|
||||
|
||||
def test_gives_up_after_the_timeout(self):
|
||||
refused = OPS.urllib.error.URLError(ConnectionRefusedError())
|
||||
with self.assertRaises(OPS.Unreachable):
|
||||
OPS.wait_reachable("http://bao:8200", timeout=3, **self.fake([refused] * 10))
|
||||
self.assertEqual(self.slept, [1, 1, 1])
|
||||
|
||||
|
||||
class Renewal(Base):
|
||||
def test_logs_in_again_before_the_lease_ends_and_revokes_the_old_token(self):
|
||||
self.bao.lease = 1 # renew_at = max(1 - margin, 0.5 s)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue