Compare commits

..

49 Commits

Author SHA1 Message Date
5650f9b102 Merge pull request #5116 from thaJeztah/26.1_update_engine
Some checks failed
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / e2e (alpine, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 23, experimental) (push) Has been cancelled
e2e / e2e (alpine, 23, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 24, experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 25, experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 23, experimental) (push) Has been cancelled
e2e / e2e (debian, 23, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 24, experimental) (push) Has been cancelled
e2e / e2e (debian, 24, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 25, experimental) (push) Has been cancelled
e2e / e2e (debian, 25, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-12) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[26.1]  vendor: github.com/docker/docker de5c9cf0b96e (v26.1.4-dev)
2024-06-05 12:47:13 +02:00
e8bc27d4ca vendor: github.com/docker/docker de5c9cf0b96e (v26.1.4-dev)
updating to tip of the v26.1 branch, which will be v26.1.4

full diff: https://github.com/docker/docker/compare/v26.1.3...de5c9cf0b96e4e172b96db54abababa4a328462f

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:40:27 +02:00
2acb9c2e8f vendor: github.com/containerd/containerd v1.7.18
no changes to vendored files

full diff: https://github.com/containerd/containerd/compare/v1.7.17...v1.7.18

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a9ea034815)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:36:57 +02:00
230d4d0bab vendor: github.com/containerd/containerd v1.7.17
no changes in vendored code

full diff: https://github.com/containerd/containerd/compare/v1.7.15...v1.7.17

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 558a910b85)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:34:30 +02:00
6d47c06b0d vendor: tags.cncf.io/container-device-interface v0.7.2
no changes in vendored code

full diff: https://github.com/cncf-tags/container-device-interface/compare/v0.6.2...v0.7.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit be2c284ee2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:34:30 +02:00
a6d757c0e3 vendor: github.com/Microsoft/hcsshim v0.11.5
full diff: https://github.com/Microsoft/hcsshim/compare/v0.11.4...v0.11.5

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 16c8f4942e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:34:30 +02:00
c463d968fc vendor: github.com/opencontainers/image-spec v1.1.0
full diff: https://github.com/opencontainers/image-spec/compare/v1.1.0-rc5...v1.1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b7548ba7f1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 12:34:27 +02:00
a61a0c3ac9 Merge pull request #5118 from thaJeztah/26.1_backport_bump_go1.21.11
[26.1 backport] update to go1.21.11, Alpine 3.20
2024-06-05 00:11:37 +02:00
0576b3dad7 update to go1.21.11
go1.21.11 (released 2024-06-04) includes security fixes to the archive/zip
and net/netip packages, as well as bug fixes to the compiler, the go command,
the runtime, and the os package. See the Go 1.21.11 milestone on our issue
tracker for details;

- https://github.com/golang/go/issues?q=milestone%3AGo1.21.11+label%3ACherryPickApproved
- full diff: https://github.com/golang/go/compare/go1.21.10...go1.21.11

From the security announcement;

We have just released Go versions 1.22.4 and 1.21.11, minor point releases.
These minor releases include 2 security fixes following the security policy:

- archive/zip: mishandling of corrupt central directory record

  The archive/zip package's handling of certain types of invalid zip files
  differed from the behavior of most zip implementations. This misalignment
  could be exploited to create an zip file with contents that vary depending
  on the implementation reading the file. The archive/zip package now rejects
  files containing these errors.

  Thanks to Yufan You for reporting this issue.

  This is CVE-2024-24789 and Go issue https://go.dev/issue/66869.

- net/netip: unexpected behavior from Is methods for IPv4-mapped IPv6 addresses

  The various Is methods (IsPrivate, IsLoopback, etc) did not work as expected
  for IPv4-mapped IPv6 addresses, returning false for addresses which would
  return true in their traditional IPv4 forms.

  Thanks to Enze Wang of Alioth and Jianjun Chen of Zhongguancun Lab
  for reporting this issue.

  This is CVE-2024-24790 and Go issue https://go.dev/issue/67680.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 630e1d3e95)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-04 23:43:37 +02:00
60b13f1f80 Dockerfile: update ALPINE_VERSION to 3.20
Update to the current version of Alpine, which is also the default for
the golang:alpine image

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e70f68595d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-04 23:43:33 +02:00
5dab29765f Merge pull request #5108 from thaJeztah/26.1_backport_use_containerd_platforms
[26.1 backport] migrate to new github.com/containerd/platforms package
2024-06-03 17:04:53 +01:00
b600054c51 migrate to new github.com/containerd/platforms package
The github.com/containerd/containerd/platforms package was moved to a separate
module in preparation of the containerd v2.0 release.

Switch to the new module, which means we also remove containerd as a direct
dependency.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 7dc271a8be)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 17:45:45 +02:00
42912d4d68 Merge pull request #5102 from thaJeztah/26.1_backport_docs
[26.1 backport] assorted docs backports
2024-06-03 16:31:45 +01:00
28638aab95 Merge pull request #5103 from thaJeztah/26.1_backport_bump_gowinio
[26.1 backport] vendor: github.com/Microsoft/go-winio v0.6.2
2024-06-03 15:55:36 +01:00
e89982aea9 Merge pull request #5105 from laurazard/update-actions-26.1
[26.1 backport] gha: update to actions/upload-artifact@v4
2024-06-03 16:47:35 +02:00
dafe63b085 gha: update to actions/upload-artifact@v4
v3 is using Node.js 16 which are being deprecated:

    Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: actions/upload-artifact@v3. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.

ci: incl. platform pair in artifact name

This fixes an the issue w/ `upload-artifact@v4`.
See: https://github.blog/2024-02-12-get-started-with-v4-of-github-actions-artifacts/#compatibility

Co-authored-by: Laura Brehm <laurabrehm@hey.com>
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b9cd722595)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 16:41:45 +02:00
7dfc99c17e Merge pull request #5104 from thaJeztah/26.1_vendor_engine
[26.1] vendor: github.com/docker/docker v26.1.3
2024-06-03 15:08:09 +02:00
079107e1bc [26.1] vendor: github.com/docker/docker v26.1.3
no changes; same commit, but tagged

full diff: https://github.com/docker/docker/compare/8e96db1c328d...v26.1.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 14:06:05 +02:00
14d7485d98 vendor: github.com/Microsoft/go-winio v0.6.2
- Fix compatibility with go1.22
- fileinfo: internally fix FileBasicInfo memory alignment (fixes compatibility
  with go1.22)
- Switch from syscall to golang.org/x/sys/windows
- Remove golang.org/x/mod as dependency
- Remove golang.org/x/tools as dependency

full diff: https://github.com/Microsoft/go-winio/compare/v0.6.1...v0.6.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 12aaeae21b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 13:31:46 +02:00
50bb59277a docs: tidy up CDI docs
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
(cherry picked from commit 116db4fc82)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 13:28:38 +02:00
c4767b3141 docs: fix json syntax error
Signed-off-by: cncal <flycalvin@qq.com>
(cherry picked from commit 6a4d38c7f2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-03 13:28:24 +02:00
3f807ede91 Merge pull request #5083 from vvoland/v26.1-5078
[26.1 backport] plugins/hooks: Don't show empty hook messages
2024-05-31 14:08:59 -06:00
836fc57e2a Merge pull request #5095 from thaJeztah/26.1_backport_context_type_stub
[26.1 backport] context list: temporarily add ContextType to JSON output
2024-05-31 22:01:29 +02:00
258e27438f context list: temporarily add ContextType to JSON output
Docker Desktop currently ships with the "cloud integration" wrapper,
which outputs an additional ContextType field in the JSON output.

While this field is non-standard, it made its way into Visual Studio's
Docker integration, which uses this to exclude "aci" and "eci" context
types that are not supported by Visual Studio.

This patch;

- conditionally adds a ContextType field to the JSON output
- but ONLY when using the default "{{json .}}" or "json" formats
  (which are the formats used by Visual Studio)
- if the context is a "aci" or "eci" context, that type is
  preserved, otherwise the default "moby" type is used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit fed9fa0f72)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-05-31 14:48:35 +02:00
29cd8591ee cli/command/context: list: add test for JSON output
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 40a1da8b42)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-05-31 14:48:19 +02:00
e23a63eb4c cli/command/context: test inspecting context with custom metadata
The CLI does not currently expose options to add custom metadata to
contexts, but contexts support them.

- update test-utilities to allow setting custom metadata
- update the inspect test to verify that custom metadata is included
  when inspecting a context.
- update the import/export tests to verify that custom metadata
  is preserved.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 2e9eff235d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-05-31 14:48:19 +02:00
1e52a86d42 cli/command/context: add test-utility to create multiple contexts
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 54291dd47a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-05-31 14:48:16 +02:00
e382a5f225 plugins/hooks: Don't show empty hooks
Don't show `Next steps:` with no messages at all when plugin returns an
unitialized value of `HookMessage` (zero-initialization sets its type to
NextSteps and empty template).

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 296a6f5872)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-05-20 17:58:52 +02:00
b72abbb6f0 Merge pull request #5073 from vvoland/vendor-docker
Some checks failed
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / e2e (alpine, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 23, experimental) (push) Has been cancelled
e2e / e2e (alpine, 23, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 24, experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 25, experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 23, experimental) (push) Has been cancelled
e2e / e2e (debian, 23, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 24, experimental) (push) Has been cancelled
e2e / e2e (debian, 24, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 25, experimental) (push) Has been cancelled
e2e / e2e (debian, 25, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-12) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[26.1] vendor: github.com/docker/docker v26.1.3-dev (8e96db1c328d)
2024-05-16 09:47:24 +02:00
26e9ff49c8 vendor: github.com/docker/docker v26.1.3-dev (8e96db1c328d)
- full diff: ef1912d8b6...8e96db1c32

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-05-15 13:01:52 +02:00
4021ee92fe Merge pull request #5071 from laurazard/backport/5051-26.1
[26.1 backport] Add OTel instrumentation to CLI plugins
2024-05-15 11:24:12 +02:00
326c7138bb OTel: implement missing MeterProvider ForceFlush
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 5f4f4f64d3)
2024-05-15 02:00:06 +01:00
ee359a394b OTel: add command.time metric to plugin commands
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit f07834d185)
2024-05-15 02:00:05 +01:00
004e2925d7 Merge pull request #5070 from laurazard/backport/5067-26.1
[26.1 backport] Centralize init of Meter/TracerProviders
2024-05-14 16:52:23 +01:00
6691085012 Use funcs on DockerCli to return Meter/TracerProviders, not initialize them. Initialize them during DockerCli struct init
Signed-off-by: Christopher Petito <chrisjpetito@gmail.com>
(cherry picked from commit 02537eac59)
2024-05-14 16:31:06 +01:00
60f2d38d53 Merge pull request #5068 from dvdksn/26.1_backport_doc-vxlan-listen-addr
[26.1 Backport] docs: clarify that --data-path-addr doesn't restrict access
2024-05-13 20:48:38 +02:00
81b482ea5e docs: clarify that --data-path-addr doesn't restrict access
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
(cherry picked from commit faf096b25c)
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-05-13 19:01:26 +02:00
211e74b240 Merge pull request #5066 from vvoland/vendor-docker
Some checks failed
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / e2e (alpine, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 23, experimental) (push) Has been cancelled
e2e / e2e (alpine, 23, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 24, experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 25, experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 23, experimental) (push) Has been cancelled
e2e / e2e (debian, 23, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 24, experimental) (push) Has been cancelled
e2e / e2e (debian, 24, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 25, experimental) (push) Has been cancelled
e2e / e2e (debian, 25, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-12) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[26.1] vendor: github.com/docker/docker v26.1.2-dev (ef1912d8b6ae)
2024-05-08 11:31:07 +02:00
8beff78d85 Merge pull request #5065 from vvoland/v26.1-5064
[26.1 backport] update to go1.21.10
2024-05-08 11:30:55 +02:00
e64914c890 vendor: github.com/docker/docker v26.1.2-dev (ef1912d8b6ae)
- full diff: ac2de55998...ef1912d8b6

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-05-08 11:04:04 +02:00
c1d70d1fbb update to go1.21.10
These minor releases include 2 security fixes following the security policy:

- cmd/go: arbitrary code execution during build on darwin
On Darwin, building a Go module which contains CGO can trigger arbitrary code execution when using the Apple version of ld, due to
usage of the -lto_library flag in a "#cgo LDFLAGS" directive.
Thanks to Juho Forsén of Mattermost for reporting this issue.
This is CVE-2024-24787 and Go issue https://go.dev/issue/67119.

- net: malformed DNS message can cause infinite loop
A malformed DNS message in response to a query can cause the Lookup functions to get stuck in an infinite loop.
Thanks to long-name-let-people-remember-you on GitHub for reporting this issue, and to Mateusz Poliwczak for bringing the issue to
our attention.
This is CVE-2024-24788 and Go issue https://go.dev/issue/66754.

View the release notes for more information:
https://go.dev/doc/devel/release#go1.22.3

- https://github.com/golang/go/issues?q=milestone%3AGo1.21.10+label%3ACherryPickApproved
- full diff: https://github.com/golang/go/compare/go1.21.9...go1.21.10

**- Description for the changelog**

```markdown changelog
Update Go runtime to 1.21.10
```

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit eb99994c75)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-05-08 09:52:05 +02:00
53a3f0be18 Merge pull request #5062 from laurazard/cherry-pick-run-hang
[26.1 backport] Fix hang when container fails to start
2024-05-07 13:35:09 +02:00
4add46d686 Add e2e tests for run w/ bad entrypoint
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 8d6e571c03)
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-05-07 11:57:36 +01:00
ccea7d8a30 Fix hang when container fails to start
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 31644d5ea7)
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-05-07 11:57:24 +01:00
4cf5afaefa Merge pull request #5047 from vvoland/v26.1-5038
Some checks failed
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / e2e (alpine, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 23, experimental) (push) Has been cancelled
e2e / e2e (alpine, 23, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 24, experimental) (push) Has been cancelled
e2e / e2e (alpine, 24, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, 25, experimental) (push) Has been cancelled
e2e / e2e (alpine, 25, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 23, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 23, experimental) (push) Has been cancelled
e2e / e2e (debian, 23, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 24, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 24, experimental) (push) Has been cancelled
e2e / e2e (debian, 24, non-experimental) (push) Has been cancelled
e2e / e2e (debian, 25, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, 25, experimental) (push) Has been cancelled
e2e / e2e (debian, 25, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-12) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[26.1 backport] cli-plugins: PluginRunCommand: use cmd.Environ instead of os.Environ
2024-04-30 13:40:03 +02:00
6c2b06d535 Merge pull request #5045 from vvoland/vendor-docker-26.1.1-dev
[26.1] vendor: github.com/docker/docker ac2de55998d4 (v26.1.1)
2024-04-30 13:12:54 +02:00
1c6a8ecf2e cli-plugins: PluginRunCommand: use cmd.Environ instead of os.Environ
Commit 5011759056 implemented a fix that
caused the current environment to be discarded, using `os.Environ()`.
On Windows, `os.Environ()` may produce an incorrect value for `PWD`,
for which a new function was added in go1.19;

- https://tip.golang.org/doc/go1.19#osexecpkgosexec
- https://go-review.googlesource.com/c/go/+/401340

Replace the use of `os.Environ()` with `cmd.Environ()` to address that.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5ccb48459b)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-04-30 13:03:15 +02:00
6d1c387af2 vendor: github.com/docker/docker ac2de55998d4 (v26.1.1)
full diff: c8af8ebe4a...ac2de55998

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-04-30 11:55:51 +02:00
1e6db5d24b Merge pull request #5044 from vvoland/wait-cancel-noerror
[26.1 backport] waitExitOrRemoved: Handle context cancellation
2024-04-29 17:46:55 +02:00
793 changed files with 10751 additions and 32895 deletions

7
.github/CODEOWNERS vendored
View File

