Skip to content

Commit eaded68

Browse files
committed
Add distant-docker backend plugin for Docker container interaction
Implements a full distant Api backend that communicates with Docker containers via the Bollard API. Supports both Unix (Linux) and Windows (nanoserver) containers through DockerFamily-based dispatch. Key features: - File I/O via Docker tar archive API (no shell required) - Process spawning with simple and PTY modes - Shell command dispatch (sh -c / cmd /c) based on container OS - Search support: rg/grep/find on Unix, findstr on Windows - Windows drive-letter path parsing in search output - Integration tests covering file ops, dirs, search, metadata, and processes
1 parent 5fbddca commit eaded68

File tree

20 files changed

+3980
-7
lines changed

20 files changed

+3980
-7
lines changed

.config/nextest.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[test-groups.ssh-integration]
22
max-threads = 4
33

4+
[test-groups.docker-integration]
5+
max-threads = 2
6+
47
[profile.ci]
58
fail-fast = false
69
retries = 4
@@ -11,3 +14,7 @@ final-status-level = "fail"
1114
[[profile.ci.overrides]]
1215
filter = 'binary_id(distant-ssh::lib)'
1316
test-group = 'ssh-integration'
17+
18+
[[profile.ci.overrides]]
19+
filter = 'binary_id(distant-docker::lib)'
20+
test-group = 'docker-integration'

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ jobs:
128128
- name: Ensure /run/sshd exists on Unix
129129
run: sudo mkdir -p /run/sshd
130130
if: matrix.os == 'ubuntu-latest'
131+
- name: Pre-pull Docker test image (Linux)
132+
run: docker pull ubuntu:22.04
133+
if: matrix.os == 'ubuntu-latest'
134+
- name: Pre-pull Docker test image (Windows)
135+
run: docker pull mcr.microsoft.com/windows/nanoserver:ltsc2025
136+
if: matrix.os == 'windows-latest'
131137
- name: Run all workspace tests (all features)
132138
run: cargo nextest run --profile ci --release --all-features --workspace
133139
- name: Run all doc tests (all features)

AGENTS.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,24 @@ manipulation.
88
## Project Overview
99

1010
- **Language:** Rust (Edition 2024, MSRV 1.88.0)
11-
- **Architecture:** Cargo workspace with 4 member crates
11+
- **Architecture:** Cargo workspace with 5 member crates
1212
- **Project Type:** CLI application with client-server architecture
1313
- **Main Crates:**
1414
- `distant` - Main binary implementation providing commands like `distant
1515
api`, `distant connect`, and `distant launch`
1616
- `distant-core` - Core library with API, protocol, plugin trait, and
1717
utilities
18+
- `distant-docker` - Docker backend plugin using the Bollard API to interact
19+
with containers; supports both Unix and Windows (`nanoserver`) containers
20+
via `DockerFamily` dispatch
1821
- `distant-host` - Custom server implementation to run on a host machine that
1922
implements the full distant specification, also providing a client-side
2023
plugin
2124
- `distant-ssh` - pure Rust SSH client-side plugin compatible with distant
2225
specification
2326
- `distant-test-harness` - non-published crate that provides test utilities to
2427
run e2e system tests that involve standing up distant servers, managers,
25-
sshd, and more
28+
sshd, Docker containers, and more
2629

2730
## General AI Workflow
2831

@@ -55,8 +58,9 @@ To move beyond basic code generation, use the following patterns:
5558
on what has changed.
5659
1. **All tests:** `cargo test --all-features --workspace`
5760
2. **Core tests:** `cargo test --all-features -p distant-core`
58-
2. **Host tests:** `cargo test --all-features -p distant-host`
59-
2. **SSH tests:** `cargo test --all-features -p distant-ssh`
61+
3. **Docker tests:** `cargo test --all-features -p distant-docker`
62+
4. **Host tests:** `cargo test --all-features -p distant-host`
63+
5. **SSH tests:** `cargo test --all-features -p distant-ssh`
6064

6165
## Memory Bank Maintenance (`CLAUDE.md` aka `AGENTS.md`)
6266

