Repository navigation
refactor: move exec, cp, export and commit to internal/containerops - #14397
Merged
Merged
Conversation
…containerops These four operations act from the outside on the container of a service. They only need the Docker client, the concurrency bound, the event bus, the dry-run switch, the Docker CLI (which owns the terminal streams) and the two container lookups, so they move out of the flat pkg/compose package into internal/containerops behind a Backend interface declaring exactly that. composeService implements the interface in a new file and keeps Exec, Copy, Export and Commit as one-line forwarders (the progress wrapper of the last three stays there), so no caller changes. The now unused checkRelayTarget forwarder is dropped. Behavior is unchanged: the cp test still runs through the forwarders. Part of docker#14396 Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
Cover the container selection and the refusals of Copy through a fake Backend: the replica asked for, one-off containers only with --all, a copy from a service reading its first container only, a service without container, copying between services and a copy with no service at all. Part of docker#14396 Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
docker-agent
left a comment
Contributor
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
dock-tor
approved these changes
Oct 27, 2026
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues were identified for the container-operations package split.
No open issues 🎉
What changed in this PR
Continues the package split tracked in #14396 by moving exec, cp, export, and commit into internal/containerops, while retaining the existing public API and progress wrappers in pkg/compose.
Changes:
- Introduces a backend interface for Docker access, terminal streams, container lookups, progress events, and execution settings.
- Moves the four operations into the internal package and adds forwarding methods in
composeService. - Adds copy-target selection tests and routes the existing concurrency test through the public
Copymethod.
| File | Description |
|---|---|
pkg/compose/relay.go |
Removes the relay-check wrapper whose callers moved. |
pkg/compose/cp_test.go |
Exercises copy concurrency through the public forwarder. |
pkg/compose/containerops.go |
Adds backend adaptation and public operation forwarders. |
internal/containerops/export.go |
Moves export logic and uses shared progress helpers. |
internal/containerops/exec.go |
Moves exec logic with backend-provided Docker CLI access. |
internal/containerops/cp.go |
Moves copy logic to backend-provided clients and streams. |
internal/containerops/cp_test.go |
Tests copy target selection and unsupported directions. |
internal/containerops/containerops.go |
Defines the backend, service, and bounded concurrency helper. |
internal/containerops/commit.go |
Moves commit logic behind the backend interface. |
Review effort: Balanced
4 of 15 tasks
docker-agent
left a comment
Contributor
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does, in one sentence
Moves
exec,cp,exportandcommit— the operations that act from the outside on the container of a service — out of the flatpkg/composepackage intointernal/containerops, the next step of splittingpkg/composeafterinternal/inspect,internal/projectloader,internal/relayandinternal/provider.Context
pkg/composeis one package where every operation is a method of the samecomposeServiceand can therefore reach anything else. The earlier moves (#14331, #14333) settled the pattern for clusters that only needed the Docker client and the event bus. These four operations are the first ones moved that talk to the user:cpreads stdin and writes stdout when the path is-,exportrefuses to write a tar archive to a terminal, andexechands the whole terminal over to the Docker CLI. They are also easy to detach (about 600 lines, and nothing else in the package calls them: they are only reached through the public API), so this is a good place to settle how the terminal crosses the boundary beforelogs,attachandrunneed it.What the PR brings
internal/containerops, with aBackendof seven methods: the Docker client, the concurrency bound, the event bus, the dry-run switch, the container lookups (Containers,SpecifiedContainer) and the Docker CLI.Backendalready exposes, not through per-stream accessors: stdin, stdout and the TTY all come fromCLI().In()/CLI().Out().execneeds the whole CLI anyway (it runs the Docker CLI's own exec implementation), and the operations that follow (attach,run,logs) need more than a reader and a writer — raw mode, terminal size — so narrowStdin()/Stdout()interfaces would only have been widened by the next move.composeServiceimplements the interface inpkg/compose/containerops.goand keepsExec,Copy,ExportandCommitas one-line forwarders; the progress wrapper of the last three stays there. No caller changes, and no other existing file ofpkg/composeis touched apart from droppingcheckRelayTarget, whose only callers moved.git mv: undoing the mechanical substitutions (receiver, calls through theBackend) on the new files gives back the old ones, except for the imports, the doc comments, the removed progress wrapper and one error event built withprogress.Errorinstead of the package's own copy. Thecpconcurrency test is untouched apart from its call, and still runs through the forwarders; the exec, cp, export and commit end-to-end scenarios pass in both standalone and plugin mode.internal/naming, the error event frominternal/progress, and theOneOffenum ofinternal/inspectfor the container lookups. The five-line bounded fan-out ofcpis copied frompkg/compose(it is still used bypauseandkillthere); both belong to the shared kernel that a later step extracts.Why this is the right next brick
It is the smallest cluster that exercises a terminal, the one thing the earlier moves never had to cross: it fixes the answer on an easy case, with no shared state and no lifecycle hook to cross, and nothing in flight touches these files, so no open pull request has to be rebased.
Part of #14396
🤖 Generated with Claude Code