@ -1,6 +1,7 @@
# GitHub code owners
# See https://github.com/blog/2392-introducing-code-owners
cli/command/stack/** @silvin-lubecki @docker/runtime-owners
contrib/completion/bash/** @albers @docker/runtime-owners
docs/** @thaJeztah @docker/runtime-owners
cli/command/stack/** @silvin-lubecki
contrib/completion/bash/** @albers
contrib/completion/zsh/** @sdurrheimer
docs/** @thaJeztah

View File

@ -8,12 +8,12 @@ body:
attributes:
value: |
Thank you for taking the time to report a bug!
If this is a security issue report it to the [Docker Security team](mailto:security@docker.com).
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
- type: textarea
id: description
attributes:
label: Description
description: Give a clear and concise description of the bug
description: Please give a clear and concise description of the bug
validations:
required: true
- type: textarea

View File

@ -4,7 +4,7 @@ contact_links:
about: "Read guidelines and tips about contributing to Docker."
url: "https://github.com/docker/cli/blob/master/CONTRIBUTING.md"
- name: "Security and Vulnerabilities"
about: "Report any security issues or vulnerabilities responsibly to the Docker security team. Do not use the public issue tracker."
about: "Please report any security issues or vulnerabilities responsibly to the Docker security team. Please do not use the public issue tracker."
url: "https://github.com/moby/moby/security/policy"
- name: "General Support"
about: "Get the help you need to build, share, and run your Docker applications"

View File

@ -1,5 +1,5 @@
<!--
Make sure you've read and understood our contributing guidelines;
Please make sure you've read and understood our contributing guidelines;
https://github.com/docker/cli/blob/master/CONTRIBUTING.md
** Make sure all your commits include a signature generated with `git commit -s` **
@ -10,7 +10,7 @@ guide https://docs.docker.com/opensource/code/
If this is a bug fix, make sure your description includes "fixes #xxxx", or
"closes #xxxx"
Provide the following information:
Please provide the following information:
-->
**- What I did**

View File

@ -1,14 +1,5 @@
name: build
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@ -28,7 +19,7 @@ on:
jobs:
prepare:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
outputs:
matrix: ${{ steps.platforms.outputs.matrix }}
steps:
@ -46,7 +37,7 @@ jobs:
echo ${{ steps.platforms.outputs.matrix }}
build:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
needs:
- prepare
strategy:
@ -70,7 +61,7 @@ jobs:
uses: docker/setup-buildx-action@v3
-
name: Build
uses: docker/bake-action@v5
uses: docker/bake-action@v4
with:
targets: ${{ matrix.target }}
set: |
@ -99,7 +90,7 @@ jobs:
if-no-files-found: error
bin-image:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
if: ${{ github.event_name != 'pull_request' && github.repository == 'docker/cli' }}
steps:
-
@ -131,7 +122,7 @@ jobs:
password: ${{ secrets.DOCKERHUB_CLIBIN_TOKEN }}
-
name: Build and push image
uses: docker/bake-action@v5
uses: docker/bake-action@v4
with:
files: |
./docker-bake.hcl
@ -143,7 +134,7 @@ jobs:
*.cache-to=type=gha,scope=bin-image,mode=max
prepare-plugins:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
outputs:
matrix: ${{ steps.platforms.outputs.matrix }}
steps:
@ -161,7 +152,7 @@ jobs:
echo ${{ steps.platforms.outputs.matrix }}
plugins:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
needs:
- prepare-plugins
strategy:
@ -177,7 +168,7 @@ jobs:
uses: docker/setup-buildx-action@v3
-
name: Build
uses: docker/bake-action@v5
uses: docker/bake-action@v4
with:
targets: plugins-cross
set: |

View File

@ -1,14 +1,5 @@
name: codeql
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
on:
push:
branches:
@ -53,6 +44,16 @@ jobs:
if: ${{ github.event_name == 'pull_request' }}
run: |
git checkout HEAD^2
-
name: Update Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
-
name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: go
# CodeQL 2.16.4's auto-build added support for multi-module repositories,
# and is trying to be smart by searching for modules in every directory,
# including vendor directories. If no module is found, it's creating one
@ -63,16 +64,6 @@ jobs:
run: |
ln -s vendor.mod go.mod
ln -s vendor.sum go.sum
-
name: Update Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
-
name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: go
-
name: Autobuild
uses: github/codeql-action/autobuild@v3

View File

@ -1,14 +1,5 @@
name: e2e
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@ -25,7 +16,7 @@ on:
jobs:
e2e:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
@ -37,8 +28,8 @@ jobs:
- alpine
- debian
engine-version:
- 27.0 # latest
- 26.1 # latest - 1
- 25.0 # latest
- 24.0 # latest - 1
- 23.0 # mirantis lts
# TODO(krissetto) 19.03 needs a look, doesn't work ubuntu 22.04 (cgroup errors).
# we could have a separate job that tests it against ubuntu 20.04
@ -49,15 +40,8 @@ jobs:
-
name: Update daemon.json
run: |
if [ ! -f /etc/docker/daemon.json ]; then
# ubuntu 24.04 runners no longer have a default daemon.json present
sudo mkdir -p /etc/docker/
echo '{"experimental": true}' | sudo tee /etc/docker/daemon.json
else
# but if there is one; let's patch it to keep other options that may be set.
sudo jq '.experimental = true' < /etc/docker/daemon.json > /tmp/docker.json
sudo mv /tmp/docker.json /etc/docker/daemon.json
fi
sudo jq '.experimental = true' < /etc/docker/daemon.json > /tmp/docker.json
sudo mv /tmp/docker.json /etc/docker/daemon.json
sudo cat /etc/docker/daemon.json
sudo service docker restart
docker version

View File

@ -1,14 +1,5 @@
name: test
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@ -25,7 +16,7 @@ on:
jobs:
ctn:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
steps:
-
name: Checkout
@ -35,7 +26,7 @@ jobs:
uses: docker/setup-buildx-action@v3
-
name: Test
uses: docker/bake-action@v5
uses: docker/bake-action@v4
with:
targets: test-coverage
-
@ -55,8 +46,7 @@ jobs:
fail-fast: false
matrix:
os:
- macos-13 # macOS 13 on Intel
- macos-14 # macOS 14 on arm64 (Apple Silicon M1)
- macos-12
# - windows-2022 # FIXME: some tests are failing on the Windows runner, as well as on Appveyor since June 24, 2018: https://ci.appveyor.com/project/docker/cli/history
steps:
-
@ -74,7 +64,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.22.7
go-version: 1.21.11
-
name: Test
run: |

View File

@ -1,14 +1,5 @@
name: validate-pr
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
on:
pull_request:
types: [opened, edited, labeled, unlabeled]
@ -41,7 +32,7 @@ jobs:
desc=$(echo "$block" | awk NF)
if [ -z "$desc" ]; then
echo "::error::Changelog section is empty. Provide a description for the changelog."
echo "::error::Changelog section is empty. Please provide a description for the changelog."
exit 1
fi
@ -62,16 +53,10 @@ jobs:
# Backports or PR that target a release branch directly should mention the target branch in the title, for example:
# [X.Y backport] Some change that needs backporting to X.Y
# [X.Y] Change directly targeting the X.Y branch
- name: Check release branch
- name: Get branch from PR title
id: title_branch
run: |
# get the intended major version prefix ("[27.1 backport]" -> "27.") from the PR title.
[[ "$PR_TITLE" =~ ^\[([0-9]*\.)[^]]*\] ]] && branch="${BASH_REMATCH[1]}"
run: echo "$PR_TITLE" | sed -n 's/^\[\([0-9]*\.[0-9]*\)[^]]*\].*/branch=\1/p' >> $GITHUB_OUTPUT
# get major version prefix from the release branch ("27.x -> "27.")
[[ "$GITHUB_BASE_REF" =~ ^([0-9]*\.) ]] && target_branch="${BASH_REMATCH[1]}" || target_branch="$GITHUB_BASE_REF"
if [[ "$target_branch" != "$branch" ]] && ! [[ "$GITHUB_BASE_REF" == "master" && "$branch" == "" ]]; then
echo "::error::PR is opened against the $GITHUB_BASE_REF branch, but its title suggests otherwise."
exit 1
fi
- name: Check release branch
if: github.event.pull_request.base.ref != steps.title_branch.outputs.branch && !(github.event.pull_request.base.ref == 'master' && steps.title_branch.outputs.branch == '')
run: echo "::error::PR title suggests targetting the ${{ steps.title_branch.outputs.branch }} branch, but is opened against ${{ github.event.pull_request.base.ref }}" && exit 1

View File

@ -1,14 +1,5 @@
name: validate
# Default to 'contents: read', which grants actions to read commits.
#
# If any permission is set, any permission not included in the list is
# implicitly set to "none".
#
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
@ -25,7 +16,7 @@ on:
jobs:
validate:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
@ -40,13 +31,13 @@ jobs:
uses: actions/checkout@v4
-
name: Run
uses: docker/bake-action@v5
uses: docker/bake-action@v4
with:
targets: ${{ matrix.target }}
# check that the generated Markdown and the checked-in files match
validate-md:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
steps:
-
name: Checkout
@ -66,7 +57,7 @@ jobs:
fi
validate-make:
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
# if you want to ignore files created by your editor/tools,
# consider a global .gitignore https://help.github.com/articles/ignoring-files
# please consider a global .gitignore https://help.github.com/articles/ignoring-files
*.exe
*.exe~
*.orig

View File

@ -44,6 +44,9 @@ linters:
run:
timeout: 5m
skip-files:
- cli/compose/schema/bindata.go
- .*generated.*
linters-settings:
depguard:
@ -55,8 +58,7 @@ linters-settings:
gocyclo:
min-complexity: 16
govet:
enable:
- shadow
check-shadowing: true
settings:
shadow:
strict: true
@ -92,10 +94,6 @@ issues:
exclude:
- parameter .* always receives
exclude-files:
- cli/compose/schema/bindata.go
- .*generated.*
exclude-rules:
# We prefer to use an "exclude-list" so that new "default" exclusions are not
# automatically inherited. We can decide whether or not to follow upstream

View File

@ -22,10 +22,7 @@ Akihiro Matsushima <amatsusbit@gmail.com> <amatsus@users.noreply.github.com>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.akihiro@lab.ntt.co.jp>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
Alano Terblanche <alano.terblanche@docker.com>
Alano Terblanche <alano.terblanche@docker.com> <18033717+Benehiko@users.noreply.github.com>
Albin Kerouanton <albinker@gmail.com>
Albin Kerouanton <albinker@gmail.com> <557933+akerouanton@users.noreply.github.com>
Albin Kerouanton <albinker@gmail.com> <albin@akerouanton.name>
Aleksa Sarai <asarai@suse.de>
Aleksa Sarai <asarai@suse.de> <asarai@suse.com>
@ -91,7 +88,6 @@ Brian Goff <cpuguy83@gmail.com>
Brian Goff <cpuguy83@gmail.com> <bgoff@cpuguy83-mbp.home>
Brian Goff <cpuguy83@gmail.com> <bgoff@cpuguy83-mbp.local>
Brian Tracy <brian.tracy33@gmail.com>
Calvin Liu <flycalvin@qq.com>
Carlos de Paula <me@carlosedp.com>
Chad Faragher <wyckster@hotmail.com>
Chander Govindarajan <chandergovind@gmail.com>
@ -258,7 +254,6 @@ Jessica Frazelle <jess@oxide.computer> <jessfraz@google.com>
Jessica Frazelle <jess@oxide.computer> <jfrazelle@users.noreply.github.com>
Jessica Frazelle <jess@oxide.computer> <me@jessfraz.com>
Jessica Frazelle <jess@oxide.computer> <princess@docker.com>
Jim Chen <njucjc@gmail.com>
Jim Galasyn <jim.galasyn@docker.com>
Jiuyue Ma <majiuyue@huawei.com>
Joey Geiger <jgeiger@gmail.com>
@ -274,8 +269,6 @@ John Howard <github@lowenna.com> <jhowardmsft@users.noreply.github.com>
John Howard <github@lowenna.com> <John.Howard@microsoft.com>
John Howard <github@lowenna.com> <john.howard@microsoft.com>
John Stephens <johnstep@docker.com> <johnstep@users.noreply.github.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com> <jonathan.sternberg@docker.com>
Jordan Arentsen <blissdev@gmail.com>
Jordan Jennings <jjn2009@gmail.com> <jjn2009@users.noreply.github.com>
Jorit Kleine-Möllhoff <joppich@bricknet.de> <joppich@users.noreply.github.com>
@ -451,7 +444,6 @@ Roch Feuillade <roch.feuillade@pandobac.com>
Roch Feuillade <roch.feuillade@pandobac.com> <46478807+rochfeu@users.noreply.github.com>
Roman Dudin <katrmr@gmail.com> <decadent@users.noreply.github.com>
Ross Boucher <rboucher@gmail.com>
Rui JingAn <quiterace@gmail.com>
Runshen Zhu <runshen.zhu@gmail.com>
Ryan Stelly <ryan.stelly@live.com>
Sakeven Jiang <jc5930@sina.cn>
@ -532,8 +524,6 @@ Tim Bart <tim@fewagainstmany.com>
Tim Bosse <taim@bosboot.org> <maztaim@users.noreply.github.com>
Tim Ruffles <oi@truffles.me.uk> <timruffles@googlemail.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
Tim Welsh <timothy.welsh@docker.com>
Tim Welsh <timothy.welsh@docker.com> <84401379+twelsh-aw@users.noreply.github.com>
Tim Zju <21651152@zju.edu.cn>
Timothy Hobbs <timothyhobbs@seznam.cz>
Toli Kuznets <toli@docker.com>

20
AUTHORS
View File

@ -26,7 +26,6 @@ Akhil Mohan <akhil.mohan@mayadata.io>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Akim Demaille <akim.demaille@docker.com>
Alan Thompson <cloojure@gmail.com>
Alano Terblanche <alano.terblanche@docker.com>
Albert Callarisa <shark234@gmail.com>
Alberto Roura <mail@albertoroura.com>
Albin Kerouanton <albinker@gmail.com>
@ -66,7 +65,6 @@ Andrew Hsu <andrewhsu@docker.com>
Andrew Macpherson <hopscotch23@gmail.com>
Andrew McDonnell <bugs@andrewmcdonnell.net>
Andrew Po <absourd.noise@gmail.com>
Andrew-Zipperer <atzipperer@gmail.com>
Andrey Petrov <andrey.petrov@shazow.net>
Andrii Berehuliak <berkusandrew@gmail.com>
André Martins <aanm90@gmail.com>
@ -126,13 +124,11 @@ Bryan Bess <squarejaw@bsbess.com>
Bryan Boreham <bjboreham@gmail.com>
Bryan Murphy <bmurphy1976@gmail.com>
bryfry <bryon.fryer@gmail.com>
Calvin Liu <flycalvin@qq.com>
Cameron Spear <cameronspear@gmail.com>
Cao Weiwei <cao.weiwei30@zte.com.cn>
Carlo Mion <mion00@gmail.com>
Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos de Paula <me@carlosedp.com>
Casey Korver <casey@korver.dev>
Ce Gao <ce.gao@outlook.com>
Cedric Davies <cedricda@microsoft.com>
Cezar Sa Espinola <cezarsa@gmail.com>
@ -164,8 +160,6 @@ Christophe Vidal <kriss@krizalys.com>
Christopher Biscardi <biscarch@sketcht.com>
Christopher Crone <christopher.crone@docker.com>
Christopher Jones <tophj@linux.vnet.ibm.com>
Christopher Petito <47751006+krissetto@users.noreply.github.com>
Christopher Petito <chrisjpetito@gmail.com>
Christopher Svensson <stoffus@stoffus.com>
Christy Norman <christy@linux.vnet.ibm.com>
Chun Chen <ramichen@tencent.com>
@ -218,7 +212,6 @@ David Cramer <davcrame@cisco.com>
David Dooling <dooling@gmail.com>
David Gageot <david@gageot.net>
David Karlsson <david.karlsson@docker.com>
David le Blanc <systemmonkey42@users.noreply.github.com>
David Lechner <david@lechnology.com>
David Scott <dave@recoil.org>
David Sheets <dsheets@docker.com>
@ -305,7 +298,6 @@ Gang Qiao <qiaohai8866@gmail.com>
Gary Schaetz <gary@schaetzkc.com>
Genki Takiuchi <genki@s21g.com>
George MacRorie <gmacr31@gmail.com>
George Margaritis <gmargaritis@protonmail.com>
George Xie <georgexsh@gmail.com>
Gianluca Borello <g.borello@gmail.com>
Gildas Cuisinier <gildas.cuisinier@gcuisinier.net>
@ -314,7 +306,6 @@ Gleb Stsenov <gleb.stsenov@gmail.com>
Goksu Toprak <goksu.toprak@docker.com>
Gou Rao <gou@portworx.com>
Govind Rai <raigovind93@gmail.com>
Grace Choi <grace.54109@gmail.com>
Graeme Wiebe <graeme.wiebe@gmail.com>
Grant Reaber <grant.reaber@gmail.com>
Greg Pflaum <gpflaum@users.noreply.github.com>
@ -395,7 +386,6 @@ Jezeniel Zapanta <jpzapanta22@gmail.com>
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
Jie Luo <luo612@zju.edu.cn>
Jilles Oldenbeuving <ojilles@gmail.com>
Jim Chen <njucjc@gmail.com>
Jim Galasyn <jim.galasyn@docker.com>
Jim Lin <b04705003@ntu.edu.tw>
Jimmy Leger <jimmy.leger@gmail.com>
@ -426,7 +416,6 @@ John Willis <john.willis@docker.com>
Jon Johnson <jonjohnson@google.com>
Jon Zeolla <zeolla@gmail.com>
Jonatas Baldin <jonatas.baldin@gmail.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com>
Jonathan Boulle <jonathanboulle@gmail.com>
Jonathan Lee <jonjohn1232009@gmail.com>
Jonathan Lomas <jonathan@floatinglomas.ca>
@ -481,7 +470,6 @@ Kevin Woblick <mail@kovah.de>
khaled souf <khaled.souf@gmail.com>
Kim Eik <kim@heldig.org>
Kir Kolyshkin <kolyshkin@gmail.com>
Kirill A. Korinsky <kirill@korins.ky>
Kotaro Yoshimatsu <kotaro.yoshimatsu@gmail.com>
Krasi Georgiev <krasi@vip-consult.solutions>
Kris-Mikael Krister <krismikael@protonmail.com>
@ -542,7 +530,6 @@ Marco Vedovati <mvedovati@suse.com>
Marcus Martins <marcus@docker.com>
Marianna Tessel <mtesselh@gmail.com>
Marius Ileana <marius.ileana@gmail.com>
Marius Meschter <marius@meschter.me>
Marius Sturm <marius@graylog.com>
Mark Oates <fl0yd@me.com>
Marsh Macy <marsma@microsoft.com>
@ -551,7 +538,6 @@ Mary Anthony <mary.anthony@docker.com>
Mason Fish <mason.fish@docker.com>
Mason Malone <mason.malone@gmail.com>
Mateusz Major <apkd@users.noreply.github.com>
Mathias Duedahl <64321057+Lussebullen@users.noreply.github.com>
Mathieu Champlon <mathieu.champlon@docker.com>
Mathieu Rollet <matletix@gmail.com>
Matt Gucci <matt9ucci@gmail.com>
@ -561,7 +547,6 @@ Matthew Heon <mheon@redhat.com>
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
Mauro Porras P <mauroporrasp@gmail.com>
Max Shytikov <mshytikov@gmail.com>
Max-Julian Pogner <max-julian@pogner.at>
Maxime Petazzoni <max@signalfuse.com>
Maximillian Fan Xavier <maximillianfx@gmail.com>
Mei ChunTao <mei.chuntao@zte.com.cn>
@ -625,7 +610,6 @@ Nathan McCauley <nathan.mccauley@docker.com>
Neil Peterson <neilpeterson@outlook.com>
Nick Adcock <nick.adcock@docker.com>
Nick Santos <nick.santos@docker.com>
Nick Sieger <nick@nicksieger.com>
Nico Stapelbroek <nstapelbroek@gmail.com>
Nicola Kabar <nicolaka@gmail.com>
Nicolas Borboën <ponsfrilus@gmail.com>
@ -720,7 +704,6 @@ Rory Hunter <roryhunter2@gmail.com>
Ross Boucher <rboucher@gmail.com>
Rubens Figueiredo <r.figueiredo.52@gmail.com>
Rui Cao <ruicao@alauda.io>
Rui JingAn <quiterace@gmail.com>
Ryan Belgrave <rmb1993@gmail.com>
Ryan Detzel <ryan.detzel@gmail.com>
Ryan Stelly <ryan.stelly@live.com>
@ -814,7 +797,6 @@ Tim Hockin <thockin@google.com>
Tim Sampson <tim@sampson.fi>
Tim Smith <timbot@google.com>
Tim Waugh <twaugh@redhat.com>
Tim Welsh <timothy.welsh@docker.com>
Tim Wraight <tim.wraight@tangentlabs.co.uk>
timfeirg <kkcocogogo@gmail.com>
Timothy Hobbs <timothyhobbs@seznam.cz>
@ -898,11 +880,9 @@ Zhang Wei <zhangwei555@huawei.com>
Zhang Wentao <zhangwentao234@huawei.com>
ZhangHang <stevezhang2014@gmail.com>
zhenghenghuo <zhenghenghuo@zju.edu.cn>
Zhiwei Liang <zliang@akamai.com>
Zhou Hao <zhouhao@cn.fujitsu.com>
Zhoulin Xie <zhoulin.xie@daocloud.io>
Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Zhuo Zhi <h.dwwwwww@gmail.com>
Álex González <agonzalezro@gmail.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
Átila Camurça Alves <camurca.home@gmail.com>

View File

@ -16,9 +16,9 @@ start participating.
## Reporting security issues
The Docker maintainers take security seriously. If you discover a security
issue, bring it to their attention right away!
issue, please bring it to their attention right away!
**DO NOT** file a public issue, instead send your report privately to
Please **DO NOT** file a public issue, instead send your report privately to
[security@docker.com](mailto:security@docker.com).
Security reports are greatly appreciated and we will publicly thank you for it.
@ -39,7 +39,7 @@ If you find a match, you can use the "subscribe" button to get notified on
updates. Do *not* leave random "+1" or "I have this too" comments, as they
only clutter the discussion, and don't help resolving it. However, if you
have ways to reproduce the issue or have additional information that may help
resolving the issue, leave a comment.
resolving the issue, please leave a comment.
When reporting issues, always include:
@ -166,10 +166,10 @@ Include an issue reference like `Closes #XXXX` or `Fixes #XXXX` in the pull requ
description that close an issue. Including references automatically closes the issue
on a merge.
Do not add yourself to the `AUTHORS` file, as it is regenerated regularly
Please do not add yourself to the `AUTHORS` file, as it is regenerated regularly
from the Git history.
See the [Coding Style](#coding-style) for further guidelines.
Please see the [Coding Style](#coding-style) for further guidelines.
### Merge approval
@ -269,8 +269,8 @@ guidelines for the community as a whole:
* Stay on topic: Make sure that you are posting to the correct channel and
avoid off-topic discussions. Remember when you update an issue or respond
to an email you are potentially sending to a large number of people. Consider
this before you update. Also remember that nobody likes spam.
to an email you are potentially sending to a large number of people. Please
consider this before you update. Also remember that nobody likes spam.
* Don't send email to the maintainers: There's no need to send email to the
maintainers to ask them to investigate an issue or to take a look at a

View File

@ -4,12 +4,12 @@ ARG BASE_VARIANT=alpine
ARG ALPINE_VERSION=3.20
ARG BASE_DEBIAN_DISTRO=bookworm
ARG GO_VERSION=1.22.7
ARG XX_VERSION=1.5.0
ARG GO_VERSION=1.21.11
ARG XX_VERSION=1.4.0
ARG GOVERSIONINFO_VERSION=v1.3.0
ARG GOTESTSUM_VERSION=v1.10.0
ARG BUILDX_VERSION=0.16.1
ARG COMPOSE_VERSION=v2.29.0
ARG BUILDX_VERSION=0.12.1
ARG COMPOSE_VERSION=v2.24.3
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@ -63,6 +63,7 @@ ARG PACKAGER_NAME
COPY --link --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
RUN --mount=type=bind,target=.,ro \
--mount=type=cache,target=/root/.cache \
--mount=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
--mount=type=tmpfs,target=cli/winresources \
# override the default behavior of go with xx-go
xx-go --wrap && \
@ -88,6 +89,7 @@ ARG GO_STRIP
ARG CGO_ENABLED
ARG VERSION
RUN --mount=ro --mount=type=cache,target=/root/.cache \
--mount=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
xx-go --wrap && \
TARGET=/out ./scripts/build/plugins e2e/cli-plugins/plugins/*

View File

@ -86,16 +86,6 @@ mod-outdated: ## check outdated dependencies
authors: ## generate AUTHORS file from git history
scripts/docs/generate-authors.sh
.PHONY: completion
completion: binary
completion: /etc/bash_completion.d/docker
completion: ## generate and install the completion scripts
.PHONY: /etc/bash_completion.d/docker
/etc/bash_completion.d/docker: ## generate and install the bash-completion script
mkdir -p /etc/bash_completion.d
docker completion bash > /etc/bash_completion.d/docker
.PHONY: manpages
manpages: ## generate man pages from go source and markdown
scripts/docs/generate-man.sh

2
NOTICE
View File

@ -14,6 +14,6 @@ United States and other governments.
It is your responsibility to ensure that your use and/or transfer does not
violate applicable laws.
For more information, see https://www.bis.doc.gov
For more information, please see https://www.bis.doc.gov
See also https://www.apache.org/dev/crypto.html and/or seek legal counsel.

View File

@ -67,7 +67,7 @@ make -f docker.Makefile shell
## Legal
*Brought to you courtesy of our legal counsel. For more context,
see the [NOTICE](https://github.com/docker/cli/blob/master/NOTICE) document in this repo.*
please see the [NOTICE](https://github.com/docker/cli/blob/master/NOTICE) document in this repo.*
Use and transfer of Docker may be subject to certain restrictions by the
United States and other governments.
@ -75,7 +75,7 @@ United States and other governments.
It is your responsibility to ensure that your use and/or transfer does not
violate applicable laws.
For more information, see https://www.bis.doc.gov
For more information, please see https://www.bis.doc.gov
## Licensing

View File

@ -1 +1 @@
27.0.1-dev
25.0.0-dev

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package manager

View File

@ -2,7 +2,7 @@ package manager
import (
"encoding/json"
"errors"
"fmt"
"testing"
"gotest.tools/v3/assert"
@ -13,7 +13,7 @@ func TestPluginError(t *testing.T) {
err := NewPluginError("new error")
assert.Check(t, is.Error(err, "new error"))
inner := errors.New("testing")
inner := fmt.Errorf("testing")
err = wrapAsPluginError(inner, "wrapping")
assert.Check(t, is.Error(err, "wrapping: testing"))
assert.Check(t, is.ErrorIs(err, inner))

View File

@ -1,7 +1,6 @@
package manager
import (
"context"
"encoding/json"
"strings"
@ -29,36 +28,29 @@ type HookPluginData struct {
// a main CLI command was executed. It calls the hook subcommand for all
// present CLI plugins that declare support for hooks in their metadata and
// parses/prints their responses.
func RunCLICommandHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
func RunCLICommandHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
commandName := strings.TrimPrefix(subCommand.CommandPath(), rootCmd.Name()+" ")
flags := getCommandFlags(subCommand)
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, cmdErrorMessage)
runHooks(dockerCli, rootCmd, subCommand, commandName, flags, cmdErrorMessage)
}
// RunPluginHooks is the entrypoint for the hooks execution flow
// after a plugin command was just executed by the CLI.
func RunPluginHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, args []string) {
func RunPluginHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, args []string) {
commandName := strings.Join(args, " ")
flags := getNaiveFlags(args)
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, "")
runHooks(dockerCli, rootCmd, subCommand, commandName, flags, "")
}
func runHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
nextSteps := invokeAndCollectHooks(ctx, dockerCli, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
func runHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
nextSteps := invokeAndCollectHooks(dockerCli, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
hooks.PrintNextSteps(dockerCli.Err(), nextSteps)
}
func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
// check if the context was cancelled before invoking hooks
select {
case <-ctx.Done():
return nil
default:
}
func invokeAndCollectHooks(dockerCli command.Cli, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
pluginsCfg := dockerCli.ConfigFile().Plugins
if pluginsCfg == nil {
return nil
@ -76,7 +68,7 @@ func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd,
continue
}
hookReturn, err := p.RunHook(ctx, HookPluginData{
hookReturn, err := p.RunHook(HookPluginData{
RootCmd: match,
Flags: flags,
CommandError: cmdErrorMessage,

View File

@ -49,16 +49,6 @@ func IsNotFound(err error) bool {
return ok
}
// getPluginDirs returns the platform-specific locations to search for plugins
// in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs [config.Path] (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs.
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
func getPluginDirs(cfg *configfile.ConfigFile) ([]string, error) {
var pluginDirs []string

View File

@ -2,19 +2,7 @@
package manager
// defaultSystemPluginDirs are the platform-specific locations to search
// for plugins in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs config-directory (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs (as defined below).
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
var defaultSystemPluginDirs = []string{
"/usr/local/lib/docker/cli-plugins",
"/usr/local/libexec/docker/cli-plugins",
"/usr/lib/docker/cli-plugins",
"/usr/libexec/docker/cli-plugins",
"/usr/local/lib/docker/cli-plugins", "/usr/local/libexec/docker/cli-plugins",
"/usr/lib/docker/cli-plugins", "/usr/libexec/docker/cli-plugins",
}

View File

@ -5,16 +5,6 @@ import (
"path/filepath"
)
// defaultSystemPluginDirs are the platform-specific locations to search
// for plugins in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs config-directory (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs (as defined below).
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
var defaultSystemPluginDirs = []string{
filepath.Join(os.Getenv("ProgramData"), "Docker", "cli-plugins"),
filepath.Join(os.Getenv("ProgramFiles"), "Docker", "cli-plugins"),

View File

@ -1,7 +1,6 @@
package manager
import (
"context"
"encoding/json"
"os"
"os/exec"
@ -106,13 +105,13 @@ func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
// RunHook executes the plugin's hooks command
// and returns its unprocessed output.
func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte, error) {
func (p *Plugin) RunHook(hookData HookPluginData) ([]byte, error) {
hDataBytes, err := json.Marshal(hookData)
if err != nil {
return nil, wrapAsPluginError(err, "failed to marshall hook data")
}
pCmd := exec.CommandContext(ctx, p.Path, p.Name, HookSubcommandName, string(hDataBytes))
pCmd := exec.Command(p.Path, p.Name, HookSubcommandName, string(hDataBytes))
pCmd.Env = os.Environ()
pCmd.Env = append(pCmd.Env, ReexecEnvvar+"="+os.Args[0])
hookCmdOutput, err := pCmd.Output()

View File

@ -36,7 +36,13 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
var err error
persistentPreRunOnce.Do(func() {
ctx, cancel := context.WithCancel(cmd.Context())
cmdContext := cmd.Context()
// TODO: revisit and make sure this check makes sense
// see: https://github.com/docker/cli/pull/4599#discussion_r1422487271
if cmdContext == nil {
cmdContext = context.TODO()
}
ctx, cancel := context.WithCancel(cmdContext)
cmd.SetContext(ctx)
// Set up the context to cancel based on signalling via CLI socket.
socket.ConnectAndWait(cancel)
@ -45,7 +51,6 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
if os.Getenv("DOCKER_CLI_PLUGIN_USE_DIAL_STDIO") != "" {
opts = append(opts, withPluginClientConn(plugin.Name()))
}
opts = append(opts, command.WithEnableGlobalMeterProvider(), command.WithEnableGlobalTracerProvider())
err = tcmd.Initialize(opts...)
ogRunE := cmd.RunE
if ogRunE == nil {

View File

@ -9,8 +9,6 @@ import (
"os"
"runtime"
"sync"
"github.com/sirupsen/logrus"
)
// EnvKey represents the well-known environment variable used to pass the
@ -32,7 +30,6 @@ func NewPluginServer(h func(net.Conn)) (*PluginServer, error) {
if err != nil {
return nil, err
}
logrus.Trace("Plugin server listening on ", l.Addr())
if h == nil {
h = func(net.Conn) {}
@ -95,10 +92,6 @@ func (pl *PluginServer) Addr() net.Addr {
//
// The error value is that of the underlying [net.Listner.Close] call.
func (pl *PluginServer) Close() error {
if pl == nil {
return nil
}
logrus.Trace("Closing plugin server")
// Close connections first to ensure the connections get io.EOF instead
// of a connection reset.
pl.closeAllConns()
@ -114,10 +107,6 @@ func (pl *PluginServer) closeAllConns() {
pl.mu.Lock()
defer pl.mu.Unlock()
if pl.closed {
return
}
// Prevent new connections from being accepted.
pl.closed = true

View File

@ -117,18 +117,6 @@ func TestPluginServer(t *testing.T) {
assert.NilError(t, err, "failed to dial returned server")
checkDirNoNewPluginServer(t)
})
t.Run("does not panic on Close if server is nil", func(t *testing.T) {
var srv *PluginServer
defer func() {
if r := recover(); r != nil {
t.Errorf("panicked on Close")
}
}()
err := srv.Close()
assert.NilError(t, err)
})
}
func checkDirNoNewPluginServer(t *testing.T) {

View File

@ -54,7 +54,7 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *c
rootCmd.SetHelpCommand(helpCommand)
rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "use --help")
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
rootCmd.PersistentFlags().Lookup("help").Hidden = true
rootCmd.Annotations = map[string]string{

View File

@ -3,7 +3,6 @@ package builder
import (
"context"
"errors"
"io"
"testing"
"github.com/docker/cli/internal/test"
@ -20,7 +19,5 @@ func TestBuilderPromptTermination(t *testing.T) {
},
})
cmd := NewPruneCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -42,7 +42,6 @@ func TestCheckpointCreateErrors(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -42,7 +42,6 @@ func TestCheckpointListErrors(t *testing.T) {
cmd := newListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -41,7 +41,6 @@ func TestCheckpointRemoveErrors(t *testing.T) {
cmd := newRemoveCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package command
@ -44,7 +44,7 @@ const defaultInitTimeout = 2 * time.Second
type Streams interface {
In() *streams.In
Out() *streams.Out
Err() *streams.Out
Err() io.Writer
}
// Cli represents the docker command line client.
@ -75,7 +75,7 @@ type DockerCli struct {
options *cliflags.ClientOptions
in *streams.In
out *streams.Out
err *streams.Out
err io.Writer
client client.APIClient
serverInfo ServerInfo
contentTrust bool
@ -92,8 +92,6 @@ type DockerCli struct {
// this may be replaced by explicitly passing a context to functions that
// need it.
baseCtx context.Context
enableGlobalMeter, enableGlobalTracer bool
}
// DefaultVersion returns api.defaultVersion.
@ -126,7 +124,7 @@ func (cli *DockerCli) Out() *streams.Out {
}
// Err returns the writer used for stderr
func (cli *DockerCli) Err() *streams.Out {
func (cli *DockerCli) Err() io.Writer {
return cli.err
}
@ -186,18 +184,9 @@ func (cli *DockerCli) BuildKitEnabled() (bool, error) {
if _, ok := aliasMap["builder"]; ok {
return true, nil
}
si := cli.ServerInfo()
if si.BuildkitVersion == types.BuilderBuildKit {
// The daemon advertised BuildKit as the preferred builder; this may
// be either a Linux daemon or a Windows daemon with experimental
// BuildKit support enabled.
return true, nil
}
// otherwise, assume BuildKit is enabled for Linux, but disabled for
// Windows / WCOW, which does not yet support BuildKit by default.
return si.OSType != "windows", nil
// otherwise, assume BuildKit is enabled but
// not if wcow reported from server side
return cli.ServerInfo().OSType != "windows", nil
}
// HooksEnabled returns whether plugin hooks are enabled.
@ -286,12 +275,8 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
}
// TODO(krissetto): pass ctx to the funcs instead of using this
if cli.enableGlobalMeter {
cli.createGlobalMeterProvider(cli.baseCtx)
}
if cli.enableGlobalTracer {
cli.createGlobalTracerProvider(cli.baseCtx)
}
cli.createGlobalMeterProvider(cli.baseCtx)
cli.createGlobalTracerProvider(cli.baseCtx)
return nil
}
@ -324,13 +309,13 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
if len(configFile.HTTPHeaders) > 0 {
opts = append(opts, client.WithHTTPHeaders(configFile.HTTPHeaders))
}
opts = append(opts, withCustomHeadersFromEnv(), client.WithUserAgent(UserAgent()))
opts = append(opts, client.WithUserAgent(UserAgent()))
return client.NewClientWithOpts(opts...)
}
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
if s == nil {
return docker.Endpoint{}, errors.New("no context store initialized")
return docker.Endpoint{}, fmt.Errorf("no context store initialized")
}
ctxMeta, err := s.GetMetadata(contextName)
if err != nil {
@ -561,7 +546,7 @@ func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error
case 1:
host = hosts[0]
default:
return "", errors.New("Specify only one -H")
return "", errors.New("Please specify only one -H")
}
return dopts.ParseHost(tlsOptions != nil, host)

View File

@ -2,18 +2,13 @@ package command
import (
"context"
"encoding/csv"
"io"
"net/http"
"os"
"strconv"
"strings"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
"github.com/moby/term"
"github.com/pkg/errors"
)
// CLIOption is a functional argument to apply options to a [DockerCli]. These
@ -28,7 +23,7 @@ func WithStandardStreams() CLIOption {
stdin, stdout, stderr := term.StdStreams()
cli.in = streams.NewIn(stdin)
cli.out = streams.NewOut(stdout)
cli.err = streams.NewOut(stderr)
cli.err = stderr
return nil
}
}
@ -45,9 +40,8 @@ func WithBaseContext(ctx context.Context) CLIOption {
// WithCombinedStreams uses the same stream for the output and error streams.
func WithCombinedStreams(combined io.Writer) CLIOption {
return func(cli *DockerCli) error {
s := streams.NewOut(combined)
cli.out = s
cli.err = s
cli.out = streams.NewOut(combined)
cli.err = combined
return nil
}
}
@ -71,7 +65,7 @@ func WithOutputStream(out io.Writer) CLIOption {
// WithErrorStream sets a cli error stream.
func WithErrorStream(err io.Writer) CLIOption {
return func(cli *DockerCli) error {
cli.err = streams.NewOut(err)
cli.err = err
return nil
}
}
@ -113,107 +107,3 @@ func WithAPIClient(c client.APIClient) CLIOption {
return nil
}
}
// envOverrideHTTPHeaders is the name of the environment-variable that can be
// used to set custom HTTP headers to be sent by the client. This environment
// variable is the equivalent to the HttpHeaders field in the configuration
// file.
//
// WARNING: If both config and environment-variable are set, the environment
// variable currently overrides all headers set in the configuration file.
// This behavior may change in a future update, as we are considering the
// environment variable to be appending to existing headers (and to only
// override headers with the same name).
//
// While this env-var allows for custom headers to be set, it does not allow
// for built-in headers (such as "User-Agent", if set) to be overridden.
// Also see [client.WithHTTPHeaders] and [client.WithUserAgent].
//
// This environment variable can be used in situations where headers must be
// set for a specific invocation of the CLI, but should not be set by default,
// and therefore cannot be set in the config-file.
//
// envOverrideHTTPHeaders accepts a comma-separated (CSV) list of key=value pairs,
// where key must be a non-empty, valid MIME header format. Whitespaces surrounding
// the key are trimmed, and the key is normalised. Whitespaces in values are
// preserved, but "key=value" pairs with an empty value (e.g. "key=") are ignored.
// Tuples without a "=" produce an error.
//
// It follows CSV rules for escaping, allowing "key=value" pairs to be quoted
// if they must contain commas, which allows for multiple values for a single
// header to be set. If a key is repeated in the list, later values override
// prior values.
//
// For example, the following value:
//
// one=one-value,"two=two,value","three= a value with whitespace ",four=,five=five=one,five=five-two
//
// Produces four headers (four is omitted as it has an empty value set):
//
// - one (value is "one-value")
// - two (value is "two,value")
// - three (value is " a value with whitespace ")
// - five (value is "five-two", the later value has overridden the prior value)
const envOverrideHTTPHeaders = "DOCKER_CUSTOM_HEADERS"
// withCustomHeadersFromEnv overriding custom HTTP headers to be sent by the
// client through the [envOverrideHTTPHeaders] environment-variable. This
// environment variable is the equivalent to the HttpHeaders field in the
// configuration file.
//
// WARNING: If both config and environment-variable are set, the environment-
// variable currently overrides all headers set in the configuration file.
// This behavior may change in a future update, as we are considering the
// environment-variable to be appending to existing headers (and to only
// override headers with the same name).
//
// TODO(thaJeztah): this is a client Option, and should be moved to the client. It is non-exported for that reason.
func withCustomHeadersFromEnv() client.Opt {
return func(apiClient *client.Client) error {
value := os.Getenv(envOverrideHTTPHeaders)
if value == "" {
return nil
}
csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read()
if err != nil {
return errdefs.InvalidParameter(errors.Errorf("failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs", envOverrideHTTPHeaders))
}
if len(fields) == 0 {
return nil
}
env := map[string]string{}
for _, kv := range fields {
k, v, hasValue := strings.Cut(kv, "=")
// Only strip whitespace in keys; preserve whitespace in values.
k = strings.TrimSpace(k)
if k == "" {
return errdefs.InvalidParameter(errors.Errorf(`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`, envOverrideHTTPHeaders, kv))
}
// We don't currently allow empty key=value pairs, and produce an error.
// This is something we could allow in future (e.g. to read value
// from an environment variable with the same name). In the meantime,
// produce an error to prevent users from depending on this.
if !hasValue {
return errdefs.InvalidParameter(errors.Errorf(`failed to set custom headers from %s environment variable: missing "=" in key=value pair: '%s'`, envOverrideHTTPHeaders, kv))
}
env[http.CanonicalHeaderKey(k)] = v
}
if len(env) == 0 {
// We should probably not hit this case, as we don't skip values
// (only return errors), but we don't want to discard existing
// headers with an empty set.
return nil
}
// TODO(thaJeztah): add a client.WithExtraHTTPHeaders() function to allow these headers to be _added_ to existing ones, instead of _replacing_
// see https://github.com/docker/cli/pull/5098#issuecomment-2147403871 (when updating, also update the WARNING in the function and env-var GoDoc)
return client.WithHTTPHeaders(env)(apiClient)
}
}

View File

@ -18,7 +18,6 @@ import (
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
@ -87,41 +86,6 @@ func TestNewAPIClientFromFlagsWithCustomHeaders(t *testing.T) {
assert.DeepEqual(t, received, expectedHeaders)
}
func TestNewAPIClientFromFlagsWithCustomHeadersFromEnv(t *testing.T) {
var received http.Header
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
received = r.Header.Clone()
_, _ = w.Write([]byte("OK"))
}))
defer ts.Close()
host := strings.Replace(ts.URL, "http://", "tcp://", 1)
opts := &flags.ClientOptions{Hosts: []string{host}}
configFile := &configfile.ConfigFile{
HTTPHeaders: map[string]string{
"My-Header": "Custom-Value from config-file",
},
}
// envOverrideHTTPHeaders should override the HTTPHeaders from the config-file,
// so "My-Header" should not be present.
t.Setenv(envOverrideHTTPHeaders, `one=one-value,"two=two,value",three=,four=four-value,four=four-value-override`)
apiClient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
assert.Equal(t, apiClient.DaemonHost(), host)
assert.Equal(t, apiClient.ClientVersion(), api.DefaultVersion)
expectedHeaders := http.Header{
"One": []string{"one-value"},
"Two": []string{"two,value"},
"Three": []string{""},
"Four": []string{"four-value-override"},
"User-Agent": []string{UserAgent()},
}
_, err = apiClient.Ping(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, received, expectedHeaders)
}
func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
customVersion := "v3.3.3"
t.Setenv("DOCKER_API_VERSION", customVersion)
@ -228,7 +192,7 @@ func TestInitializeFromClientHangs(t *testing.T) {
ts.Start()
defer ts.Close()
opts := &flags.ClientOptions{Hosts: []string{"unix://" + socket}}
opts := &flags.ClientOptions{Hosts: []string{fmt.Sprintf("unix://%s", socket)}}
configFile := &configfile.ConfigFile{}
apiClient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
@ -289,7 +253,7 @@ func TestExperimentalCLI(t *testing.T) {
},
}
cli := &DockerCli{client: apiclient, err: streams.NewOut(os.Stderr)}
cli := &DockerCli{client: apiclient, err: os.Stderr}
config.SetDir(dir.Path())
err := cli.Initialize(flags.NewClientOptions())
assert.NilError(t, err)

View File

@ -2,41 +2,29 @@ package completion
import (
"os"
"strings"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
"github.com/docker/docker/client"
"github.com/spf13/cobra"
)
// ValidArgsFn a function to be used by cobra command as `ValidArgsFunction` to offer command line completion
type ValidArgsFn func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
// APIClientProvider provides a method to get an [client.APIClient], initializing
// it if needed.
//
// It's a smaller interface than [command.Cli], and used in situations where an
// APIClient is needed, but we want to postpone initializing the client until
// it's used.
type APIClientProvider interface {
Client() client.APIClient
}
// ImageNames offers completion for images present within the local store
func ImageNames(dockerCLI APIClientProvider) ValidArgsFn {
func ImageNames(dockerCli command.Cli) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCLI.Client().ImageList(cmd.Context(), image.ListOptions{})
list, err := dockerCli.Client().ImageList(cmd.Context(), image.ListOptions{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
var names []string
for _, img := range list {
names = append(names, img.RepoTags...)
for _, image := range list {
names = append(names, image.RepoTags...)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
@ -45,9 +33,9 @@ func ImageNames(dockerCLI APIClientProvider) ValidArgsFn {
// ContainerNames offers completion for container names and IDs
// By default, only names are returned.
// Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs.
func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(types.Container) bool) ValidArgsFn {
func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Container) bool) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCLI.Client().ContainerList(cmd.Context(), container.ListOptions{
list, err := dockerCli.Client().ContainerList(cmd.Context(), container.ListOptions{
All: all,
})
if err != nil {
@ -57,10 +45,10 @@ func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(types
showContainerIDs := os.Getenv("DOCKER_COMPLETION_SHOW_CONTAINER_IDS") == "yes"
var names []string
for _, ctr := range list {
for _, container := range list {
skip := false
for _, fn := range filters {
if !fn(ctr) {
if !fn(container) {
skip = true
break
}
@ -69,18 +57,18 @@ func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(types
continue
}
if showContainerIDs {
names = append(names, ctr.ID)
names = append(names, container.ID)
}
names = append(names, formatter.StripNamePrefix(ctr.Names)...)
names = append(names, formatter.StripNamePrefix(container.Names)...)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
}
// VolumeNames offers completion for volumes
func VolumeNames(dockerCLI APIClientProvider) ValidArgsFn {
func VolumeNames(dockerCli command.Cli) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCLI.Client().VolumeList(cmd.Context(), volume.ListOptions{})
list, err := dockerCli.Client().VolumeList(cmd.Context(), volume.ListOptions{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
@ -93,56 +81,21 @@ func VolumeNames(dockerCLI APIClientProvider) ValidArgsFn {
}
// NetworkNames offers completion for networks
func NetworkNames(dockerCLI APIClientProvider) ValidArgsFn {
func NetworkNames(dockerCli command.Cli) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCLI.Client().NetworkList(cmd.Context(), network.ListOptions{})
list, err := dockerCli.Client().NetworkList(cmd.Context(), types.NetworkListOptions{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
var names []string
for _, nw := range list {
names = append(names, nw.Name)
for _, network := range list {
names = append(names, network.Name)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
}
// EnvVarNames offers completion for environment-variable names. This
// completion can be used for "--env" and "--build-arg" flags, which
// allow obtaining the value of the given environment-variable if present
// in the local environment, so we only should complete the names of the
// environment variables, and not their value. This also prevents the
// completion script from printing values of environment variables
// containing sensitive values.
//
// For example;
//
// export MY_VAR=hello
// docker run --rm --env MY_VAR alpine printenv MY_VAR
// hello
func EnvVarNames(_ *cobra.Command, _ []string, _ string) (names []string, _ cobra.ShellCompDirective) {
envs := os.Environ()
names = make([]string, 0, len(envs))
for _, env := range envs {
name, _, _ := strings.Cut(env, "=")
names = append(names, name)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
// FromList offers completion for the given list of options.
func FromList(options ...string) ValidArgsFn {
return cobra.FixedCompletions(options, cobra.ShellCompDirectiveNoFileComp)
}
// FileNames is a convenience function to use [cobra.ShellCompDirectiveDefault],
// which indicates to let the shell perform its default behavior after
// completions have been provided.
func FileNames(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveDefault
}
// NoComplete is used for commands where there's no relevant completion
func NoComplete(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
func NoComplete(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
}

View File

@ -30,9 +30,9 @@ func NewConfigCommand(dockerCli command.Cli) *cobra.Command {
}
// completeNames offers completion for swarm configs
func completeNames(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
func completeNames(dockerCli command.Cli) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCLI.Client().ConfigList(cmd.Context(), types.ConfigListOptions{})
list, err := dockerCli.Client().ConfigList(cmd.Context(), types.ConfigListOptions{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}

View File

@ -43,18 +43,14 @@ func TestConfigCreateErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.expectedError, func(t *testing.T) {
cmd := newConfigCreateCommand(
test.NewFakeCli(&fakeClient{
configCreateFunc: tc.configCreateFunc,
}),
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
cmd := newConfigCreateCommand(
test.NewFakeCli(&fakeClient{
configCreateFunc: tc.configCreateFunc,
}),
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package config

View File

@ -61,7 +61,6 @@ func TestConfigInspectErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -42,7 +42,6 @@ func TestConfigListErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -37,7 +37,6 @@ func TestConfigRemoveErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -75,7 +74,6 @@ func TestConfigRemoveContinueAfterError(t *testing.T) {
cmd := newConfigRemoveCommand(cli)
cmd.SetArgs(names)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.Error(t, cmd.Execute(), "error removing config: foo")
assert.Check(t, is.DeepEqual(names, removedConfigs))
}

View File

@ -2,6 +2,7 @@ package container
import (
"context"
"fmt"
"io"
"github.com/docker/cli/cli"
@ -73,8 +74,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
apiClient := dockerCLI.Client()
// request channel to wait for client
waitCtx := context.WithoutCancel(ctx)
resultC, errC := apiClient.ContainerWait(waitCtx, containerID, "")
resultC, errC := apiClient.ContainerWait(ctx, containerID, "")
c, err := inspectContainerAndCheckState(ctx, apiClient, containerID)
if err != nil {
@ -105,12 +105,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
if opts.Proxy && !c.Config.Tty {
sigc := notifyAllSignals()
// since we're explicitly setting up signal handling here, and the daemon will
// get notified independently of the clients ctx cancellation, we use this context
// but without cancellation to avoid ForwardAllSignals from returning
// before all signals are forwarded.
bgCtx := context.WithoutCancel(ctx)
go ForwardAllSignals(bgCtx, apiClient, containerID, sigc)
go ForwardAllSignals(ctx, apiClient, containerID, sigc)
defer signal.StopCatch(sigc)
}
@ -147,8 +142,7 @@ func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, o
detachKeys: options.DetachKeys,
}
// if the context was canceled, this was likely intentional and we shouldn't return an error
if err := streamer.stream(ctx); err != nil && !errors.Is(err, context.Canceled) {
if err := streamer.stream(ctx); err != nil {
return err
}
@ -159,15 +153,12 @@ func getExitStatus(errC <-chan error, resultC <-chan container.WaitResponse) err
select {
case result := <-resultC:
if result.Error != nil {
return errors.New(result.Error.Message)
return fmt.Errorf(result.Error.Message)
}
if result.StatusCode != 0 {
return cli.StatusError{StatusCode: int(result.StatusCode)}
}
case err := <-errC:
if errors.Is(err, context.Canceled) {
return nil
}
return err
}

View File

@ -1,7 +1,7 @@
package container
import (
"context"
"fmt"
"io"
"testing"
@ -70,19 +70,19 @@ func TestNewAttachCommandErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}))
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}))
cmd.SetOut(io.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestGetExitStatus(t *testing.T) {
expectedErr := errors.New("unexpected error")
var (
expectedErr = fmt.Errorf("unexpected error")
errC = make(chan error, 1)
resultC = make(chan container.WaitResponse, 1)
)
testcases := []struct {
result *container.WaitResponse
@ -110,24 +110,16 @@ func TestGetExitStatus(t *testing.T) {
},
expectedError: cli.StatusError{StatusCode: 15},
},
{
err: context.Canceled,
expectedError: nil,
},
}
for _, testcase := range testcases {
errC := make(chan error, 1)
resultC := make(chan container.WaitResponse, 1)
if testcase.err != nil {
errC <- testcase.err
}
if testcase.result != nil {
resultC <- *testcase.result
}
err := getExitStatus(errC, resultC)
if testcase.expectedError == nil {
assert.NilError(t, err)
} else {

View File

@ -17,8 +17,8 @@ import (
type fakeClient struct {
client.Client
inspectFunc func(string) (types.ContainerJSON, error)
execInspectFunc func(execID string) (container.ExecInspect, error)
execCreateFunc func(containerID string, options container.ExecOptions) (types.IDResponse, error)
execInspectFunc func(execID string) (types.ContainerExecInspect, error)
execCreateFunc func(containerID string, config types.ExecConfig) (types.IDResponse, error)
createContainerFunc func(config *container.Config,
hostConfig *container.HostConfig,
networkingConfig *network.NetworkingConfig,
@ -27,8 +27,8 @@ type fakeClient struct {
containerStartFunc func(containerID string, options container.StartOptions) error
imageCreateFunc func(parentReference string, options image.CreateOptions) (io.ReadCloser, error)
infoFunc func() (system.Info, error)
containerStatPathFunc func(containerID, path string) (container.PathStat, error)
containerCopyFromFunc func(containerID, srcPath string) (io.ReadCloser, container.PathStat, error)
containerStatPathFunc func(containerID, path string) (types.ContainerPathStat, error)
containerCopyFromFunc func(containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
logFunc func(string, container.LogsOptions) (io.ReadCloser, error)
waitFunc func(string) (<-chan container.WaitResponse, <-chan error)
containerListFunc func(container.ListOptions) ([]types.Container, error)
@ -36,8 +36,7 @@ type fakeClient struct {
containerExecResizeFunc func(id string, options container.ResizeOptions) error
containerRemoveFunc func(ctx context.Context, containerID string, options container.RemoveOptions) error
containerKillFunc func(ctx context.Context, containerID, signal string) error
containerPruneFunc func(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error)
containerAttachFunc func(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error)
containerPruneFunc func(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
Version string
}
@ -55,21 +54,21 @@ func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (ty
return types.ContainerJSON{}, nil
}
func (f *fakeClient) ContainerExecCreate(_ context.Context, containerID string, config container.ExecOptions) (types.IDResponse, error) {
func (f *fakeClient) ContainerExecCreate(_ context.Context, containerID string, config types.ExecConfig) (types.IDResponse, error) {
if f.execCreateFunc != nil {
return f.execCreateFunc(containerID, config)
}
return types.IDResponse{}, nil
}
func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (container.ExecInspect, error) {
func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (types.ContainerExecInspect, error) {
if f.execInspectFunc != nil {
return f.execInspectFunc(execID)
}
return container.ExecInspect{}, nil
return types.ContainerExecInspect{}, nil
}
func (f *fakeClient) ContainerExecStart(context.Context, string, container.ExecStartOptions) error {
func (f *fakeClient) ContainerExecStart(context.Context, string, types.ExecStartCheck) error {
return nil
}
@ -108,18 +107,18 @@ func (f *fakeClient) Info(_ context.Context) (system.Info, error) {
return system.Info{}, nil
}
func (f *fakeClient) ContainerStatPath(_ context.Context, containerID, path string) (container.PathStat, error) {
func (f *fakeClient) ContainerStatPath(_ context.Context, containerID, path string) (types.ContainerPathStat, error) {
if f.containerStatPathFunc != nil {
return f.containerStatPathFunc(containerID, path)
}
return container.PathStat{}, nil
return types.ContainerPathStat{}, nil
}
func (f *fakeClient) CopyFromContainer(_ context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error) {
func (f *fakeClient) CopyFromContainer(_ context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
if f.containerCopyFromFunc != nil {
return f.containerCopyFromFunc(containerID, srcPath)
}
return nil, container.PathStat{}, nil
return nil, types.ContainerPathStat{}, nil
}
func (f *fakeClient) ContainerLogs(_ context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) {
@ -168,16 +167,9 @@ func (f *fakeClient) ContainerKill(ctx context.Context, containerID, signal stri
return nil
}
func (f *fakeClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) {
func (f *fakeClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
if f.containerPruneFunc != nil {
return f.containerPruneFunc(ctx, pruneFilters)
}
return container.PruneReport{}, nil
}
func (f *fakeClient) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
if f.containerAttachFunc != nil {
return f.containerAttachFunc(ctx, containerID, options)
}
return types.HijackedResponse{}, nil
return types.ContainersPruneReport{}, nil
}

View File

@ -1,94 +0,0 @@
package container
import (
"github.com/docker/cli/cli/command/completion"
"github.com/docker/docker/api/types/container"
"github.com/moby/sys/signal"
"github.com/spf13/cobra"
)
// allLinuxCapabilities is a list of all known Linux capabilities.
//
// This list was based on the containerd pkg/cap package;
// https://github.com/containerd/containerd/blob/v1.7.19/pkg/cap/cap_linux.go#L133-L181
//
// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
var allLinuxCapabilities = []string{
"ALL", // magic value for "all capabilities"
// caps35 is the caps of kernel 3.5 (37 entries)
"CAP_CHOWN", // 2.2
"CAP_DAC_OVERRIDE", // 2.2
"CAP_DAC_READ_SEARCH", // 2.2
"CAP_FOWNER", // 2.2
"CAP_FSETID", // 2.2
"CAP_KILL", // 2.2
"CAP_SETGID", // 2.2
"CAP_SETUID", // 2.2
"CAP_SETPCAP", // 2.2
"CAP_LINUX_IMMUTABLE", // 2.2
"CAP_NET_BIND_SERVICE", // 2.2
"CAP_NET_BROADCAST", // 2.2
"CAP_NET_ADMIN", // 2.2
"CAP_NET_RAW", // 2.2
"CAP_IPC_LOCK", // 2.2
"CAP_IPC_OWNER", // 2.2
"CAP_SYS_MODULE", // 2.2
"CAP_SYS_RAWIO", // 2.2
"CAP_SYS_CHROOT", // 2.2
"CAP_SYS_PTRACE", // 2.2
"CAP_SYS_PACCT", // 2.2
"CAP_SYS_ADMIN", // 2.2
"CAP_SYS_BOOT", // 2.2
"CAP_SYS_NICE", // 2.2
"CAP_SYS_RESOURCE", // 2.2
"CAP_SYS_TIME", // 2.2
"CAP_SYS_TTY_CONFIG", // 2.2
"CAP_MKNOD", // 2.4
"CAP_LEASE", // 2.4
"CAP_AUDIT_WRITE", // 2.6.11
"CAP_AUDIT_CONTROL", // 2.6.11
"CAP_SETFCAP", // 2.6.24
"CAP_MAC_OVERRIDE", // 2.6.25
"CAP_MAC_ADMIN", // 2.6.25
"CAP_SYSLOG", // 2.6.37
"CAP_WAKE_ALARM", // 3.0
"CAP_BLOCK_SUSPEND", // 3.5
// caps316 is the caps of kernel 3.16 (38 entries)
"CAP_AUDIT_READ",
// caps58 is the caps of kernel 5.8 (40 entries)
"CAP_PERFMON",
"CAP_BPF",
// caps59 is the caps of kernel 5.9 (41 entries)
"CAP_CHECKPOINT_RESTORE",
}
// restartPolicies is a list of all valid restart-policies..
//
// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
var restartPolicies = []string{
string(container.RestartPolicyDisabled),
string(container.RestartPolicyAlways),
string(container.RestartPolicyOnFailure),
string(container.RestartPolicyUnlessStopped),
}
func completeLinuxCapabilityNames(cmd *cobra.Command, args []string, toComplete string) (names []string, _ cobra.ShellCompDirective) {
return completion.FromList(allLinuxCapabilities...)(cmd, args, toComplete)
}
func completeRestartPolicies(cmd *cobra.Command, args []string, toComplete string) (names []string, _ cobra.ShellCompDirective) {
return completion.FromList(restartPolicies...)(cmd, args, toComplete)
}
func completeSignals(cmd *cobra.Command, args []string, toComplete string) (names []string, _ cobra.ShellCompDirective) {
// TODO(thaJeztah): do we want to provide the full list here, or a subset?
signalNames := make([]string, 0, len(signal.SignalMap))
for k := range signal.SignalMap {
signalNames = append(signalNames, k)
}
return completion.FromList(signalNames...)(cmd, args, toComplete)
}

View File

@ -15,7 +15,7 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/system"
units "github.com/docker/go-units"
@ -397,7 +397,7 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
}
}
options := container.CopyToContainerOptions{
options := types.CopyToContainerOptions{
AllowOverwriteDirWithFile: false,
CopyUIDGID: copyConfig.copyUIDGID,
}
@ -433,18 +433,18 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
// so we have to check for a `/` or `.` prefix. Also, in the case of a Windows
// client, a `:` could be part of an absolute Windows path, in which case it
// is immediately proceeded by a backslash.
func splitCpArg(arg string) (ctr, path string) {
func splitCpArg(arg string) (container, path string) {
if system.IsAbs(arg) {
// Explicit local absolute path, e.g., `C:\foo` or `/foo`.
return "", arg
}
ctr, path, ok := strings.Cut(arg, ":")
if !ok || strings.HasPrefix(ctr, ".") {
container, path, ok := strings.Cut(arg, ":")
if !ok || strings.HasPrefix(container, ".") {
// Either there's no `:` in the arg
// OR it's an explicit local relative path like `./file:name.txt`.
return "", arg
}
return ctr, path
return container, path
}

View File

@ -9,7 +9,7 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -51,16 +51,15 @@ func TestRunCopyWithInvalidArguments(t *testing.T) {
func TestRunCopyFromContainerToStdout(t *testing.T) {
tarContent := "the tar content"
cli := test.NewFakeCli(&fakeClient{
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
assert.Check(t, is.Equal("container", ctr))
return io.NopCloser(strings.NewReader(tarContent)), container.PathStat{}, nil
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
return io.NopCloser(strings.NewReader(tarContent)), types.ContainerPathStat{}, nil
},
})
err := runCopy(context.TODO(), cli, copyOptions{
source: "container:/path",
destination: "-",
})
}
options := copyOptions{source: "container:/path", destination: "-"}
cli := test.NewFakeCli(fakeClient)
err := runCopy(context.TODO(), cli, options)
assert.NilError(t, err)
assert.Check(t, is.Equal(tarContent, cli.OutBuffer().String()))
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
@ -71,18 +70,16 @@ func TestRunCopyFromContainerToFilesystem(t *testing.T) {
fs.WithFile("file1", "content\n"))
defer destDir.Remove()
cli := test.NewFakeCli(&fakeClient{
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
assert.Check(t, is.Equal("container", ctr))
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
return readCloser, container.PathStat{}, err
return readCloser, types.ContainerPathStat{}, err
},
})
err := runCopy(context.TODO(), cli, copyOptions{
source: "container:/path",
destination: destDir.Path(),
quiet: true,
})
}
options := copyOptions{source: "container:/path", destination: destDir.Path(), quiet: true}
cli := test.NewFakeCli(fakeClient)
err := runCopy(context.TODO(), cli, options)
assert.NilError(t, err)
assert.Check(t, is.Equal("", cli.OutBuffer().String()))
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
@ -97,17 +94,20 @@ func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.
fs.WithFile("file1", "content\n"))
defer destDir.Remove()
cli := test.NewFakeCli(&fakeClient{
containerCopyFromFunc: func(ctr, srcPath string) (io.ReadCloser, container.PathStat, error) {
assert.Check(t, is.Equal("container", ctr))
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
return readCloser, container.PathStat{}, err
return readCloser, types.ContainerPathStat{}, err
},
})
err := runCopy(context.TODO(), cli, copyOptions{
}
options := copyOptions{
source: "container:/path",
destination: destDir.Join("missing", "foo"),
})
}
cli := test.NewFakeCli(fakeClient)
err := runCopy(context.TODO(), cli, options)
assert.ErrorContains(t, err, destDir.Join("missing"))
}
@ -115,11 +115,12 @@ func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
srcFile := fs.NewFile(t, t.Name())
defer srcFile.Remove()
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(context.TODO(), cli, copyOptions{
options := copyOptions{
source: srcFile.Path() + string(os.PathSeparator),
destination: "container:/path",
})
}
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(context.TODO(), cli, options)
expectedError := "not a directory"
if runtime.GOOS == "windows" {
@ -129,11 +130,12 @@ func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
}
func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(context.TODO(), cli, copyOptions{
options := copyOptions{
source: "/does/not/exist",
destination: "container:/path",
})
}
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(context.TODO(), cli, options)
expected := "no such file or directory"
if runtime.GOOS == "windows" {
expected = "cannot find the file specified"
@ -178,24 +180,21 @@ func TestSplitCpArg(t *testing.T) {
expectedContainer: "container",
},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.doc, func(t *testing.T) {
skip.If(t, tc.os == "windows" && runtime.GOOS != "windows" || tc.os == "linux" && runtime.GOOS == "windows")
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
skip.If(t, testcase.os != "" && testcase.os != runtime.GOOS)
ctr, path := splitCpArg(tc.path)
assert.Check(t, is.Equal(tc.expectedContainer, ctr))
assert.Check(t, is.Equal(tc.expectedPath, path))
container, path := splitCpArg(testcase.path)
assert.Check(t, is.Equal(testcase.expectedContainer, container))
assert.Check(t, is.Equal(testcase.expectedPath, path))
})
}
}
func TestRunCopyFromContainerToFilesystemIrregularDestination(t *testing.T) {
options := copyOptions{source: "container:/dev/null", destination: "/dev/random"}
cli := test.NewFakeCli(nil)
err := runCopy(context.TODO(), cli, copyOptions{
source: "container:/dev/null",
destination: "/dev/random",
})
err := runCopy(context.TODO(), cli, options)
assert.Assert(t, err != nil)
expected := `"/dev/random" must be a directory or a regular file`
assert.ErrorContains(t, err, expected)

View File

@ -77,16 +77,6 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
command.AddPlatformFlag(flags, &options.platform)
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli))
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever))
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
return cmd
}
@ -140,9 +130,9 @@ func pullImage(ctx context.Context, dockerCli command.Cli, img string, options *
out := dockerCli.Err()
if options.quiet {
out = streams.NewOut(io.Discard)
out = io.Discard
}
return jsonmessage.DisplayJSONMessagesToStream(responseBody, out, nil)
return jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(out), nil)
}
type cidFile struct {

View File

@ -3,6 +3,7 @@ package container
import (
"context"
"errors"
"fmt"
"io"
"os"
"runtime"
@ -230,13 +231,12 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
platform *specs.Platform,
containerName string,
) (container.CreateResponse, error) {
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
return container.CreateResponse{}, fmt.Errorf("shouldn't try to pull image")
},
}, test.EnableContentTrust)
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := NewCreateCommand(fakeCLI)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -11,8 +12,7 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
apiclient "github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@ -43,18 +43,19 @@ func NewExecOptions() ExecOptions {
// NewExecCommand creates a new cobra.Command for `docker exec`
func NewExecCommand(dockerCli command.Cli) *cobra.Command {
options := NewExecOptions()
var container string
cmd := &cobra.Command{
Use: "exec [OPTIONS] CONTAINER COMMAND [ARG...]",
Short: "Execute a command in a running container",
Args: cli.RequiresMinArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
containerIDorName := args[0]
container = args[0]
options.Command = args[1:]
return RunExec(cmd.Context(), dockerCli, containerIDorName, options)
return RunExec(cmd.Context(), dockerCli, container, options)
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(ctr types.Container) bool {
return ctr.State != "paused"
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool {
return container.State != "paused"
}),
Annotations: map[string]string{
"category-top": "2",
@ -78,37 +79,47 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVarP(&options.Workdir, "workdir", "w", "", "Working directory inside the container")
flags.SetAnnotation("workdir", "version", []string{"1.35"})
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
cmd.RegisterFlagCompletionFunc(
"env",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return os.Environ(), cobra.ShellCompDirectiveNoFileComp
},
)
cmd.RegisterFlagCompletionFunc(
"env-file",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveDefault // _filedir
},
)
return cmd
}
// RunExec executes an `exec` command
func RunExec(ctx context.Context, dockerCli command.Cli, containerIDorName string, options ExecOptions) error {
execOptions, err := parseExec(options, dockerCli.ConfigFile())
func RunExec(ctx context.Context, dockerCli command.Cli, container string, options ExecOptions) error {
execConfig, err := parseExec(options, dockerCli.ConfigFile())
if err != nil {
return err
}
apiClient := dockerCli.Client()
client := dockerCli.Client()
// We need to check the tty _before_ we do the ContainerExecCreate, because
// otherwise if we error out we will leak execIDs on the server (and
// there's no easy way to clean those up). But also in order to make "not
// exist" errors take precedence we do a dummy inspect first.
if _, err := apiClient.ContainerInspect(ctx, containerIDorName); err != nil {
if _, err := client.ContainerInspect(ctx, container); err != nil {
return err
}
if !execOptions.Detach {
if err := dockerCli.In().CheckTty(execOptions.AttachStdin, execOptions.Tty); err != nil {
if !execConfig.Detach {
if err := dockerCli.In().CheckTty(execConfig.AttachStdin, execConfig.Tty); err != nil {
return err
}
}
fillConsoleSize(execOptions, dockerCli)
fillConsoleSize(execConfig, dockerCli)
response, err := apiClient.ContainerExecCreate(ctx, containerIDorName, *execOptions)
response, err := client.ContainerExecCreate(ctx, container, *execConfig)
if err != nil {
return err
}
@ -118,50 +129,52 @@ func RunExec(ctx context.Context, dockerCli command.Cli, containerIDorName strin
return errors.New("exec ID empty")
}
if execOptions.Detach {
return apiClient.ContainerExecStart(ctx, execID, container.ExecStartOptions{
Detach: execOptions.Detach,
Tty: execOptions.Tty,
ConsoleSize: execOptions.ConsoleSize,
})
if execConfig.Detach {
execStartCheck := types.ExecStartCheck{
Detach: execConfig.Detach,
Tty: execConfig.Tty,
ConsoleSize: execConfig.ConsoleSize,
}
return client.ContainerExecStart(ctx, execID, execStartCheck)
}
return interactiveExec(ctx, dockerCli, execOptions, execID)
return interactiveExec(ctx, dockerCli, execConfig, execID)
}
func fillConsoleSize(execOptions *container.ExecOptions, dockerCli command.Cli) {
if execOptions.Tty {
func fillConsoleSize(execConfig *types.ExecConfig, dockerCli command.Cli) {
if execConfig.Tty {
height, width := dockerCli.Out().GetTtySize()
execOptions.ConsoleSize = &[2]uint{height, width}
execConfig.ConsoleSize = &[2]uint{height, width}
}
}
func interactiveExec(ctx context.Context, dockerCli command.Cli, execOptions *container.ExecOptions, execID string) error {
func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *types.ExecConfig, execID string) error {
// Interactive exec requested.
var (
out, stderr io.Writer
in io.ReadCloser
)
if execOptions.AttachStdin {
if execConfig.AttachStdin {
in = dockerCli.In()
}
if execOptions.AttachStdout {
if execConfig.AttachStdout {
out = dockerCli.Out()
}
if execOptions.AttachStderr {
if execOptions.Tty {
if execConfig.AttachStderr {
if execConfig.Tty {
stderr = dockerCli.Out()
} else {
stderr = dockerCli.Err()
}
}
fillConsoleSize(execOptions, dockerCli)
fillConsoleSize(execConfig, dockerCli)
apiClient := dockerCli.Client()
resp, err := apiClient.ContainerExecAttach(ctx, execID, container.ExecAttachOptions{
Tty: execOptions.Tty,
ConsoleSize: execOptions.ConsoleSize,
})
client := dockerCli.Client()
execStartCheck := types.ExecStartCheck{
Tty: execConfig.Tty,
ConsoleSize: execConfig.ConsoleSize,
}
resp, err := client.ContainerExecAttach(ctx, execID, execStartCheck)
if err != nil {
return err
}
@ -178,17 +191,17 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execOptions *co
outputStream: out,
errorStream: stderr,
resp: resp,
tty: execOptions.Tty,
detachKeys: execOptions.DetachKeys,
tty: execConfig.Tty,
detachKeys: execConfig.DetachKeys,
}
return streamer.stream(ctx)
}()
}()
if execOptions.Tty && dockerCli.In().IsTerminal() {
if execConfig.Tty && dockerCli.In().IsTerminal() {
if err := MonitorTtySize(ctx, dockerCli, execID, true); err != nil {
_, _ = fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err)
fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err)
}
}
@ -197,14 +210,14 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execOptions *co
return err
}
return getExecExitStatus(ctx, apiClient, execID)
return getExecExitStatus(ctx, client, execID)
}
func getExecExitStatus(ctx context.Context, apiClient client.ContainerAPIClient, execID string) error {
resp, err := apiClient.ContainerExecInspect(ctx, execID)
func getExecExitStatus(ctx context.Context, client apiclient.ContainerAPIClient, execID string) error {
resp, err := client.ContainerExecInspect(ctx, execID)
if err != nil {
// If we can't connect, then the daemon probably died.
if !client.IsErrConnectionFailed(err) {
if !apiclient.IsErrConnectionFailed(err) {
return err
}
return cli.StatusError{StatusCode: -1}
@ -218,8 +231,8 @@ func getExecExitStatus(ctx context.Context, apiClient client.ContainerAPIClient,
// parseExec parses the specified args for the specified command and generates
// an ExecConfig from it.
func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*container.ExecOptions, error) {
execOptions := &container.ExecOptions{
func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*types.ExecConfig, error) {
execConfig := &types.ExecConfig{
User: execOpts.User,
Privileged: execOpts.Privileged,
Tty: execOpts.TTY,
@ -230,23 +243,23 @@ func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*contai
// collect all the environment variables for the container
var err error
if execOptions.Env, err = opts.ReadKVEnvStrings(execOpts.EnvFile.GetAll(), execOpts.Env.GetAll()); err != nil {
if execConfig.Env, err = opts.ReadKVEnvStrings(execOpts.EnvFile.GetAll(), execOpts.Env.GetAll()); err != nil {
return nil, err
}
// If -d is not set, attach to everything by default
if !execOpts.Detach {
execOptions.AttachStdout = true
execOptions.AttachStderr = true
execConfig.AttachStdout = true
execConfig.AttachStderr = true
if execOpts.Interactive {
execOptions.AttachStdin = true
execConfig.AttachStdin = true
}
}
if execOpts.DetachKeys != "" {
execOptions.DetachKeys = execOpts.DetachKeys
execConfig.DetachKeys = execOpts.DetachKeys
} else {
execOptions.DetachKeys = configFile.DetachKeys
execConfig.DetachKeys = configFile.DetachKeys
}
return execOptions, nil
return execConfig, nil
}

View File

@ -11,7 +11,6 @@ import (
"github.com/docker/cli/internal/test"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/pkg/errors"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -38,10 +37,10 @@ TWO=2
testcases := []struct {
options ExecOptions
configFile configfile.ConfigFile
expected container.ExecOptions
expected types.ExecConfig
}{
{
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command"},
AttachStdout: true,
AttachStderr: true,
@ -49,7 +48,7 @@ TWO=2
options: withDefaultOpts(ExecOptions{}),
},
{
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command1", "command2"},
AttachStdout: true,
AttachStderr: true,
@ -64,7 +63,7 @@ TWO=2
TTY: true,
User: "uid",
}),
expected: container.ExecOptions{
expected: types.ExecConfig{
User: "uid",
AttachStdin: true,
AttachStdout: true,
@ -75,7 +74,7 @@ TWO=2
},
{
options: withDefaultOpts(ExecOptions{Detach: true}),
expected: container.ExecOptions{
expected: types.ExecConfig{
Detach: true,
Cmd: []string{"command"},
},
@ -86,7 +85,7 @@ TWO=2
Interactive: true,
Detach: true,
}),
expected: container.ExecOptions{
expected: types.ExecConfig{
Detach: true,
Tty: true,
Cmd: []string{"command"},
@ -95,7 +94,7 @@ TWO=2
{
options: withDefaultOpts(ExecOptions{Detach: true}),
configFile: configfile.ConfigFile{DetachKeys: "de"},
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command"},
DetachKeys: "de",
Detach: true,
@ -107,14 +106,14 @@ TWO=2
DetachKeys: "ab",
}),
configFile: configfile.ConfigFile{DetachKeys: "de"},
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command"},
DetachKeys: "ab",
Detach: true,
},
},
{
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command"},
AttachStdout: true,
AttachStderr: true,
@ -127,7 +126,7 @@ TWO=2
}(),
},
{
expected: container.ExecOptions{
expected: types.ExecConfig{
Cmd: []string{"command"},
AttachStdout: true,
AttachStderr: true,
@ -162,7 +161,7 @@ func TestRunExec(t *testing.T) {
testcases := []struct {
doc string
options ExecOptions
client *fakeClient
client fakeClient
expectedError string
expectedOut string
expectedErr string
@ -172,12 +171,12 @@ func TestRunExec(t *testing.T) {
options: withDefaultOpts(ExecOptions{
Detach: true,
}),
client: &fakeClient{execCreateFunc: execCreateWithID},
client: fakeClient{execCreateFunc: execCreateWithID},
},
{
doc: "inspect error",
options: NewExecOptions(),
client: &fakeClient{
client: fakeClient{
inspectFunc: func(string) (types.ContainerJSON, error) {
return types.ContainerJSON{}, errors.New("failed inspect")
},
@ -188,13 +187,12 @@ func TestRunExec(t *testing.T) {
doc: "missing exec ID",
options: NewExecOptions(),
expectedError: "exec ID empty",
client: &fakeClient{},
},
}
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
fakeCLI := test.NewFakeCli(testcase.client)
fakeCLI := test.NewFakeCli(&testcase.client)
err := RunExec(context.TODO(), fakeCLI, "thecontainer", testcase.options)
if testcase.expectedError != "" {
@ -208,7 +206,7 @@ func TestRunExec(t *testing.T) {
}
}
func execCreateWithID(_ string, _ container.ExecOptions) (types.IDResponse, error) {
func execCreateWithID(_ string, _ types.ExecConfig) (types.IDResponse, error) {
return types.IDResponse{ID: "execid"}, nil
}
@ -237,9 +235,9 @@ func TestGetExecExitStatus(t *testing.T) {
for _, testcase := range testcases {
client := &fakeClient{
execInspectFunc: func(id string) (container.ExecInspect, error) {
execInspectFunc: func(id string) (types.ContainerExecInspect, error) {
assert.Check(t, is.Equal(execID, id))
return container.ExecInspect{ExitCode: testcase.exitCode}, testcase.inspectError
return types.ContainerExecInspect{ExitCode: testcase.exitCode}, testcase.inspectError
},
}
err := getExecExitStatus(context.Background(), client, execID)

View File

@ -39,7 +39,6 @@ func TestContainerExportOutputToIrregularFile(t *testing.T) {
})
cmd := NewExportCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs([]string{"-o", "/dev/random", "container"})
err := cmd.Execute()

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package container

View File

@ -38,9 +38,6 @@ func NewKillCommand(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.StringVarP(&opts.signal, "signal", "s", "", "Signal to send to the container")
_ = cmd.RegisterFlagCompletionFunc("signal", completeSignals)
return cmd
}
@ -53,7 +50,7 @@ func runKill(ctx context.Context, dockerCli command.Cli, opts *killOptions) erro
if err := <-errChan; err != nil {
errs = append(errs, err.Error())
} else {
_, _ = fmt.Fprintln(dockerCli.Out(), name)
fmt.Fprintln(dockerCli.Out(), name)
}
}
if len(errs) > 0 {

View File

@ -1,7 +1,7 @@
package container
import (
"errors"
"fmt"
"io"
"testing"
@ -147,7 +147,7 @@ func TestContainerListErrors(t *testing.T) {
},
{
containerListFunc: func(_ container.ListOptions) ([]types.Container, error) {
return nil, errors.New("error listing containers")
return nil, fmt.Errorf("error listing containers")
},
expectedError: "error listing containers",
},
@ -163,7 +163,6 @@ func TestContainerListErrors(t *testing.T) {
assert.Check(t, cmd.Flags().Set(key, value))
}
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -30,7 +30,7 @@ func TestRunLogs(t *testing.T) {
testcases := []struct {
doc string
options *logsOptions
client *fakeClient
client fakeClient
expectedError string
expectedOut string
expectedErr string
@ -39,13 +39,13 @@ func TestRunLogs(t *testing.T) {
doc: "successful logs",
expectedOut: "foo",
options: &logsOptions{},
client: &fakeClient{logFunc: logFn("foo"), inspectFunc: inspectFn},
client: fakeClient{logFunc: logFn("foo"), inspectFunc: inspectFn},
},
}
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
cli := test.NewFakeCli(testcase.client)
cli := test.NewFakeCli(&testcase.client)
err := runLogs(context.TODO(), cli, testcase.options)
if testcase.expectedError != "" {

View File

@ -208,7 +208,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.Var(copts.ulimits, "ulimit", "Ulimit options")
flags.StringVarP(&copts.user, "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])")
flags.StringVarP(&copts.workingDir, "workdir", "w", "", "Working directory inside the container")
flags.BoolVar(&copts.autoRemove, "rm", false, "Automatically remove the container and its associated anonymous volumes when it exits")
flags.BoolVar(&copts.autoRemove, "rm", false, "Automatically remove the container when it exits")
// Security
flags.Var(&copts.capAdd, "cap-add", "Add Linux capabilities")
@ -574,10 +574,10 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
return nil, errors.Errorf("--health-retries cannot be negative")
}
if copts.healthStartPeriod < 0 {
return nil, errors.New("--health-start-period cannot be negative")
return nil, fmt.Errorf("--health-start-period cannot be negative")
}
if copts.healthStartInterval < 0 {
return nil, errors.New("--health-start-interval cannot be negative")
return nil, fmt.Errorf("--health-start-interval cannot be negative")
}
healthConfig = &container.HealthConfig{

View File

@ -335,7 +335,7 @@ func TestParseHostname(t *testing.T) {
hostnameWithDomain := "--hostname=hostname.domainname"
hostnameWithDomainTld := "--hostname=hostname.domainname.tld"
for hostname, expectedHostname := range validHostnames {
if config, _, _ := mustParse(t, "--hostname="+hostname); config.Hostname != expectedHostname {
if config, _, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname {
t.Fatalf("Expected the config to have 'hostname' as %q, got %q", expectedHostname, config.Hostname)
}
}

View File

@ -2,11 +2,10 @@ package container
import (
"context"
"io"
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
)
@ -16,12 +15,10 @@ func TestContainerPrunePromptTermination(t *testing.T) {
t.Cleanup(cancel)
cli := test.NewFakeCli(&fakeClient{
containerPruneFunc: func(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) {
return container.PruneReport{}, errors.New("fakeClient containerPruneFunc should not be called")
containerPruneFunc: func(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
return types.ContainersPruneReport{}, errors.New("fakeClient containerPruneFunc should not be called")
},
})
cmd := NewPruneCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
test.TerminatePrompt(ctx, t, cmd, cli)
}

View File

@ -43,9 +43,6 @@ func NewRestartCommand(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.StringVarP(&opts.signal, "signal", "s", "", "Signal to send to the container")
flags.IntVarP(&opts.timeout, "time", "t", 0, "Seconds to wait before killing the container")
_ = cmd.RegisterFlagCompletionFunc("signal", completeSignals)
return cmd
}

View File

@ -2,7 +2,7 @@ package container
import (
"context"
"errors"
"fmt"
"io"
"sort"
"sync"
@ -37,7 +37,7 @@ func TestRemoveForce(t *testing.T) {
mutex.Unlock()
if container == "nosuchcontainer" {
return errdefs.NotFound(errors.New("Error: no such container: " + container))
return errdefs.NotFound(fmt.Errorf("Error: no such container: " + container))
}
return nil
},
@ -45,7 +45,6 @@ func TestRemoveForce(t *testing.T) {
})
cmd := NewRmCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"os"
"strings"
"syscall"
@ -69,15 +70,22 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli))
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever))
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
cmd.RegisterFlagCompletionFunc(
"env",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return os.Environ(), cobra.ShellCompDirectiveNoFileComp
},
)
cmd.RegisterFlagCompletionFunc(
"env-file",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveDefault
},
)
cmd.RegisterFlagCompletionFunc(
"network",
completion.NetworkNames(dockerCli),
)
return cmd
}
@ -111,8 +119,6 @@ func runRun(ctx context.Context, dockerCli command.Cli, flags *pflag.FlagSet, ro
//nolint:gocyclo
func runContainer(ctx context.Context, dockerCli command.Cli, runOpts *runOptions, copts *containerOptions, containerCfg *containerConfig) error {
ctx = context.WithoutCancel(ctx)
config := containerCfg.Config
stdout, stderr := dockerCli.Out(), dockerCli.Err()
apiClient := dockerCli.Client()
@ -144,12 +150,7 @@ func runContainer(ctx context.Context, dockerCli command.Cli, runOpts *runOption
}
if runOpts.sigProxy {
sigc := notifyAllSignals()
// since we're explicitly setting up signal handling here, and the daemon will
// get notified independently of the clients ctx cancellation, we use this context
// but without cancellation to avoid ForwardAllSignals from returning
// before all signals are forwarded.
bgCtx := context.WithoutCancel(ctx)
go ForwardAllSignals(bgCtx, apiClient, containerID, sigc)
go ForwardAllSignals(ctx, apiClient, containerID, sigc)
defer signal.StopCatch(sigc)
}
@ -172,9 +173,6 @@ func runContainer(ctx context.Context, dockerCli command.Cli, runOpts *runOption
detachKeys = runOpts.detachKeys
}
// ctx should not be cancellable here, as this would kill the stream to the container
// and we want to keep the stream open until the process in the container exits or until
// the user forcefully terminates the CLI.
closeFn, err := attachContainer(ctx, dockerCli, containerID, &errCh, config, container.AttachOptions{
Stream: true,
Stdin: config.AttachStdin,

View File

@ -3,18 +3,13 @@ package container
import (
"context"
"errors"
"fmt"
"io"
"net"
"syscall"
"testing"
"time"
"github.com/creack/pty"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
specs "github.com/opencontainers/image-spec/specs-go/v1"
@ -37,158 +32,6 @@ func TestRunLabel(t *testing.T) {
assert.NilError(t, cmd.Execute())
}
func TestRunAttach(t *testing.T) {
p, tty, err := pty.Open()
assert.NilError(t, err)
defer func() {
_ = tty.Close()
_ = p.Close()
}()
var conn net.Conn
attachCh := make(chan struct{})
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *specs.Platform, _ string) (container.CreateResponse, error) {
return container.CreateResponse{
ID: "id",
}, nil
},
containerAttachFunc: func(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
server, client := net.Pipe()
conn = server
t.Cleanup(func() {
_ = server.Close()
})
attachCh <- struct{}{}
return types.NewHijackedResponse(client, types.MediaTypeRawStream), nil
},
waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) {
responseChan := make(chan container.WaitResponse, 1)
errChan := make(chan error)
responseChan <- container.WaitResponse{
StatusCode: 33,
}
return responseChan, errChan
},
// use new (non-legacy) wait API
// see: 38591f20d07795aaef45d400df89ca12f29c603b
Version: "1.30",
}, func(fc *test.FakeCli) {
fc.SetOut(streams.NewOut(tty))
fc.SetIn(streams.NewIn(tty))
})
cmd := NewRunCommand(fakeCLI)
cmd.SetArgs([]string{"-it", "busybox"})
cmd.SilenceUsage = true
cmdErrC := make(chan error, 1)
go func() {
cmdErrC <- cmd.Execute()
}()
// run command should attempt to attach to the container
select {
case <-time.After(5 * time.Second):
t.Fatal("containerAttachFunc was not called before the 5 second timeout")
case <-attachCh:
}
// end stream from "container" so that we'll detach
conn.Close()
select {
case cmdErr := <-cmdErrC:
assert.Equal(t, cmdErr, cli.StatusError{
StatusCode: 33,
})
case <-time.After(2 * time.Second):
t.Fatal("cmd did not return within timeout")
}
}
func TestRunAttachTermination(t *testing.T) {
p, tty, err := pty.Open()
assert.NilError(t, err)
defer func() {
_ = tty.Close()
_ = p.Close()
}()
var conn net.Conn
killCh := make(chan struct{})
attachCh := make(chan struct{})
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ *specs.Platform, _ string) (container.CreateResponse, error) {
return container.CreateResponse{
ID: "id",
}, nil
},
containerKillFunc: func(ctx context.Context, containerID, signal string) error {
killCh <- struct{}{}
return nil
},
containerAttachFunc: func(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
server, client := net.Pipe()
conn = server
t.Cleanup(func() {
_ = server.Close()
})
attachCh <- struct{}{}
return types.NewHijackedResponse(client, types.MediaTypeRawStream), nil
},
waitFunc: func(_ string) (<-chan container.WaitResponse, <-chan error) {
responseChan := make(chan container.WaitResponse, 1)
errChan := make(chan error)
responseChan <- container.WaitResponse{
StatusCode: 130,
}
return responseChan, errChan
},
// use new (non-legacy) wait API
// see: 38591f20d07795aaef45d400df89ca12f29c603b
Version: "1.30",
}, func(fc *test.FakeCli) {
fc.SetOut(streams.NewOut(tty))
fc.SetIn(streams.NewIn(tty))
})
cmd := NewRunCommand(fakeCLI)
cmd.SetArgs([]string{"-it", "busybox"})
cmd.SilenceUsage = true
cmdErrC := make(chan error, 1)
go func() {
cmdErrC <- cmd.Execute()
}()
// run command should attempt to attach to the container
select {
case <-time.After(5 * time.Second):
t.Fatal("containerAttachFunc was not called before the timeout")
case <-attachCh:
}
assert.NilError(t, syscall.Kill(syscall.Getpid(), syscall.SIGINT))
// end stream from "container" so that we'll detach
conn.Close()
select {
case <-killCh:
case <-time.After(5 * time.Second):
t.Fatal("containerKillFunc was not called before the timeout")
}
select {
case cmdErr := <-cmdErrC:
assert.Equal(t, cmdErr, cli.StatusError{
StatusCode: 130,
})
case <-time.After(2 * time.Second):
t.Fatal("cmd did not return before the timeout")
}
}
func TestRunCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
@ -216,27 +59,23 @@ func TestRunCommandWithContentTrustErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
hostConfig *container.HostConfig,
networkingConfig *network.NetworkingConfig,
platform *specs.Platform,
containerName string,
) (container.CreateResponse, error) {
return container.CreateResponse{}, errors.New("shouldn't try to pull image")
},
}, test.EnableContentTrust)
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := NewRunCommand(fakeCLI)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.Assert(t, err != nil)
assert.Assert(t, is.Contains(fakeCLI.ErrBuffer().String(), tc.expectedError))
})
fakeCLI := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
hostConfig *container.HostConfig,
networkingConfig *network.NetworkingConfig,
platform *specs.Platform,
containerName string,
) (container.CreateResponse, error) {
return container.CreateResponse{}, fmt.Errorf("shouldn't try to pull image")
},
}, test.EnableContentTrust)
fakeCLI.SetNotaryClient(tc.notaryFunc)
cmd := NewRunCommand(fakeCLI)
cmd.SetArgs(tc.args)
cmd.SetOut(io.Discard)
err := cmd.Execute()
assert.Assert(t, err != nil)
assert.Assert(t, is.Contains(fakeCLI.ErrBuffer().String(), tc.expectedError))
}
}

View File

@ -87,8 +87,7 @@ func RunStart(ctx context.Context, dockerCli command.Cli, opts *StartOptions) er
// We always use c.ID instead of container to maintain consistency during `docker start`
if !c.Config.Tty {
sigc := notifyAllSignals()
bgCtx := context.WithoutCancel(ctx)
go ForwardAllSignals(bgCtx, dockerCli.Client(), c.ID, sigc)
go ForwardAllSignals(ctx, dockerCli.Client(), c.ID, sigc)
defer signal.StopCatch(sigc)
}

View File

@ -13,6 +13,7 @@ import (
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/formatter"
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
@ -163,7 +164,7 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions)
// is not valid for filtering containers.
f := options.Filters.Clone()
f.Add("type", string(events.ContainerEventType))
eventChan, errChan := apiClient.Events(ctx, events.ListOptions{
eventChan, errChan := apiClient.Events(ctx, types.EventsOptions{
Filters: f,
})
@ -218,7 +219,7 @@ func RunStats(ctx context.Context, dockerCLI command.Cli, options *StatsOptions)
// with a list of container names/IDs.
if options.Filters != nil && options.Filters.Len() > 0 {
return errors.New("filtering is not supported when specifying a list of containers")
return fmt.Errorf("filtering is not supported when specifying a list of containers")
}
// Create the list of containers, and start collecting stats for all

View File

@ -7,7 +7,7 @@ import (
"sync"
"time"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@ -50,7 +50,7 @@ func (s *stats) isKnownContainer(cid string) (int, bool) {
return -1, false
}
func collect(ctx context.Context, s *Stats, cli client.ContainerAPIClient, streamStats bool, waitFirst *sync.WaitGroup) {
func collect(ctx context.Context, s *Stats, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
logrus.Debugf("collecting stats for %s", s.Container)
var (
getFirst bool
@ -78,7 +78,7 @@ func collect(ctx context.Context, s *Stats, cli client.ContainerAPIClient, strea
go func() {
for {
var (
v *container.StatsResponse
v *types.StatsJSON
memPercent, cpuPercent float64
blkRead, blkWrite uint64 // Only used on Linux
mem, memLimit float64
@ -163,7 +163,7 @@ func collect(ctx context.Context, s *Stats, cli client.ContainerAPIClient, strea
}
}
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *container.StatsResponse) float64 {
func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 {
var (
cpuPercent = 0.0
// calculate the change for the cpu usage of the container in between readings
@ -182,7 +182,7 @@ func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *container.St
return cpuPercent
}
func calculateCPUPercentWindows(v *container.StatsResponse) float64 {
func calculateCPUPercentWindows(v *types.StatsJSON) float64 {
// Max number of 100ns intervals between the previous time read and now
possIntervals := uint64(v.Read.Sub(v.PreRead).Nanoseconds()) // Start with number of ns intervals
possIntervals /= 100 // Convert to number of 100ns intervals
@ -198,7 +198,7 @@ func calculateCPUPercentWindows(v *container.StatsResponse) float64 {
return 0.00
}
func calculateBlockIO(blkio container.BlkioStats) (uint64, uint64) {
func calculateBlockIO(blkio types.BlkioStats) (uint64, uint64) {
var blkRead, blkWrite uint64
for _, bioEntry := range blkio.IoServiceBytesRecursive {
if len(bioEntry.Op) == 0 {
@ -214,7 +214,7 @@ func calculateBlockIO(blkio container.BlkioStats) (uint64, uint64) {
return blkRead, blkWrite
}
func calculateNetwork(network map[string]container.NetworkStats) (float64, float64) {
func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) {
var rx, tx float64
for _, v := range network {
@ -236,7 +236,7 @@ func calculateNetwork(network map[string]container.NetworkStats) (float64, float
//
// On Docker 19.03 and older, the result was `mem.Usage - mem.Stats["cache"]`.
// See https://github.com/moby/moby/issues/40727 for the background.
func calculateMemUsageUnixNoCache(mem container.MemoryStats) float64 {
func calculateMemUsageUnixNoCache(mem types.MemoryStats) float64 {
// cgroup v1
if v, isCgroup1 := mem.Stats["total_inactive_file"]; isCgroup1 && v < mem.Usage {
return float64(mem.Usage - v)

View File

@ -4,12 +4,18 @@ import (
"fmt"
"testing"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types"
"gotest.tools/v3/assert"
)
func TestCalculateMemUsageUnixNoCache(t *testing.T) {
result := calculateMemUsageUnixNoCache(container.MemoryStats{Usage: 500, Stats: map[string]uint64{"total_inactive_file": 400}})
// Given
stats := types.MemoryStats{Usage: 500, Stats: map[string]uint64{"total_inactive_file": 400}}
// When
result := calculateMemUsageUnixNoCache(stats)
// Then
assert.Assert(t, inDelta(100.0, result, 1e-6))
}
@ -30,28 +36,6 @@ func TestCalculateMemPercentUnixNoCache(t *testing.T) {
})
}
func TestCalculateBlockIO(t *testing.T) {
blkRead, blkWrite := calculateBlockIO(container.BlkioStats{
IoServiceBytesRecursive: []container.BlkioStatEntry{
{Major: 8, Minor: 0, Op: "read", Value: 1234},
{Major: 8, Minor: 1, Op: "read", Value: 4567},
{Major: 8, Minor: 0, Op: "Read", Value: 6},
{Major: 8, Minor: 1, Op: "Read", Value: 8},
{Major: 8, Minor: 0, Op: "write", Value: 123},
{Major: 8, Minor: 1, Op: "write", Value: 456},
{Major: 8, Minor: 0, Op: "Write", Value: 6},
{Major: 8, Minor: 1, Op: "Write", Value: 8},
{Major: 8, Minor: 1, Op: "", Value: 456},
},
})
if blkRead != 5815 {
t.Fatalf("blkRead = %d, want 5815", blkRead)
}
if blkWrite != 593 {
t.Fatalf("blkWrite = %d, want 593", blkWrite)
}
}
func inDelta(x, y, delta float64) func() (bool, string) {
return func() (bool, string) {
diff := x - y

View File

@ -0,0 +1,30 @@
package container
import (
"testing"
"github.com/docker/docker/api/types"
)
func TestCalculateBlockIO(t *testing.T) {
blkio := types.BlkioStats{
IoServiceBytesRecursive: []types.BlkioStatEntry{
{Major: 8, Minor: 0, Op: "read", Value: 1234},
{Major: 8, Minor: 1, Op: "read", Value: 4567},
{Major: 8, Minor: 0, Op: "Read", Value: 6},
{Major: 8, Minor: 1, Op: "Read", Value: 8},
{Major: 8, Minor: 0, Op: "write", Value: 123},
{Major: 8, Minor: 1, Op: "write", Value: 456},
{Major: 8, Minor: 0, Op: "Write", Value: 6},
{Major: 8, Minor: 1, Op: "Write", Value: 8},
{Major: 8, Minor: 1, Op: "", Value: 456},
},
}
blkRead, blkWrite := calculateBlockIO(blkio)
if blkRead != 5815 {
t.Fatalf("blkRead = %d, want 5815", blkRead)
}
if blkWrite != 593 {
t.Fatalf("blkWrite = %d, want 593", blkWrite)
}
}

View File

@ -43,9 +43,6 @@ func NewStopCommand(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.StringVarP(&opts.signal, "signal", "s", "", "Signal to send to the container")
flags.IntVarP(&opts.timeout, "time", "t", 0, "Seconds to wait before killing the container")
_ = cmd.RegisterFlagCompletionFunc("signal", completeSignals)
return cmd
}

View File

@ -83,8 +83,6 @@ func NewUpdateCommand(dockerCli command.Cli) *cobra.Command {
flags.Var(&options.cpus, "cpus", "Number of CPUs")
flags.SetAnnotation("cpus", "version", []string{"1.29"})
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies)
return cmd
}

View File

@ -5,6 +5,7 @@ import (
"errors"
"strconv"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
@ -67,11 +68,11 @@ func legacyWaitExitOrRemoved(ctx context.Context, apiClient client.APIClient, co
f := filters.NewArgs()
f.Add("type", "container")
f.Add("container", containerID)
eventCtx, cancel := context.WithCancel(ctx)
eventq, errq := apiClient.Events(eventCtx, events.ListOptions{
options := types.EventsOptions{
Filters: f,
})
}
eventCtx, cancel := context.WithCancel(ctx)
eventq, errq := apiClient.Events(eventCtx, options)
eventProcessor := func(e events.Message) bool {
stopProcessing := false

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package command

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package context

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package context

View File

@ -42,7 +42,7 @@ func writeTo(dockerCli command.Cli, reader io.Reader, dest string) error {
var printDest bool
if dest == "-" {
if dockerCli.Out().IsTerminal() {
return errors.New("cowardly refusing to export to a terminal, specify a file path")
return errors.New("cowardly refusing to export to a terminal, please specify a file path")
}
writer = dockerCli.Out()
} else {

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package context

View File

@ -1,6 +1,3 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
package context
import (

View File

@ -1,6 +1,7 @@
package context
import (
"fmt"
"strconv"
"strings"
@ -75,7 +76,7 @@ func validateConfig(config map[string]string, allowedKeys map[string]struct{}) e
var errs []string
for k := range config {
if _, ok := allowedKeys[k]; !ok {
errs = append(errs, "unrecognized config key: "+k)
errs = append(errs, fmt.Sprintf("%s: unrecognized config key", k))
}
}
if len(errs) == 0 {

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package command

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package command

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package command

View File

@ -0,0 +1,51 @@
package command
import (
"sync"
"github.com/docker/docker/api/types/events"
"github.com/sirupsen/logrus"
)
// EventHandler is abstract interface for user to customize
// own handle functions of each type of events
//
// Deprecated: EventHandler is no longer used, and will be removed in the next release.
type EventHandler interface {
Handle(action events.Action, h func(events.Message))
Watch(c <-chan events.Message)
}
// InitEventHandler initializes and returns an EventHandler
//
// Deprecated: InitEventHandler is no longer used, and will be removed in the next release.
func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[events.Action]func(events.Message))}
}
type eventHandler struct {
handlers map[events.Action]func(events.Message)
mu sync.Mutex
}
func (w *eventHandler) Handle(action events.Action, h func(events.Message)) {
w.mu.Lock()
w.handlers[action] = h
w.mu.Unlock()
}
// Watch ranges over the passed in event chan and processes the events based on the
// handlers created for a given action.
// To stop watching, close the event chan.
func (w *eventHandler) Watch(c <-chan events.Message) {
for e := range c {
w.mu.Lock()
h, exists := w.handlers[e.Action]
w.mu.Unlock()
if !exists {
continue
}
logrus.Debugf("event handler: received event: %v", e)
go h(e)
}
}

View File

@ -1,11 +1,10 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter
import (
"fmt"
"net"
"sort"
"strconv"
"strings"
@ -332,8 +331,7 @@ func DisplayablePorts(ports []types.Port) string {
portKey := port.Type
if port.IP != "" {
if port.PublicPort != current {
hAddrPort := net.JoinHostPort(port.IP, strconv.Itoa(int(port.PublicPort)))
hostMappings = append(hostMappings, fmt.Sprintf("%s->%d/%s", hAddrPort, port.PrivatePort, port.Type))
hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type))
continue
}
portKey = port.IP + "/" + port.Type

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter
@ -471,16 +471,6 @@ func TestDisplayablePorts(t *testing.T) {
},
"0.0.0.0:0->9988/tcp",
},
{
[]types.Port{
{
IP: "::",
PrivatePort: 9988,
Type: "tcp",
},
},
"[::]:0->9988/tcp",
},
{
[]types.Port{
{

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -106,7 +106,7 @@ type Writer struct {
cell cell // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
endChar byte // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
lines [][]cell // list of lines; each line is a list of cells
widths []int // list of column widths in runes - reused during formatting
widths []int // list of column widths in runes - re-used during formatting
}
// addLine adds a new line.
@ -115,7 +115,7 @@ type Writer struct {
func (b *Writer) addLine(flushed bool) {
// Grow slice instead of appending,
// as that gives us an opportunity
// to reuse an existing []cell.
// to re-use an existing []cell.
if n := len(b.lines) + 1; n <= cap(b.lines) {
b.lines = b.lines[:n]
b.lines[n-1] = b.lines[n-1][:0]
@ -159,7 +159,7 @@ func (b *Writer) reset() {
// - the sizes and widths of processed text are kept in the lines list
// which contains a list of cells for each line
// - the widths list is a temporary list with current widths used during
// formatting; it is kept in Writer because it's reused
// formatting; it is kept in Writer because it's re-used
//
// |<---------- size ---------->|
// | |

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package formatter

View File

@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.21
//go:build go1.19
package idresolver

View File

@ -15,7 +15,6 @@ import (
"strings"
"github.com/distribution/reference"
"github.com/docker/cli-docs-tool/annotation"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image/build"
@ -30,6 +29,7 @@ import (
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
units "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -81,7 +81,7 @@ func (o buildOptions) contextFromStdin() bool {
}
func newBuildOptions() buildOptions {
ulimits := make(map[string]*container.Ulimit)
ulimits := make(map[string]*units.Ulimit)
return buildOptions{
tags: opts.NewListOpts(validateTag),
buildArgs: opts.NewListOpts(opts.ValidateEnv),
@ -105,7 +105,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "4",
"aliases": "docker image build, docker build, docker builder build",
"aliases": "docker image build, docker build, docker buildx build, docker builder build",
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveFilterDirs
@ -115,12 +115,9 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.VarP(&options.tags, "tag", "t", `Name and optionally a tag in the "name:tag" format`)
flags.SetAnnotation("tag", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#tag"})
flags.Var(&options.buildArgs, "build-arg", "Set build-time variables")
flags.SetAnnotation("build-arg", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#build-arg"})
flags.Var(options.ulimits, "ulimit", "Ulimit options")
flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (Default is "PATH/Dockerfile")`)
flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#file"})
flags.VarP(&options.memory, "memory", "m", "Memory limit")
flags.Var(&options.memorySwap, "memory-swap", `Swap limit equal to memory plus swap: -1 to enable unlimited swap`)
flags.Var(&options.shmSize, "shm-size", `Size of "/dev/shm"`)
@ -130,7 +127,6 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVar(&options.cpuSetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
flags.StringVar(&options.cpuSetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)")
flags.StringVar(&options.cgroupParent, "cgroup-parent", "", `Set the parent cgroup for the "RUN" instructions during build`)
flags.SetAnnotation("cgroup-parent", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#cgroup-parent"})
flags.StringVar(&options.isolation, "isolation", "", "Container isolation technology")
flags.Var(&options.labels, "label", "Set metadata for an image")
flags.BoolVar(&options.noCache, "no-cache", false, "Do not use cache when building the image")
@ -143,11 +139,8 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags.StringSliceVar(&options.securityOpt, "security-opt", []string{}, "Security options")
flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build")
flags.SetAnnotation("network", "version", []string{"1.25"})
flags.SetAnnotation("network", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#network"})
flags.Var(&options.extraHosts, "add-host", `Add a custom host-to-IP mapping ("host:ip")`)
flags.SetAnnotation("add-host", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#add-host"})
flags.StringVar(&options.target, "target", "", "Set the target build stage to build.")
flags.SetAnnotation("target", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/buildx/build/#target"})
flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file")
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
@ -465,7 +458,7 @@ func rewriteDockerfileFromForContentTrust(ctx context.Context, dockerfile io.Rea
return nil, nil, err
}
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, "FROM "+reference.FamiliarString(trustedRef))
line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", reference.FamiliarString(trustedRef)))
resolvedTags = append(resolvedTags, &resolvedTag{
digestRef: trustedRef,
tagRef: ref,

View File

@ -226,7 +226,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
progressOutput := streamformatter.NewProgressOutput(out)
// Pass the response body through a progress reader.
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", "Downloading build context from remote url: "+remoteURL)
progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", fmt.Sprintf("Downloading build context from remote url: %s", remoteURL))
return GetContextFromReader(ioutils.NewReadCloserWrapper(progReader, func() error { return response.Body.Close() }), dockerfileName)
}
@ -234,7 +234,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
// getWithStatusError does an http.Get() and returns an error if the
// status code is 4xx or 5xx.
func getWithStatusError(url string) (resp *http.Response, err error) {
//nolint:gosec // Ignore G107: Potential HTTP request made with variable url
//#nosec G107 -- Ignore G107: Potential HTTP request made with variable url
if resp, err = http.Get(url); err != nil {
return nil, err
}

View File

@ -116,7 +116,7 @@ COPY data /data
assert.DeepEqual(t, expected, fakeBuild.filenames(t))
}
// TestRunBuildFromGitHubSpecialCase tests that build contexts
// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that build contexts
// starting with `github.com/` are special-cased, and the build command attempts
// to clone the remote repo.
// TODO: test "context selection" logic directly when runBuild is refactored
@ -127,13 +127,12 @@ func TestRunBuildFromGitHubSpecialCase(t *testing.T) {
// Clone a small repo that exists so git doesn't prompt for credentials
cmd.SetArgs([]string{"github.com/docker/for-win"})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)
err := cmd.Execute()
assert.ErrorContains(t, err, "unable to prepare context")
assert.ErrorContains(t, err, "docker-build-git")
}
// TestRunBuildFromLocalGitHubDir tests that a local directory
// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that a local directory
// starting with `github.com` takes precedence over the `github.com` special
// case.
func TestRunBuildFromLocalGitHubDir(t *testing.T) {

View File

@ -21,11 +21,11 @@ type fakeClient struct {
imagePushFunc func(ref string, options image.PushOptions) (io.ReadCloser, error)
infoFunc func() (system.Info, error)
imagePullFunc func(ref string, options image.PullOptions) (io.ReadCloser, error)
imagesPruneFunc func(pruneFilter filters.Args) (image.PruneReport, error)
imageLoadFunc func(input io.Reader, quiet bool) (image.LoadResponse, error)
imagesPruneFunc func(pruneFilter filters.Args) (types.ImagesPruneReport, error)
imageLoadFunc func(input io.Reader, quiet bool) (types.ImageLoadResponse, error)
imageListFunc func(options image.ListOptions) ([]image.Summary, error)
imageInspectFunc func(image string) (types.ImageInspect, []byte, error)
imageImportFunc func(source image.ImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error)
imageImportFunc func(source types.ImageImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error)
imageHistoryFunc func(image string) ([]image.HistoryResponseItem, error)
imageBuildFunc func(context.Context, io.Reader, types.ImageBuildOptions) (types.ImageBuildResponse, error)
}
@ -74,18 +74,18 @@ func (cli *fakeClient) ImagePull(_ context.Context, ref string, options image.Pu
return io.NopCloser(strings.NewReader("")), nil
}
func (cli *fakeClient) ImagesPrune(_ context.Context, pruneFilter filters.Args) (image.PruneReport, error) {
func (cli *fakeClient) ImagesPrune(_ context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error) {
if cli.imagesPruneFunc != nil {
return cli.imagesPruneFunc(pruneFilter)
}
return image.PruneReport{}, nil
return types.ImagesPruneReport{}, nil
}
func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) {
func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) {
if cli.imageLoadFunc != nil {
return cli.imageLoadFunc(input, quiet)
}
return image.LoadResponse{}, nil
return types.ImageLoadResponse{}, nil
}
func (cli *fakeClient) ImageList(_ context.Context, options image.ListOptions) ([]image.Summary, error) {
@ -102,7 +102,7 @@ func (cli *fakeClient) ImageInspectWithRaw(_ context.Context, img string) (types
return types.ImageInspect{}, nil, nil
}
func (cli *fakeClient) ImageImport(_ context.Context, source image.ImportSource, ref string,
func (cli *fakeClient) ImageImport(_ context.Context, source types.ImageImportSource, ref string,
options image.ImportOptions,
) (io.ReadCloser, error) {
if cli.imageImportFunc != nil {

Some files were not shown because too many files have changed in this diff Show More