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
@@ -36,6 +36,12 @@ class NetworkCreate(BaseModel):
|
||||
attachable: bool = True
|
||||
|
||||
|
||||
class ContainerRef(BaseModel):
|
||||
container: str
|
||||
aliases: list[str] | None = None
|
||||
force: bool = False
|
||||
|
||||
|
||||
@router.get("")
|
||||
def list_networks(_user: User = Depends(get_current_user)) -> list[dict]:
|
||||
return network_service.list_networks()
|
||||
@@ -43,7 +49,58 @@ def list_networks(_user: User = Depends(get_current_user)) -> list[dict]:
|
||||
|
||||
@router.get("/{network_id}")
|
||||
def inspect_network(network_id: str, _user: User = Depends(get_current_user)) -> dict:
|
||||
return network_service.inspect_network(network_id)
|
||||
try:
|
||||
return network_service.inspect_network(network_id)
|
||||
except DockerError as exc:
|
||||
_map(exc)
|
||||
|
||||
|
||||
@router.get("/{network_id}/containers")
|
||||
def network_containers(
|
||||
network_id: str, _user: User = Depends(get_current_user)
|
||||
) -> list[dict]:
|
||||
try:
|
||||
return network_service.connectable_containers(network_id)
|
||||
except DockerError as exc:
|
||||
_map(exc)
|
||||
|
||||
|
||||
@router.post("/{network_id}/connect")
|
||||
def connect_container(
|
||||
network_id: str,
|
||||
body: ContainerRef,
|
||||
request: Request,
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(require_admin),
|
||||
) -> dict:
|
||||
try:
|
||||
network_service.connect_container(network_id, body.container, body.aliases)
|
||||
except DockerError as exc:
|
||||
_map(exc)
|
||||
audit_service.record(
|
||||
session, user=user.username, action="network.connect", target=network_id,
|
||||
detail=body.container, ip=_ip(request),
|
||||
)
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.post("/{network_id}/disconnect")
|
||||
def disconnect_container(
|
||||
network_id: str,
|
||||
body: ContainerRef,
|
||||
request: Request,
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(require_admin),
|
||||
) -> dict:
|
||||
try:
|
||||
network_service.disconnect_container(network_id, body.container, body.force)
|
||||
except DockerError as exc:
|
||||
_map(exc)
|
||||
audit_service.record(
|
||||
session, user=user.username, action="network.disconnect", target=network_id,
|
||||
detail=body.container, ip=_ip(request),
|
||||
)
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.post("", status_code=201)
|
||||
|
||||
Reference in New Issue
Block a user