@@ -88,6 +92,16 @@ later to resolve will be placed here.
8892
may be incomplete/untested.
8993
2. Windows CI SSH tests have intermittent auth failures from resource
9094
contention — mitigated with nextest retries (4x), not root-caused.
95+
3. `distant-docker` search on Windows containers uses `findstr.exe` which has
96+
limited regex support (no `+`, `?`, `|`, `{n,m}`). `Regex` and `Or` query
97+
conditions return `Unsupported` on Windows — only `Contains`, `Equals`,
98+
`StartsWith`, and `EndsWith` are supported.
99+
4. `distant-docker` `append_file` on Windows falls back to tar read-modify-write
100+
because there's no good stdin-append equivalent to `cat >>` on nanoserver.
101+
5. Nanoserver `ContainerUser` cannot write to `C:\Windows\Temp` or other system
102+
directories via exec commands (`mkdir`, `move`, etc.). The Docker tar API
103+
bypasses permissions but exec-based operations require a user-writable
104+
directory. Tests use `C:\temp` (pre-created via tar API in the test harness).
91105

92106
## Tooling & Command Reference
93107

@@ -105,6 +119,7 @@ cargo build --all-features --workspace
105119

106120
# Build specific crates
107121
cargo build -p distant-core
122+
cargo build -p distant-docker
108123
cargo build -p distant-host
109124
cargo build -p distant-ssh
110125
```
@@ -191,6 +206,43 @@ Keep a list of patterns to **avoid**:
191206
4. Don't run mass parallel SSH integration tests without throttling — use
192207
nextest `test-groups` with `max-threads` (configured in
193208
`.config/nextest.toml`).
209+
5. Always create a **feature branch** before starting multi-file or multi-phase
210+
work — never commit directly to `master`. Use
211+
`git checkout -b feature/<name>` before writing any code.
212+
6. **Commit per-phase** (or at minimum per logical unit of work) — don't
213+
accumulate an entire feature as uncommitted changes across many phases. Each
214+
phase should be a separate commit with `cargo fmt` and `cargo clippy` passing
215+
before the commit is created.
216+
7. Always **run tests** (`cargo test --all-features -p <crate>`) after creating
217+
or modifying test files — don't assume tests compile or pass without actually
218+
executing them.
219+
8. Don't hardcode `sh -c` for shell commands in `distant-docker` — Windows
220+
containers (nanoserver) don't have `sh`. Use the `run_shell_cmd` /
221+
`run_shell_cmd_stdout` helpers which dispatch to `sh -c` or `cmd /c` based
222+
on `DockerFamily`.
223+
9. Don't hardcode Unix paths like `/tmp` in Docker tests — use `test_temp_dir()`
224+
which returns `/tmp` on Unix and `C:\temp` on Windows. Don't use
225+
`C:\Windows\Temp``ContainerUser` cannot write there.
226+
10. Don't double-wrap Windows commands with `cmd /c` — when using
227+
`run_shell_cmd` the shell prefix is already provided, so command strings
228+
should contain only the inner command (e.g. `mkdir "path"` not
229+
`cmd /c mkdir "path"`).
230+
11. Don't use forward-slash separators inside `PathBuf::join()` for
231+
multi-component paths — `join("a/b/c")` embeds a Unix separator and
232+
can break on Windows. Use chained `.join("a").join("b").join("c")`.
233+
12. When writing Docker tests (commands, paths, filenames), always consider
234+
Windows container compatibility — use `test_temp_dir()` for temp paths,
235+
chain `.join()` calls for path components, and use `cfg!(windows)` for
236+
any platform-specific commands or assertions.
237+
13. Never bypass GPG commit signing — don't use `-c commit.gpgsign=false`
238+
or `--no-gpg-sign`. If `gpg failed to sign the data`, stop and let the
239+
user resolve the signing issue. The user's GPG key also handles SSH
240+
push authentication.
241+
14. Never dismiss test failures as "intermittent" or "pre-existing" without
242+
investigation. Every failure — even if it only reproduces sometimes —
243+
must be analyzed to determine the root cause and a recommendation given
244+
to fix it. If the root cause is a bug in production code, focus the
245+
recommendation on the production code fix, not on test workarounds.
194246

195247
### Format standards
196248

Cargo.lock

Lines changed: 154 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)