Compare commits

..

44 Commits

Author SHA1 Message Date
569dd73db1 Merge pull request #4126 from thaJeztah/23.0_backport_align_go_ver
Some checks failed
build / build (cross, ) (push) Has been cancelled
build / build (cross, glibc) (push) Has been cancelled
build / build (dynbinary-cross, ) (push) Has been cancelled
build / build (dynbinary-cross, glibc) (push) Has been cancelled
build / plugins (push) Has been cancelled
e2e / e2e (19.03-dind, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, non-experimental) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-11) (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-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[23.0 backport] Dockerfile: align go version
2023-03-27 17:44:26 +02:00
f6643207a2 don't use null values in the bake definition
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit bec5d37e91)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-27 17:18:38 +02:00
f381e08425 Dockerfile: align go version
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit b854eff300)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-27 17:18:35 +02:00
18f20a5537 Merge pull request #4124 from thaJeztah/23.0_e2e_fix_certs
[23.0 backport] e2e: update notary certificates
2023-03-27 17:18:13 +02:00
d3a36fc38c e2e: update notary certificates
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit b201ce5efd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-27 15:26:23 +02:00
59bb07f2e4 e2e: increase tests certificates duration (10 years)
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit c6c33380da)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-27 15:26:22 +02:00
80f27987f4 bake target to generate certs for e2e tets
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit d234a81de7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-27 15:26:20 +02:00
6a8406e602 Merge pull request #4092 from crazy-max/23.0_backport_buildx-completion
[23.0 backport] Add bash completion for available plugins
2023-03-22 20:05:09 +01:00
c2c122fb65 Merge pull request #4107 from thaJeztah/23.0_backport_size_flag_ps
[23.0 backport] Don't automatically request size if `--size` was explicitly set to `false`
2023-03-21 17:54:09 +01:00
40a48e4154 Merge pull request #4106 from thaJeztah/23.0_backport_fix_comments
[23.0 backport] cli/command: ElectAuthServer: fix deprecation comment
2023-03-21 17:52:39 +01:00
a43c9f3440 Don't automatically request size if --size was explicitly set to false
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 9733334487)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-21 17:02:35 +01:00
114e17ac4b cli/command: fix imports formatting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 742881fc58)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-21 16:58:47 +01:00
e2c402118c cli/command: ElectAuthServer: fix deprecation comment
The comment was not formatted correctly, and because of that not picked up as
being deprecated.

updates b4ca1c7368

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e3fa7280ad)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-21 16:58:47 +01:00
d07453890c Add bash completion for available plugins
Signed-off-by: CrazyMax <github@crazymax.dev>
(cherry picked from commit aa0aa4a6dc)
2023-03-17 15:06:45 +01:00
288b6c79fe Merge pull request #4083 from thaJeztah/23.0_backport_windows_drive_cwd_env
[23.0 backport] stack/loader: Ignore cmd.exe special env variables
2023-03-10 13:04:29 +01:00
fbab8cd2be Merge pull request #4086 from thaJeztah/23.0_backport_bump_go1.19.7
[23.0 backport] update to go1.19.7
2023-03-10 13:04:03 +01:00
b898a46135 Merge pull request #4088 from thaJeztah/23.0_backport_update_buildx
[23.0 backport] Dockerfile: update buildx to v0.10.4
2023-03-10 12:54:16 +01:00
90a72a5894 Dockerfile: update buildx to v0.10.4
release notes: https://github.com/docker/buildx/releases/tag/v0.10.4

full diff: https://github.com/docker/buildx/compare/v0.10.3...v0.10.4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 74c4ed4171)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-10 12:33:03 +01:00
4c63110a92 update to go1.19.7
Includes a security fix for crypto/elliptic (CVE-2023-24532).

> go1.19.7 (released 2023-03-07) includes a security fix to the crypto/elliptic
> package, as well as bug fixes to the linker, the runtime, and the crypto/x509
> and syscall packages. See the Go 1.19.7 milestone on our issue tracker for
> details.

https://go.dev/doc/devel/release#go1.19.minor

From the announcement:

> We have just released Go versions 1.20.2 and 1.19.7, minor point releases.
>
> These minor releases include 1 security fixes following the security policy:
>
> - crypto/elliptic: incorrect P-256 ScalarMult and ScalarBaseMult results
    >
    >   The ScalarMult and ScalarBaseMult methods of the P256 Curve may return an
    >   incorrect result if called with some specific unreduced scalars (a scalar larger
    >   than the order of the curve).
    >
    >   This does not impact usages of crypto/ecdsa or crypto/ecdh.
>
> This is CVE-2023-24532 and Go issue https://go.dev/issue/58647.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 23da1cec6c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-10 10:24:22 +01:00
b61b5a9878 stack: Change unexpected environment variable error
Make the error more specific by stating that it's caused by a specific
environment variable and not an environment as a whole.
Also don't escape the variable to make it more readable.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 012b77952e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-09 22:13:20 +01:00
84fe451ec7 stack/loader: Ignore cmd.exe special env variables
On Windows, ignore all variables that start with "=" when building an
environment variables map for stack.
For MS-DOS compatibility cmd.exe can set some special environment
variables that start with a "=" characters, which breaks the general
assumption that the first encountered "=" separates a variable name from
variable value and causes trouble when parsing.

These variables don't seem to be documented anywhere, but they are
described by some third-party sources and confirmed empirically on my
Windows installation.

Useful sources:
https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
https://ss64.com/nt/syntax-variables.html

Known variables:

- `=ExitCode` stores the exit code returned by external command (in hex
  format)
- `=ExitCodeAscii` - same as above, except the value is the ASCII
  representation of the code (so exit code 65 (0x41) becomes 'A').
