Add local reachability descriptor for same-host extensions (SAND-WP-0013-T04)
Reachability gains pid/workspace_dir, populated by enrich_reachability whenever a backend's wait_ready() returns a pid: endpoint (currently just ext.bwrap). build_reachability_report() now also returns a local_exec_hint (nsenter into the pid's namespaces) alongside the existing ssh_one_liner, so glas-harness can branch on which is populated instead of assuming every sandbox is SSH-reachable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
76c38e758c
commit
cf490220f4
6 changed files with 67 additions and 6 deletions
|
|
@ -105,9 +105,9 @@
|
||||||
| task | SAND-WP-0012-T04 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
| task | SAND-WP-0012-T04 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
||||||
| task | SAND-WP-0012-T05 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
| task | SAND-WP-0012-T05 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
||||||
| task | SAND-WP-0012-T06 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
| task | SAND-WP-0012-T06 | done | — | workplans/SAND-WP-0012-packer-orchestration.md |
|
||||||
| task | SAND-WP-0013-T01 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T01 | done | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
| task | SAND-WP-0013-T02 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T02 | done | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
| task | SAND-WP-0013-T03 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T03 | done | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
| task | SAND-WP-0013-T04 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T04 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
| task | SAND-WP-0013-T05 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T05 | done | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
| task | SAND-WP-0013-T06 | todo | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
| task | SAND-WP-0013-T06 | done | — | workplans/SAND-WP-0013-bwrap-extension.md |
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,23 @@ sandboxer create \
|
||||||
| `reachability.remote_dir` | sand-boxer | Workspace root on remote host |
|
| `reachability.remote_dir` | sand-boxer | Workspace root on remote host |
|
||||||
| `state` | sand-boxer | Lifecycle state (`ready`, etc.) |
|
| `state` | sand-boxer | Lifecycle state (`ready`, etc.) |
|
||||||
|
|
||||||
|
## Two reachability modes
|
||||||
|
|
||||||
|
Not every sandbox has an SSH hop. `ext.compose-ssh` / `ext.vm-packer`
|
||||||
|
always run remote and populate `reachability.ssh` + `reachability.
|
||||||
|
remote_dir`; glas-harness execs tools over that SSH channel. `ext.bwrap`
|
||||||
|
(SAND-WP-0013) runs same-host and never populates `reachability.ssh` —
|
||||||
|
instead it populates `reachability.pid` (the placeholder process holding
|
||||||
|
the bwrap namespaces) and `reachability.workspace_dir`. glas-harness
|
||||||
|
execs tools by entering that pid's namespaces directly
|
||||||
|
(`nsenter --target <pid> --mount --pid --net --uts --ipc -- <cmd>`, no
|
||||||
|
tunnel needed) rather than opening an SSH channel. `reachability/enrich.
|
||||||
|
build_reachability_report()` returns both an `ssh_one_liner` and a
|
||||||
|
`local_exec_hint`; exactly one is non-null depending on which mode the
|
||||||
|
resolved extension uses. Consumers should branch on which field is
|
||||||
|
populated, not on profile id, since routing can fall back between
|
||||||
|
extensions.
|
||||||
|
|
||||||
## Ownership
|
## Ownership
|
||||||
|
|
||||||
| Concern | Owner |
|
| Concern | Owner |
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,11 @@ class Reachability(BaseModel):
|
||||||
tunnel: str | None = None
|
tunnel: str | None = None
|
||||||
tunnel_via: str | None = None
|
tunnel_via: str | None = None
|
||||||
identity: str | None = None
|
identity: str | None = None
|
||||||
|
# Local (no-SSH-hop) descriptor — populated for same-host extensions
|
||||||
|
# like ext.bwrap. A consumer execs into the sandbox directly
|
||||||
|
# (e.g. `nsenter --target <pid> ...`) rather than over SSH.
|
||||||
|
pid: str | None = None
|
||||||
|
workspace_dir: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class SandboxStatus(BaseModel):
|
class SandboxStatus(BaseModel):
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ def enrich_reachability(
|
||||||
enriched = dict(reach)
|
enriched = dict(reach)
|
||||||
spec = profile.reachability
|
spec = profile.reachability
|
||||||
|
|
||||||
|
if handle.get("workspace_dir"):
|
||||||
|
enriched.setdefault("workspace_dir", handle["workspace_dir"])
|
||||||
|
if handle.get("pid") and enriched.get("endpoint", "").startswith("pid:"):
|
||||||
|
enriched.setdefault("pid", handle["pid"])
|
||||||
|
|
||||||
if spec.tunnel:
|
if spec.tunnel:
|
||||||
enriched.setdefault("tunnel_via", spec.tunnel)
|
enriched.setdefault("tunnel_via", spec.tunnel)
|
||||||
if spec.identity:
|
if spec.identity:
|
||||||
|
|
@ -50,6 +55,20 @@ def ssh_one_liner(reach: Reachability) -> str | None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def local_exec_hint(reach: Reachability) -> str | None:
|
||||||
|
"""No-SSH-hop exec hint for same-host extensions (e.g. ext.bwrap).
|
||||||
|
|
||||||
|
Consumers exec directly into the sandbox's namespaces via the
|
||||||
|
placeholder process's pid, rather than opening an SSH channel.
|
||||||
|
"""
|
||||||
|
if reach.pid and reach.workspace_dir:
|
||||||
|
return (
|
||||||
|
f"nsenter --target {reach.pid} --mount --pid --net --uts --ipc "
|
||||||
|
f"-- sh -c 'cd {reach.workspace_dir} && exec $SHELL'"
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def build_reachability_report(status: SandboxStatus) -> dict[str, Any]:
|
def build_reachability_report(status: SandboxStatus) -> dict[str, Any]:
|
||||||
"""Consumer-facing reachability report with ops-bridge pointer."""
|
"""Consumer-facing reachability report with ops-bridge pointer."""
|
||||||
reach = status.reachability
|
reach = status.reachability
|
||||||
|
|
@ -65,4 +84,5 @@ def build_reachability_report(status: SandboxStatus) -> dict[str, Any]:
|
||||||
}
|
}
|
||||||
if reach:
|
if reach:
|
||||||
payload["ssh_one_liner"] = ssh_one_liner(reach)
|
payload["ssh_one_liner"] = ssh_one_liner(reach)
|
||||||
|
payload["local_exec_hint"] = local_exec_hint(reach)
|
||||||
return payload
|
return payload
|
||||||
|
|
@ -164,3 +164,22 @@ def test_supports_snapshots_is_false() -> None:
|
||||||
assert ext.supports_snapshots() is False
|
assert ext.supports_snapshots() is False
|
||||||
with pytest.raises(NotImplementedError):
|
with pytest.raises(NotImplementedError):
|
||||||
ext.snapshot({})
|
ext.snapshot({})
|
||||||
|
|
||||||
|
|
||||||
|
def test_reachability_local_exec_hint_for_bwrap_handle() -> None:
|
||||||
|
from sandboxer.reachability.enrich import enrich_reachability, local_exec_hint
|
||||||
|
from sandboxer.models import Reachability
|
||||||
|
|
||||||
|
handle = {"pid": "555", "workspace_dir": "/tmp/sandboxer-bwrap/abc", "host": "localhost"}
|
||||||
|
reach = {"host": "localhost", "endpoint": "pid:555"}
|
||||||
|
profile = _profile()
|
||||||
|
|
||||||
|
enriched = enrich_reachability(reach, profile, handle)
|
||||||
|
reachability = Reachability(**enriched)
|
||||||
|
|
||||||
|
assert reachability.pid == "555"
|
||||||
|
assert reachability.workspace_dir == "/tmp/sandboxer-bwrap/abc"
|
||||||
|
assert local_exec_hint(reachability) == (
|
||||||
|
"nsenter --target 555 --mount --pid --net --uts --ipc "
|
||||||
|
"-- sh -c 'cd /tmp/sandboxer-bwrap/abc && exec $SHELL'"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ built against the other.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: SAND-WP-0013-T04
|
id: SAND-WP-0013-T04
|
||||||
status: todo
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "1d8b3e18-d067-4364-89e9-5d5bc5923deb"
|
state_hub_task_id: "1d8b3e18-d067-4364-89e9-5d5bc5923deb"
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue