dev_gateway #22
2 changed files with 72 additions and 6 deletions
|
|
@ -214,13 +214,27 @@ def run_connect(gateway_url: str, registration_token: str, box_name: str) -> Non
|
|||
systemd-run from `POST /api/gateway/connect`), writing state
|
||||
transitions as it goes so the UI can poll instead of the request
|
||||
thread blocking on a slow/unreachable gateway.
|
||||
|
||||
A registration saved by an earlier attempt whose tunnel failed to come
|
||||
up is reused rather than registering again — re-registering would leave
|
||||
the first box (and its wg-easy peer) orphaned on the gateway.
|
||||
"""
|
||||
write_state("registering")
|
||||
try:
|
||||
config = register(gateway_url, registration_token, box_name)
|
||||
except GatewayError as e:
|
||||
write_state("error", error=str(e))
|
||||
return
|
||||
existing = load_config()
|
||||
if existing is not None:
|
||||
if existing["gateway_url"] != gateway_url.rstrip("/"):
|
||||
write_state(
|
||||
"error",
|
||||
error=f"already registered with {existing['gateway_url']} — disconnect first",
|
||||
)
|
||||
return
|
||||
config = existing
|
||||
else:
|
||||
write_state("registering")
|
||||
try:
|
||||
config = register(gateway_url, registration_token, box_name)
|
||||
except GatewayError as e:
|
||||
write_state("error", error=str(e))
|
||||
return
|
||||
|
||||
write_state("starting_tunnel")
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -280,6 +280,58 @@ def test_run_connect_tunnel_failure_writes_error_state(gw, monkeypatch):
|
|||
assert gw.load_config()["box_id"] == "abc"
|
||||
|
||||
|
||||
def test_run_connect_retry_after_tunnel_failure_reuses_registration(gw, monkeypatch):
|
||||
register_calls = []
|
||||
|
||||
def urlopen(req, timeout):
|
||||
register_calls.append(req.full_url)
|
||||
return _FakeResp({"box_id": "abc", "box_token": "abc.x", "wg": WG})
|
||||
|
||||
monkeypatch.setattr("urllib.request.urlopen", urlopen)
|
||||
|
||||
def failing_tunnel(enabled, wg=None):
|
||||
raise gw.wireguard.WireguardError("systemctl failed: unit missing")
|
||||
|
||||
monkeypatch.setattr(gw.wireguard, "set_tunnel_enabled", failing_tunnel)
|
||||
gw.run_connect("https://gw.example.com", "tok", "my-box")
|
||||
assert gw.read_state()["stage"] == "error"
|
||||
|
||||
tunnel_calls = []
|
||||
monkeypatch.setattr(
|
||||
gw.wireguard,
|
||||
"set_tunnel_enabled",
|
||||
lambda enabled, wg=None: tunnel_calls.append((enabled, wg)),
|
||||
)
|
||||
gw.run_connect("https://gw.example.com/", "tok", "my-box")
|
||||
|
||||
# Registered exactly once; the retry only brought the tunnel up.
|
||||
assert register_calls == ["https://gw.example.com/v1/boxes/register"]
|
||||
assert tunnel_calls == [(True, WG)]
|
||||
assert gw.read_state()["stage"] == "done"
|
||||
assert gw.load_config()["box_id"] == "abc"
|
||||
|
||||
|
||||
def test_run_connect_refuses_a_different_gateway_while_registered(gw, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"urllib.request.urlopen",
|
||||
lambda req, timeout: _FakeResp({"box_id": "abc", "box_token": "abc.x", "wg": WG}),
|
||||
)
|
||||
gw.register("https://gw.example.com", "tok", "box")
|
||||
|
||||
def must_not_call(req, timeout):
|
||||
raise AssertionError("must not register with a second gateway")
|
||||
|
||||
monkeypatch.setattr("urllib.request.urlopen", must_not_call)
|
||||
monkeypatch.setattr(gw.wireguard, "set_tunnel_enabled", lambda enabled, wg=None: None)
|
||||
|
||||
gw.run_connect("https://other.example.com", "tok", "box")
|
||||
|
||||
state = gw.read_state()
|
||||
assert state["stage"] == "error"
|
||||
assert "disconnect first" in state["error"]
|
||||
assert gw.load_config()["gateway_url"] == "https://gw.example.com"
|
||||
|
||||
|
||||
def test_deregister_failure_keeps_local_config_for_retry(gw, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"urllib.request.urlopen",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue