Phase 11: remote UX & network attach (0.11.0)
- Live remote-stack logs over a WebSocket proxied through the central app to
the agent (/ws/agent-logs/{agent}/{stack}); agent gains a WS log endpoint.
- Deploy to a remote host from the UI: host selector in the New Stack editor
and template dialog; templates instantiate onto an agent via the proxy.
- Network attach/detach: expandable inspect view per network with
connect/disconnect + container picker; GET /{id}/containers, POST connect/disconnect.
- Remove dead pages/Placeholder.tsx.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ec7e3e706f
commit
1931500c24
@@ -86,6 +86,43 @@ def create_network(spec: dict) -> dict:
|
||||
return _summary(net)
|
||||
|
||||
|
||||
def connectable_containers(network_id: str) -> list[dict]:
|
||||
"""All containers on the host, flagged whether already on this network."""
|
||||
client = get_client()
|
||||
net = safe_call(client.networks.get, network_id)
|
||||
net.reload()
|
||||
connected = set((net.attrs.get("Containers") or {}).keys())
|
||||
out = []
|
||||
for c in safe_call(client.containers.list, all=True):
|
||||
labels = c.labels or {}
|
||||
out.append(
|
||||
{
|
||||
"id": c.id[:12],
|
||||
"name": c.name,
|
||||
"state": c.status,
|
||||
"stack": labels.get(COMPOSE_PROJECT_LABEL),
|
||||
"connected": c.id in connected,
|
||||
}
|
||||
)
|
||||
return sorted(out, key=lambda x: x["name"])
|
||||
|
||||
|
||||
def connect_container(network_id: str, container: str, aliases: Optional[list[str]] = None) -> None:
|
||||
if not (container or "").strip():
|
||||
raise DockerError("invalid_request", "Container is required")
|
||||
client = get_client()
|
||||
net = safe_call(client.networks.get, network_id)
|
||||
safe_call(net.connect, container, aliases=aliases or None)
|
||||
|
||||
|
||||
def disconnect_container(network_id: str, container: str, force: bool = False) -> None:
|
||||
if not (container or "").strip():
|
||||
raise DockerError("invalid_request", "Container is required")
|
||||
client = get_client()
|
||||
net = safe_call(client.networks.get, network_id)
|
||||
safe_call(net.disconnect, container, force=force)
|
||||
|
||||
|
||||
def delete_network(network_id: str) -> None:
|
||||
client = get_client()
|
||||
net = safe_call(client.networks.get, network_id)
|
||||
|
||||
Reference in New Issue
Block a user