- `=::=::\` and friends - store drive specific working directory.
  There is one env variable for each separate drive letter that was
  accessed in the shell session and stores the working directory for that
  specific drive.
  The general format for these is:
    `=<DRIVE_LETTER>:=<CWD>`  (key=`=<DRIVE_LETTER>:`, value=`<CWD>`)
  where <CWD> is a working directory for the drive that is assigned to
  the letter <DRIVE_LETTER>

  A couple of examples:
    `=C:=C:\some\dir`  (key: `=C:`, value: `C:\some\dir`)
    `=D:=D:\some\other\dir`  (key: `=C:`, value: `C:\some\dir`)
    `=Z:=Z:\`  (key: `=Z:`, value: `Z:\`)

  `=::=::\` is the one that seems to be always set and I'm not exactly
  sure what this one is for (what's drive `::`?). Others are set as
  soon as you CD to a path on some drive. Considering that you start a
  cmd.exe also has some working directory, there are 2 of these on start.

All these variables can be safely ignored because they can't be
deliberately set by the user, their meaning is only relevant to the
cmd.exe session and they're all are related to the MS-DOS/Batch feature
that are irrelevant for us.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit a47058bbd5)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-09 22:13:18 +01:00
71615c2df1 Merge pull request #4077 from thaJeztah/23.0_update_buildx
[23.0 backport] Dockerfile: update buildx to v0.10.3
2023-03-09 12:08:43 +01:00
a1acc9af91 Merge pull request #4076 from thaJeztah/23.0_backport_deprecate_buildinfo
[23.0 backport] docs: Deprecate buildkit's build information
2023-03-06 20:06:22 +01:00
95066ff3a2 Dockerfile: update buildx to v0.10.3
release notes: https://github.com/docker/buildx/releases/tag/v0.10.3

Signed-off-by: Jacopo Rigoli <rigoli.jacopo@gmail.com>
(cherry picked from commit dac79b19a7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-06 18:28:30 +01:00
0dbf70fad2 docs: Deprecate buildkit's build information
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 8bc1aaceae)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-06 18:25:03 +01:00
e0b8e19687 Merge pull request #4035 from thaJeztah/23.0_backport_carry_4027
[23.0 backport] changed the container name in docker stats page
2023-03-03 16:47:47 +01:00
98e874dac7 Merge pull request #4039 from thaJeztah/23.0_backport_bump_go_1.19.6
[23.0 backport] update to go1.19.6
2023-03-02 14:34:36 +01:00
92164b0306 Merge pull request #4065 from vvoland/dangling-images-none-23
[23.0 backport] formatter: Consider empty RepoTags and RepoDigests as dangling
2023-03-02 14:31:31 +01:00
5af8077eeb formatter: Consider empty RepoTags and RepoDigests as dangling
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 89687d5b3f)
2023-03-02 09:48:45 +01:00
d352c504a8 Merge pull request #4061 from vvoland/test-fakecli-images-mock-23
[23.0 backport] test/cli: Use empty array as empty output of images/json
2023-03-01 21:03:06 +01:00
28c74b759b Merge pull request #4063 from thaJeztah/23.0_backport_write_file
[23.0 backport] context: avoid corrupt file writes
2023-03-01 21:02:40 +01:00
57a502772b context: avoid corrupt file writes
Write to a tempfile then move, so that if the
process dies mid-write it doesn't corrupt the store.

Also improve error messaging so that if a file does
get corrupted, the user has some hope of figuring
out which file is broken.

For background, see:
https://github.com/docker/for-win/issues/13180
https://github.com/docker/for-win/issues/12561

For a repro case, see:
https://github.com/nicks/contextstore-sandbox

Signed-off-by: Nick Santos <nick.santos@docker.com>
(cherry picked from commit c2487c2997)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-03-01 16:14:03 +01:00
14ac8db968 test/cli: Use empty array as empty output of images/json
Tests mocking the output of GET images/json with fakeClient used an
array with one empty element as an empty response.
Change it to just an empty array.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit a1953e19b2)
2023-03-01 15:59:31 +01:00
1ab7665be8 Merge pull request #4047 from neersighted/backport/4019/23.0
[23.0 backport] docs: drop dated comments about graphdrivers
2023-02-23 18:41:54 +01:00
1810e922ac docs: drop dated comments about graphdrivers
Signed-off-by: Bjorn Neergaard <bneergaard@mirantis.com>
(cherry picked from commit e636747a14)
Signed-off-by: Bjorn Neergaard <bneergaard@mirantis.com>
2023-02-23 09:28:27 -07:00
5051d82a17 update to go1.19.6
go1.19.6 (released 2023-02-14) includes security fixes to the crypto/tls,
mime/multipart, net/http, and path/filepath packages, as well as bug fixes to
the go command, the linker, the runtime, and the crypto/x509, net/http, and
time packages. See the Go 1.19.6 milestone on our issue tracker for details:

https://github.com/golang/go/issues?q=milestone%3AGo1.19.6+label%3ACherryPickApproved

From the announcement on the security mailing:

We have just released Go versions 1.20.1 and 1.19.6, minor point releases.

These minor releases include 4 security fixes following the security policy:

- path/filepath: path traversal in filepath.Clean on Windows

  On Windows, the filepath.Clean function could transform an invalid path such
  as a/../c:/b into the valid path c:\b. This transformation of a relative (if
  invalid) path into an absolute path could enable a directory traversal attack.
  The filepath.Clean function will now transform this path into the relative
  (but still invalid) path .\c:\b.

  This is CVE-2022-41722 and Go issue https://go.dev/issue/57274.

- net/http, mime/multipart: denial of service from excessive resource
  consumption

  Multipart form parsing with mime/multipart.Reader.ReadForm can consume largely
  unlimited amounts of memory and disk files. This also affects form parsing in
  the net/http package with the Request methods FormFile, FormValue,
  ParseMultipartForm, and PostFormValue.

  ReadForm takes a maxMemory parameter, and is documented as storing "up to
  maxMemory bytes +10MB (reserved for non-file parts) in memory". File parts
  which cannot be stored in memory are stored on disk in temporary files. The
  unconfigurable 10MB reserved for non-file parts is excessively large and can
  potentially open a denial of service vector on its own. However, ReadForm did
  not properly account for all memory consumed by a parsed form, such as map
  ntry overhead, part names, and MIME headers, permitting a maliciously crafted
  form to consume well over 10MB. In addition, ReadForm contained no limit on
  the number of disk files created, permitting a relatively small request body
  to create a large number of disk temporary files.

  ReadForm now properly accounts for various forms of memory overhead, and
  should now stay within its documented limit of 10MB + maxMemory bytes of
  memory consumption. Users should still be aware that this limit is high and
  may still be hazardous.

  ReadForm now creates at most one on-disk temporary file, combining multiple
  form parts into a single temporary file. The mime/multipart.File interface
  type's documentation states, "If stored on disk, the File's underlying
  concrete type will be an *os.File.". This is no longer the case when a form
  contains more than one file part, due to this coalescing of parts into a
  single file. The previous behavior of using distinct files for each form part
  may be reenabled with the environment variable
  GODEBUG=multipartfiles=distinct.

  Users should be aware that multipart.ReadForm and the http.Request methods
  that call it do not limit the amount of disk consumed by temporary files.
  Callers can limit the size of form data with http.MaxBytesReader.

  This is CVE-2022-41725 and Go issue https://go.dev/issue/58006.

- crypto/tls: large handshake records may cause panics

  Both clients and servers may send large TLS handshake records which cause
  servers and clients, respectively, to panic when attempting to construct
  responses.

  This affects all TLS 1.3 clients, TLS 1.2 clients which explicitly enable
  session resumption (by setting Config.ClientSessionCache to a non-nil value),
  and TLS 1.3 servers which request client certificates (by setting
  Config.ClientAuth
  > = RequestClientCert).

  This is CVE-2022-41724 and Go issue https://go.dev/issue/58001.

- net/http: avoid quadratic complexity in HPACK decoding

  A maliciously crafted HTTP/2 stream could cause excessive CPU consumption
  in the HPACK decoder, sufficient to cause a denial of service from a small
  number of small requests.

  This issue is also fixed in golang.org/x/net/http2 v0.7.0, for users manually
  configuring HTTP/2.

  This is CVE-2022-41723 and Go issue https://go.dev/issue/57855.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e921e103a4)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-17 01:11:03 +01:00
7f4e3ead75 changed the container name in docker stats page
Signed-off-by: Aslam Ahemad <aslamahemad@gmail.com>
(cherry picked from commit d2f726d5ad)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-15 11:53:36 +01:00
a5ee5b1dfc Merge pull request #4018 from thaJeztah/23.0_backport_fix_ci_events
Some checks failed
build / build (cross, ) (push) Has been cancelled
build / build (cross, glibc) (push) Has been cancelled
build / build (dynbinary-cross, ) (push) Has been cancelled
build / build (dynbinary-cross, glibc) (push) Has been cancelled
build / plugins (push) Has been cancelled
e2e / e2e (19.03-dind, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, non-experimental) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (bullseye, stable-dind, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-11) (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-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[23.0 backport] ci: fix branch filter pattern
2023-02-09 20:15:59 +01:00
27b19a6acf ci: fix branch filter pattern
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 0f39598687)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-09 19:55:03 +01:00
ab4ef4aed4 Merge pull request #4004 from thaJeztah/23.0_backports
[23.0 backports] assorted backports
2023-02-06 11:38:55 -08:00
14aac2c232 vendor: github.com/docker/docker v23.0.0
- client: improve error messaging on crash

full diff: https://github.com/docker/docker/compare/v23.0.0-rc.3...v23.0.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit bbebebaedf)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-06 14:47:36 +01:00
0cd15abfde vendor: github.com/containerd/containerd v1.6.16
no changes in vendored code

full diff: https://github.com/containerd/containerd/compare/v1.6.15...v1.6.16

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5195db1ff5)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-06 14:47:36 +01:00
168f1b55e2 cli/command/container: exit 126 on EISDIR error
The error returned from "os/exec".Command when attempting to execute a
directory has been changed from syscall.EACCESS to syscall.EISDIR on
Go 1.20. 2b8f214094
Consequently, any runc runtime built against Go 1.20 will return an
error containing 'is a directory' and not 'permission denied'. Update
the string matching so the CLI exits with status code 126 on 'is a
directory' errors (EISDIR) in addition to 'permission denied' (EACCESS).

Signed-off-by: Cory Snider <csnider@mirantis.com>
(cherry picked from commit 9b5ceb52b0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-06 14:47:36 +01:00
53ed25d9b6 Fix bad ThrottleDevice path
Fixes moby/moby#44904.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
(cherry picked from commit 56051b84b0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-02-06 14:47:33 +01:00
796 changed files with 10685 additions and 31067 deletions

View File

@ -15,64 +15,43 @@ on:
pull_request:
jobs:
prepare:
runs-on: ubuntu-20.04
outputs:
matrix: ${{ steps.platforms.outputs.matrix }}
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Create matrix
id: platforms
run: |
echo "matrix=$(docker buildx bake cross --print | jq -cr '.target."cross".platforms')" >>${GITHUB_OUTPUT}
-
name: Show matrix
run: |
echo ${{ steps.platforms.outputs.matrix }}
build:
runs-on: ubuntu-20.04
needs:
- prepare
strategy:
fail-fast: false
matrix:
target:
- binary
- dynbinary
platform: ${{ fromJson(needs.prepare.outputs.matrix) }}
- cross
- dynbinary-cross
use_glibc:
- ""
- glibc
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Build
uses: docker/bake-action@v3
name: Run ${{ matrix.target }}
uses: docker/bake-action@v2
with:
targets: ${{ matrix.target }}
set: |
*.platform=${{ matrix.platform }}
env:
USE_GLIBC: ${{ matrix.use_glibc }}
-
name: Create tarball
name: Flatten artifacts
working-directory: ./build
run: |
mkdir /tmp/out
platform=${{ matrix.platform }}
platformPair=${platform//\//-}
tar -cvzf "/tmp/out/docker-${platformPair}.tar.gz" .
for dir in */; do
base=$(basename "$dir")
echo "Creating ${base}.tar.gz ..."
tar -cvzf "${base}.tar.gz" "$dir"
rm -rf "$dir"
done
if [ -z "${{ matrix.use_glibc }}" ]; then
echo "ARTIFACT_NAME=${{ matrix.target }}" >> $GITHUB_ENV
else
@ -83,46 +62,20 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: ${{ env.ARTIFACT_NAME }}
path: /tmp/out/*
path: ./build/*
if-no-files-found: error
prepare-plugins:
runs-on: ubuntu-20.04
outputs:
matrix: ${{ steps.platforms.outputs.matrix }}
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Create matrix
id: platforms
run: |
echo "matrix=$(docker buildx bake plugins-cross --print | jq -cr '.target."plugins-cross".platforms')" >>${GITHUB_OUTPUT}
-
name: Show matrix
run: |
echo ${{ steps.platforms.outputs.matrix }}
plugins:
runs-on: ubuntu-20.04
needs:
- prepare-plugins
strategy:
fail-fast: false
matrix:
platform: ${{ fromJson(needs.prepare-plugins.outputs.matrix) }}
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Build
uses: docker/bake-action@v3
name: Build plugins
uses: docker/bake-action@v2
with:
targets: plugins-cross
set: |
*.platform=${{ matrix.platform }}

View File

@ -19,7 +19,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 2
-

View File

@ -36,7 +36,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Update daemon.json
run: |

View File

@ -20,13 +20,13 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Test
uses: docker/bake-action@v3
uses: docker/bake-action@v2
with:
targets: test-coverage
-
@ -56,14 +56,14 @@ jobs:
git config --system core.eol lf
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
path: ${{ env.GOPATH }}/src/github.com/docker/cli
-
name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v3
with:
go-version: 1.20.13
go-version: 1.19.4
-
name: Test
run: |

View File

@ -28,34 +28,15 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: Run
uses: docker/bake-action@v3
uses: docker/bake-action@v2
with:
targets: ${{ matrix.target }}
# check that the generated Markdown and the checked-in files match
validate-md:
runs-on: ubuntu-20.04
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Generate
shell: 'script --return --quiet --command "bash {0}"'
run: |
make -f docker.Makefile mddocs
-
name: Validate
run: |
if [[ $(git diff --stat) != '' ]]; then
echo 'fail: generated files do not match checked-in files'
git --no-pager diff
exit 1
fi
validate-make:
runs-on: ubuntu-20.04
strategy:
@ -67,7 +48,9 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: Run
shell: 'script --return --quiet --command "bash {0}"'

View File

@ -32,11 +32,12 @@ run:
linters-settings:
depguard:
rules:
main:
deny:
- pkg: io/ioutil
desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
list-type: blacklist
include-go-root: true
packages:
# The io/ioutil package has been deprecated.
# https://go.dev/doc/go1.16#ioutil
- io/ioutil
gocyclo:
min-complexity: 16
govet:
@ -116,10 +117,7 @@ issues:
- text: "package-comments: should have a package comment"
linters:
- revive
# FIXME temporarily suppress these (see https://github.com/gotestyourself/gotest.tools/issues/272)
- text: "SA1019: (assert|cmp|is)\\.ErrorType is deprecated"
linters:
- staticcheck
# Exclude some linters from running on tests files.
- path: _test\.go
linters:

View File

@ -192,7 +192,7 @@ For more details, see the [MAINTAINERS](MAINTAINERS) page.
The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch or otherwise have the right to pass
it on as an open-source patch. The rules are pretty simple: if you can certify
the below (from [developercertificate.org](https://developercertificate.org):
the below (from [developercertificate.org](http://developercertificate.org/)):
```
Developer Certificate of Origin
@ -336,8 +336,9 @@ The rules:
1. All code should be formatted with `gofumpt` (preferred) or `gofmt -s`.
2. All code should pass the default levels of
[`golint`](https://github.com/golang/lint).
3. All code should follow the guidelines covered in [Effective Go](https://go.dev/doc/effective_go)
and [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
3. All code should follow the guidelines covered in [Effective
Go](http://golang.org/doc/effective_go.html) and [Go Code Review
Comments](https://github.com/golang/go/wiki/CodeReviewComments).
4. Comment the code. Tell us the why, the history and the context.
5. Document _all_ declarations and methods, even private ones. Declare
expectations, caveats and anything else that may be important. If a type
@ -359,6 +360,6 @@ The rules:
guidelines. Since you've read all the rules, you now know that.
If you are having trouble getting into the mood of idiomatic Go, we recommend
reading through [Effective Go](https://go.dev/doc/effective_go). The
[Go Blog](https://go.dev/blog/) is also a great resource. Drinking the
reading through [Effective Go](https://golang.org/doc/effective_go.html). The
[Go Blog](https://blog.golang.org) is also a great resource. Drinking the
kool-aid is a lot easier than going thirsty.

View File

@ -1,19 +1,17 @@
# syntax=docker/dockerfile:1
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.20.13
ARG ALPINE_VERSION=3.18
ARG XX_VERSION=1.2.1
ARG GO_VERSION=1.19.7
ARG ALPINE_VERSION=3.16
ARG XX_VERSION=1.1.1
ARG GOVERSIONINFO_VERSION=v1.3.0
ARG GOTESTSUM_VERSION=v1.10.0
ARG BUILDX_VERSION=0.11.2
ARG COMPOSE_VERSION=v2.22.0
ARG GOTESTSUM_VERSION=v1.8.2
ARG BUILDX_VERSION=0.10.4
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build-base-alpine
ENV GOTOOLCHAIN=local
COPY --link --from=xx / /
COPY --from=xx / /
RUN apk add --no-cache bash clang lld llvm file git
WORKDIR /go/src/github.com/docker/cli
@ -23,8 +21,7 @@ ARG TARGETPLATFORM
RUN xx-apk add --no-cache musl-dev gcc
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-bullseye
ENV GOTOOLCHAIN=local
COPY --link --from=xx / /
COPY --from=xx / /
RUN apt-get update && apt-get install --no-install-recommends -y bash clang lld llvm file
WORKDIR /go/src/github.com/docker/cli
@ -43,13 +40,13 @@ FROM build-base-${BASE_VARIANT} AS goversioninfo
ARG GOVERSIONINFO_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
GOBIN=/out GO111MODULE=on go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}"
FROM build-base-${BASE_VARIANT} AS gotestsum
ARG GOTESTSUM_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
GOBIN=/out GO111MODULE=on CGO_ENABLED=0 go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
GOBIN=/out GO111MODULE=on go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}" \
&& /out/gotestsum --version
FROM build-${BASE_VARIANT} AS build
@ -65,7 +62,7 @@ ARG CGO_ENABLED
ARG VERSION
# PACKAGER_NAME sets the company that produced the windows binary
ARG PACKAGER_NAME
COPY --link --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
COPY --from=goversioninfo /out/goversioninfo /usr/bin/goversioninfo
# in bullseye arm64 target does not link with lld so configure it to use ld instead
RUN [ ! -f /etc/alpine-release ] && xx-info is-cross && [ "$(xx-info arch)" = "arm64" ] && XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple || true
RUN --mount=type=bind,target=.,ro \
@ -79,7 +76,7 @@ RUN --mount=type=bind,target=.,ro \
xx-verify $([ "$GO_LINKMODE" = "static" ] && echo "--static") /out/docker
FROM build-${BASE_VARIANT} AS test
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
ENV GO111MODULE=auto
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/root/.cache \
@ -101,34 +98,35 @@ RUN --mount=ro --mount=type=cache,target=/root/.cache \
TARGET=/out ./scripts/build/plugins e2e/cli-plugins/plugins/*
FROM build-base-alpine AS e2e-base-alpine
RUN apk add --no-cache build-base curl openssl openssh-client
RUN apk add --no-cache build-base curl docker-compose openssl openssh-client
FROM build-base-bullseye AS e2e-base-bullseye
RUN apt-get update && apt-get install -y build-essential curl openssl openssh-client
ARG COMPOSE_VERSION=1.29.2
RUN curl -fsSL https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
FROM docker/compose-bin:${COMPOSE_VERSION} AS compose
FROM docker/buildx-bin:${BUILDX_VERSION} AS buildx
FROM e2e-base-${BASE_VARIANT} AS e2e
ARG NOTARY_VERSION=v0.6.1
ADD --chmod=0755 https://github.com/theupdateframework/notary/releases/download/${NOTARY_VERSION}/notary-Linux-amd64 /usr/local/bin/notary
COPY --link e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
COPY e2e/testdata/notary/root-ca.cert /usr/share/ca-certificates/notary.cert
RUN echo 'notary.cert' >> /etc/ca-certificates.conf && update-ca-certificates
COPY --link --from=gotestsum /out/gotestsum /usr/bin/gotestsum
COPY --link --from=build /out ./build/
COPY --link --from=build-plugins /out ./build/
COPY --link --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
COPY --link --from=compose /docker-compose /usr/libexec/docker/cli-plugins/docker-compose
COPY --link . .
COPY --from=gotestsum /out/gotestsum /usr/bin/gotestsum
COPY --from=build /out ./build/
COPY --from=build-plugins /out ./build/
COPY --from=buildx /buildx /usr/libexec/docker/cli-plugins/docker-buildx
COPY . .
ENV DOCKER_BUILDKIT=1
ENV PATH=/go/src/github.com/docker/cli/build:$PATH
CMD ./scripts/test/e2e/entry
FROM build-base-${BASE_VARIANT} AS dev
COPY --link . .
FROM scratch AS plugins
COPY --from=build-plugins /out .
COPY . .
FROM scratch AS binary
COPY --from=build /out .
FROM scratch AS plugins
COPY --from=build-plugins /out .

View File

@ -49,9 +49,9 @@
people = [
"bsousaa",
"neersighted",
"programmerq",
"sam-thibault",
"thajeztah",
"vvoland"
]
@ -103,11 +103,6 @@
Email = "nicolas.deloof@gmail.com"
GitHub = "ndeloof"
[people.neersighted]
Name = "Bjorn Neergaard"
Email = "bneergaard@mirantis.com"
GitHub = "neersighted"
[people.programmerq]
Name = "Jeff Anderson"
Email = "jeff@docker.com"

View File

@ -1 +1 @@
24.0.0-dev
23.0.0-dev

View File

@ -74,7 +74,7 @@ func TestValidateCandidate(t *testing.T) {
{name: "experimental + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental}},
} {
t.Run(tc.name, func(t *testing.T) {
p, err := newPlugin(tc.c, fakeroot.Commands())
p, err := newPlugin(tc.c, fakeroot)
if tc.err != "" {
assert.ErrorContains(t, err, tc.err)
} else if tc.invalid != "" {

View File

@ -3,7 +3,6 @@ package manager
import (
"fmt"
"os"
"sync"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
@ -32,69 +31,64 @@ const (
CommandAnnotationPluginInvalid = "com.docker.cli.plugin-invalid"
)
var pluginCommandStubsOnce sync.Once
// AddPluginCommandStubs adds a stub cobra.Commands for each valid and invalid
// plugin. The command stubs will have several annotations added, see
// `CommandAnnotationPlugin*`.
func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err error) {
pluginCommandStubsOnce.Do(func() {
var plugins []Plugin
plugins, err = ListPlugins(dockerCli, rootCmd)
if err != nil {
return
func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) error {
plugins, err := ListPlugins(dockerCli, rootCmd)
if err != nil {
return err
}
for _, p := range plugins {
p := p
vendor := p.Vendor
if vendor == "" {
vendor = "unknown"
}
for _, p := range plugins {
p := p
vendor := p.Vendor
if vendor == "" {
vendor = "unknown"
}
annotations := map[string]string{
CommandAnnotationPlugin: "true",
CommandAnnotationPluginVendor: vendor,
CommandAnnotationPluginVersion: p.Version,
}
if p.Err != nil {
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
}
rootCmd.AddCommand(&cobra.Command{
Use: p.Name,
Short: p.ShortDescription,
Run: func(_ *cobra.Command, _ []string) {},
Annotations: annotations,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
flags := rootCmd.PersistentFlags()
flags.SetOutput(nil)
perr := flags.Parse(args)
if perr != nil {
return err
}
if flags.Changed("help") {
cmd.HelpFunc()(rootCmd, args)
return nil
}
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name())
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Delegate completion to plugin
cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name}
cargs = append(cargs, args...)
cargs = append(cargs, toComplete)
os.Args = cargs
runCommand, runErr := PluginRunCommand(dockerCli, p.Name, cmd)
if runErr != nil {
return nil, cobra.ShellCompDirectiveError
}
runErr = runCommand.Run()
if runErr == nil {
os.Exit(0) // plugin already rendered complete data
}
annotations := map[string]string{
CommandAnnotationPlugin: "true",
CommandAnnotationPluginVendor: vendor,
CommandAnnotationPluginVersion: p.Version,
}
if p.Err != nil {
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
}
rootCmd.AddCommand(&cobra.Command{
Use: p.Name,
Short: p.ShortDescription,
Run: func(_ *cobra.Command, _ []string) {},
Annotations: annotations,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
flags := rootCmd.PersistentFlags()
flags.SetOutput(nil)
err := flags.Parse(args)
if err != nil {
return err
}
if flags.Changed("help") {
cmd.HelpFunc()(rootCmd, args)
return nil
}
return fmt.Errorf("docker: '%s' is not a docker command.\nSee 'docker --help'", cmd.Name())
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Delegate completion to plugin
cargs := []string{p.Path, cobra.ShellCompRequestCmd, p.Name}
cargs = append(cargs, args...)
cargs = append(cargs, toComplete)
os.Args = cargs
runCommand, err := PluginRunCommand(dockerCli, p.Name, cmd)
if err != nil {
return nil, cobra.ShellCompDirectiveError
},
})
}
})
return err
}
err = runCommand.Run()
if err == nil {
os.Exit(0) // plugin already rendered complete data
}
return nil, cobra.ShellCompDirectiveError
},
})
}
return nil
}

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.19
package manager
import (

View File

@ -1,18 +1,15 @@
package manager
import (
"context"
"os"
"path/filepath"
"sort"
"strings"
"sync"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/config"
"github.com/fvbommel/sortorder"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
exec "golang.org/x/sys/execabs"
)
@ -123,7 +120,7 @@ func GetPlugin(name string, dockerCli command.Cli, rootcmd *cobra.Command) (*Plu
return nil, errPluginNotFound(name)
}
c := &candidate{paths[0]}
p, err := newPlugin(c, rootcmd.Commands())
p, err := newPlugin(c, rootcmd)
if err != nil {
return nil, err
}
@ -149,32 +146,19 @@ func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error
}
var plugins []Plugin
var mu sync.Mutex
eg, _ := errgroup.WithContext(context.TODO())
cmds := rootcmd.Commands()
for _, paths := range candidates {
func(paths []string) {
eg.Go(func() error {
if len(paths) == 0 {
return nil
}
c := &candidate{paths[0]}
p, err := newPlugin(c, cmds)
if err != nil {
return err
}
if !IsNotFound(p.Err) {
p.ShadowedPaths = paths[1:]
mu.Lock()
defer mu.Unlock()
plugins = append(plugins, p)
}
return nil
})
}(paths)
}
if err := eg.Wait(); err != nil {
return nil, err
if len(paths) == 0 {
continue
}
c := &candidate{paths[0]}
p, err := newPlugin(c, rootcmd)
if err != nil {
return nil, err
}
if !IsNotFound(p.Err) {
p.ShadowedPaths = paths[1:]
plugins = append(plugins, p)
}
}
sort.Slice(plugins, func(i, j int) bool {
@ -215,7 +199,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
}
c := &candidate{path: path}
plugin, err := newPlugin(c, rootcmd.Commands())
plugin, err := newPlugin(c, rootcmd)
if err != nil {
return nil, err
}

View File

@ -23,7 +23,6 @@ type Metadata struct {
// URL is a pointer to the plugin's homepage.
URL string `json:",omitempty"`
// Experimental specifies whether the plugin is experimental.
//
// Deprecated: experimental features are now always enabled in the CLI
Experimental bool `json:",omitempty"`
}

View File

@ -31,7 +31,7 @@ type Plugin struct {
// is set, and is always a `pluginError`, but the `Plugin` is still
// returned with no error. An error is only returned due to a
// non-recoverable error.
func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) {
path := c.Path()
if path == "" {
return Plugin{}, errors.New("plugin candidate path cannot be empty")
@ -62,20 +62,22 @@ func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
return p, nil
}
for _, cmd := range cmds {
// Ignore conflicts with commands which are
// just plugin stubs (i.e. from a previous
// call to AddPluginCommandStubs).
if IsPluginCommand(cmd) {
continue
}
if cmd.Name() == p.Name {
p.Err = NewPluginError("plugin %q duplicates builtin command", p.Name)
return p, nil
}
if cmd.HasAlias(p.Name) {
p.Err = NewPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
return p, nil
if rootcmd != nil {
for _, cmd := range rootcmd.Commands() {
// Ignore conflicts with commands which are
// just plugin stubs (i.e. from a previous
// call to AddPluginCommandStubs).
if IsPluginCommand(cmd) {
continue
}
if cmd.Name() == p.Name {
p.Err = NewPluginError("plugin %q duplicates builtin command", p.Name)
return p, nil
}
if cmd.HasAlias(p.Name) {
p.Err = NewPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
return p, nil
}
}
}

View File

@ -204,16 +204,6 @@ func DisableFlagsInUseLine(cmd *cobra.Command) {
})
}
// HasCompletionArg returns true if a cobra completion arg request is found.
func HasCompletionArg(args []string) bool {
for _, arg := range args {
if arg == cobra.ShellCompRequestCmd || arg == cobra.ShellCompNoDescRequestCmd {
return true
}
}
return false
}
var helpCommand = &cobra.Command{
Use: "help [command]",
Short: "Help about the command",
@ -426,7 +416,7 @@ func invalidPluginReason(cmd *cobra.Command) string {
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
}
const usageTemplate = `Usage:
var usageTemplate = `Usage:
{{- if not .HasSubCommands}} {{.UseLine}}{{end}}
{{- if .HasSubCommands}} {{ .CommandPath}}{{- if .HasAvailableFlags}} [OPTIONS]{{end}} COMMAND{{end}}
@ -525,5 +515,5 @@ Run '{{.CommandPath}} COMMAND --help' for more information on a command.
{{- end}}
`
const helpTemplate = `
var helpTemplate = `
{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}`

View File

@ -14,21 +14,21 @@ type fakeClient struct {
checkpointListFunc func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error)
}
func (cli *fakeClient) CheckpointCreate(_ context.Context, container string, options types.CheckpointCreateOptions) error {
func (cli *fakeClient) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error {
if cli.checkpointCreateFunc != nil {
return cli.checkpointCreateFunc(container, options)
}
return nil
}
func (cli *fakeClient) CheckpointDelete(_ context.Context, container string, options types.CheckpointDeleteOptions) error {
func (cli *fakeClient) CheckpointDelete(ctx context.Context, container string, options types.CheckpointDeleteOptions) error {
if cli.checkpointDeleteFunc != nil {
return cli.checkpointDeleteFunc(container, options)
}
return nil
}
func (cli *fakeClient) CheckpointList(_ context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) {
func (cli *fakeClient) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) {
if cli.checkpointListFunc != nil {
return cli.checkpointListFunc(container, options)
}

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.19
package command
import (
@ -11,6 +8,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"
@ -50,7 +48,9 @@ type Streams interface {
// Cli represents the docker command line client.
type Cli interface {
Client() client.APIClient
Streams
Out() *streams.Out
Err() io.Writer
In() *streams.In
SetIn(in *streams.In)
Apply(ops ...DockerCliOption) error
ConfigFile() *configfile.ConfigFile
@ -164,8 +164,8 @@ func (cli *DockerCli) ContentTrustEnabled() bool {
// BuildKitEnabled returns buildkit is enabled or not.
func (cli *DockerCli) BuildKitEnabled() (bool, error) {
// use DOCKER_BUILDKIT env var value if set and not empty
if v := os.Getenv("DOCKER_BUILDKIT"); v != "" {
// use DOCKER_BUILDKIT env var value if set
if v, ok := os.LookupEnv("DOCKER_BUILDKIT"); ok {
enabled, err := strconv.ParseBool(v)
if err != nil {
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
@ -191,7 +191,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
// RegistryClient returns a client for communicating with a Docker distribution
// registry
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
resolver := func(ctx context.Context, index *registry.IndexInfo) types.AuthConfig {
return ResolveAuthConfig(ctx, cli, index)
}
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
@ -329,8 +329,13 @@ func (cli *DockerCli) getInitTimeout() time.Duration {
func (cli *DockerCli) initializeFromClient() {
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, cli.getInitTimeout())
defer cancel()
if !strings.HasPrefix(cli.dockerEndpoint.Host, "ssh://") {
// @FIXME context.WithTimeout doesn't work with connhelper / ssh connections
// time="2020-04-10T10:16:26Z" level=warning msg="commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
var cancel func()
ctx, cancel = context.WithTimeout(ctx, cli.getInitTimeout())
defer cancel()
}
ping, err := cli.client.Ping(ctx)
if err != nil {
@ -378,7 +383,7 @@ func (cli *DockerCli) ContextStore() store.Store {
// the "default" context is used if:
//
// - The "--host" option is set
// - The "DOCKER_HOST" ([client.EnvOverrideHost]) environment variable is set
// - The "DOCKER_HOST" ([DefaultContextName]) environment variable is set
// to a non-empty value.
//
// In these cases, the default context is used, which uses the host as

View File

@ -6,7 +6,7 @@ import (
"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/volume"
"github.com/docker/docker/api/types/filters"
"github.com/spf13/cobra"
)
@ -66,13 +66,13 @@ func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Conta
// VolumeNames offers completion for volumes
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(), filters.Args{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
var names []string
for _, vol := range list.Volumes {
names = append(names, vol.Name)
for _, volume := range list.Volumes {
names = append(names, volume.Name)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
@ -94,6 +94,6 @@ func NetworkNames(dockerCli command.Cli) ValidArgsFn {
}
// NoComplete is used for commands where there's no relevant completion
func NoComplete(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
func NoComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
}

View File

@ -10,34 +10,34 @@ import (
type fakeClient struct {
client.Client
configCreateFunc func(context.Context, swarm.ConfigSpec) (types.ConfigCreateResponse, error)
configInspectFunc func(context.Context, string) (swarm.Config, []byte, error)
configListFunc func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error)
configInspectFunc func(string) (swarm.Config, []byte, error)
configListFunc func(types.ConfigListOptions) ([]swarm.Config, error)
configRemoveFunc func(string) error
}
func (c *fakeClient) ConfigCreate(ctx context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if c.configCreateFunc != nil {
return c.configCreateFunc(ctx, spec)
return c.configCreateFunc(spec)
}
return types.ConfigCreateResponse{}, nil
}
func (c *fakeClient) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
if c.configInspectFunc != nil {
return c.configInspectFunc(ctx, id)
return c.configInspectFunc(id)
}
return swarm.Config{}, nil, nil
}
func (c *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
if c.configListFunc != nil {
return c.configListFunc(ctx, options)
return c.configListFunc(options)
}
return []swarm.Config{}, nil
}
func (c *fakeClient) ConfigRemove(_ context.Context, name string) error {
func (c *fakeClient) ConfigRemove(ctx context.Context, name string) error {
if c.configRemoveFunc != nil {
return c.configRemoveFunc(name)
}

View File

@ -1,7 +1,6 @@
package config
import (
"context"
"io"
"os"
"path/filepath"
@ -23,7 +22,7 @@ const configDataFile = "config-create-with-name.golden"
func TestConfigCreateErrors(t *testing.T) {
testCases := []struct {
args []string
configCreateFunc func(context.Context, swarm.ConfigSpec) (types.ConfigCreateResponse, error)
configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error)
expectedError string
}{
{
@ -36,7 +35,7 @@ func TestConfigCreateErrors(t *testing.T) {
},
{
args: []string{"name", filepath.Join("testdata", configDataFile)},
configCreateFunc: func(_ context.Context, configSpec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
configCreateFunc: func(configSpec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
return types.ConfigCreateResponse{}, errors.Errorf("error creating config")
},
expectedError: "error creating config",
@ -58,7 +57,7 @@ func TestConfigCreateWithName(t *testing.T) {
name := "foo"
var actual []byte
cli := test.NewFakeCli(&fakeClient{
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if spec.Name != name {
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
@ -97,7 +96,7 @@ func TestConfigCreateWithLabels(t *testing.T) {
}
cli := test.NewFakeCli(&fakeClient{
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if !reflect.DeepEqual(spec, expected) {
return types.ConfigCreateResponse{}, errors.Errorf("expected %+v, got %+v", expected, spec)
}
@ -123,7 +122,7 @@ func TestConfigCreateWithTemplatingDriver(t *testing.T) {
name := "foo"
cli := test.NewFakeCli(&fakeClient{
configCreateFunc: func(_ context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if spec.Name != name {
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}

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.19
package config
import (

View File

@ -1,7 +1,6 @@
package config
import (
"context"
"fmt"
"io"
"testing"
@ -19,7 +18,7 @@ func TestConfigInspectErrors(t *testing.T) {
testCases := []struct {
args []string
flags map[string]string
configInspectFunc func(_ context.Context, configID string) (swarm.Config, []byte, error)
configInspectFunc func(configID string) (swarm.Config, []byte, error)
expectedError string
}{
{
@ -27,7 +26,7 @@ func TestConfigInspectErrors(t *testing.T) {
},
{
args: []string{"foo"},
configInspectFunc: func(_ context.Context, configID string) (swarm.Config, []byte, error) {
configInspectFunc: func(configID string) (swarm.Config, []byte, error) {
return swarm.Config{}, nil, errors.Errorf("error while inspecting the config")
},
expectedError: "error while inspecting the config",
@ -41,7 +40,7 @@ func TestConfigInspectErrors(t *testing.T) {
},
{
args: []string{"foo", "bar"},
configInspectFunc: func(_ context.Context, configID string) (swarm.Config, []byte, error) {
configInspectFunc: func(configID string) (swarm.Config, []byte, error) {
if configID == "foo" {
return *Config(ConfigName("foo")), nil, nil
}
@ -69,12 +68,12 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
testCases := []struct {
name string
args []string
configInspectFunc func(_ context.Context, configID string) (swarm.Config, []byte, error)
configInspectFunc func(configID string) (swarm.Config, []byte, error)
}{
{
name: "single-config",
args: []string{"foo"},
configInspectFunc: func(_ context.Context, name string) (swarm.Config, []byte, error) {
configInspectFunc: func(name string) (swarm.Config, []byte, error) {
if name != "foo" {
return swarm.Config{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
}
@ -84,7 +83,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
{
name: "multiple-configs-with-labels",
args: []string{"foo", "bar"},
configInspectFunc: func(_ context.Context, name string) (swarm.Config, []byte, error) {
configInspectFunc: func(name string) (swarm.Config, []byte, error) {
return *Config(ConfigID("ID-"+name), ConfigName(name), ConfigLabels(map[string]string{
"label1": "label-foo",
})), nil, nil
@ -101,7 +100,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
}
func TestConfigInspectWithFormat(t *testing.T) {
configInspectFunc := func(_ context.Context, name string) (swarm.Config, []byte, error) {
configInspectFunc := func(name string) (swarm.Config, []byte, error) {
return *Config(ConfigName("foo"), ConfigLabels(map[string]string{
"label1": "label-foo",
})), nil, nil
@ -110,7 +109,7 @@ func TestConfigInspectWithFormat(t *testing.T) {
name string
format string
args []string
configInspectFunc func(_ context.Context, name string) (swarm.Config, []byte, error)
configInspectFunc func(name string) (swarm.Config, []byte, error)
}{
{
name: "simple-template",
@ -140,11 +139,11 @@ func TestConfigInspectWithFormat(t *testing.T) {
func TestConfigInspectPretty(t *testing.T) {
testCases := []struct {
name string
configInspectFunc func(context.Context, string) (swarm.Config, []byte, error)
configInspectFunc func(string) (swarm.Config, []byte, error)
}{
{
name: "simple",
configInspectFunc: func(_ context.Context, id string) (swarm.Config, []byte, error) {
configInspectFunc: func(id string) (swarm.Config, []byte, error) {
return *Config(
ConfigLabels(map[string]string{
"lbl1": "value1",

View File

@ -1,7 +1,6 @@
package config
import (
"context"
"io"
"testing"
"time"
@ -20,7 +19,7 @@ import (
func TestConfigListErrors(t *testing.T) {
testCases := []struct {
args []string
configListFunc func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
configListFunc func(types.ConfigListOptions) ([]swarm.Config, error)
expectedError string
}{
{
@ -28,7 +27,7 @@ func TestConfigListErrors(t *testing.T) {
expectedError: "accepts no argument",
},
{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{}, errors.Errorf("error listing configs")
},
expectedError: "error listing configs",
@ -48,7 +47,7 @@ func TestConfigListErrors(t *testing.T) {
func TestConfigList(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{
*Config(ConfigID("ID-1-foo"),
ConfigName("1-foo"),
@ -78,7 +77,7 @@ func TestConfigList(t *testing.T) {
func TestConfigListWithQuietOption(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{
*Config(ConfigID("ID-foo"), ConfigName("foo")),
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
@ -95,7 +94,7 @@ func TestConfigListWithQuietOption(t *testing.T) {
func TestConfigListWithConfigFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{
*Config(ConfigID("ID-foo"), ConfigName("foo")),
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
@ -114,7 +113,7 @@ func TestConfigListWithConfigFormat(t *testing.T) {
func TestConfigListWithFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{
*Config(ConfigID("ID-foo"), ConfigName("foo")),
*Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{
@ -131,7 +130,7 @@ func TestConfigListWithFormat(t *testing.T) {
func TestConfigListWithFilter(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(_ context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]))
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
return []swarm.Config{

View File

@ -64,7 +64,7 @@ func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (typ
return types.ContainerExecInspect{}, nil
}
func (f *fakeClient) ContainerExecStart(context.Context, string, types.ExecStartCheck) error {
func (f *fakeClient) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
return nil
}
@ -89,7 +89,7 @@ func (f *fakeClient) ContainerRemove(ctx context.Context, container string, opti
return nil
}
func (f *fakeClient) ImageCreate(_ context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
if f.imageCreateFunc != nil {
return f.imageCreateFunc(parentReference, options)
}

View File

@ -1,20 +1,15 @@
package container
import (
"bytes"
"context"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"strings"
"sync/atomic"
"time"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/system"
@ -53,73 +48,26 @@ type cpConfig struct {
// copying files to/from a container.
type copyProgressPrinter struct {
io.ReadCloser
total *int64
toContainer bool
total *float64
writer io.Writer
}
const (
copyToContainerHeader = "Copying to container - "
copyFromContainerHeader = "Copying from container - "
copyProgressUpdateThreshold = 75 * time.Millisecond
)
func (pt *copyProgressPrinter) Read(p []byte) (int, error) {
n, err := pt.ReadCloser.Read(p)
atomic.AddInt64(pt.total, int64(n))
return n, err
}
*pt.total += float64(n)
func copyProgress(ctx context.Context, dst io.Writer, header string, total *int64) (func(), <-chan struct{}) {
done := make(chan struct{})
if !streams.NewOut(dst).IsTerminal() {
close(done)
return func() {}, done
}
fmt.Fprint(dst, aec.Save)
fmt.Fprint(dst, "Preparing to copy...")
restore := func() {
fmt.Fprint(dst, aec.Restore)
fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
}
go func() {
defer close(done)
fmt.Fprint(dst, aec.Hide)
defer fmt.Fprint(dst, aec.Show)
fmt.Fprint(dst, aec.Restore)
fmt.Fprint(dst, aec.EraseLine(aec.EraseModes.All))
fmt.Fprint(dst, header)
var last int64
fmt.Fprint(dst, progressHumanSize(last))
buf := bytes.NewBuffer(nil)
ticker := time.NewTicker(copyProgressUpdateThreshold)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
n := atomic.LoadInt64(total)
if n == last {
// Don't write to the terminal, if we don't need to.
continue
}
// Write to the buffer first to avoid flickering and context switching
fmt.Fprint(buf, aec.Column(uint(len(header)+1)))
fmt.Fprint(buf, aec.EraseLine(aec.EraseModes.Tail))
fmt.Fprint(buf, progressHumanSize(n))
buf.WriteTo(dst)
buf.Reset()
last += n
}
if err == nil {
fmt.Fprint(pt.writer, aec.Restore)
fmt.Fprint(pt.writer, aec.EraseLine(aec.EraseModes.All))
if pt.toContainer {
fmt.Fprintln(pt.writer, "Copying to container - "+units.HumanSize(*pt.total))
} else {
fmt.Fprintln(pt.writer, "Copying from container - "+units.HumanSize(*pt.total))
}
}()
return restore, done
}
return n, err
}
// NewCopyCommand creates a new `docker cp` command
@ -165,10 +113,6 @@ func NewCopyCommand(dockerCli command.Cli) *cobra.Command {
return cmd
}
func progressHumanSize(n int64) string {
return units.HumanSizeWithPrecision(float64(n), 3)
}
func runCopy(dockerCli command.Cli, opts copyOptions) error {
srcContainer, srcPath := splitCpArg(opts.source)
destContainer, destPath := splitCpArg(opts.destination)
@ -209,7 +153,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
if absPath, err = filepath.Abs(localPath); err != nil {
return
}
return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
return archive.PreserveTrailingDotOrSeparator(absPath, localPath, filepath.Separator), nil
}
func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpConfig) (err error) {
@ -249,9 +193,6 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
}
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
defer cancel()
content, stat, err := client.CopyFromContainer(ctx, copyConfig.container, srcPath)
if err != nil {
return err
@ -270,11 +211,13 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
RebaseName: rebaseName,
}
var copiedSize int64
var copiedSize float64
if !copyConfig.quiet {
content = &copyProgressPrinter{
ReadCloser: content,
total: &copiedSize,
ReadCloser: content,
toContainer: false,
writer: dockerCli.Err(),
total: &copiedSize,
}
}
@ -288,12 +231,12 @@ func copyFromContainer(ctx context.Context, dockerCli command.Cli, copyConfig cp
return archive.CopyTo(preArchive, srcInfo, dstPath)
}
restore, done := copyProgress(ctx, dockerCli.Err(), copyFromContainerHeader, &copiedSize)
fmt.Fprint(dockerCli.Err(), aec.Save)
fmt.Fprintln(dockerCli.Err(), "Preparing to copy...")
res := archive.CopyTo(preArchive, srcInfo, dstPath)
cancel()
<-done
restore()
fmt.Fprintln(dockerCli.Err(), "Successfully copied", progressHumanSize(copiedSize), "to", dstPath)
fmt.Fprint(dockerCli.Err(), aec.Restore)
fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All))
fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", dstPath)
return res
}
@ -350,7 +293,7 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
var (
content io.ReadCloser
resolvedDstPath string
copiedSize int64
copiedSize float64
)
if srcPath == "-" {
@ -394,8 +337,10 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
content = preparedArchive
if !copyConfig.quiet {
content = &copyProgressPrinter{
ReadCloser: content,
total: &copiedSize,
ReadCloser: content,
toContainer: true,
writer: dockerCli.Err(),
total: &copiedSize,
}
}
}
@ -409,13 +354,12 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
return client.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options)
}
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
restore, done := copyProgress(ctx, dockerCli.Err(), copyToContainerHeader, &copiedSize)
fmt.Fprint(dockerCli.Err(), aec.Save)
fmt.Fprintln(dockerCli.Err(), "Preparing to copy...")
res := client.CopyToContainer(ctx, copyConfig.container, resolvedDstPath, content, options)
cancel()
<-done
restore()
fmt.Fprintln(dockerCli.Err(), "Successfully copied", progressHumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path)
fmt.Fprint(dockerCli.Err(), aec.Restore)
fmt.Fprint(dockerCli.Err(), aec.EraseLine(aec.EraseModes.All))
fmt.Fprintln(dockerCli.Err(), "Successfully copied", units.HumanSize(copiedSize), "to", copyConfig.container+":"+dstInfo.Path)
return res
}

View File

@ -12,7 +12,6 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/image"
"github.com/docker/cli/cli/streams"
"github.com/docker/cli/opts"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
@ -20,6 +19,7 @@ import (
"github.com/docker/docker/api/types/versions"
apiclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -95,16 +95,16 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
}
}
copts.env = *opts.NewListOptsRef(&newEnv, nil)
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
if err != nil {
reportError(dockerCli.Err(), "create", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
if err = validateAPIVersion(containerCfg, dockerCli.Client().ClientVersion()); err != nil {
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
reportError(dockerCli.Err(), "create", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
response, err := createContainer(context.Background(), dockerCli, containerCfg, options)
response, err := createContainer(context.Background(), dockerCli, containerConfig, options)
if err != nil {
return err
}
@ -112,27 +112,41 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, options *createOptio
return nil
}
// FIXME(thaJeztah): this is the only code-path that uses APIClient.ImageCreate. Rewrite this to use the regular "pull" code (or vice-versa).
func pullImage(ctx context.Context, dockerCli command.Cli, image string, opts *createOptions) error {
encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image)
func pullImage(ctx context.Context, dockerCli command.Cli, image string, platform string, out io.Writer) error {
ref, err := reference.ParseNormalizedNamed(image)
if err != nil {
return err
}
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, types.ImageCreateOptions{
// Resolve the Repository name from fqn to RepositoryInfo
repoInfo, err := registry.ParseRepositoryInfo(ref)
if err != nil {
return err
}
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
if err != nil {
return err
}
options := types.ImageCreateOptions{
RegistryAuth: encodedAuth,
Platform: opts.platform,
})
Platform: platform,
}
responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
if err != nil {
return err
}
defer responseBody.Close()
out := dockerCli.Err()
if opts.quiet {
out = io.Discard
}
return jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(out), nil)
return jsonmessage.DisplayJSONMessagesStream(
responseBody,
out,
dockerCli.Out().FD(),
dockerCli.Out().IsTerminal(),
nil)
}
type cidFile struct {
@ -185,10 +199,10 @@ func newCIDFile(path string) (*cidFile, error) {
}
//nolint:gocyclo
func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
config := containerCfg.Config
hostConfig := containerCfg.HostConfig
networkingConfig := containerCfg.NetworkingConfig
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.CreateResponse, error) {
config := containerConfig.Config
hostConfig := containerConfig.HostConfig
networkingConfig := containerConfig.NetworkingConfig
warnOnOomKillDisable(*hostConfig, dockerCli.Err())
warnOnLocalhostDNS(*hostConfig, dockerCli.Err())
@ -213,7 +227,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted {
var err error
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef)
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
if err != nil {
return nil, err
}
@ -222,7 +236,11 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
}
pullAndTagImage := func() error {
if err := pullImage(ctx, dockerCli, config.Image, opts); err != nil {
pullOut := dockerCli.Err()
if opts.quiet {
pullOut = io.Discard
}
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, pullOut); err != nil {
return err
}
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
@ -275,8 +293,8 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
}
}
for _, w := range response.Warnings {
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", w)
for _, warning := range response.Warnings {
fmt.Fprintf(dockerCli.Err(), "WARNING: %s\n", warning)
}
err = containerIDFile.Write(response.ID)
return &response, err

View File

@ -3,6 +3,7 @@ package container
import (
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
)
const (
@ -22,7 +23,7 @@ func NewDiffFormat(source string) formatter.Format {
}
// DiffFormatWrite writes formatted diff using the Context
func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange) error {
func DiffFormatWrite(ctx formatter.Context, changes []container.ContainerChangeResponseItem) error {
render := func(format func(subContext formatter.SubContext) error) error {
for _, change := range changes {
if err := format(&diffContext{c: change}); err != nil {
@ -36,7 +37,7 @@ func DiffFormatWrite(ctx formatter.Context, changes []container.FilesystemChange
type diffContext struct {
formatter.HeaderContext
c container.FilesystemChange
c container.ContainerChangeResponseItem
}
func newDiffContext() *diffContext {
@ -53,7 +54,16 @@ func (d *diffContext) MarshalJSON() ([]byte, error) {
}
func (d *diffContext) Type() string {
return d.c.Kind.String()
var kind string
switch d.c.Kind {
case archive.ChangeModify:
kind = "C"
case archive.ChangeAdd:
kind = "A"
case archive.ChangeDelete:
kind = "D"
}
return kind
}
func (d *diffContext) Path() string {

View File

@ -6,6 +6,7 @@ import (
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
"gotest.tools/v3/assert"
)
@ -40,10 +41,10 @@ D: /usr/app/old_app.js
},
}
diffs := []container.FilesystemChange{
{Kind: container.ChangeModify, Path: "/var/log/app.log"},
{Kind: container.ChangeAdd, Path: "/usr/app/app.js"},
{Kind: container.ChangeDelete, Path: "/usr/app/old_app.js"},
diffs := []container.ContainerChangeResponseItem{
{Kind: archive.ChangeModify, Path: "/var/log/app.log"},
{Kind: archive.ChangeAdd, Path: "/usr/app/app.js"},
{Kind: archive.ChangeDelete, Path: "/usr/app/old_app.js"},
}
for _, tc := range cases {

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.19
package container
import (

View File

@ -120,8 +120,6 @@ func runPs(dockerCli command.Cli, options *psOptions) error {
if len(options.format) == 0 {
// load custom psFormat from CLI config (if any)
options.format = dockerCli.ConfigFile().PsFormat
} else if options.quiet {
_, _ = dockerCli.Err().Write([]byte("WARNING: Ignoring custom format, because both --format and --quiet are set.\n"))
}
listOptions, err := buildContainerListOptions(options)

View File

@ -309,22 +309,8 @@ func TestContainerListWithFormat(t *testing.T) {
}, nil
},
})
t.Run("with format", func(t *testing.T) {
cli.OutBuffer().Reset()
cmd := newListCommand(cli)
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
})
t.Run("with format and quiet", func(t *testing.T) {
cli.OutBuffer().Reset()
cmd := newListCommand(cli)
assert.Check(t, cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}"))
assert.Check(t, cmd.Flags().Set("quiet", "true"))
assert.NilError(t, cmd.Execute())
assert.Equal(t, cli.ErrBuffer().String(), "WARNING: Ignoring custom format, because both --format and --quiet are set.\n")
golden.Assert(t, cli.OutBuffer().String(), "container-list-quiet.golden")
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
}

View File

@ -123,7 +123,6 @@ type containerOptions struct {
runtime string
autoRemove bool
init bool
annotations *opts.MapOpts
Image string
Args []string
@ -164,7 +163,6 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
ulimits: opts.NewUlimitOpt(nil),
volumes: opts.NewListOpts(nil),
volumesFrom: opts.NewListOpts(nil),
annotations: opts.NewMapOpts(nil, nil),
}
// General purpose flags
@ -299,10 +297,6 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.BoolVar(&copts.init, "init", false, "Run an init inside the container that forwards signals and reaps processes")
flags.SetAnnotation("init", "version", []string{"1.25"})
flags.Var(copts.annotations, "annotation", "Add an annotation to the container (passed through to the OCI runtime)")
flags.SetAnnotation("annotation", "version", []string{"1.43"})
return copts
}
@ -354,10 +348,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
volumes := copts.volumes.GetMap()
// add any bind targets to the list of container volumes
for bind := range copts.volumes.GetMap() {
parsed, err := loader.ParseVolume(bind)
if err != nil {
return nil, err
}
parsed, _ := loader.ParseVolume(bind)
if parsed.Source != "" {
toBind := bind
@ -663,7 +654,6 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
Mounts: mounts,
MaskedPaths: maskedPaths,
ReadonlyPaths: readonlyPaths,
Annotations: copts.annotations.GetAll(),
}
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {

View File

@ -49,11 +49,11 @@ func parseRun(args []string) (*container.Config, *container.HostConfig, *network
return nil, nil, nil, err
}
// TODO: fix tests to accept ContainerConfig
containerCfg, err := parse(flags, copts, runtime.GOOS)
containerConfig, err := parse(flags, copts, runtime.GOOS)
if err != nil {
return nil, nil, nil, err
}
return containerCfg.Config, containerCfg.HostConfig, containerCfg.NetworkingConfig, err
return containerConfig.Config, containerConfig.HostConfig, containerConfig.NetworkingConfig, err
}
func setupRunFlags() (*pflag.FlagSet, *containerOptions) {

View File

@ -75,6 +75,6 @@ func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint6
// RunPrune calls the Container Prune API
// This returns the amount of space reclaimed and a detailed output string
func RunPrune(dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
return runPrune(dockerCli, pruneOptions{force: true, filter: filter})
}

View File

@ -105,22 +105,22 @@ func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copt
}
}
copts.env = *opts.NewListOptsRef(&newEnv, nil)
containerCfg, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
containerConfig, err := parse(flags, copts, dockerCli.ServerInfo().OSType)
// just in case the parse does not exit
if err != nil {
reportError(dockerCli.Err(), "run", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
if err = validateAPIVersion(containerCfg, dockerCli.CurrentVersion()); err != nil {
if err = validateAPIVersion(containerConfig, dockerCli.CurrentVersion()); err != nil {
reportError(dockerCli.Err(), "run", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
return runContainer(dockerCli, ropts, copts, containerCfg)
return runContainer(dockerCli, ropts, copts, containerConfig)
}
//nolint:gocyclo
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerCfg *containerConfig) error {
config := containerCfg.Config
func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptions, containerConfig *containerConfig) error {
config := containerConfig.Config
stdout, stderr := dockerCli.Out(), dockerCli.Err()
client := dockerCli.Client()
@ -144,7 +144,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
ctx, cancelFun := context.WithCancel(context.Background())
defer cancelFun()
createResponse, err := createContainer(ctx, dockerCli, containerCfg, &opts.createOptions)
createResponse, err := createContainer(ctx, dockerCli, containerConfig, &opts.createOptions)
if err != nil {
reportError(stderr, "run", err.Error(), true)
return runStartContainerErr(err)
@ -173,11 +173,11 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
dockerCli.ConfigFile().DetachKeys = opts.detachKeys
}
closeFn, err := attachContainer(ctx, dockerCli, &errCh, config, createResponse.ID)
close, err := attachContainer(ctx, dockerCli, &errCh, config, createResponse.ID)
if err != nil {
return err
}
defer closeFn()
defer close()
}
statusChan := waitExitOrRemoved(ctx, dockerCli, createResponse.ID, copts.autoRemove)

View File

@ -1,2 +0,0 @@
container_id
container_id

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.19
package command
import (

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.19
package context
import (
@ -121,7 +118,10 @@ func createNewContext(o *CreateOptions, cli command.Cli, s store.Writer) error {
if err := s.CreateOrUpdate(contextMetadata); err != nil {
return err
}
return s.ResetTLSMaterial(o.Name, &contextTLSData)
if err := s.ResetTLSMaterial(o.Name, &contextTLSData); err != nil {
return err
}
return nil
}
func checkContextNameForCreation(s store.Reader, name string) error {

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.19
package context
import (

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.19
package context
import (

View File

@ -6,7 +6,6 @@ import (
"io"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/docker/cli/cli/command"
@ -14,6 +13,7 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/flags"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/homedir"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
@ -57,11 +57,7 @@ func TestUseDefaultWithoutConfigFile(t *testing.T) {
// the _default_ configuration file. If we specify a custom configuration
// file, the CLI produces an error if the file doesn't exist.
tmpHomeDir := t.TempDir()
if runtime.GOOS == "windows" {
t.Setenv("USERPROFILE", tmpHomeDir)
} else {
t.Setenv("HOME", tmpHomeDir)
}
t.Setenv(homedir.Key(), tmpHomeDir)
configDir := filepath.Join(tmpHomeDir, ".docker")
configFilePath := filepath.Join(configDir, "config.json")

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.19
package command
import (

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.19
package command
import (

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.19
package command
import (

View File

@ -3,28 +3,28 @@ package command
import (
"sync"
"github.com/docker/docker/api/types/events"
eventtypes "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
type EventHandler interface {
Handle(action string, h func(events.Message))
Watch(c <-chan events.Message)
Handle(action string, h func(eventtypes.Message))
Watch(c <-chan eventtypes.Message)
}
// InitEventHandler initializes and returns an EventHandler
func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[string]func(events.Message))}
return &eventHandler{handlers: make(map[string]func(eventtypes.Message))}
}
type eventHandler struct {
handlers map[string]func(events.Message)
handlers map[string]func(eventtypes.Message)
mu sync.Mutex
}
func (w *eventHandler) Handle(action string, h func(events.Message)) {
func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
w.mu.Lock()
w.handlers[action] = h
w.mu.Unlock()
@ -33,7 +33,7 @@ func (w *eventHandler) Handle(action string, h func(events.Message)) {
// 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) {
func (w *eventHandler) Watch(c <-chan eventtypes.Message) {
for e := range c {
w.mu.Lock()
h, exists := w.handlers[e.Action]

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.19
package formatter
import (
@ -58,9 +55,6 @@ ports: {{- pad .Ports 1 0}}
}
return Format(format)
default: // custom format
if quiet {
return DefaultQuietFormat
}
return Format(source)
}
}

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.19
package formatter
import (
@ -166,7 +163,7 @@ containerID2 ubuntu "" 24 hours ago foobar_bar
},
{
Context{Format: NewContainerFormat("table {{.Image}}", true, false)},
"containerID1\ncontainerID2\n",
"IMAGE\nubuntu\nubuntu\n",
},
{
Context{Format: NewContainerFormat("table", true, false)},

View File

@ -84,3 +84,10 @@ func (c *clientContextContext) Error() string {
// TODO(thaJeztah) add "--no-trunc" option to context ls and set default to 30 cols to match "docker service ps"
return Ellipsis(c.c.Error, maxErrLength)
}
// KubernetesEndpoint returns the kubernetes endpoint.
//
// Deprecated: support for kubernetes endpoints in contexts has been removed, and this formatting option will always be empty.
func (c *clientContextContext) KubernetesEndpoint() string {
return ""
}

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.19
package formatter
import "strings"

View File

@ -14,7 +14,7 @@ import (
)
const (
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
@ -296,10 +296,10 @@ func (c *diskUsageImagesContext) Reclaimable() string {
for _, i := range c.images {
if i.Containers != 0 {
if i.Size == -1 || i.SharedSize == -1 {
if i.VirtualSize == -1 || i.SharedSize == -1 {
continue
}
used += i.Size - i.SharedSize
used += i.VirtualSize - i.SharedSize
}
}

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.19
package formatter
import (
@ -22,7 +19,7 @@ const (
JSONFormatKey = "json"
DefaultQuietFormat = "{{.ID}}"
JSONFormat = "{{json .}}"
jsonFormat = "{{json .}}"
)
// Format is the format string rendered using the Context
@ -65,7 +62,7 @@ func (c *Context) preFormat() {
case c.Format.IsTable():
c.finalFormat = c.finalFormat[len(TableFormatKey):]
case c.Format.IsJSON():
c.finalFormat = JSONFormat
c.finalFormat = jsonFormat
}
c.finalFormat = strings.Trim(c.finalFormat, " ")

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.19
package formatter
import (

View File

@ -205,7 +205,7 @@ func newImageContext() *imageContext {
"CreatedAt": CreatedAtHeader,
"Size": SizeHeader,
"Containers": containersHeader,
"VirtualSize": SizeHeader, // Deprecated: VirtualSize is deprecated, and equivalent to Size.
"VirtualSize": SizeHeader,
"SharedSize": sharedSizeHeader,
"UniqueSize": uniqueSizeHeader,
}
@ -260,13 +260,8 @@ func (c *imageContext) Containers() string {
return fmt.Sprintf("%d", c.i.Containers)
}
// VirtualSize shows the virtual size of the image and all of its parent
// images. Starting with docker 1.10, images are self-contained, and
// the VirtualSize is identical to Size.
//
// Deprecated: VirtualSize is deprecated, and equivalent to [imageContext.Size].
func (c *imageContext) VirtualSize() string {
return units.HumanSize(float64(c.i.Size))
return units.HumanSize(float64(c.i.VirtualSize))
}
func (c *imageContext) SharedSize() string {
@ -277,8 +272,8 @@ func (c *imageContext) SharedSize() string {
}
func (c *imageContext) UniqueSize() string {
if c.i.Size == -1 || c.i.SharedSize == -1 {
if c.i.VirtualSize == -1 || c.i.SharedSize == -1 {
return "N/A"
}
return units.HumanSize(float64(c.i.Size - c.i.SharedSize))
return units.HumanSize(float64(c.i.VirtualSize - c.i.SharedSize))
}

View File

@ -36,7 +36,7 @@ func TestImageContext(t *testing.T) {
call: ctx.ID,
},
{
imageCtx: imageContext{i: types.ImageSummary{Size: 10}, trunc: true},
imageCtx: imageContext{i: types.ImageSummary{Size: 10, VirtualSize: 10}, trunc: true},
expValue: "10B",
call: ctx.Size,
},
@ -70,9 +70,9 @@ func TestImageContext(t *testing.T) {
call: ctx.Containers,
},
{
imageCtx: imageContext{i: types.ImageSummary{Size: 10000}},
imageCtx: imageContext{i: types.ImageSummary{VirtualSize: 10000}},
expValue: "10kB",
call: ctx.VirtualSize, //nolint:staticcheck // ignore SA1019: field is deprecated, but still set on API < v1.44.
call: ctx.VirtualSize,
},
{
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 10000}},
@ -80,7 +80,7 @@ func TestImageContext(t *testing.T) {
call: ctx.SharedSize,
},
{
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, Size: 20000}},
imageCtx: imageContext{i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}},
expValue: "15kB",
call: ctx.UniqueSize,
},

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.19
package formatter
import (

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.19
package formatter
import (

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.19
package formatter
import (

View File

@ -14,14 +14,14 @@ type fakeClient struct {
serviceInspectFunc func(string) (swarm.Service, []byte, error)
}
func (cli *fakeClient) NodeInspectWithRaw(_ context.Context, nodeID string) (swarm.Node, []byte, error) {
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) {
if cli.nodeInspectFunc != nil {
return cli.nodeInspectFunc(nodeID)
}
return swarm.Node{}, []byte{}, nil
}
func (cli *fakeClient) ServiceInspectWithRaw(_ context.Context, serviceID string, _ types.ServiceInspectOptions) (swarm.Service, []byte, error) {
func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
if cli.serviceInspectFunc != nil {
return cli.serviceInspectFunc(serviceID)
}

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.19
package idresolver
import (

View File

@ -22,7 +22,6 @@ import (
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
@ -128,7 +127,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
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.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
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")
@ -280,7 +279,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
var resolvedTags []*resolvedTag
if !options.untrusted {
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
return TrustedReference(ctx, dockerCli, ref)
return TrustedReference(ctx, dockerCli, ref, nil)
}
// if there is a tar wrapper, the dockerfile needs to be replaced inside it
if buildCtx != nil {
@ -323,9 +322,9 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
configFile := dockerCli.ConfigFile()
creds, _ := configFile.GetAllCredentials()
authConfigs := make(map[string]registrytypes.AuthConfig, len(creds))
authConfigs := make(map[string]types.AuthConfig, len(creds))
for k, auth := range creds {
authConfigs[k] = registrytypes.AuthConfig(auth)
authConfigs[k] = types.AuthConfig(auth)
}
buildOptions := imageBuildOptions(dockerCli, options)
buildOptions.Version = types.BuilderV1

View File

@ -18,7 +18,7 @@ import (
const dockerfileContents = "FROM busybox"
func prepareEmpty(_ *testing.T) string {
func prepareEmpty(t *testing.T) string {
return ""
}

View File

@ -1,12 +1,11 @@
package build
import (
"fmt"
"os"
"path/filepath"
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
"github.com/moby/patternmatcher"
"github.com/moby/patternmatcher/ignorefile"
)
// ReadDockerignore reads the .dockerignore file in the context directory and
@ -23,11 +22,7 @@ func ReadDockerignore(contextDir string) ([]string, error) {
}
defer f.Close()
patterns, err := ignorefile.ReadAll(f)
if err != nil {
return nil, fmt.Errorf("error reading .dockerignore: %w", err)
}
return patterns, nil
return dockerignore.ReadAll(f)
}
// TrimBuildFilesFromExcludes removes the named Dockerfile and .dockerignore from

View File

@ -34,7 +34,7 @@ func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
dockerfile := bytes.NewBufferString(`
FROM alpine:frozen
FROM alpine:3.6
COPY foo /
`)
cli.SetIn(streams.NewIn(io.NopCloser(dockerfile)))
@ -66,7 +66,7 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
dir := fs.NewDir(t, "test-build-context",
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
fs.WithFile("Dockerfile", `
FROM alpine:frozen
FROM alpine:3.6
COPY foo bar /
`),
)
@ -155,7 +155,7 @@ func TestRunBuildFromLocalGitHubDir(t *testing.T) {
func TestRunBuildWithSymlinkedContext(t *testing.T) {
t.Setenv("DOCKER_BUILDKIT", "0")
dockerfile := `
FROM alpine:frozen
FROM alpine:3.6
RUN echo hello world
`

View File

@ -87,7 +87,7 @@ func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool)
return types.ImageLoadResponse{}, nil
}
func (cli *fakeClient) ImageList(_ context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
func (cli *fakeClient) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) {
if cli.imageListFunc != nil {
return cli.imageListFunc(options)
}

View File

@ -11,6 +11,7 @@ import (
"github.com/pkg/errors"
"gotest.tools/v3/assert"
"gotest.tools/v3/golden"
"gotest.tools/v3/skip"
)
func TestNewHistoryCommandErrors(t *testing.T) {
@ -42,7 +43,13 @@ func TestNewHistoryCommandErrors(t *testing.T) {
}
}
func notUTCTimezone() bool {
now := time.Now()
return now != now.UTC()
}
func TestNewHistoryCommandSuccess(t *testing.T) {
skip.If(t, notUTCTimezone, "expected output requires UTC timezone")
testCases := []struct {
name string
args []string
@ -55,7 +62,6 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
return []image.HistoryResponseItem{{
ID: "1234567890123456789",
Created: time.Now().Unix(),
Comment: "none",
}}, nil
},
},
@ -87,19 +93,13 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
// Set to UTC timezone as timestamps in output are
// printed in the current timezone
t.Setenv("TZ", "UTC")
cli := test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc})
cmd := NewHistoryCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
actual := cli.OutBuffer().String()
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
})
cli := test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc})
cmd := NewHistoryCommand(cli)
cmd.SetOut(io.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
actual := cli.OutBuffer().String()
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
}
}

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.19
package image
import (

View File

@ -69,7 +69,7 @@ func RunPull(cli command.Cli, opts PullOptions) error {
}
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
if err != nil {
return err
}

View File

@ -11,7 +11,6 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/pkg/errors"
@ -77,7 +76,7 @@ func RunPush(dockerCli command.Cli, opts pushOptions) error {
// Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
if err != nil {
return err
}

View File

@ -1,2 +1,2 @@
IMAGE CREATED AT CREATED BY SIZE COMMENT
abcdef 2017-01-01T12:00:03Z rose 0 new history item!
IMAGE CREATED AT CREATED BY SIZE COMMENT
abcdef 2017-01-01T12:00:03Z rose 0 new history item!

View File

@ -1,2 +1,2 @@
IMAGE CREATED CREATED BY SIZE COMMENT
123456789012 Less than a second ago 0B none
IMAGE CREATED CREATED BY SIZE COMMENT
123456789012 Less than a second ago 0B

View File

@ -14,6 +14,7 @@
"Architecture": "",
"Os": "",
"Size": 0,
"VirtualSize": 0,
"GraphDriver": {
"Data": null,
"Name": ""
@ -38,6 +39,7 @@
"Architecture": "",
"Os": "",
"Size": 0,
"VirtualSize": 0,
"GraphDriver": {
"Data": null,
"Name": ""

View File

@ -14,6 +14,7 @@
"Architecture": "",
"Os": "",
"Size": 0,
"VirtualSize": 0,
"GraphDriver": {
"Data": null,
"Name": ""

View File

@ -30,7 +30,7 @@ type target struct {
}
// TrustedPush handles content trust pushing of an image
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, options types.ImagePushOptions) error {
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, options types.ImagePushOptions) error {
responseBody, err := cli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
if err != nil {
return err
@ -44,7 +44,7 @@ func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
// PushTrustedReference pushes a canonical reference to the trust server.
//
//nolint:gocyclo
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader) error {
func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, in io.Reader) error {
// If it is a trusted push we would like to find the target entry which match the
// tag provided in the function and then do an AddTarget later.
target := &client.Target{}
@ -186,7 +186,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
if err != nil {
return err
}
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
if err != nil {
return err
}
@ -262,17 +262,20 @@ func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth)
// imagePullPrivileged pulls the image and displays it to the output
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, opts PullOptions) error {
encodedAuth, err := registrytypes.EncodeAuthConfig(*imgRefAndAuth.AuthConfig())
ref := reference.FamiliarString(imgRefAndAuth.Reference())
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
if err != nil {
return err
}
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
responseBody, err := cli.Client().ImagePull(ctx, reference.FamiliarString(imgRefAndAuth.Reference()), types.ImagePullOptions{
options := types.ImagePullOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: requestPrivilege,
All: opts.all,
Platform: opts.platform,
})
}
responseBody, err := cli.Client().ImagePull(ctx, ref, options)
if err != nil {
return err
}
@ -286,8 +289,8 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
}
// TrustedReference returns the canonical trusted reference for an image reference
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) {
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), ref.String())
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
if err != nil {
return nil, err
}
@ -337,8 +340,8 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
}
// AuthResolver returns an auth resolver function from a command.Cli
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
return func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
return command.ResolveAuthConfig(ctx, cli, index)
}
}

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.19
package inspect
import (

View File

@ -16,7 +16,7 @@ type osArch struct {
// Remove any unsupported os/arch combo
// list of valid os/arch values (see "Optional Environment Variables" section
// of https://go.dev/doc/install/source
// of https://golang.org/doc/install/source
// Added linux/s390x as we know System z support already exists
// Keep in sync with _docker_manifest_annotate in contrib/completion/bash/docker
var validOSArches = map[osArch]bool{

View File

@ -52,6 +52,6 @@ func (c *fakeClient) NetworkRemove(ctx context.Context, networkID string) error
return nil
}
func (c *fakeClient) NetworkInspectWithRaw(context.Context, string, types.NetworkInspectOptions) (types.NetworkResource, []byte, error) {
func (c *fakeClient) NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) {
return types.NetworkResource{}, nil, nil
}

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.19
package network
import (

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.19
package network
import (

View File

@ -70,7 +70,7 @@ func runPrune(dockerCli command.Cli, options pruneOptions) (output string, err e
// RunPrune calls the Network Prune API
// This returns the amount of space reclaimed and a detailed output string
func RunPrune(dockerCli command.Cli, _ bool, filter opts.FilterOpt) (uint64, string, error) {
func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
output, err := runPrune(dockerCli, pruneOptions{force: true, filter: filter})
return 0, output, err
}

View File

@ -20,49 +20,49 @@ type fakeClient struct {
serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error)
}
func (cli *fakeClient) NodeInspectWithRaw(context.Context, string) (swarm.Node, []byte, error) {
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
if cli.nodeInspectFunc != nil {
return cli.nodeInspectFunc()
}
return swarm.Node{}, []byte{}, nil
}
func (cli *fakeClient) NodeList(context.Context, types.NodeListOptions) ([]swarm.Node, error) {
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
if cli.nodeListFunc != nil {
return cli.nodeListFunc()
}
return []swarm.Node{}, nil
}
func (cli *fakeClient) NodeRemove(context.Context, string, types.NodeRemoveOptions) error {
func (cli *fakeClient) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error {
if cli.nodeRemoveFunc != nil {
return cli.nodeRemoveFunc()
}
return nil
}
func (cli *fakeClient) NodeUpdate(_ context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error {
func (cli *fakeClient) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error {
if cli.nodeUpdateFunc != nil {
return cli.nodeUpdateFunc(nodeID, version, node)
}
return nil
}
func (cli *fakeClient) Info(context.Context) (types.Info, error) {
func (cli *fakeClient) Info(ctx context.Context) (types.Info, error) {
if cli.infoFunc != nil {
return cli.infoFunc()
}
return types.Info{}, nil
}
func (cli *fakeClient) TaskInspectWithRaw(_ context.Context, taskID string) (swarm.Task, []byte, error) {
func (cli *fakeClient) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) {
if cli.taskInspectFunc != nil {
return cli.taskInspectFunc(taskID)
}
return swarm.Task{}, []byte{}, nil
}
func (cli *fakeClient) TaskList(_ context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
if cli.taskListFunc != nil {
return cli.taskListFunc(options)
}

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.19
package node
import (

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.19
package node
import (

View File

@ -20,42 +20,42 @@ type fakeClient struct {
pluginInspectFunc func(name string) (*types.Plugin, []byte, error)
}
func (c *fakeClient) PluginCreate(_ context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error {
func (c *fakeClient) PluginCreate(ctx context.Context, createContext io.Reader, createOptions types.PluginCreateOptions) error {
if c.pluginCreateFunc != nil {
return c.pluginCreateFunc(createContext, createOptions)
}
return nil
}
func (c *fakeClient) PluginEnable(_ context.Context, name string, enableOptions types.PluginEnableOptions) error {
func (c *fakeClient) PluginEnable(ctx context.Context, name string, enableOptions types.PluginEnableOptions) error {
if c.pluginEnableFunc != nil {
return c.pluginEnableFunc(name, enableOptions)
}
return nil
}
func (c *fakeClient) PluginDisable(_ context.Context, name string, disableOptions types.PluginDisableOptions) error {
func (c *fakeClient) PluginDisable(context context.Context, name string, disableOptions types.PluginDisableOptions) error {
if c.pluginDisableFunc != nil {
return c.pluginDisableFunc(name, disableOptions)
}
return nil
}
func (c *fakeClient) PluginRemove(_ context.Context, name string, removeOptions types.PluginRemoveOptions) error {
func (c *fakeClient) PluginRemove(context context.Context, name string, removeOptions types.PluginRemoveOptions) error {
if c.pluginRemoveFunc != nil {
return c.pluginRemoveFunc(name, removeOptions)
}
return nil
}
func (c *fakeClient) PluginInstall(_ context.Context, name string, installOptions types.PluginInstallOptions) (io.ReadCloser, error) {
func (c *fakeClient) PluginInstall(context context.Context, name string, installOptions types.PluginInstallOptions) (io.ReadCloser, error) {
if c.pluginInstallFunc != nil {
return c.pluginInstallFunc(name, installOptions)
}
return nil, nil
}
func (c *fakeClient) PluginList(_ context.Context, filter filters.Args) (types.PluginsListResponse, error) {
func (c *fakeClient) PluginList(context context.Context, filter filters.Args) (types.PluginsListResponse, error) {
if c.pluginListFunc != nil {
return c.pluginListFunc(filter)
}
@ -63,7 +63,7 @@ func (c *fakeClient) PluginList(_ context.Context, filter filters.Args) (types.P
return types.PluginsListResponse{}, nil
}
func (c *fakeClient) PluginInspectWithRaw(_ context.Context, name string) (*types.Plugin, []byte, error) {
func (c *fakeClient) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
if c.pluginInspectFunc != nil {
return c.pluginInspectFunc(name)
}
@ -71,6 +71,6 @@ func (c *fakeClient) PluginInspectWithRaw(_ context.Context, name string) (*type
return nil, nil, nil
}
func (c *fakeClient) Info(context.Context) (types.Info, error) {
func (c *fakeClient) Info(ctx context.Context) (types.Info, error) {
return types.Info{}, nil
}

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.19
package plugin
import (

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.19
package plugin
import (

View File

@ -10,7 +10,6 @@ import (
"github.com/docker/cli/cli/command/image"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/pkg/errors"
@ -55,6 +54,26 @@ func newInstallCommand(dockerCli command.Cli) *cobra.Command {
return cmd
}
type pluginRegistryService struct {
registry.Service
}
func (s pluginRegistryService) ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error) {
repoInfo, err := s.Service.ResolveRepository(name)
if repoInfo != nil {
repoInfo.Class = "plugin"
}
return repoInfo, err
}
func newRegistryService() (registry.Service, error) {
svc, err := registry.NewService(registry.ServiceOptions{})
if err != nil {
return nil, err
}
return pluginRegistryService{Service: svc}, nil
}
func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
// Names with both tag and digest will be treated by the daemon
// as a pull by digest with a local name for the tag
@ -79,7 +98,12 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String())
}
trusted, err := image.TrustedReference(context.Background(), dockerCli, nt)
ctx := context.Background()
svc, err := newRegistryService()
if err != nil {
return types.PluginInstallOptions{}, err
}
trusted, err := image.TrustedReference(ctx, dockerCli, nt, svc)
if err != nil {
return types.PluginInstallOptions{}, err
}
@ -87,7 +111,8 @@ func buildPullConfig(ctx context.Context, dockerCli command.Cli, opts pluginOpti
}
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
if err != nil {
return types.PluginInstallOptions{}, err
}

View File

@ -7,7 +7,6 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image"
"github.com/docker/distribution/reference"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/pkg/errors"
@ -56,7 +55,8 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
return err
}
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
if err != nil {
return err
}
@ -68,6 +68,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
defer responseBody.Close()
if !opts.untrusted {
repoInfo.Class = "plugin"
return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody)
}

View File

@ -3,6 +3,8 @@ package command
import (
"bufio"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"os"
@ -10,7 +12,6 @@ import (
"strings"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/hints"
"github.com/docker/cli/cli/streams"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
@ -20,15 +21,20 @@ import (
"github.com/pkg/errors"
)
const patSuggest = "You can log in with your password or a Personal Access " +
"Token (PAT). Using a limited-scope PAT grants better security and is required " +
"for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/"
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
// ElectAuthServer returns the default registry to use.
//
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
return registrytypes.EncodeAuthConfig(authConfig)
// Deprecated: use [registry.IndexServer] instead.
func ElectAuthServer(_ context.Context, _ Cli) string {
return registry.IndexServer
}
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload
func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(buf), nil
}
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
@ -46,29 +52,26 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
if err != nil {
return "", err
}
return registrytypes.EncodeAuthConfig(authConfig)
return EncodeAuthToBase64(authConfig)
}
}
// ResolveAuthConfig returns auth-config for the given registry from the
// credential-store. It returns an empty AuthConfig if no credentials were
// found.
//
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
// store, instead of looking up credentials from a map.
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
// ResolveAuthConfig is like registry.ResolveAuthConfig, but if using the
// default index, it uses the default index name for the daemon's platform,
// not the client's platform.
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) types.AuthConfig {
configKey := index.Name
if index.Official {
configKey = registry.IndexServer
}
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
return registrytypes.AuthConfig(a)
return types.AuthConfig(a)
}
// GetDefaultAuthConfig gets the default auth config given a serverAddress
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) {
if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress)
}
@ -77,27 +80,20 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
if checkCredStore {
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
if err != nil {
return registrytypes.AuthConfig{
return types.AuthConfig{
ServerAddress: serverAddress,
}, err
}
}
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
res := registrytypes.AuthConfig(authconfig)
res := types.AuthConfig(authconfig)
return res, nil
}
// ConfigureAuth handles prompting of user's username and password if needed
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error {
// On Windows, force the use of the regular OS stdin stream.
//
// See:
// - https://github.com/moby/moby/issues/14336
// - https://github.com/moby/moby/issues/14210
// - https://github.com/moby/moby/pull/17738
//
// TODO(thaJeztah): we need to confirm if this special handling is still needed, as we may not be doing this in other places.
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *types.AuthConfig, isDefaultRegistry bool) error {
// On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210
if runtime.GOOS == "windows" {
cli.SetIn(streams.NewIn(os.Stdin))
}
@ -118,18 +114,11 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
if flUser = strings.TrimSpace(flUser); flUser == "" {
if isDefaultRegistry {
// if this is a default registry (docker hub), then display the following message.
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.")
if hints.Enabled() {
fmt.Fprintln(cli.Out(), patSuggest)
fmt.Fprintln(cli.Out())
}
fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
}
promptWithDefault(cli.Out(), "Username", authconfig.Username)
var err error
flUser, err = readInput(cli.In())
if err != nil {
return err
}
flUser = readInput(cli.In(), cli.Out())
flUser = strings.TrimSpace(flUser)
if flUser == "" {
flUser = authconfig.Username
}
@ -143,15 +132,12 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
return err
}
fmt.Fprintf(cli.Out(), "Password: ")
_ = term.DisableEcho(cli.In().FD(), oldState)
defer func() {
_ = term.RestoreTerminal(cli.In().FD(), oldState)
}()
flPassword, err = readInput(cli.In())
if err != nil {
return err
}
term.DisableEcho(cli.In().FD(), oldState)
flPassword = readInput(cli.In(), cli.Out())
fmt.Fprint(cli.Out(), "\n")
term.RestoreTerminal(cli.In().FD(), oldState)
if flPassword == "" {
return errors.Errorf("Error: Password Required")
}
@ -163,15 +149,14 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
return nil
}
// readInput reads, and returns user input from in. It tries to return a
// single line, not including the end-of-line bytes, and trims leading
// and trailing whitespace.
func readInput(in io.Reader) (string, error) {
line, _, err := bufio.NewReader(in).ReadLine()
func readInput(in io.Reader, out io.Writer) string {
reader := bufio.NewReader(in)
line, _, err := reader.ReadLine()
if err != nil {
return "", errors.Wrap(err, "error while reading input")
fmt.Fprintln(out, err.Error())
os.Exit(1)
}
return strings.TrimSpace(string(line)), nil
return string(line)
}
func promptWithDefault(out io.Writer, prompt string, configDefault string) {
@ -182,19 +167,14 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
}
}
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete
// image. The auth configuration is serialized as a base64url encoded RFC4648,
// section 5) JSON string for sending through the X-Registry-Auth header.
//
// For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) {
// Retrieve encoded auth token from the image reference
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image)
if err != nil {
return "", err
}
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
encodedAuth, err := EncodeAuthToBase64(authConfig)
if err != nil {
return "", err
}
@ -202,14 +182,14 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
}
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (types.AuthConfig, error) {
registryRef, err := reference.ParseNormalizedNamed(image)
if err != nil {
return registrytypes.AuthConfig{}, err
return types.AuthConfig{}, err
}
repoInfo, err := registry.ParseRepositoryInfo(registryRef)
if err != nil {
return registrytypes.AuthConfig{}, err
return types.AuthConfig{}, err
}
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
}

View File

@ -10,6 +10,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
@ -163,7 +164,7 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint:gocyclo
return nil
}
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authConfig *types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
fmt.Fprintf(dockerCli.Out(), "Authenticating with existing credentials...\n")
cliClient := dockerCli.Client()
response, err := cliClient.RegistryLogin(ctx, *authConfig)
@ -177,7 +178,7 @@ func loginWithCredStoreCreds(ctx context.Context, dockerCli command.Cli, authCon
return response, err
}
func loginClientSide(ctx context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
func loginClientSide(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
svc, err := registry.NewService(registry.ServiceOptions{})
if err != nil {
return registrytypes.AuthenticateOKBody{}, err

View File

@ -34,11 +34,11 @@ type fakeClient struct {
client.Client
}
func (c fakeClient) Info(context.Context) (types.Info, error) {
func (c fakeClient) Info(ctx context.Context) (types.Info, error) {
return types.Info{}, nil
}
func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
func (c fakeClient) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
if auth.Password == expiredPassword {
return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
}
@ -53,16 +53,16 @@ func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConf
func TestLoginWithCredStoreCreds(t *testing.T) {
testCases := []struct {
inputAuthConfig registrytypes.AuthConfig
inputAuthConfig types.AuthConfig
expectedMsg string
expectedErr string
}{
{
inputAuthConfig: registrytypes.AuthConfig{},
inputAuthConfig: types.AuthConfig{},
expectedMsg: "Authenticating with existing credentials...\n",
},
{
inputAuthConfig: registrytypes.AuthConfig{
inputAuthConfig: types.AuthConfig{
Username: userErr,
},
expectedMsg: "Authenticating with existing credentials...\n",

View File

@ -8,7 +8,6 @@ import (
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/registry"
"github.com/spf13/cobra"
)
@ -55,19 +54,25 @@ func runSearch(dockerCli command.Cli, options searchOptions) error {
}
ctx := context.Background()
authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo)
encodedAuth, err := registrytypes.EncodeAuthConfig(authConfig)
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
if err != nil {
return err
}
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search")
results, err := dockerCli.Client().ImageSearch(ctx, options.term, types.ImageSearchOptions{
searchOptions := types.ImageSearchOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: requestPrivilege,
Filters: options.filter.Value(),
Limit: options.limit,
})
}
clnt := dockerCli.Client()
results, err := clnt.ImageSearch(ctx, options.term, searchOptions)
if err != nil {
return err
}

View File

@ -10,7 +10,6 @@ import (
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
@ -21,7 +20,7 @@ type fakeClient struct {
infoFunc func() (types.Info, error)
}
var testAuthConfigs = []registry.AuthConfig{
var testAuthConfigs = []types.AuthConfig{
{
ServerAddress: "https://index.docker.io/v1/",
Username: "u0",
@ -46,13 +45,13 @@ func TestGetDefaultAuthConfig(t *testing.T) {
checkCredStore bool
inputServerAddress string
expectedErr string
expectedAuthConfig registry.AuthConfig
expectedAuthConfig types.AuthConfig
}{
{
checkCredStore: false,
inputServerAddress: "",
expectedErr: "",
expectedAuthConfig: registry.AuthConfig{
expectedAuthConfig: types.AuthConfig{
ServerAddress: "",
Username: "",
Password: "",
@ -102,7 +101,7 @@ func TestGetDefaultAuthConfig_HelperError(t *testing.T) {
cli.SetErr(errBuf)
cli.ConfigFile().CredentialsStore = "fake-does-not-exist"
serverAddress := "test-server-address"
expectedAuthConfig := registry.AuthConfig{
expectedAuthConfig := types.AuthConfig{
ServerAddress: serverAddress,
}
authconfig, err := GetDefaultAuthConfig(cli, true, serverAddress, serverAddress == "https://index.docker.io/v1/")

View File

@ -10,36 +10,36 @@ import (
type fakeClient struct {
client.Client
secretCreateFunc func(context.Context, swarm.SecretSpec) (types.SecretCreateResponse, error)
secretInspectFunc func(context.Context, string) (swarm.Secret, []byte, error)
secretListFunc func(context.Context, types.SecretListOptions) ([]swarm.Secret, error)
secretRemoveFunc func(context.Context, string) error
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
secretInspectFunc func(string) (swarm.Secret, []byte, error)
secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error)
secretRemoveFunc func(string) error
}
func (c *fakeClient) SecretCreate(ctx context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if c.secretCreateFunc != nil {
return c.secretCreateFunc(ctx, spec)
return c.secretCreateFunc(spec)
}
return types.SecretCreateResponse{}, nil
}
func (c *fakeClient) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) {
if c.secretInspectFunc != nil {
return c.secretInspectFunc(ctx, id)
return c.secretInspectFunc(id)
}
return swarm.Secret{}, nil, nil
}
func (c *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
if c.secretListFunc != nil {
return c.secretListFunc(ctx, options)
return c.secretListFunc(options)
}
return []swarm.Secret{}, nil
}
func (c *fakeClient) SecretRemove(ctx context.Context, name string) error {
if c.secretRemoveFunc != nil {
return c.secretRemoveFunc(ctx, name)
return c.secretRemoveFunc(name)
}
return nil
}

View File

@ -1,7 +1,6 @@
package secret
import (
"context"
"io"
"os"
"path/filepath"
@ -22,7 +21,7 @@ const secretDataFile = "secret-create-with-name.golden"
func TestSecretCreateErrors(t *testing.T) {
testCases := []struct {
args []string
secretCreateFunc func(context.Context, swarm.SecretSpec) (types.SecretCreateResponse, error)
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
expectedError string
}{
{
@ -35,7 +34,7 @@ func TestSecretCreateErrors(t *testing.T) {
},
{
args: []string{"name", filepath.Join("testdata", secretDataFile)},
secretCreateFunc: func(_ context.Context, secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) {
secretCreateFunc: func(secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) {
return types.SecretCreateResponse{}, errors.Errorf("error creating secret")
},
expectedError: "error creating secret",
@ -67,7 +66,7 @@ func TestSecretCreateWithName(t *testing.T) {
}
cli := test.NewFakeCli(&fakeClient{
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if !reflect.DeepEqual(spec, expected) {
return types.SecretCreateResponse{}, errors.Errorf("expected %+v, got %+v", expected, spec)
}
@ -90,7 +89,7 @@ func TestSecretCreateWithDriver(t *testing.T) {
name := "foo"
cli := test.NewFakeCli(&fakeClient{
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if spec.Name != name {
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
@ -119,7 +118,7 @@ func TestSecretCreateWithTemplatingDriver(t *testing.T) {
name := "foo"
cli := test.NewFakeCli(&fakeClient{
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if spec.Name != name {
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
@ -149,7 +148,7 @@ func TestSecretCreateWithLabels(t *testing.T) {
name := "foo"
cli := test.NewFakeCli(&fakeClient{
secretCreateFunc: func(_ context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if spec.Name != name {
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}

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.19
package secret
import (

View File

@ -1,7 +1,6 @@
package secret
import (
"context"
"fmt"
"io"
"testing"
@ -19,7 +18,7 @@ func TestSecretInspectErrors(t *testing.T) {
testCases := []struct {
args []string
flags map[string]string
secretInspectFunc func(ctx context.Context, secretID string) (swarm.Secret, []byte, error)
secretInspectFunc func(secretID string) (swarm.Secret, []byte, error)
expectedError string
}{
{
@ -27,7 +26,7 @@ func TestSecretInspectErrors(t *testing.T) {
},
{
args: []string{"foo"},
secretInspectFunc: func(_ context.Context, secretID string) (swarm.Secret, []byte, error) {
secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) {
return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret")
},
expectedError: "error while inspecting the secret",
@ -41,7 +40,7 @@ func TestSecretInspectErrors(t *testing.T) {
},
{
args: []string{"foo", "bar"},
secretInspectFunc: func(_ context.Context, secretID string) (swarm.Secret, []byte, error) {
secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) {
if secretID == "foo" {
return *Secret(SecretName("foo")), nil, nil
}
@ -69,12 +68,12 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
testCases := []struct {
name string
args []string
secretInspectFunc func(ctx context.Context, secretID string) (swarm.Secret, []byte, error)
secretInspectFunc func(secretID string) (swarm.Secret, []byte, error)
}{
{
name: "single-secret",
args: []string{"foo"},
secretInspectFunc: func(_ context.Context, name string) (swarm.Secret, []byte, error) {
secretInspectFunc: func(name string) (swarm.Secret, []byte, error) {
if name != "foo" {
return swarm.Secret{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name)
}
@ -84,7 +83,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
{
name: "multiple-secrets-with-labels",
args: []string{"foo", "bar"},
secretInspectFunc: func(_ context.Context, name string) (swarm.Secret, []byte, error) {
secretInspectFunc: func(name string) (swarm.Secret, []byte, error) {
return *Secret(SecretID("ID-"+name), SecretName(name), SecretLabels(map[string]string{
"label1": "label-foo",
})), nil, nil
@ -103,7 +102,7 @@ func TestSecretInspectWithoutFormat(t *testing.T) {
}
func TestSecretInspectWithFormat(t *testing.T) {
secretInspectFunc := func(_ context.Context, name string) (swarm.Secret, []byte, error) {
secretInspectFunc := func(name string) (swarm.Secret, []byte, error) {
return *Secret(SecretName("foo"), SecretLabels(map[string]string{
"label1": "label-foo",
})), nil, nil
@ -112,7 +111,7 @@ func TestSecretInspectWithFormat(t *testing.T) {
name string
format string
args []string
secretInspectFunc func(_ context.Context, name string) (swarm.Secret, []byte, error)
secretInspectFunc func(name string) (swarm.Secret, []byte, error)
}{
{
name: "simple-template",
@ -142,11 +141,11 @@ func TestSecretInspectWithFormat(t *testing.T) {
func TestSecretInspectPretty(t *testing.T) {
testCases := []struct {
name string
secretInspectFunc func(context.Context, string) (swarm.Secret, []byte, error)
secretInspectFunc func(string) (swarm.Secret, []byte, error)
}{
{
name: "simple",
secretInspectFunc: func(_ context.Context, id string) (swarm.Secret, []byte, error) {
secretInspectFunc: func(id string) (swarm.Secret, []byte, error) {
return *Secret(
SecretLabels(map[string]string{
"lbl1": "value1",

View File

@ -1,7 +1,6 @@
package secret
import (
"context"
"io"
"testing"
"time"
@ -20,7 +19,7 @@ import (
func TestSecretListErrors(t *testing.T) {
testCases := []struct {
args []string
secretListFunc func(context.Context, types.SecretListOptions) ([]swarm.Secret, error)
secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error)
expectedError string
}{
{
@ -28,7 +27,7 @@ func TestSecretListErrors(t *testing.T) {
expectedError: "accepts no argument",
},
{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{}, errors.Errorf("error listing secrets")
},
expectedError: "error listing secrets",
@ -48,7 +47,7 @@ func TestSecretListErrors(t *testing.T) {
func TestSecretList(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{
*Secret(SecretID("ID-1-foo"),
SecretName("1-foo"),
@ -80,7 +79,7 @@ func TestSecretList(t *testing.T) {
func TestSecretListWithQuietOption(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{
*Secret(SecretID("ID-foo"), SecretName("foo")),
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
@ -97,7 +96,7 @@ func TestSecretListWithQuietOption(t *testing.T) {
func TestSecretListWithConfigFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{
*Secret(SecretID("ID-foo"), SecretName("foo")),
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
@ -116,7 +115,7 @@ func TestSecretListWithConfigFormat(t *testing.T) {
func TestSecretListWithFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{
*Secret(SecretID("ID-foo"), SecretName("foo")),
*Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{
@ -133,7 +132,7 @@ func TestSecretListWithFormat(t *testing.T) {
func TestSecretListWithFilter(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(_ context.Context, options types.SecretListOptions) ([]swarm.Secret, error) {
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]), "foo")
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
return []swarm.Secret{

View File

@ -1,7 +1,6 @@
package secret
import (
"context"
"io"
"strings"
"testing"
@ -15,7 +14,7 @@ import (
func TestSecretRemoveErrors(t *testing.T) {
testCases := []struct {
args []string
secretRemoveFunc func(context.Context, string) error
secretRemoveFunc func(string) error
expectedError string
}{
{
@ -24,7 +23,7 @@ func TestSecretRemoveErrors(t *testing.T) {
},
{
args: []string{"foo"},
secretRemoveFunc: func(_ context.Context, name string) error {
secretRemoveFunc: func(name string) error {
return errors.Errorf("error removing secret")
},
expectedError: "error removing secret",
@ -46,7 +45,7 @@ func TestSecretRemoveWithName(t *testing.T) {
names := []string{"foo", "bar"}
var removedSecrets []string
cli := test.NewFakeCli(&fakeClient{
secretRemoveFunc: func(_ context.Context, name string) error {
secretRemoveFunc: func(name string) error {
removedSecrets = append(removedSecrets, name)
return nil
},
@ -63,7 +62,7 @@ func TestSecretRemoveContinueAfterError(t *testing.T) {
var removedSecrets []string
cli := test.NewFakeCli(&fakeClient{
secretRemoveFunc: func(_ context.Context, name string) error {
secretRemoveFunc: func(name string) error {
removedSecrets = append(removedSecrets, name)
if name == "foo" {
return errors.Errorf("error removing secret: %s", name)

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