docker mode: allow username override
This commit is contained in:
@@ -107,6 +107,15 @@ When a container starts with either label, it automatically appears in the dashb
|
||||
|
||||
Containers that only specify `webterm-theme` are still included and use the default auto command.
|
||||
|
||||
**Environment Variables:**
|
||||
- `WEBTERM_DOCKER_USERNAME` - Set to run Docker exec sessions as a specific user (default: root)
|
||||
- `WEBTERM_DOCKER_AUTO_COMMAND` - Override the default `auto` command (default: `tmux new-session -As webterm`)
|
||||
|
||||
Example: Start containers and exec into them as `developer` user:
|
||||
```bash
|
||||
WEBTERM_DOCKER_USERNAME=developer webterm --docker-watch
|
||||
```
|
||||
|
||||
Example docker-compose.yaml:
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -43,6 +43,7 @@ DA_PARTIAL_PATTERN = re.compile(rb"\x1b(?:\[(?:\?[\d;]*)?)?$")
|
||||
class DockerExecSpec:
|
||||
container: str
|
||||
command: list[str]
|
||||
user: str | None = None
|
||||
|
||||
|
||||
class DockerExecSession(Session):
|
||||
@@ -162,6 +163,8 @@ class DockerExecSession(Session):
|
||||
"Tty": True,
|
||||
"Cmd": self.exec_spec.command,
|
||||
}
|
||||
if self.exec_spec.user:
|
||||
payload["User"] = self.exec_spec.user
|
||||
response = self._request_json(
|
||||
"POST", f"/containers/{self.exec_spec.container}/exec", payload
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
import shlex
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -137,9 +138,11 @@ class SessionManager:
|
||||
log.warning("Sorry, webterm does not currently support terminals on Windows")
|
||||
return None
|
||||
if app.command == AUTO_COMMAND_SENTINEL:
|
||||
docker_user = os.environ.get("WEBTERM_DOCKER_USERNAME")
|
||||
exec_spec = DockerExecSpec(
|
||||
container=app.name,
|
||||
command=shlex.split(_get_auto_command()),
|
||||
user=docker_user,
|
||||
)
|
||||
session_process = DockerExecSession(self.poller, session_id, exec_spec)
|
||||
else:
|
||||
|
||||
@@ -214,6 +214,32 @@ class TestSessionManager:
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, DockerExecSession)
|
||||
assert result.exec_spec.user is None
|
||||
|
||||
async def test_new_docker_exec_session_with_user(self, mock_poller, mock_path, monkeypatch):
|
||||
from webterm.docker_exec_session import DockerExecSession
|
||||
|
||||
monkeypatch.setenv("WEBTERM_DOCKER_USERNAME", "testuser")
|
||||
|
||||
app = App(
|
||||
name="my-container",
|
||||
slug="my-container",
|
||||
path="./",
|
||||
command=AUTO_COMMAND_SENTINEL,
|
||||
terminal=True,
|
||||
)
|
||||
manager = SessionManager(mock_poller, mock_path, [app])
|
||||
|
||||
with patch.object(DockerExecSession, "open", new_callable=AsyncMock):
|
||||
result = await manager.new_session(
|
||||
"my-container",
|
||||
SessionID("test-session"),
|
||||
RouteKey("test-route"),
|
||||
)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, DockerExecSession)
|
||||
assert result.exec_spec.user == "testuser"
|
||||
|
||||
|
||||
class TestSessionManagerRoutes:
|
||||
|
||||
Reference in New Issue
Block a user