refactor(gateway): each backend's transport in its own gateway_transport.py
Give every backend a `gateway_transport.py` holding just its `GatewayTransport` impl, named consistently with the backend: `DockerGatewayTransport`, `MacosGatewayTransport` (was `AppleGatewayTransport`), and `FirecrackerGatewayTransport` (was `SshGatewayTransport`). - docker: split `DockerGatewayTransport` out of `gateway_provision.py`, which keeps only the backend-neutral provisioning logic (provision_git_gate / deprovision_git_gate) the other backends share. - macOS: `gateway_provision.py` held only the transport, so it's replaced by `gateway_transport.py`. - firecracker: move the transport out of `gateway.py`. Behaviour-preserving; importers + tests updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -18,11 +18,14 @@ from bot_bottle.backend.firecracker import infra_vm
|
||||
from bot_bottle.backend.firecracker.gateway import (
|
||||
GATEWAY_NAME,
|
||||
FirecrackerGateway,
|
||||
SshGatewayTransport,
|
||||
)
|
||||
from bot_bottle.backend.firecracker.gateway_transport import (
|
||||
FirecrackerGatewayTransport,
|
||||
)
|
||||
from bot_bottle.gateway import GatewayError, GatewayProvisionError
|
||||
|
||||
_GW = "bot_bottle.backend.firecracker.gateway"
|
||||
_GW_TRANSPORT = "bot_bottle.backend.firecracker.gateway_transport"
|
||||
|
||||
_ORCH_URL = "http://10.243.255.1:8099"
|
||||
_TOKEN = "gw-jwt-token"
|
||||
@@ -115,24 +118,24 @@ class TestFirecrackerGatewaySurface(unittest.TestCase):
|
||||
def test_provisioning_transport_targets_the_gateway_link(self) -> None:
|
||||
gw = FirecrackerGateway()
|
||||
transport = gw.provisioning_transport()
|
||||
assert isinstance(transport, SshGatewayTransport)
|
||||
assert isinstance(transport, FirecrackerGatewayTransport)
|
||||
self.assertEqual(infra_vm.netpool.gw_slot().guest_ip, transport._ip)
|
||||
|
||||
|
||||
class TestSshGatewayTransport(unittest.TestCase):
|
||||
class TestFirecrackerGatewayTransport(unittest.TestCase):
|
||||
def test_cp_into_preserves_source_mode(self) -> None:
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
os.chmod(f.name, 0o700) # like the staged access-hook
|
||||
t = SshGatewayTransport(Path("/k"), "10.0.0.1")
|
||||
with patch(f"{_GW}.subprocess.run",
|
||||
t = FirecrackerGatewayTransport(Path("/k"), "10.0.0.1")
|
||||
with patch(f"{_GW_TRANSPORT}.subprocess.run",
|
||||
return_value=CompletedProcess([], 0)) as run:
|
||||
t.cp_into(f.name, "/etc/git-gate/access-hook")
|
||||
remote_cmd = run.call_args.args[0][-1]
|
||||
self.assertIn("chmod 700", remote_cmd) # exec bit preserved over SSH
|
||||
|
||||
def test_exec_raises_on_failure(self) -> None:
|
||||
t = SshGatewayTransport(Path("/k"), "10.0.0.1")
|
||||
with patch(f"{_GW}.subprocess.run",
|
||||
t = FirecrackerGatewayTransport(Path("/k"), "10.0.0.1")
|
||||
with patch(f"{_GW_TRANSPORT}.subprocess.run",
|
||||
return_value=CompletedProcess([], 1, stderr="nope")), \
|
||||
self.assertRaises(GatewayProvisionError):
|
||||
t.exec(["mkdir", "-p", "/git-gate"])
|
||||
|
||||
@@ -8,13 +8,13 @@ from unittest.mock import Mock, patch
|
||||
|
||||
from bot_bottle.backend.docker.gateway_provision import (
|
||||
GatewayProvisionError,
|
||||
DockerGatewayTransport,
|
||||
deprovision_git_gate,
|
||||
provision_git_gate,
|
||||
)
|
||||
from bot_bottle.backend.docker.gateway_transport import DockerGatewayTransport
|
||||
from bot_bottle.git_gate import GitGatePlan, GitGateUpstream
|
||||
|
||||
_RUN = "bot_bottle.backend.docker.gateway_provision.run_docker"
|
||||
_RUN = "bot_bottle.backend.docker.gateway_transport.run_docker"
|
||||
|
||||
|
||||
def _proc(returncode: int = 0, stderr: str = "") -> Mock:
|
||||
|
||||
@@ -135,11 +135,11 @@ class TestMacosGatewayLifecycle(unittest.TestCase):
|
||||
self.gw.ca_cert_pem(timeout=0)
|
||||
|
||||
def test_provisioning_transport_targets_the_gateway_container(self) -> None:
|
||||
from bot_bottle.backend.macos_container.gateway_provision import (
|
||||
AppleGatewayTransport,
|
||||
from bot_bottle.backend.macos_container.gateway_transport import (
|
||||
MacosGatewayTransport,
|
||||
)
|
||||
transport = self.gw.provisioning_transport()
|
||||
assert isinstance(transport, AppleGatewayTransport)
|
||||
assert isinstance(transport, MacosGatewayTransport)
|
||||
self.assertEqual(self.gw.name, transport.gateway)
|
||||
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ class TestDockerGateway(unittest.TestCase):
|
||||
self.sc.address()
|
||||
|
||||
def test_provisioning_transport_targets_the_gateway_container(self) -> None:
|
||||
from bot_bottle.backend.docker.gateway_provision import DockerGatewayTransport
|
||||
from bot_bottle.backend.docker.gateway_transport import DockerGatewayTransport
|
||||
|
||||
transport = self.sc.provisioning_transport()
|
||||
assert isinstance(transport, DockerGatewayTransport)
|
||||
|
||||
Reference in New Issue
Block a user