Compare commits

...
351 Commits
Author SHA1 Message Date
Sebastiaan van StijnandGitHub eb310fca49 Merge pull request #2373 from tiborvass/19.03-bump-grpc-1.23.1
[19.03 backport] Bump grpc to v1.23.1
2020-03-03 22:59:52 +01:00
Sebastiaan van StijnandTibor Vass 0e40b91921 vendor: bump google.golang.org/grpc v1.23.1
full diff: https://github.com/grpc/grpc-go/compare/v1.23.0...v1.23.1

- grpc/grpc-go#3018 server: set and advertise max frame size of 16KB
- grpc/grpc-go#3017 grpclb: fix deadlock in grpclb connection cache
    - Before the fix, if the timer to remove a SubConn fires at the
      same time NewSubConn cancels the timer, it caused a mutex leak
      and deadlock.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 013151ff78)
Signed-off-by: Tibor Vass <tibor@docker.com>
2020-03-03 21:39:18 +00:00
Tibor Vass a51e9e6397 vendor: update grpc to v1.23.0
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 70a4eb2a49)
Signed-off-by: Tibor Vass <tibor@docker.com>
2020-03-03 21:39:13 +00:00
Silvin LubeckiandGitHub 3ff19c3755 Merge pull request #2352 from thaJeztah/19.03_backport_add_daemon_redirect
[19.03 backport] docs: add redirect for old location of daemon reference
2020-02-26 17:18:59 +01:00
Sebastiaan van Stijn e94a87225a docs: add redirect for old location of daemon reference
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4cd4305b31)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-26 16:35:08 +01:00
Sebastiaan van StijnandGitHub 7c803f7c34 Merge pull request #2344 from thaJeztah/19.03_backport_builder_prune_flags
[19.03 backport] fix builder prune flag descriptions
2020-02-26 16:32:45 +01:00
Silvin LubeckiandGitHub 4591b13318 Merge pull request #2342 from thaJeztah/19.03_backport_bump_golang_1.12.17
[19.03 backport] Update Golang 1.12.17
2020-02-19 11:48:11 +01:00
Sebastiaan van Stijn f9a5c1f152 Fix builder prune -a/--all flag description
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit aad9d2c958)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-18 14:33:42 +01:00
Samuel CochranandSebastiaan van Stijn 829843333b unused-for is a deprecated synonym
See https://github.com/moby/moby/blob/9e7d5ac5ea55dc57185f49476e03d6efa76b3512/builder/builder-next/builder.go#L574

Signed-off-by: Samuel Cochran <sj26@sj26.com>
(cherry picked from commit 758d12e651)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-18 14:33:28 +01:00
Sebastiaan van Stijn f0e74408cf Update Golang 1.12.17
full diff: https://github.com/golang/go/compare/go1.12.16...go1.12.17

go1.12.17 (released 2020/02/12) includes a fix to the runtime. See the Go 1.12.17
milestone on the issue tracker for details:

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

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5e5ef9e0b9)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-17 14:58:54 +01:00
Silvin LubeckiandGitHub a4bedce165 Merge pull request #2320 from thaJeztah/19.03_docs_backports
[19.03 backport] assorted documentation updates
2020-02-10 17:20:36 +01:00
Sebastiaan van Stijn d4755cfbd5 docs: update deprecated status for --disable-legacy-registry
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 73c9a44d58)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:55:02 +01:00
Sebastiaan van Stijn 6eef644faf docs: add status table to "deprecated.md"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit d4c0de2719)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:37 +01:00
Sebastiaan van Stijn f47f8e333b docs: mark deprecation of "docker engine" subcommands
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e8c2dba697)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:36 +01:00
Sebastiaan van Stijn 64838b6907 docs: mark deprecation of "dab" files and top-level "deploy" subcommand
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c7aca08497)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:33 +01:00
Sebastiaan van Stijn c8308ecf6c docs: sort "deprecated.md" by deprecation release
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b6875ad690)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:31 +01:00
Sebastiaan van Stijn 793c75015e docs: update some release-versions in "deprecated.md"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 672c00e1cc)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:29 +01:00
Sebastiaan van Stijn 776e181628 docs: minor touch-ups in "deprecated.md"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c3092d9408)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:32:27 +01:00
Sebastiaan van Stijn 7fac7eb1af docs: service create: document os/arch constraints and more examples
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f26e9a3a61)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:31:41 +01:00
Sebastiaan van Stijn 27f0612665 docs: service create: document non-matching/exclude constraints
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b059c93c92)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:31:39 +01:00
Sebastiaan van Stijn d5ce81172f docs: service create: use markdown table for constraints
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit abeb7babdf)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:31:36 +01:00
Misty Stanley-JonesandSebastiaan van Stijn 3a1d0c67ff Give an example for --reserve-memory
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 76852f82ba)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 16:30:55 +01:00
Silvin LubeckiandGitHub e1c31c8910 Merge pull request #2315 from thaJeztah/19.03_backport_carry_855_config_opts
[19.03 backport] Add examples for configs
2020-02-10 12:01:37 +01:00
Abreto FUandSebastiaan van Stijn 2d6231ad4d Remove a useless '\' and enhance a script in an example in the section 'Add entries ... (--add-host)'
Signed-off-by: Abreto FU <public@abreto.email>
(cherry picked from commit 07436dfe78)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 10:41:32 +01:00
Misty Stanley-JonesandSebastiaan van Stijn be60297514 Add examples for configs
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 473a9d20cd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-10 10:38:58 +01:00
Silvin LubeckiandGitHub 528b959ebc Merge pull request #2311 from thaJeztah/19.03_backport_carry_1889_build_docs_update
[19.03 backport] documentation updates
2020-02-06 17:16:35 +01:00
Venkateswara Reddy BukkasamudramandSebastiaan van Stijn b668f31022 Syntax corrected
Below are the changes proposed.
- Corrected syntax error.
- Updated example commands to maintain consistency.
- Provided more clarity.

Signed-off-by: Venkateswara Reddy Bukkasamudram <bukkasamudram@outlook.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 74cc062d24)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 16:52:11 +01:00
Tonis TiigiandSebastiaan van Stijn 7bfe3d2006 docs: document dockerignore update
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4f3bc15817)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 16:52:09 +01:00
Tonis TiigiandSebastiaan van Stijn f6ec0a368e docs: document build outputs
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tibor Vass <tibor@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f7009ee126)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 16:52:07 +01:00
Tonis TiigiandSebastiaan van Stijn 56324e6348 docs: document cache-from
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Tibor Vass <tibor@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 73cd257d0f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 16:52:04 +01:00
KovahandSebastiaan van Stijn 040920f428 Add notice about port binding and overriding of UFW to docker run reference
Signed-off-by: Kovah <mail@kovah.de>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a955ed6477)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-02-06 16:52:02 +01:00
Silvin LubeckiandGitHub 5908cdf87c Merge pull request #2302 from thaJeztah/19.03_bump_golang_1.12.16
[19.03 backport] Update Golang 1.12.16, golang.org/x/crypto (CVE-2020-0601, CVE-2020-7919)
2020-01-30 16:25:51 +01:00
Sebastiaan van Stijn 3179a3b1e5 vendor: update golang.org/x/crypto 69ecbb4d6d5dab05e49161c6e77ea40a030884e1 (CVE-2020-7919)
Includes https://github.com/golang/crypto/commit/69ecbb4d6d5dab05e49161c6e77ea40a030884e1
(forward-port of https://github.com/golang/crypto/commit/8b5121be2f68d8fc40bb06467003bdde1040a094),
which fixes CVE-2020-7919:

- Panic in crypto/x509 certificate parsing and golang.org/x/crypto/cryptobyte
  On 32-bit architectures, a malformed input to crypto/x509 or the ASN.1 parsing
  functions of golang.org/x/crypto/cryptobyte can lead to a panic.
  The malformed certificate can be delivered via a crypto/tls connection to a
  client, or to a server that accepts client certificates. net/http clients can
  be made to crash by an HTTPS server, while net/http servers that accept client
  certificates will recover the panic and are unaffected.
  Thanks to Project Wycheproof for providing the test cases that led to the
  discovery of this issue. The issue is CVE-2020-7919 and Go issue golang.org/issue/36837.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 27d9aa2d9f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-29 22:39:00 +01:00
Sebastiaan van Stijn 4d630fe843 Update Golang 1.12.16 (CVE-2020-0601, CVE-2020-7919)
full diff: https://github.com/golang/go/compare/go1.12.15...go1.12.16

go1.12.16 (released 2020/01/28) includes two security fixes. One mitigates the
CVE-2020-0601 certificate verification bypass on Windows. The other affects only
32-bit architectures.

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

- X.509 certificate validation bypass on Windows 10
  A Windows vulnerability allows attackers to spoof valid certificate chains when
  the system root store is in use. These releases include a mitigation for Go
  applications, but it’s strongly recommended that affected users install the
  Windows security update to protect their system.
  This issue is CVE-2020-0601 and Go issue golang.org/issue/36834.
- Panic in crypto/x509 certificate parsing and golang.org/x/crypto/cryptobyte
  On 32-bit architectures, a malformed input to crypto/x509 or the ASN.1 parsing
  functions of golang.org/x/crypto/cryptobyte can lead to a panic.
  The malformed certificate can be delivered via a crypto/tls connection to a
  client, or to a server that accepts client certificates. net/http clients can
  be made to crash by an HTTPS server, while net/http servers that accept client
  certificates will recover the panic and are unaffected.
  Thanks to Project Wycheproof for providing the test cases that led to the
  discovery of this issue. The issue is CVE-2020-7919 and Go issue golang.org/issue/36837.
  This is also fixed in version v0.0.0-20200124225646-8b5121be2f68 of golang.org/x/crypto/cryptobyte.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 19fd390c36)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-29 22:23:41 +01:00
Silvin LubeckiandGitHub 9b02509a69 Merge pull request #2291 from thaJeztah/19.03_backport_update_flag_description
[19.03 backport] Update flag description for docker rm -v
2020-01-28 16:10:01 +01:00
Silvin LubeckiandGitHub 696605c99b Merge pull request #2292 from thaJeztah/19.03_backport_hide_unsupported_buildkit_flags
[19.03 backport] Annotate flags that are not supported by Buildkit
2020-01-27 18:19:34 +01:00
Sebastiaan van Stijn 25d53feb65 Annotate flags that are not supported by Buildkit
Before this patch:

```

Usage:	docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --cgroup-parent string    Optional parent cgroup for the container
      --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
  -c, --cpu-shares int          CPU shares (relative weight)
      --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --force-rm                Always remove intermediate containers
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
  -m, --memory bytes            Memory limit
      --memory-swap bytes       Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --network string          Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                Do not use cache when building the image
  -o, --output stringArray      Output destination (format: type=local,dest=path)
      --platform string         Set platform if server is multi-platform capable
      --progress string         Set type of progress output (auto, plain, tty). Use plain to show container output (default "auto")
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --rm                      Remove intermediate containers after a successful build (default true)
      --secret stringArray      Secret file to expose to the build (only if BuildKit enabled): id=mysecret,src=/local/secret
      --security-opt strings    Security options
      --shm-size bytes          Size of /dev/shm
      --squash                  Squash newly built layers into a single new layer
      --ssh stringArray         SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|<id>[=<socket>|<key>[,<key>]])
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
      --target string           Set the target build stage to build.
      --ulimit ulimit           Ulimit options (default [])
```

With this patch applied:

```
DOCKER_BUILDKIT=1 docker build --help

Usage:	docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
      --add-host list           Add a custom host-to-IP mapping (host:ip)
      --build-arg list          Set build-time variables
      --cache-from strings      Images to consider as cache sources
      --disable-content-trust   Skip image verification (default true)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
      --iidfile string          Write the image ID to the file
      --isolation string        Container isolation technology
      --label list              Set metadata for an image
      --network string          Set the networking mode for the RUN instructions during build (default "default")
      --no-cache                Do not use cache when building the image
  -o, --output stringArray      Output destination (format: type=local,dest=path)
      --platform string         Set platform if server is multi-platform capable
      --progress string         Set type of progress output (auto, plain, tty). Use plain to show container output (default "auto")
      --pull                    Always attempt to pull a newer version of the image
  -q, --quiet                   Suppress the build output and print image ID on success
      --secret stringArray      Secret file to expose to the build (only if BuildKit enabled): id=mysecret,src=/local/secret
      --squash                  Squash newly built layers into a single new layer
      --ssh stringArray         SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|<id>[=<socket>|<key>[,<key>]])
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
      --target string           Set the target build stage to build.
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 7eecbb96af)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-27 15:57:30 +01:00
Sebastiaan van Stijn 1d540a50d0 Update flag description for docker rm -v
The `-v` option removes anonymous volume only, and keeps
named volumes.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8f5379b301)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-27 15:53:37 +01:00
Silvin LubeckiandGitHub 16d5974584 Merge pull request #2276 from thaJeztah/19.03_backport_bump_golang_1.12.15
[19.03 backport] Update Golang 1.12.15
2020-01-21 14:36:04 +01:00
Sebastiaan van Stijn 3694e78a56 Update Golang 1.12.15
full diff: https://github.com/golang/go/compare/go1.12.14...go1.12.15

go1.12.15 (released 2020/01/09) includes fixes to the runtime and the net/http
package. See the Go 1.12.15 milestone on the issue tracker for details:

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

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 84c6b08cf6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-21 13:11:24 +01:00
Sebastiaan van Stijn 998d8235c3 Bump Golang 1.12.14
go1.12.14 (released 2019/12/04) includes a fix to the runtime. See the Go 1.12.14
milestone on our issue tracker for details:

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

Update Golang 1.12.13
------------------------

go1.12.13 (released 2019/10/31) fixes an issue on macOS 10.15 Catalina where the
non-notarized installer and binaries were being rejected by Gatekeeper. Only macOS
users who hit this issue need to update.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4beea58531)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-21 13:11:17 +01:00
Silvin LubeckiandGitHub a3e131b323 Merge pull request #2264 from thaJeztah/19.03_backport_passthrough_user_pass
[19.03 backport] Allow username/password in config file
2020-01-17 14:53:33 +01:00
Silvin LubeckiandGitHub 7a9a020688 Merge pull request #2265 from thaJeztah/19.03_backport_fix_pull_test
[19.03 backport] fix(pull_test): for quiet option
2020-01-17 14:49:03 +01:00
Silvin LubeckiandGitHub 39676cc33e Merge pull request #2266 from thaJeztah/19.03_backport_circleci_updates
[19.03 backport] CircleCI: add some info steps, and re-group jobs
2020-01-17 14:47:14 +01:00
Silvin LubeckiandGitHub 4b4e4c2504 Merge pull request #2267 from thaJeztah/19.03_backport_fix_print
[19.03 backport] fix formatting issue of encoded url
2020-01-17 14:46:14 +01:00
Silvin LubeckiandGitHub 66905dcff8 Merge pull request #2268 from thaJeztah/19.03_backport_docs_changes
[19.03 backport] assorted documentation changes
2020-01-17 14:44:41 +01:00
Oscar WiemanandSebastiaan van Stijn 05aa524a7b Change example networks
Signed-off-by: Oscar Wieman <oscar@oscarr.nl>
(cherry picked from commit 2d6aec78a1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:59:38 +01:00
Sebastiaan van Stijn 3f39587e3b Add docs for proxy configuration in config.json
Setting proxy-configuration in config.json was added in
commit 35f1e301b5 (docker
17.07), but never found its way to the documentation.

This patch adds some basic information about the feature.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e70d6bcb8a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:59:07 +01:00
Adrian PlataandSebastiaan van Stijn e22f088abb Fixing some links and deleting an older page reference
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
(cherry picked from commit 8195512206)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:57:47 +01:00
Jose J. EscobarandSebastiaan van Stijn ae7bb665e7 Update service_create.md
Typo in word propagation.

Signed-off-by: Jose Escobar <joseescobar@JE-MBP15-2017.local>
(cherry picked from commit 265bee4d57)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:56:59 +01:00
Sebastiaan van Stijn f0bf0d2c46 Docs: add note about management commands targeting a manager
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f540eae7fe)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:56:23 +01:00
SamandSebastiaan van Stijn 5761759e43 fix formatting issue of encoded url
Signed-off-by: Sam <samashah@microsoft.com>
(cherry picked from commit ee76ac8f93)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:48:54 +01:00
Sebastiaan van Stijn e669be6a1b CircleCI: add some info steps, and re-group jobs
This patch:

- Combines the shellcheck and lint stages. Free CircleCI plans allow a maximum
  of 4 concurrent jobs, and from the timing, the "lint" and "shellcheck" stages
  combined would still take less time than the other stages, so combining them
  keeps the same overall duration, but saving one machine "slot".
- Splits some steps, so that their output can be found more easily in the CI
  results. For example, separating building of Docker images from running them.
- Adds a "Docker info" step, because information about the environment can be
  useful when debugging.
- Adds the "Docker info" and "Docker version" steps to all stages, so that it's
  possible to get that information without having to find the stage in which
  it's printed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 937e65cac5)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:45:00 +01:00
knqyf263andSebastiaan van Stijn 8291738733 fix(pull_test): for quiet option
Signed-off-by: Teppei Fukuda <knqyf263@gmail.com>
(cherry picked from commit 7634872a39)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:40:54 +01:00
Jon JohnsonandSebastiaan van Stijn a42f8129fd Fix lint issue
Signed-off-by: Jon Johnson <jonjohnson@google.com>
(cherry picked from commit 8f11fbc876)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:37:04 +01:00
Jon JohnsonandSebastiaan van Stijn 41b01f1319 Add test case to cover non-empty auth entry
Signed-off-by: Jon Johnson <jonjohnson@google.com>
(cherry picked from commit 415f608620)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:36:56 +01:00
Jon JohnsonandSebastiaan van Stijn a1c4a0f9e8 Allow username/password in config file
Signed-off-by: Jon Johnson <jonjohnson@google.com>
(cherry picked from commit 37e9cabf11)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-17 13:36:48 +01:00
Silvin LubeckiandGitHub ab4a5cc0f7 Merge pull request #2195 from tiborvass/19.03-fix-cp
[19.03 backport] cp: allow trailing slash in non-existant destination
2020-01-16 22:39:34 +01:00
Sebastiaan van StijnandGitHub a7cad2fec2 Merge pull request #2184 from thaJeztah/19.03_backport_fix_max_replicas_per_node_interpolation
[19.03 backport] Add interpolation type cast for max_replicas_per_node
2020-01-16 21:17:38 +01:00
Silvin LubeckiandGitHub e6e0fa0c8f Merge pull request #2261 from zappy-shu/19.03_backport_2250-reverse-port-long-format-order
[19.03 backport] Reverse order of long-form ports
2020-01-16 15:02:24 +01:00
Nick Adcock 813cc7ed9c Reverse order of long-form ports
Reverses the order long-form port options when converted to short-form
to correctly match the documentation and `docker service create`.

Post change `-p published=8111,target=8112` is the equivalent of
`8111:8112`

Signed-off-by: Nick Adcock <nick.adcock@docker.com>
(cherry picked from commit 154a1f6df8)
Signed-off-by: Nick Adcock <nick.adcock@docker.com>
2020-01-16 12:29:56 +00:00
Silvin LubeckiandGitHub 2c7de2070e Merge pull request #2239 from thaJeztah/19.03_backport_carry_golangci_lint
[19.03 backport] Replace gometalinter with Golangci lint [carry 1797]
2020-01-06 16:33:04 +01:00
Silvin LubeckiandGitHub 3d91ba436c Merge pull request #2240 from thaJeztah/19.03_backport_carry_platform_docs
[19.03 backport] docs: document from platform
2020-01-06 16:22:35 +01:00
Tonis TiigiandSebastiaan van Stijn b5e0dca08d docs: document from platform
Co-Authored-By: Tibor Vass <tiborvass@users.noreply.github.com>
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ce42168940)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 15:23:32 +01:00
Silvin LubeckiandSebastiaan van Stijn 7374c0a152 Remove now obsolete gometalinter and use golangci-lint instead
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b7e06f2845)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:23:38 +01:00
Sebastiaan van Stijn e70edc3576 cli/command/stack/kubernetes: Using the variable on range scope c in function literal (scopelint)
```
cli/command/stack/kubernetes/convert_test.go:199:35: Using the variable on range scope `c` in function literal (scopelint)
			conv, err := NewStackConverter(c.version)
			                               ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 640305f33c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:04 +01:00
Sebastiaan van Stijn b320feff9b cli/command/container: Using the variable on range scope c in function literal (scopelint)
```
cli/command/container/create_test.go:120:20: Using the variable on range scope `c` in function literal (scopelint)
				defer func() { c.ResponseCounter++ }()
				               ^
cli/command/container/create_test.go:121:12: Using the variable on range scope `c` in function literal (scopelint)
				switch c.ResponseCounter {
				       ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 542f80241e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:03 +01:00
Sebastiaan van Stijn 73dad4356e cli/command/stack/kubernetes: Using a reference for the variable on range scope obj (scopelint)
```
cli/command/stack/kubernetes/watcher_test.go:44:20: Using a reference for the variable on range scope `obj` (scopelint)
		if err := o.Add(&obj); err != nil {
		                 ^
cli/command/stack/kubernetes/watcher_test.go:49:20: Using a reference for the variable on range scope `obj` (scopelint)
		if err := o.Add(&obj); err != nil {
		                 ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 754fc6fe67)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:02 +01:00
Sebastiaan van Stijn 201e44907d opts: Using the variable on range scope tc in function literal (scopelint)
```
opts/network_test.go:74:35: Using the variable on range scope `tc` in function literal (scopelint)
			assert.NilError(t, network.Set(tc.value))
			                               ^
opts/network_test.go:102:40: Using the variable on range scope `tc` in function literal (scopelint)
			assert.ErrorContains(t, network.Set(tc.value), tc.expectedError)
			                                    ^
opts/opts_test.go:270:30: Using the variable on range scope `tc` in function literal (scopelint)
			val, err := ValidateLabel(tc.value)
			                          ^
opts/opts_test.go:271:7: Using the variable on range scope `tc` in function literal (scopelint)
			if tc.expectedErr != "" {
			   ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c2b069f4db)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:02 +01:00
Sebastiaan van Stijn 1b35214c11 cli/manifest: Using the variable on range scope testcase in function literal (scopelint)
```
cli/manifest/store/store_test.go:97:29: Using the variable on range scope `testcase` in function literal (scopelint)
			actual, err := store.Get(testcase.listRef, testcase.manifestRef)
			                         ^
cli/manifest/store/store_test.go:98:7: Using the variable on range scope `testcase` in function literal (scopelint)
			if testcase.expectedErr != "" {
			   ^
cli/manifest/store/store_test.go:99:26: Using the variable on range scope `testcase` in function literal (scopelint)
				assert.Error(t, err, testcase.expectedErr)
				                     ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit cd3dca37b8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:01 +01:00
Sebastiaan van Stijn fccc105d4d cli/compose/template: Using the variable on range scope tc in function literal (scopelint)
```
cli/compose/template/template_test.go:279:31: Using the variable on range scope `tc` in function literal (scopelint)
			actual := ExtractVariables(tc.dict, defaultPattern)
			                           ^
cli/compose/template/template_test.go:280:41: Using the variable on range scope `tc` in function literal (scopelint)
			assert.Check(t, is.DeepEqual(actual, tc.expected))
			                                     ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit aafe3df8b3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:00 +01:00
Sebastiaan van Stijn 37ef1f56f7 cli/command/container: suppress dogsled warnings
```
cli/command/container/opts_test.go:68:2: declaration has 3 blank identifiers (dogsled)
	_, _, _, err := parseRun(strings.Split(args+" ubuntu bash", " "))
	^
cli/command/container/opts_test.go:542:2: declaration has 3 blank identifiers (dogsled)
	_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"})
	^
cli/command/container/opts_test.go:603:2: declaration has 3 blank identifiers (dogsled)
	_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"})
	^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 79dc83e78b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:17:00 +01:00
Sebastiaan van Stijn 65e0d7c562 e2e: remove unnecessary trailing newline (whitespace)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit dd4d216afd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:59 +01:00
Sebastiaan van Stijn 09c94458c7 internal: remove unnecessary newlines (whitespace)
```
internal/licenseutils/client_test.go:98: unnecessary leading newline (whitespace)
func (c *fakeLicensingClient) LoadLocalLicense(ctx context.Context, dclnt licensing.WrappedDockerClient) (*model.Subscription, error) {
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 63e45e6320)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:59 +01:00
Sebastiaan van Stijn be5a3ccb7d cli/command: Using the variable on range scope testcase in function literal (scopelint)
```
cli/command/cli_test.go:157:15: Using the variable on range scope `testcase` in function literal (scopelint)
				pingFunc: testcase.pingFunc,
				          ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 2ec424a2d9)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:58 +01:00
Sebastiaan van Stijn b083f625e4 cli: remove unnecessary newlines (whitespace)
```
cli/config/config_test.go:465: unnecessary trailing newline (whitespace)

}
cli/compose/interpolation/interpolation.go:56: unnecessary leading newline (whitespace)
	switch value := value.(type) {

cli/compose/interpolation/interpolation.go:94: unnecessary trailing newline (whitespace)

	}
cli/command/image/build/context.go:348: unnecessary trailing newline (whitespace)

		}
internal/licenseutils/client_test.go:98: unnecessary leading newline (whitespace)
func (c *fakeLicensingClient) LoadLocalLicense(ctx context.Context, dclnt licensing.WrappedDockerClient) (*model.Subscription, error) {

cli/registry/client/fetcher.go:211: unnecessary leading newline (whitespace)
	for _, endpoint := range endpoints {
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 612d83d6df)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:57 +01:00
Sebastiaan van Stijn f7b23cf572 cli/command/trust: Using the variable on range scope keyBytes in function literal (scopelint)
```
cli/command/trust/key_load_test.go:121:27: Using the variable on range scope `keyID` in function literal (scopelint)
			testLoadKeyFromPath(t, keyID, keyBytes)
			                       ^
cli/command/trust/key_load_test.go:176:32: Using the variable on range scope `keyBytes` in function literal (scopelint)
			testLoadKeyTooPermissive(t, keyBytes)
			                            ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 7c4b63b1c3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:56 +01:00
Sebastiaan van Stijn bda413e0ae cli/command/context: Using the variable on range scope c in function literal (scopelint)
```
cli/command/context/create_test.go:270:31: Using the variable on range scope `c` in function literal (scopelint)
				Name:                     c.name,
				                          ^
cli/command/context/create_test.go:271:31: Using the variable on range scope `c` in function literal (scopelint)
				Description:              c.description,
				                          ^
cli/command/context/create_test.go:272:31: Using the variable on range scope `c` in function literal (scopelint)
				DefaultStackOrchestrator: c.orchestrator,

cli/command/context/create_test.go:346:31: Using the variable on range scope `c` in function literal (scopelint)
				Name:                     c.name,
				                          ^
cli/command/context/create_test.go:347:31: Using the variable on range scope `c` in function literal (scopelint)
				Description:              c.description,
				                          ^
cli/command/context/create_test.go:348:31: Using the variable on range scope `c` in function literal (scopelint)
				DefaultStackOrchestrator: c.orchestrator,
				                          ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a269e17d72)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:55 +01:00
Sebastiaan van Stijn 0cab2689a5 e2e/cli-plugins: Using the variable on range scope args in function literal (scopelint)
```
e2e/cli-plugins/flags_test.go:135:27: Using the variable on range scope `args` in function literal (scopelint)
			res := icmd.RunCmd(run(args...))
			                       ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 1736662bea)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:54 +01:00
Sebastiaan van Stijn 42ad2446e0 cli/compose/loader: Using a reference for the variable on range scope overrideService (scopelint)
```
cli/compose/loader/merge.go:64:41: Using a reference for the variable on range scope `overrideService` (scopelint)
			if err := mergo.Merge(&baseService, &overrideService, mergo.WithAppendSlice, mergo.WithOverride, mergo.WithTransformers(specials)); err != nil {
			                                     ^
cli/compose/loader/loader_test.go:1587:28: Using the variable on range scope `testcase` in function literal (scopelint)
			config, err := loadYAML(testcase.yaml)
			                        ^
cli/compose/loader/loader_test.go:1590:58: Using the variable on range scope `testcase` in function literal (scopelint)
			assert.Check(t, is.DeepEqual(config.Services[0].Init, testcase.init))
			                                                      ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 96ec7299d8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:53 +01:00
Sebastiaan van Stijn ae7b1f737b templates: Using the variable on range scope testCase in function literal (scopelint)
```
templates/templates_test.go:74:29: Using the variable on range scope `testCase` in function literal (scopelint)
			assert.Check(t, is.Equal(testCase.expected, b.String()))
			                         ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 54d48de216)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:53 +01:00
Sebastiaan van Stijn a087595fb6 service/logs: Using the variable on range scope testcase in function literal (scopelint)
```
service/logs/parse_logs_test.go:26:35: Using the variable on range scope `testcase` in function literal (scopelint)
			actual, err := ParseLogDetails(testcase.line)
			                               ^
service/logs/parse_logs_test.go:27:7: Using the variable on range scope `testcase` in function literal (scopelint)
			if testcase.err != nil {
			   ^
service/logs/parse_logs_test.go:28:26: Using the variable on range scope `testcase` in function literal (scopelint)
				assert.Error(t, err, testcase.err.Error())
				                     ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c828fa141d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:52 +01:00
Sebastiaan van Stijn 43b498829b cli/config: Using the variable on range scope tc in function literal (scopelint)
```
cli/config/config_test.go:590:11: Using the variable on range scope `tc` in function literal (scopelint)
			SetDir(tc.dir)
			       ^
cli/config/config_test.go:591:19: Using the variable on range scope `tc` in function literal (scopelint)
			f, err := Path(tc.path...)
			               ^
cli/config/config_test.go:592:23: Using the variable on range scope `tc` in function literal (scopelint)
			assert.Equal(t, f, tc.expected)
			                   ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5a2a9d9ca8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:51 +01:00
Sebastiaan van Stijn bd778fc27b cli/command/formatter: Error return value of ContainerWrite is not checked (errcheck)
```
cli/command/formatter/container_test.go:315:17: Error return value of `ContainerWrite` is not checked (errcheck)
		ContainerWrite(context.context, containers)
		              ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit e74e2c7741)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:51 +01:00
Sebastiaan van Stijn 10fda078a0 cli/command: Error return value of cli.Apply is not checked (errcheck)
```
cli/command/cli_test.go:297:11: Error return value of `cli.Apply` is not checked (errcheck)
	cli.Apply(
	         ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 008f6a2da3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:50 +01:00
Sebastiaan van Stijn 49253c7b00 cli/command/formatter: Error return value of ImageWrite is not checked (errcheck)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9275e2cb66)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:50 +01:00
Sebastiaan van Stijn 98150ae8ac cli/context/store: SA5001: should check returned error before deferring f.Close() (staticcheck)
```
cli/context/store/store_test.go:156:2: SA5001: should check returned error before deferring f.Close() (staticcheck)
	defer f.Close()
	^
cli/context/store/store_test.go:189:2: SA5001: should check returned error before deferring f.Close() (staticcheck)
	defer f.Close()
	^
cli/context/store/store_test.go:240:2: SA5001: should check returned error before deferring f.Close() (staticcheck)
	defer f.Close()
	^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit fe3cc6eb7b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:49 +01:00
Sebastiaan van Stijn fbe24f3e54 cli/command/image: SA1006: printf-style with no further arguments (staticcheck)
cli/command/image/build.go:434:32: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
    		fmt.Fprintf(dockerCli.Out(), imageID)
    		                             ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 709728e723)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:49 +01:00
Sebastiaan van Stijn 50a23edef3 cli/command/utils: SA1006: printf-style with no further arguments (staticcheck)
```
cli/command/utils.go:81:20: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
	fmt.Fprintf(outs, message)
	                  ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ea64a1ceb9)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:48 +01:00
Sebastiaan van Stijn 3bfa0f36b2 cli/command/trust: SA1006: printf-style with no further arguments (staticcheck)
```
cli/command/trust/key_generate.go:91:30: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
		fmt.Fprintf(streams.Out(), err.Error())
		                           ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f0614ca788)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:47 +01:00
Sebastiaan van Stijn acec6cb56f cli/command/image/build: G107: Potential HTTP request made with variable url (gosec)
cli/command/image/build/context.go:235: G107: Potential HTTP request made with variable url (gosec)
    	if resp, err = http.Get(url); err != nil {

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 0e4bd30cfe)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:47 +01:00
Sebastiaan van Stijn f969531205 cli/command/service: SA1012: do not pass a nil Context (staticcheck)
```
cli/command/service/update_test.go:31:16: SA1012: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (staticcheck)
	updateService(nil, nil, flags, spec)
	              ^
cli/command/service/update_test.go:535:16: SA1012: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (staticcheck)
	updateService(nil, nil, flags, spec)
	              ^
cli/command/service/update_test.go:540:16: SA1012: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (staticcheck)
	updateService(nil, nil, flags, spec)
	              ^
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8d64c2af1a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:46 +01:00
Sebastiaan van Stijn c10bf24fb2 cli/command/secret: G101: Potential hardcoded credentials (gosec)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 1850a0595b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:46 +01:00
Sebastiaan van Stijn 1a57296c26 cli/compose/convert: driverObjectConfig - result 1 (error) is always nil (unparam)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 34f595975d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:45 +01:00
Sebastiaan van Stijn 7467a6a7de e2e/container: containerExistsWithStatus - t is unused (unparam)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 6205ef33be)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:44 +01:00
Silvin LubeckiandSebastiaan van Stijn 98d2661522 cli/command/image/build/context_test.go:244:38: createTestTempDir - prefix always receives "builder-context-test" (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit b83545ebbc)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:44 +01:00
Silvin LubeckiandSebastiaan van Stijn 44c8cec274 cli/command/registry/login_test.go:66:25: unnecessary conversion (unconvert)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 4be924a0af)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:43 +01:00
Silvin LubeckiandSebastiaan van Stijn b2f6b4902c File is not goimports-ed (goimports)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 6047259e5a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:43 +01:00
Silvin LubeckiandSebastiaan van Stijn 2441946ce7 cli/compose/convert/service_test.go:274:72: unnecessary conversion (unconvert)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit c237379167)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:42 +01:00
Silvin LubeckiandSebastiaan van Stijn 03dbef8931 cli/command/trust/sign_test.go:119:70: unnecessary conversion (unconvert)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 0153624a56)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:41 +01:00
Silvin LubeckiandSebastiaan van Stijn 315715e145 Disable unparam linter: e2e/image/push_test.go:299:27: withNotaryPassphrase - pwd always receives "foo" (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit f123e43c1f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:41 +01:00
Silvin LubeckiandSebastiaan van Stijn c749704b83 Disable unparam linter: cli/required.go:102:16: pluralize - word always receives "argument" (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 7d823438bb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:40 +01:00
Sebastiaan van Stijn b49a07b63d compose/loader: define type for transformer-functions
Also explicitly type transformer-functions

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9118b2b2b8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:40 +01:00
Silvin LubeckiandSebastiaan van Stijn c77f5255a4 disable unparam linter on these functions, as we need an error in these function signatures
cli/compose/loader/loader.go:756:66: transformServiceNetworkMap - result 1 (error) is always nil (unparam)
cli/compose/loader/loader.go:767:67: transformStringOrNumberList - result 1 (error) is always nil (unparam)

Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 6eb0c9c613)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:39 +01:00
Silvin LubeckiandSebastiaan van Stijn 67a7fe0b3b cli/compose/convert: result 1 (error) is always nil (unparam)
cli/compose/convert/service.go:592:76: convertDNSConfig - result 1 (error) is always nil (unparam)
cli/compose/convert/service.go:538:110: convertEndpointSpec - result 1 (error) is always nil (unparam)

Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit d640f44df3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:38 +01:00
Silvin LubeckiandSebastiaan van Stijn 9ac043bc9d cli/command/system/info.go:116:68: prettyPrintClientInfo - result 0 (error) is always nil (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 47741f81d1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:38 +01:00
Silvin LubeckiandSebastiaan van Stijn 7db8c83e3a cli/command/stack/kubernetes/deploy_test.go:65:68: checkOwnerReferences - stackName always receives "test" (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit a3c7cb4f12)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:37 +01:00
Silvin LubeckiandSebastiaan van Stijn a1f67cc029 cli/command/plugin/list_test.go:61:31: TestList$1 - filter is unused (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit ab1aeedb27)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:37 +01:00
Silvin LubeckiandSebastiaan van Stijn a3912a4713 cli/command/image/build_session.go:133:45: getBuildSharedKey - result 1 (error) is always nil (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 75c60c1af7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:36 +01:00
Silvin LubeckiandSebastiaan van Stijn 20ae2a6c4e cli/command/image/build_buildkit.go:450:56: parseSSH - result 1 (error) is always nil (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 28ac2f82c6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:36 +01:00
Silvin LubeckiandSebastiaan van Stijn 9c7b701de5 cli/command/image/build/context_test.go:252:71: createTestTempFile - perm always receives 0777 (511) (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 0ce2eae5a2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:35 +01:00
Silvin LubeckiandSebastiaan van Stijn 6f91e46b7b cli/command/image/build/context_test.go:244:38: createTestTempDir - dir always receives "" (unparam)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 70bd64d037)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:35 +01:00
Silvin LubeckiandSebastiaan van Stijn 1f3468bb77 unchecked errors
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit e1c0c7979e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:34 +01:00
Silvin LubeckiandSebastiaan van Stijn c8c14206aa cli/command/container/attach.go:141:15: nilness: impossible condition: nil != nil (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 584da37756)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:33 +01:00
Silvin LubeckiandSebastiaan van Stijn 7d9b95d7ec opts/ulimit_test.go:11:13: composites: *github.com/docker/cli/vendor/github.com/docker/go-units.Ulimit composite literal uses unkeyed fields (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit b3d4c6aac7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:33 +01:00
Silvin LubeckiandSebastiaan van Stijn 0f72909216 cli/compose/types/types.go:106:2: structtag: struct field tag yaml:",inline", json:"-" not compatible with reflect.StructTag.Get: key:"value" pairs not separated by spaces (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 1bfe81318d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:32 +01:00
Silvin LubeckiandSebastiaan van Stijn 66b760d2b1 cli/registry/client/fetcher.go:106:9: nilness: impossible condition: nil != nil (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 5ceed3059f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:31 +01:00
Silvin LubeckiandSebastiaan van Stijn c83334119c cli/command/container/start.go:157:20: nilness: nil dereference in type assertion (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 9afeb6f432)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:31 +01:00
Silvin LubeckiandSebastiaan van Stijn cdc9d1095b cli/command/stack/kubernetes/list.go:32:47: nilness: tautological condition: non-nil != nil (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 85cfd4e518)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:30 +01:00
Silvin LubeckiandSebastiaan van Stijn fe1a85f1e9 cli/command/trust/key_generate.go:112:9: nilness: impossible condition: nil != nil (govet)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit f5e8387067)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:29 +01:00
Silvin LubeckiandSebastiaan van Stijn 60aa890a06 SA1019: httputil.ErrPersistEOF is deprecated: No longer used. (staticcheck)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 3a428202bf)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:29 +01:00
Silvin LubeckiandSebastiaan van Stijn 49ff9c82db cli/command/container/stats.go:211:21: SA1015: using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here (staticcheck)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 7da9360477)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:28 +01:00
Silvin LubeckiandSebastiaan van Stijn 1ed4e67b34 cli/command/trust/inspect_pretty_test.go:399:24: SA4010: this result of append is never used, except maybe in other appends (staticcheck)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 8018a850cb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:27 +01:00
Silvin LubeckiandSebastiaan van Stijn ad7bd8235f opts/throttledevice.go:51:5: SA4003: unsigned values are never < 0 (staticcheck)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 296297190c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:26 +01:00
Sebastiaan van Stijn b71d5e32cd compose/loader: fix TestIsAbs not testing all combinations
This test was intending to run all tests, but didn't, which was
caught by golangci-lint;

    cli/compose/loader/windows_path_test.go:46:17: SA4010: this result of append is never used, except maybe in other appends (staticcheck)
    	tests := append(isabstests, winisabstests...)
    	               ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 0a21de05d2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:16:21 +01:00
Sebastiaan van Stijn 3bc713c157 Gometalinter: raise deadline to 3 minutes
Looks like we're just on the edge of the deadline, and it's sometimes
failing;

```
cli/command/image/trust.go:346:1⚠️ nolint directive did not match any issue (nolint)
cli/command/manifest/push.go:211:1⚠️ nolint directive did not match any issue (nolint)
internal/pkg/containerized/snapshot.go:95:1⚠️ nolint directive did not match any issue (nolint)
internal/pkg/containerized/snapshot.go:138:1⚠️ nolint directive did not match any issue (nolint)
WARNING: deadline exceeded by linter interfacer (try increasing --deadline)
Exited with code 3
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 3e78cbc021)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:12:59 +01:00
Sebastiaan van Stijn d85a3b265c gometalinter: fix configuration
The configuration abused "Exclude" to exclude file-paths by filtering
on the output, however, the `Skip` option was designed for that, whereas
`Exclude` is for matching warnings.

An explicit "Skip" was added for "vendor", because even though the vendor
directory should already be ignored by the linter, in some situations,
it still seemed to warn on issues, so let's explicitly ignore it.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 71e525f74f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2020-01-06 13:12:45 +01:00
Silvin LubeckiandGitHub 08b5f63b0e Merge pull request #2222 from thaJeztah/19.03_backport_fix_docker_cp_npe
[19.03 backport] docker cp: prevent NPE when failing to stat destination
2019-12-10 10:53:34 +01:00
Sebastiaan van Stijn c2d4bd4ec2 docker cp: prevent NPE when failing to stat destination
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 585ec4da97)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-12-10 09:36:13 +01:00
Tibor Vass 2fa69baf8d cp: allow trailing slash in non-existant destination
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 26dbc3226c)
Signed-off-by: Tibor Vass <tibor@docker.com>
2019-11-12 17:26:32 +00:00
Djordje LukicandSebastiaan van Stijn e3657b0a8c Add interpolation type cast for max_replicas_per_node
Fixes https://github.com/docker/app/issues/688

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
(cherry picked from commit cb29ef6c6d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-11-05 13:15:57 -08:00
Andrew HsuandGitHub 99c5edceb4 Merge pull request #2177 from thaJeztah/19.03_backport_fix_sig_proxy
[19.03 backport] Do not disable sig-proxy when using a TTY
2019-11-04 16:55:15 -08:00
Andrew HsuandGitHub ad6c667034 Merge pull request #2178 from thaJeztah/19.03_backport_docs_updates
[19.03 backport] docs updates
2019-10-29 16:36:30 -07:00
Andrew HsuandGitHub 5cef8fc8e5 Merge pull request #2176 from thaJeztah/19.03_backport_completion
[19.03 backport] completion script updates and fixes
2019-10-29 16:36:23 -07:00
Daniel HelfandandSebastiaan van Stijn 9597e681cb update Jenkins Build Status urls for README
Signed-off-by: danielhelfand <helfand.4@gmail.com>
(cherry picked from commit 46f3f9ac04)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:27:54 +01:00
Brandon MitchellandSebastiaan van Stijn c050ae7fb1 Adjusting glossary reference and clarrifying the start of a Dockerfile
Signed-off-by: Brandon Mitchell <git@bmitch.net>
(cherry picked from commit 937ce69b42)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:27:42 +01:00
Adrian PlataandSebastiaan van Stijn aa45ea366c Minor formatting changes and a typo fix.
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
(cherry picked from commit ba7ec36de2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:27:28 +01:00
Daniel ArtineandSebastiaan van Stijn df5c7130df Updating deprecated command example in search.md
--stars example is deprecated. Changing to --filter=stars=5

Signed-off-by: danielartine <daniel.artine@ufrj.br>
(cherry picked from commit bba0a4d5ac)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:26:32 +01:00
Odin UgedalandSebastiaan van Stijn a90e5598a4 Fix phrasing when referring to the freezer cgroup
Signed-off-by: Odin Ugedal <odin@ugedal.com>
(cherry picked from commit a0dd6e025d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:26:20 +01:00
Daniel CassidyandSebastiaan van Stijn 66f8d279c1 builder.md: Correct copy/paste error
Signed-off-by: Daniel Cassidy <mail@danielcassidy.me.uk>
(cherry picked from commit e9ada56a88)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:26:09 +01:00
Forest JohnsonandSebastiaan van Stijn c4e5fd7e53 Explain -s flag on docker ps
https://github.com/docker/docker.github.io/issues/1520#issuecomment-467971886

Signed-off-by: Forest Johnson <fjohnson@peoplenetonline.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f7ab2987c3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:25:56 +01:00
Kir KolyshkinandSebastiaan van Stijn 149f69ca06 TestSigProxyWithTTY: fix
exec.CombinedOutput should not be used here because:
 - it redirects cmd Stdout and Stderr and we want it to be the tty
 - it calls cmd.Run which we already did

While at it
 - use pty.Start() as it is cleaner
 - make sure we don't leave a zombie running, by calling Wait() in defer
 - use test.Name() for containerName

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit bc4ed69a23)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:20:53 +01:00
Sebastiaan van Stijn 79f5dbcd55 Add test for --sig-proxy with a TTY
Add a test to verify that killing the docker CLI forwards
the signal to the container. Test-case for moby/moby 28872

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 7cf1a8d4c9)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:19:30 +01:00
Sebastiaan van Stijn 137b3cc89e Do not disable sig-proxy when using a TTY
This partially reverts https://github.com/moby/moby/commit/e0b59ab52b87b8fc15dd5534c3231fdd74843f9f,
and does not automatically disable proxying signals in TTY-mode

Before this change:
------------------------------------

Start a container with a TTY in one shell:

```
docker run -it --init --name repro-28872 busybox sleep 30
```

then, in another shell, kill the docker cli:

```
kill `pgrep -f repro-28872`
```

Notice that the CLI was killed, but the signal not forwarded to the container;
the container continues running

```
docker container inspect --format '{{ .State.Status }}' repro-28872
running

docker container rm -f repro-28872
```

After this change:
------------------------------------

Start a container with a TTY in one shell:

```
docker run -it --init --name repro-28872 busybox sleep 30
```

then, in another shell, kill the docker cli:

```
kill `pgrep -f repro-28872`
```

Verify that the signal was forwarded to the container, and the container exited

```
docker container inspect --format '{{ .State.Status }}' repro-28872
exited

docker container rm -f repro-28872
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ee29504923)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:19:21 +01:00
Harald AlbersandSebastiaan van Stijn 57332bcea3 Add bash completion for builder build options
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit cd9b39fc52)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:42 +01:00
Trapier MarshallandSebastiaan van Stijn 2fe281d170 Add bash completion for builder build
Signed-off-by: Trapier Marshall <trapier.marshall@docker.com>
(cherry picked from commit 86ae871e0a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:28 +01:00
Morten HekkvangandSebastiaan van Stijn 69f0132397 Fix erroneous space indentation of shell script
Signed-off-by: Morten Hekkvang <morten.hekkvang@sbab.se>
(cherry picked from commit fc19fb6d95)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:15 +01:00
Morten HekkvangandSebastiaan van Stijn 9447d7431b Move filtering to __docker_complete_services, as suggested by @albers
Signed-off-by: Morten Hekkvang <morten.hekkvang@sbab.se>
(cherry picked from commit 6ebcc211a7)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:13 +01:00
Morten HekkvangandSebastiaan van Stijn c70ce79adc Fix substitution of comma to space character, suggested by @albers
Signed-off-by: Morten Hekkvang <morten.hekkvang@sbab.se>
(cherry picked from commit b85e1e2efe)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:10 +01:00
Morten HekkvangandSebastiaan van Stijn 667bd9a1b8 Make service completion faster
Signed-off-by: Morten Hekkvang <morten.hekkvang@sbab.se>
(cherry picked from commit f55c5b6566)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:11:08 +01:00
Tim SampsonandSebastiaan van Stijn 6c66c799c7 add rudimentary fish completions for docker network
Signed-off-by: Tim Sampson <tim@sampson.fi>
(cherry picked from commit 2f7b364cb3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-29 15:10:42 +01:00
Andrew HsuandGitHub 8a9e86c728 Merge pull request #2124 from chris-crone/backport-19.03-env-merge
[19.03 backport] Add option to remove `env_file` entry once it's merged in the `environment` section
2019-10-22 14:52:48 -07:00
Andrew HsuandGitHub e176053a3f Merge pull request #2150 from thaJeztah/19.03_backport_bump_golang_1.12.12
[19.03 backport] Update Golang 1.12.12 (CVE-2019-17596)
2019-10-22 14:50:04 -07:00
Sebastiaan van Stijn f38bea4ac3 Update Golang 1.12.12 (CVE-2019-17596)
Golang 1.12.12
-------------------------------

full diff: https://github.com/golang/go/compare/go1.12.11...go1.12.12

go1.12.12 (released 2019/10/17) includes fixes to the go command, runtime,
syscall and net packages. See the Go 1.12.12 milestone on our issue tracker for
details.

https://github.com/golang/go/issues?q=milestone%3AGo1.12.12

Golang 1.12.11 (CVE-2019-17596)
-------------------------------

full diff: https://github.com/golang/go/compare/go1.12.10...go1.12.11

go1.12.11 (released 2019/10/17) includes security fixes to the crypto/dsa
package. See the Go 1.12.11 milestone on our issue tracker for details.

https://github.com/golang/go/issues?q=milestone%3AGo1.12.11

    [security] Go 1.13.2 and Go 1.12.11 are released

    Hi gophers,

    We have just released Go 1.13.2 and Go 1.12.11 to address a recently reported
    security issue. We recommend that all affected users update to one of these
    releases (if you're not sure which, choose Go 1.13.2).

    Invalid DSA public keys can cause a panic in dsa.Verify. In particular, using
    crypto/x509.Verify on a crafted X.509 certificate chain can lead to a panic,
    even if the certificates don't chain to a trusted root. The chain can be
    delivered via a crypto/tls connection to a client, or to a server that accepts
    and verifies client certificates. net/http clients can be made to crash by an
    HTTPS server, while net/http servers that accept client certificates will
    recover the panic and are unaffected.

    Moreover, an application might crash invoking
    crypto/x509.(*CertificateRequest).CheckSignature on an X.509 certificate
    request, parsing a golang.org/x/crypto/openpgp Entity, or during a
    golang.org/x/crypto/otr conversation. Finally, a golang.org/x/crypto/ssh client
    can panic due to a malformed host key, while a server could panic if either
    PublicKeyCallback accepts a malformed public key, or if IsUserAuthority accepts
    a certificate with a malformed public key.

    The issue is CVE-2019-17596 and Go issue golang.org/issue/34960.

    Thanks to Daniel Mandragona for discovering and reporting this issue. We'd also
    like to thank regilero for a previous disclosure of CVE-2019-16276.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 474d522ee2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-22 03:48:54 +02:00
Ulysses SouzaandChristopher Crone 379470969b Add option remove env_file entry after merged
This avoids having a redundant `env_file` entry
output when rendering the compose file

Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
(cherry picked from commit 821f5ecf53)
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
2019-10-04 17:32:48 +02:00
Andrew HsuandGitHub 2355349d8b Merge pull request #2119 from thaJeztah/19.03_backport_bump_yaml.v2_2.2.3
[19.03 backport] vendor: Bump gopkg.in/yaml.v2
2019-10-03 10:52:44 -07:00
Andrew HsuandGitHub 73d513e56a Merge pull request #2120 from thaJeztah/19.03_backport_experimental_note
[19.03 backport] backport docs changes
2019-10-01 14:27:56 -07:00
Adrian PlataandSebastiaan van Stijn 9fd5604d80 Adding experimental feature info
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
(cherry picked from commit 031bd2d530)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-01 19:11:06 +02:00
Adrian PlataandSebastiaan van Stijn 82ac89901f Clarifying docker config rules
Signed-off-by: Adrian Plata <adrian.plata@docker.com>
(cherry picked from commit 131eefc54f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-01 19:11:01 +02:00
Christopher CroneandSebastiaan van Stijn 29e3a70b04 vendor: Bump gopkg.in/yaml.v2
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
(cherry picked from commit 91cf8b04c9)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-10-01 14:54:49 +02:00
Sebastiaan van StijnandGitHub 3fb239756d Merge pull request #2113 from thaJeztah/19.03_backport_bump_golang_1.12.10
[19.03 backport] bump golang 1.12.10 (CVE-2019-16276)
2019-09-28 01:53:31 +02:00
Sebastiaan van Stijn ff72c27a7a bump golang 1.12.10 (CVE-2019-16276)
full diff: https://github.com/golang/go/compare/go1.12.9...go1.12.10

```
Hi gophers,

We have just released Go 1.13.1 and Go 1.12.10 to address a recently reported security issue. We recommend that all affected users update to one of these releases (if you're not sure which, choose Go 1.13.1).

net/http (through net/textproto) used to accept and normalize invalid HTTP/1.1 headers with a space before the colon, in violation of RFC 7230. If a Go server is used behind an uncommon reverse proxy that accepts and forwards but doesn't normalize such invalid headers, the reverse proxy and the server can interpret the headers differently. This can lead to filter bypasses or request smuggling, the latter if requests from separate clients are multiplexed onto the same upstream connection by the proxy. Such invalid headers are now rejected by Go servers, and passed without normalization to Go client applications.

The issue is CVE-2019-16276 and Go issue golang.org/issue/34540.

Thanks to Andrew Stucki, Adam Scarr (99designs.com), and Jan Masarik (masarik.sh) for discovering and reporting this issue.

Downloads are available at https://golang.org/dl for all supported platforms.

Alla prossima,
Filippo on behalf of the Go team
```

From the patch: https://github.com/golang/go/commit/6e6f4aaf70c8b1cc81e65a26332aa9409de03ad8

```
net/textproto: don't normalize headers with spaces before the colon

RFC 7230 is clear about headers with a space before the colon, like

X-Answer : 42

being invalid, but we've been accepting and normalizing them for compatibility
purposes since CL 5690059 in 2012.

On the client side, this is harmless and indeed most browsers behave the same
to this day. On the server side, this becomes a security issue when the
behavior doesn't match that of a reverse proxy sitting in front of the server.

For example, if a WAF accepts them without normalizing them, it might be
possible to bypass its filters, because the Go server would interpret the
header differently. Worse, if the reverse proxy coalesces requests onto a
single HTTP/1.1 connection to a Go server, the understanding of the request
boundaries can get out of sync between them, allowing an attacker to tack an
arbitrary method and path onto a request by other clients, including
authentication headers unknown to the attacker.

This was recently presented at multiple security conferences:
https://portswigger.net/blog/http-desync-attacks-request-smuggling-reborn

net/http servers already reject header keys with invalid characters.
Simply stop normalizing extra spaces in net/textproto, let it return them
unchanged like it does for other invalid headers, and let net/http enforce
RFC 7230, which is HTTP specific. This loses us normalization on the client
side, but there's no right answer on the client side anyway, and hiding the
issue sounds worse than letting the application decide.
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8743e36a45)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-09-27 23:33:06 +02:00
Sebastiaan van StijnandGitHub ed54e85144 Merge pull request #2079 from thaJeztah/19.03_backport_bump_pkcs11
[19.03 backport] bump miekg/pkcs11 v1.0.2
2019-09-27 13:41:10 +02:00
Sebastiaan van Stijn 0bc3d1fd2d bump miekg/pkcs11 v1.0.2
full diff: https://github.com/miekg/pkcs11/compare/6120d95c0e9576ccf4a78ba40855809dca31a9ed...v1.0.2

relevant changes:

- miekg/pkcs11#110 Fix issue freeing memory on GetOperationState when NOT CK_OK
- miekg/pkcs11#106 Move to go modules
- miekg/pkcs11#104 Expose login API for vendor specific login types

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 54428b1f37)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-09-27 11:51:03 +02:00
Andrew HsuandGitHub 50bb8c70f3 Merge pull request #2102 from tiborvass/19.03-buildkit-vendor
[19.03] vendor: update buildkit to docker-19.03
2019-09-23 18:18:48 -07:00
Tibor Vass 25168137bd vendor: update buildkit to docker-19.03
Signed-off-by: Tibor Vass <tibor@docker.com>
2019-09-24 00:36:30 +00:00
Andrew HsuandGitHub 3af5c3f8c6 Merge pull request #2099 from thaJeztah/19.03_backport_bump_vndr
[19.03 backport] bump LK4D4/vndr v0.0.3 and revendor
2019-09-23 16:59:17 -07:00
Sebastiaan van Stijn 3143ba5700 bump LK4D4/vndr v0.0.3 and revendor
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 909b85460c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-09-23 19:30:55 +02:00
Andrew HsuandGitHub a89484e338 Merge pull request #2090 from thaJeztah/19.03_backport_bump_go_1.12.9
[19.03 backport] Bump golang 1.12.9
2019-09-23 10:21:02 -07:00
Jintao ZhangandSebastiaan van Stijn 2ac9213069 Bump golang 1.12.9
Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
(cherry picked from commit d9856049e5)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-09-16 16:35:02 +02:00
Andrew HsuandGitHub 578ab52ece Merge pull request #2048 from thaJeztah/19.03_backport_ci_improvements
[19.03 backport] CI and testing improvements
2019-08-22 10:57:08 -07:00
Sebastiaan van StijnandGitHub c8e9c04d19 Merge pull request #2061 from thaJeztah/19.03_backport_issue39654
[19.03 backport] restore support for env variables to configure proxy
2019-08-22 19:55:05 +02:00
Nicolas De LoofandSebastiaan van Stijn 2fead2a50f restore support for env variables to configure proxy
regression introduced by b34f34
close #39654

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
(cherry picked from commit e25e077a20)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-22 19:11:41 +02:00
Sebastiaan van StijnandGitHub df1fe15cf6 Merge pull request #1985 from thaJeztah/19.03_backport_consistent_output_on_context_create
[19.03 backport] context: produce consistent output on `context create`.
2019-08-22 10:19:01 +02:00
Sebastiaan van Stijn be9adbd5c1 e2e: remove docker engine testing remnants
These changes were made as part of the `docker engine` feature
in commit fd2f1b3b66, but later
reverted in f250152bf4 and
b7ec4a42d9

These lines were forgotten to be removed, and should no longer
be needed.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit de01e72455)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:19:38 +02:00
Sebastiaan van Stijn 2907276eca e2e: enable buildkit
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 893db86d6e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:18:42 +02:00
Sebastiaan van Stijn 59b02c04bf Circle-CI: use progress=plain
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ae58e356ea)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:18:39 +02:00
Sebastiaan van Stijn 6a3eb417d5 Circle-CI: enable buildkit
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 9a6519db76)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:18:37 +02:00
Sebastiaan van Stijn c30ccb308d Update dockerignore
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 82e01807bc)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:18:34 +02:00
Sebastiaan van Stijn 1572845a2f Update CircleCI Docker version to 18.09.3
18.03 has reached EOL; let's use a more current version in CI

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8b19c1d73a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:16:52 +02:00
Sebastiaan van Stijn caad34cf58 Circle-CI: fix indentation in circle.yml
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 53fc63a93f)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-15 03:16:49 +02:00
Andrew HsuandGitHub bf683dfe52 Merge pull request #2044 from thaJeztah/19.03_backport_bump_golang_1.12.8
[19.03 backport] Bump golang 1.12.8 (CVE-2019-9512, CVE-2019-9514)
2019-08-14 11:55:59 -07:00
Sebastiaan van Stijn 307befd7e2 Adjust tests for changes in Go 1.12.8 / 1.11.13
For now, just verifying that an error is returned, but not checking the
error message itself, because those are not under our control, and may
change with different Go versions.

```
=== Failed
=== FAIL: opts TestParseDockerDaemonHost (0.00s)
    hosts_test.go:87: tcp tcp:a.b.c.d address expected error "Invalid bind address format: tcp:a.b.c.d" return, got "parse tcp://tcp:a.b.c.d: invalid port \":a.b.c.d\" after host" and addr
    hosts_test.go:87: tcp tcp:a.b.c.d/path address expected error "Invalid bind address format: tcp:a.b.c.d/path" return, got "parse tcp://tcp:a.b.c.d/path: invalid port \":a.b.c.d\" after host" and addr

=== FAIL: opts TestParseTCP (0.00s)
    hosts_test.go:129: tcp tcp:a.b.c.d address expected error Invalid bind address format: tcp:a.b.c.d return, got parse tcp://tcp:a.b.c.d: invalid port ":a.b.c.d" after host and addr
    hosts_test.go:129: tcp tcp:a.b.c.d/path address expected error Invalid bind address format: tcp:a.b.c.d/path return, got parse tcp://tcp:a.b.c.d/path: invalid port ":a.b.c.d" after host and addr
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit de1523d221)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-14 10:20:43 +02:00
Sebastiaan van Stijn b58270ba69 Bump golang 1.12.8 (CVE-2019-9512, CVE-2019-9514)
go1.12.8 (released 2019/08/13) includes security fixes to the net/http and net/url packages.
See the Go 1.12.8 milestone on our issue tracker for details:

https://github.com/golang/go/issues?q=milestone%3AGo1.12.8

- net/http: Denial of Service vulnerabilities in the HTTP/2 implementation
  net/http and golang.org/x/net/http2 servers that accept direct connections from untrusted
  clients could be remotely made to allocate an unlimited amount of memory, until the program
  crashes. Servers will now close connections if the send queue accumulates too many control
  messages.
  The issues are CVE-2019-9512 and CVE-2019-9514, and Go issue golang.org/issue/33606.
  Thanks to Jonathan Looney from Netflix for discovering and reporting these issues.
  This is also fixed in version v0.0.0-20190813141303-74dc4d7220e7 of golang.org/x/net/http2.
  net/url: parsing validation issue
- url.Parse would accept URLs with malformed hosts, such that the Host field could have arbitrary
  suffixes that would appear in neither Hostname() nor Port(), allowing authorization bypasses
  in certain applications. Note that URLs with invalid, not numeric ports will now return an error
  from url.Parse.
  The issue is CVE-2019-14809 and Go issue golang.org/issue/29098.
  Thanks to Julian Hector and Nikolai Krein from Cure53, and Adi Cohen (adico.me) for discovering
  and reporting this issue.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit bbd179f25b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-14 03:03:11 +02:00
Sebastiaan van Stijn 0ecfcb5997 Dockerfile: use GO_VERSION build-arg for overriding Go version
This allows overriding the version of Go without making modifications in the
source code, which can be useful to test against multiple versions.

For example:

    make GO_VERSION=1.13beta1 -f docker.Makefile binary

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 0d3022c6d2)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-08-14 03:03:04 +02:00
Sebastiaan van StijnandGitHub 0ea69840c6 Merge pull request #1970 from thaJeztah/19.03_backport_skip_windows_permissions_check
[19.03 backport] Windows: skip permissions check on key
2019-08-09 20:17:09 +02:00
Andrew HsuandGitHub 208de55a17 Merge pull request #1983 from thaJeztah/19.03_backport_bump_credential_helpers
[19.03 backport] bump docker-credential-helpers v0.6.3
2019-08-07 19:02:50 -07:00
Andrew HsuandGitHub 1a8077b814 Merge pull request #1998 from thaJeztah/19.03_backport_bump_golang_1.12.7
[19.03 backport] Bump golang 1.12.7
2019-08-07 17:48:16 -07:00
Kirill KolyshkinandGitHub fa0e2597e6 Merge pull request #2022 from thaJeztah/19.03_backport_fix_e2e
[19.03 backport] Disable TLS for e2e docker-in-docker daemon
2019-08-07 17:29:48 -07:00
Sebastiaan van Stijn f357def036 Disable TLS for e2e docker-in-docker daemon
The docker-in-docker image now enables TLS by default (added in
docker-library/docker#166), which complicates testing in our
environment, and isn't needed for the tests we're running.

This patch sets the `DOCKER_TLS_CERTDIR` to an empty value to
disable TLS.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b1a3c1aad1)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-29 17:11:28 -07:00
Sebastiaan van Stijn 792ce891be e2e: use stable-dind image for testing
The edge channel is deprecated and no longer updated

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 08fd6dd63c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-29 17:11:25 -07:00
Sebastiaan van StijnandGitHub d473c60571 Merge pull request #1995 from thaJeztah/19.03_backport_cross_platform_bind
[19.03 backport] Detect Windows absolute paths on non-Windows CLI
2019-07-26 13:11:18 -07:00
Kirill KolyshkinandGitHub b020a36d10 Merge pull request #2001 from thaJeztah/19.03_backport_docs
[19.03 backport] assorted docs and completion script fixes
2019-07-23 14:16:08 -07:00
Sebastiaan van Stijn d2e8ff9e20 bump docker-credential-helpers v0.6.3
full diff: https://github.com/docker/docker-credential-helpers/compare/v0.6.2...v0.6.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 64f0ae4252)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-17 17:02:21 +02:00
Rohan VermaandSebastiaan van Stijn 10a899b6bd fix: docker login autocomplete for zsh
Changed `--user` to `--username`

Signed-off-by: Rohan Verma <hello@rohanverma.net>
(cherry picked from commit 1dc756e8df)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-12 16:14:52 +02:00
Adrian PlataandSebastiaan van Stijn 41718b98f6 adding nvidia gpu access info
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

Removing prerequisites section.
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

Removing prerequisites section.
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

adding nvidia gpu access info
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

Refining information.

Removing prerequisites section.

adding nvidia gpu access info
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

Refining information.

Removing prerequisites section.

adding nvidia gpu access info
Signed-off-by: Adrian Plata <adrian.plata@docker.com>

Refining information.

Removing prerequisites section.

(cherry picked from commit f7b75eeb9b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-12 16:14:04 +02:00
Bret FisherandSebastiaan van Stijn caf21526a0 docs: add info for events backlog and scope
1. Adds `docker events` description info on the two scope types of events.
2. Adds `docker events` note in two places about backlog limit of event log.

Further info and background info in Issue 727

Signed-off-by: Bret Fisher <bret@bretfisher.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 988b9a0d96)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-12 16:13:22 +02:00
Andrew HsuandGitHub 5b38d82aa0 Merge pull request #1972 from thaJeztah/19.03_backport_bump_compose_on_kube
[19.03 backport] bump compose-on-kubernetes v0.4.23
2019-07-11 10:57:10 -07:00
Andrew HsuandGitHub e303dfb6fd Merge pull request #1979 from thaJeztah/19.03_backport_fix_rollback_config_interpolation
[WIP][19.03 backport] Fix Rollback config type interpolation
2019-07-11 10:56:15 -07:00
Sebastiaan van Stijn 94b98bfa21 Bump golang 1.12.7
go1.12.7 (released 2019/07/08) includes fixes to cgo, the compiler, and the
linker. See the Go 1.12.7 milestone on our issue tracker for details:
https://github.com/golang/go/issues?q=milestone%3AGo1.12.7

full diff: https://github.com/golang/go/compare/go1.12.6...go1.12.7

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b06f9e9595)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-11 14:10:40 +02:00
Sebastiaan van Stijn 87e400e44e Detect Windows absolute paths on non-Windows CLI
When deploying a stack using a relative path as bind-mount
source in the compose file, the CLI converts the relative
path to an absolute path, relative to the location of the
docker-compose file.

This causes a problem when deploying a stack that uses
an absolute Windows path, because a non-Windows client will
fail to detect that the path (e.g. `C:\somedir`) is an absolute
path (and not a relative directory named `C:\`).

The existing code did already take Windows clients deploying
a Linux stack into account (by checking if the path had a leading
slash). This patch adds the reverse, and adds detection for Windows
absolute paths on non-Windows clients.

The code used to detect Windows absolute paths is copied from the
Golang filepath package;
https://github.com/golang/go/blob/1d0e94b1e13d5e8a323a63cd1cc1ef95290c9c36/src/path/filepath/path_windows.go#L12-L65

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit d6dd08d568)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-10 23:40:22 +02:00
Ian CampbellandSebastiaan van Stijn 8cb2456248 context: produce consistent output on context create.
Refactor `RunCreate` slightly so that all three paths always produce the same
output, namely the name of the new context of `stdout` (for scripting) and the
success log message on `stderr`.

Validate by extending the existing unit tests to always check the output is as
expected.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit ff44305c47)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-04 21:37:25 +02:00
Sebastiaan van Stijn 11b15544c5 bump docker-credential-helpers v0.6.2
full diff: https://github.com/docker/docker-credential-helpers/compare/5241b46610f2491efdf9d1c85f1ddf5b02f6d962...8a9f93a99ff87f416cc79f267c68151af0026f60

includes:

- docker/docker-credential-helpers#29 C.free(unsafe.Pointer(err)) -> C.g_error_free(err)
- docker/docker-credential-helpers#124 pass: changed the way for checking if password-store is initalized
  - addresses docker/docker-credential-helpers#133 docker-credential-pass commits about 10 times every time I run a docker command
- docker/docker-credential-helpers#143 Fix docker-credential-osxkeychain list behaviour in case of missing entry in keychain
- docker/docker-credential-helpers#139 make docker-credential-wincred work like docker-credential-osxkeychain

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f6a4c76fbb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-04 21:12:56 +02:00
Silvin LubeckiandSebastiaan van Stijn 344adac7a6 Rollback config type interpolation on fields "parallelism" and "max_failure_ratio" were missing, as it uses the same type as update_config.
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit efdf36fa81)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-03 19:20:41 +02:00
Andrew HsuandGitHub 2027d17a9d Merge pull request #1976 from thaJeztah/19.03_backport_deprecate_aufs
[19.03 backport] Deprecate AuFS storage driver
2019-07-02 13:44:40 -07:00
Sebastiaan van Stijn ff881608fb Deprecate AuFS storage driver
The `aufs` storage driver is deprecated in favor of `overlay2`, and will
be removed in a future release. Users of the `aufs` storage driver are
recommended to migrate to a different storage driver, such as `overlay2`, which
is now the default storage driver.

The `aufs` storage driver facilitates running Docker on distros that have no
support for OverlayFS, such as Ubuntu 14.04 LTS, which originally shipped with
a 3.14 kernel.

Now that Ubuntu 14.04 is no longer a supported distro for Docker, and `overlay2`
is available to all supported distros (as they are either on kernel 4.x, or have
support for multiple lowerdirs backported), there is no reason to continue
maintenance of the `aufs` storage driver.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c8e9233b93)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-07-02 17:36:19 +02:00
Sebastiaan van Stijn 8947ee2709 bump compose-on-kubernetes v0.4.23
no local changes

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 1877ed6aa3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-26 13:10:51 +02:00
Andrew HsuandGitHub 2f1931f9eb Merge pull request #1967 from thaJeztah/19.03_backport_fix_advanced_options_for_backward_compat
[19.03 backport] Fix advanced options for backward compatibility
2019-06-25 12:17:58 -07:00
Sebastiaan van StijnandGitHub 8164090257 Merge pull request #1960 from thaJeztah/19.03_backport_deprecate_schema1
[19.03 backport] deprecate registry v2 schema 1
2019-06-25 15:56:41 +02:00
Sebastiaan van Stijn e803e487c3 Windows: skip permissions check on key
This code was attempting to check Linux file permissions
to determine if the key was accessible by other users, which
doesn't work, and therefore prevented users on Windows
to load keys.

Skipping this check on Windows (correspinding tests
were already skipped).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 15d361fd77)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-25 12:54:33 +02:00
Andrew HsuandSebastiaan van Stijn 5b636878fc deprecate registry v2 schema 1
Co-Authored-By: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8b4e52f0bf)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-24 23:20:42 +02:00
Sebastiaan van Stijn 3bc3f0390e Fix advanced options for backward compatibility
For backward compatibility: if no custom options are provided for the network,
and only a single network is specified, omit the endpoint-configuration
on the client (the daemon will still create it when creating the container)

This fixes an issue on older versions of legacy Swarm, which did not support
`NetworkingConfig.EndpointConfig`.

This was introduced in 5bc09639cc (#1767)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4d7e6bf629)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-24 23:18:34 +02:00
Jintao ZhangandSebastiaan van Stijn 296e10c0c5 Bump golang 1.12.6
Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
(cherry picked from commit 459099e175)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-13 15:52:38 +02:00
Sebastiaan van StijnandGitHub a63faebcf1 Merge pull request #1927 from cpuguy83/backport_goarm
[19.03] Backport #1857: Support GOARM and windows .exe in binary target
2019-06-06 21:10:27 +02:00
Sebastiaan van StijnandGitHub 49236a4391 Merge pull request #1929 from thaJeztah/19.03_backport_fix_empty_context_import
[19.03 backport] Fix detection of invalid context files when importing
2019-06-06 21:09:29 +02:00
Sebastiaan van Stijn 17b3250f0f Fix detection of invalid context files when importing
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5f93509668)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-06-06 15:02:52 +02:00
Brian Goff 5d246f4998 Support GOARM and windows .exe in binary target
This just makes it easier to build a targeted binary for the
goos/goach/goarm version.

This of course will not work for all cases but is nice to get things
going.
Specifically cross-compiling pkcs for yubikey support requires some
extra work whichis not tackled here.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 15130e3043)
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2019-06-05 14:13:14 -07:00
Sebastiaan van StijnandGitHub f913afa98c Merge pull request #1912 from thaJeztah/19.03_backport_import_zip
[19.03 backport] Introduce .zip import for docker context
2019-05-29 23:53:59 +03:00
Goksu ToprakandSebastiaan van Stijn 90f256aeab Introduce .zip import for docker context
Adds capabilities to import a .zip file with importZip.
Detects the content type of source by checking bytes & DetectContentType.
Adds LimitedReader reader, a fork of io.LimitedReader,
was needed for better error messaging instead of just getting back EOF.
We are using limited reader to avoid very big files causing memory issues.
Adds a new file size limit for context imports,
this limit is used for the main file for .zip & .tar and individual compressed
files for .zip.
Added TestImportZip that will check the import content type
Then will assert no err on Importing .zip file

Signed-off-by: Goksu Toprak <goksu.toprak@docker.com>
(cherry picked from commit 291e86289b)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-29 23:09:20 +03:00
Sebastiaan van StijnandGitHub ee10970b05 Merge pull request #1911 from thaJeztah/19.03_bump_engine_19.03_3
[19.03 backport] bump docker/docker to tip of 19.03 branch
2019-05-27 23:00:57 +03:00
Sebastiaan van Stijn 35c929ed5e bump docker/docker to tip of 19.03 branch
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-27 22:18:14 +03:00
Sebastiaan van StijnandGitHub 60eb4ceaf7 Merge pull request #1886 from thaJeztah/19.03_bump_engine_19.03_2
[19.03] bump  bump docker/docker bff7e300e6bdb18c2417e23594bf26063a378dee (19.03)
2019-05-27 22:05:41 +03:00
Sebastiaan van StijnandGitHub 1b15368c47 Merge pull request #1907 from silvin-lubecki/19.03_backport-reduce-vendoring-impact2
[19.03 backport] Dynamically register kubernetes context store endpoint type.
2019-05-27 20:50:39 +03:00
Ian CampbellandSilvin Lubecki a720cf572f Push check for kubernetes requirement down into the endpoint
This is less of a layering violation and removes some ugly hardcoded
`"kubernetes"` strings which were needed to avoid an import loop.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit c455193d14)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 16:50:21 +02:00
Ian CampbellandSilvin Lubecki ec7a9ad6e4 Dynamically register kubernetes context store endpoint type.
This removes the need for the core context code to import
`github.com/docker/cli/cli/context/kubernetes` which in turn reduces the
transitive import tree in this file to not pull in all of Kubernetes.

Note that this means that any calling code which is interested in the
kubernetes endpoint must import `github.com/docker/cli/cli/context/kubernetes`
itself somewhere in order to trigger the dynamic registration. In practice
anything which is interested in Kubernetes must import that package (e.g.
`./cli/command/context.list` does for the `EndpointFromContext` function) to do
anything useful, so this restriction is not too onerous.

As a special case a small amount of Kubernetes related logic remains in
`ResolveDefaultContext` to handle error handling when the stack orchestrator
includes Kubernetes. In order to avoid a circular import loop this hardcodes
the kube endpoint name.

Similarly to avoid an import loop the existing `TestDefaultContextInitializer`
cannot continue to unit test for the Kubernetes case, so that aspect of the
test is carved off into a very similar test in the kubernetes context package.

Lastly, note that the kubernetes endpoint is now modifiable via
`WithContextEndpointType`.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 520be05c49)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:55:50 +02:00
Ian CampbellandSilvin Lubecki 5e413159e5 Export DefaultContextStoreConfig() and ResolveDefaultContext()
These are needed by any dynamically registered (via
`RegisterDefaultStoreEndpoints`) endpoint type to write a useful/sensible unit
test.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit f820766f6a)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:55:40 +02:00
Ian CampbellandSilvin Lubecki d4226d2f73 Allow dynamically registered context endpoint to provide their defaults.
Previously an endpoint registered using `RegisterDefaultStoreEndpoints` would
not be taken into consideration by `resolveDefaultContext` and so could not
provide any details.

Resolve this by passing a `store.Config` to `resolveDefaultContext` and using
it to iterate over all registered endpoints. Any endpoint can ensure that their
type implements the new `EndpointDefaultResolver` in order to provide a default.

The Docker and Kubernetes endpoints are special cased, shortly the Kubernetes
one will be refactored to be dynamically registered.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 1433e27420)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:55:34 +02:00
Ian CampbellandSilvin Lubecki a7c10adf4e Add a helper to iterate over all endpoint types in a context store
Unused for now.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 4f14c4995e)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:55:24 +02:00
Ian CampbellandSilvin Lubecki a4f41d94db Support dynamic registration of context store endpoint types
This is a yet unused and the default set remains the same, no expected
functional change.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 087c3f7d08)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:55:18 +02:00
Ian CampbellandSilvin Lubecki 71e1883ca0 e2e: add a test for context ls
I'm about to refactor the code which includes the Kubernetes support in a way
which relies on something vendoring `./cli/context/kubernetes/` in order to
trigger the inclusion of support for the Kubernetes endpoint in the final
binary.

In practice anything which is interested in Kubernetes must import that package
(e.g. `./cli/command/context.list` does for the `EndpointFromContext`
function). However if it was somehow possible to build without that import then
the `KUBERNETES ENDPOINT` column would be mysteriously empty.

Out of an abundance of caution add a specific check on the final binary.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit d5d693aa6e)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:53:45 +02:00
Ian CampbellandSilvin Lubecki 06eb05570a fix a few typos
Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit d84e278aac)
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
2019-05-24 15:53:36 +02:00
Silvin LubeckiandGitHub a1b83ffd2c Merge pull request #1894 from thaJeztah/19.03_backport_reduce_vendoring_impact
[19.03 backport] Allow vendorers of docker/cli to avoid transitively pulling in a big chunk if k8s too
2019-05-24 11:10:13 +02:00
Tibor VassandGitHub 649097ffe0 Merge pull request #1905 from thaJeztah/19.03_backport_plugin_experimental
[19.03 backport] cli-plugins: add concept of experimental plugin, only enabled in experimental mode
2019-05-23 14:05:21 -07:00
Tibor VassandSebastiaan van Stijn 57f1de13b3 cli-plugins: add test names for easier debugging
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit bb8e89bb2e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-23 21:28:18 +02:00
Tibor VassandSebastiaan van Stijn c5431132d7 cli-plugins: add concept of experimental plugin, only enabled in experimental mode
To test, add $(pwd)/build/plugins-linux-amd64 to "cliPluginsExtraDirs" config and run:
make plugins
make binary
HELLO_EXPERIMENTAL=1 docker helloworld

To show it enabled:
HELLO_EXPERIMENTAL=1 DOCKER_CLI_EXPERIMENTAL=enabled docker helloworld

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 6ca8783730)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-23 21:28:09 +02:00
Ian CampbellandSebastiaan van Stijn c66cebee7a Use underlying NewKubernetesConfig directly from compose-on-kubernetes.
The comment on `github.com/docker/cli/kubernetes.NewKubernetesConfig` said:

    // Deprecated: Use github.com/docker/compose-on-kubernetes/api.NewKubernetesConfig instead

By making this switch in `github.com/docker/cli/context/kubernetes/load.go` we
break a vendoring chain:

`github.com/docker/cli/cli/command`
→ `vendor/github.com/docker/cli/cli/context/kubernetes/load.go`
  → `vendor/github.com/docker/cli/kubernetes`
     → `github.com/docker/compose-on-kubernetes/api/compose/...`

This means that projects which just want `github.com/docker/cli/cli/command`
(which is itself pulled in transitively by
`github.com/docker/cli/cli-plugins/plugin`) which do not themselves need the
compose-on-kubernetes API avoid a huge pile of transitive dependencies.

On one of my private projects the diff on the vendor dir is:

    280 files changed, 21 insertions(+), 211346 deletions(-)

and includes dropping:

* `github.com/docker/compose-on-kubernetes/api/compose/{clone,impersonation}`
* `github.com/docker/compose-on-kubernetes/api/compose/{v1alpha3,v1beta1,v1beta2,v1beta3}`
* `github.com/google/btree`
* `github.com/googleapis/gnostic`
* `github.com/gregjones/httpcache`
* `github.com/peterbourgon/diskv`
* `k8s.io/api/*` (_lots_ of subpackages)
* `k8s.io/client-go/{discovery,kubernetes/scheme}`

and I've gone from:

    $ du -sh vendor/k8s.io/
    8.1M	vendor/k8s.io/

to:

    $ du -sh vendor/k8s.io/
    2.1M	vendor/k8s.io/

(overall I went from 36M → 29M of vendor dir for this particular project)

The change to `cli/command/system/version.go` is just for consistency and
allows us to drop the now unused alias.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 8635abd662)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-20 18:14:36 +02:00
Ian CampbellandSebastiaan van Stijn c105a58f65 rename package import kubcontext → kubecontext
The (small number) of other places which name this import use `kubecontext`,
make it consistent.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 1e5129f027)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-20 18:14:27 +02:00
Sebastiaan van Stijn 545fd2ad76 add containerd/ttrpc f02858b1457c5ca3aaec3a0803eb0d59f96e41d6
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 41fe464139)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:59:47 -07:00
Sebastiaan van Stijn 315f7d7d04 bump golang.org/x/crypto 88737f569e3a9c7ab309cdc09a07fe7fc87233c3
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 51de9a883a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:47 -07:00
Sebastiaan van Stijn 6aedc5e912 bump gogo/protobuf v1.2.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4de6cb0136)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:38 -07:00
Sebastiaan van Stijn 3ac398aa49 bump gogo/googleapis v1.2.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 415cb3d90e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:29 -07:00
Sebastiaan van Stijn 781c427788 bump containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4cb01169ec)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:20 -07:00
Sebastiaan van Stijn 47e66c5812 bump containerd/continuity aaeac12a7ffcd198ae25440a9dff125c2e2703a7
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit dbfeaae5eb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:10 -07:00
Sebastiaan van Stijn 9933222452 bump containerd aaeac12a7ffcd198ae25440a9dff125c2e2703a7
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8ea94a1724)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:52:01 -07:00
Sebastiaan van Stijn 3f5553548b vendor: bump runc v1.0.0-rc8
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a4f01d8765)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:51:52 -07:00
Sebastiaan van Stijn c8273616ee bump docker/docker bff7e300e6bdb18c2417e23594bf26063a378dee (19.03 branch)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 21:51:30 -07:00
Tibor VassandGitHub 8aebc31806 Merge pull request #1884 from thaJeztah/19.03_bump_buildkit_grpc
[19.03 backport] vendor buildkit to f238f1e, bump google.golang.org/grpc v1.20.1
2019-05-13 18:56:16 -07:00
Sebastiaan van Stijn 57ef4e32f4 bump google.golang.org/grpc v1.20.1
full diff: https://github.com/grpc/grpc-go/compare/v1.12.2...v1.20.1

includes  grpc/grpc-go#2695 transport: do not close channel that can lead to panic
addresses moby/moby#39053

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 93d76c5c90)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 18:43:30 -07:00
Tibor VassandSebastiaan van Stijn c15fb3a8e5 vendor buildkit to f238f1e
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 529ef6e89a)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 18:43:13 -07:00
Sebastiaan van StijnandGitHub cb07256868 Merge pull request #1882 from thaJeztah/19.03_backport_fix_powershell_codehint
[19.03 backport] Fix PowerShell codehint for rouge
2019-05-13 17:49:29 -07:00
Sebastiaan van Stijn 5ec13f81a2 Fix PowerShell codehint for rouge
Rouge is case-sensitive, and only works with powershell
all lowercase.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 5331358d3e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 17:31:56 -07:00
Tibor VassandGitHub 394c393998 Merge pull request #1878 from thaJeztah/19.03_plugin_fixes
[19.03 backport] plugin fixes
2019-05-13 14:40:08 -07:00
Tibor VassandGitHub a4ba5831a0 Merge pull request #1875 from thaJeztah/19.03_backport_bump-golang-1.12.5
[19.03 backport] Bump golang 1.12.5
2019-05-13 14:33:46 -07:00
Sebastiaan van StijnandGitHub ac45214f7d Merge pull request #1876 from thaJeztah/19.03_backport_completion_scripts
[19.03 backport] backport bash completion scripts
2019-05-13 14:25:23 -07:00
Sebastiaan van StijnandGitHub 12a1cf4783 Merge pull request #1879 from thaJeztah/19.03_backport_buildkit_fixes
[19.03 backport] backport BuildKit fixes
2019-05-13 14:24:38 -07:00
Silvin LubeckiandGitHub 7fd21aefd8 Merge pull request #1877 from thaJeztah/19.03_backport_authors_ci_fixes
[19.03 backport] update authors and upload junit.xml
2019-05-13 18:18:20 +02:00
Tibor VassandSebastiaan van Stijn 3f9063e775 vendor buildkit to 646fc0af6d283397b9e47cd0a18779e9d0376e0e (v0.5.1)
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 7f45a0e52c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:13:40 -07:00
Tibor VassandSebastiaan van Stijn 8758cdca10 build: add --platform local
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit daca70d820)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:13:25 -07:00
Tibor VassandSebastiaan van Stijn 529b1e7ec7 build: honor BUILDKIT_PROGRESS env config
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 8adcedd658)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:13:17 -07:00
Ian CampbellandSebastiaan van Stijn b8bfba8dc6 cli-plugins: fix when plugin does not use PersistentPreRun* hooks
This regressed in 3af168c7df ("Ensure plugins can use `PersistentPreRunE`
again.") but this wasn't noticed because the helloworld test plugin has it's
own `PersistentPreRunE` which has the effect of deferring the resolution of the
global variable. In the case where the hook isn't used the variable is resolved
during `newPluginCommand` which is before the global variable was set.

Initialize the plugin command with a stub function wrapping the call to the
(global) hook, this defers resolving the variable until after it has been set,
otherwise the initial value (`nil`) is used in the struct.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit af200f14ed)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:06:08 -07:00
Ian CampbellandSebastiaan van Stijn d6ddcdfa6a Use command.Cli instead of command.DockerCli
The linter is complaining:

    cmd/docker/docker.go:72:23⚠️ dockerCli can be github.com/docker/cli/cli/command.Cli (interfacer)

Unclear precisely which change in the preceeding commits caused it to notice
this possibility.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 7d0645c5fe)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:05:54 -07:00
Ian CampbellandSebastiaan van Stijn 7380aae601 Include CLI plugins in help output on unknown flag.
Previously `docker --badopt` output would not include CLI plugins.

Fixes #1813

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 40a6cf7c47)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:05:45 -07:00
Ian CampbellandSebastiaan van Stijn 6a6cd35985 Hide experimental builtin commands in help output on unknown flag.
Previously `docker --badopt` would always include experimental commands even if
experimental was not enabled.

Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit 79a75da0fd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:05:34 -07:00
Ian CampbellandSebastiaan van Stijn 941a493f49 Move subtests of TestGlobalHelp into actual subtests
Signed-off-by: Ian Campbell <ijc@docker.com>
(cherry picked from commit d57175aa2e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 09:05:25 -07:00
Sebastiaan van Stijn 1e275568f1 CircleCI: store junit.xml as artifact
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit dcc414be3e)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:59:06 -07:00
Sebastiaan van Stijn 2a78b4e9a3 Update AUTHORS and mailmap
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ffc168ed51)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:58:21 -07:00
Harald AlbersandSebastiaan van Stijn 8cf8fc27fa Add bash completion for events --filter node
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit c1639e1e42)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:51:15 -07:00
Harald AlbersandSebastiaan van Stijn 68d67f2cbf Add bash completion for context create --from
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit b55992afc6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:51:04 -07:00
Trapier MarshallandSebastiaan van Stijn c1754d9e5d bash completion: add node type filter
Signed-off-by: Trapier Marshall <trapier.marshall@docker.com>
(cherry picked from commit 50a45babac)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:50:52 -07:00
Harald AlbersandSebastiaan van Stijn af9b8c1be3 Add bash completion for --security-opt systempaths=unconfined
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 1648d6c4a4)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:50:37 -07:00
Harald AlbersandSebastiaan van Stijn 292fc5c580 Remove deprecated storage drivers from bash completion
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit bfa43d2989)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:45:10 -07:00
Jintao ZhangandSebastiaan van Stijn 11f5e33a90 Bump golang 1.12.5
Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
(cherry picked from commit c32d1de57c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-05-13 08:28:50 -07:00
Silvin LubeckiandGitHub f28d9cc929 Merge pull request #1846 from andrewhsu/v
update vndr docker/docker ac48309 and related packages
2019-04-24 21:43:12 +02:00
Andrew Hsu eb2bfeccf7 update vndr coreos/etcd d57e8b8
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2019-04-24 18:29:33 +00:00
Andrew Hsu c1a4fb4922 update vndr moby/buildkit 8818c67
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2019-04-24 18:26:58 +00:00
Andrew Hsu e243174b30 update vndr Microsoft/go-winio 84b4ab4
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2019-04-24 18:24:26 +00:00
Andrew Hsu af053bc278 update vndr Microsoft/hcsshim 672e52e
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2019-04-24 18:14:51 +00:00
Andrew Hsu 30cc5d96b3 update vndr docker/docker to ac48309
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2019-04-24 18:10:45 +00:00
Tõnis TiigiandGitHub 70f48f2231 Merge pull request #1840 from tiborvass/cli-plugin-aliases
cli-plugins: alias an existing allowed command (only builder for now)
2019-04-23 19:13:51 -07:00
Silvin LubeckiandGitHub 9a0b171192 Merge pull request #1844 from thaJeztah/bump_go_units
bump docker/go-units v0.4.0
2019-04-23 17:14:49 +02:00
Sebastiaan van Stijn c94308fa99 bump docker/go-units v0.4.0
relevant changes:

- docker/go-units#33 Fix handling of unlimited (-1) ulimit values
- docker/go-units#34 Revert 46 minute threshold

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-23 17:01:07 +02:00
Tibor Vass 1ed02c40fe cli-plugins: alias an existing allowed command (only builder for now)
With this patch it is possible to alias an existing allowed command.
At the moment only builder allows an alias.

This also properly puts the build command under builder, instead of image
where it was for historical reasons.

Signed-off-by: Tibor Vass <tibor@docker.com>
2019-04-19 01:26:45 +00:00
Sebastiaan van StijnandGitHub 8ca1f0bb7d Merge pull request #1715 from AkihiroSuda/fix-bastion
commandconn: set SysProcAttr.Setsid (Fix DOCKER_HOST=ssh://host-behind-bastion)
2019-04-18 19:55:53 +02:00
Sebastiaan van StijnandGitHub 59952a0146 Merge pull request #1839 from thaJeztah/bump_engine3
bump docker/docker 92a6266c9d4f1bacbfb68d1c6b9c94f673d6cfde
2019-04-18 19:32:32 +02:00
Sebastiaan van Stijn ba8388f052 bump github.com/davecgh/go-spew v1.1.1
full diff: https://github.com/davecgh/go-spew/compare/v1.1.0...v1.1.1

- davecgh/go-spew#79 simpler, more robust bypass

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:20:31 +02:00
Sebastiaan van Stijn 6a562c9b33 bump beorn7/perks e7f67b54abbeac9c40a31de0f81159e4cafebd6a
no local changes

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:14:39 +02:00
Sebastiaan van Stijn df4dc54374 bump docker/swarmkit 59163bf75df38489d4a10392265d27156dc473c5
full diff: https://github.com/docker/swarmkit/compare/18e7e58ea1a5ec016625a636d0d52500eea123bc...59163bf75df38489d4a10392265d27156dc473c5

- Add missing return when configuring VXLAN port
- Prevent possible panic in cnmallocator.IsAttachmentAllocated()
- update github.com/pivotal-golang/clock
  - new name for package: code.cloudfoundry.org/clock

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:13:13 +02:00
Sebastiaan van Stijn 84dc462ea4 bump containerd/go-runc 7d11b49dc0769f6dbb0d1b19f3d48524d1bad9ad
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:12:10 +02:00
Sebastiaan van Stijn ac234326a6 bump containerd/fifo a9fb20d87448d386e6d50b1f2e1fa70dcf0de43c
- containerd/fifo#17 Expose underlying file's `SyscallConn` method

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:10:16 +02:00
Sebastiaan van Stijn eeaa4e543a bump syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
full diff: https://github.com/syndtr/gocapability/compare/2c00daeb6c3b45114c80ac44119e7b8801fdd852...d98352740cb2c55f81556b63d4a1ec64c5a319c2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:07:59 +02:00
Sebastiaan van Stijn 1962ec66bb bump docker/docker 92a6266c9d4f1bacbfb68d1c6b9c94f673d6cfde
full diff: https://github.com/docker/docker/compare/ed07e1152879a4d156dff2e86abca3c4c811e743...92a6266c9d4f1bacbfb68d1c6b9c94f673d6cfde

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-18 19:06:05 +02:00
Sebastiaan van StijnandGitHub d365225c32 Merge pull request #1838 from simonferquel/remove-context-in-function-names
Remove "context" from context store interfaces function names
2019-04-18 18:38:01 +02:00
Sebastiaan van StijnandGitHub fe19be2530 Merge pull request #1810 from albers/completion-buildkit
Add BuildKit specific options to bash completion
2019-04-18 17:56:12 +02:00
Sebastiaan van StijnandGitHub 5ad82fafb3 Merge pull request #1829 from thaJeztah/bump_gotestsum_v0.3.4
bump gotestsum v0.3.4
2019-04-18 17:55:12 +02:00
Sebastiaan van StijnandGitHub f99e0b00e9 Merge pull request #1828 from thaJeztah/bump_shlex
bump github.com/google/shlex c34317bd91bf98fab745d77b03933cf8769299fe
2019-04-18 17:55:02 +02:00
Sebastiaan van StijnandGitHub 04751fd58e Merge pull request #1830 from thaJeztah/use_google_shlex
Switch to google/shlex
2019-04-18 17:53:37 +02:00
Sebastiaan van StijnandGitHub 438426e0fc Merge pull request #1811 from thaJeztah/bump_grpc_1.12.2
bump google.golang.org/grpc v1.12.2
2019-04-18 17:49:19 +02:00
Sebastiaan van StijnandGitHub 71570160c1 Merge pull request #1826 from thaJeztah/bump_engine2
bump docker/docker ed07e1152879a4d156dff2e86abca3c4c811e743
2019-04-18 17:48:44 +02:00
Simon Ferquel a3efd5d195 Cleanup context store interfaces
This remove the term "context" from context store interfaces, to make
them more concise

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
2019-04-18 15:49:36 +02:00
Sebastiaan van StijnandGitHub 84b3805feb Merge pull request #1836 from simonferquel/context-export-source
Split the context store interface
2019-04-18 15:36:13 +02:00
Simon Ferquel 225c9b189a Split the context store interface
This is to make it easier to implement support for exporting contexts in
3rd party code, or to create mocks in tests.

2 exemples where it simplify things:
- docker-app desktop-specific context decorator (which rewrites parts of
the docker context to simplify UX when using on Docker Desktop contexts)
- ucp for including a context in the connection bundle

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
2019-04-18 15:03:46 +02:00
Sebastiaan van StijnandGitHub 552e8d1a73 Merge pull request #1832 from thaJeztah/bump_golang_1.12.4
Bump Golang 1.12.4
2019-04-18 01:53:53 +02:00
Tibor VassandGitHub 2432af701a Merge pull request #1808 from martencassel/securityopt-systempaths-unconfined
add cli integration for unconfined systempaths
2019-04-16 11:48:43 -07:00
Sebastiaan van StijnandGitHub 49bd6b729d Merge pull request #1835 from dhiltgen/refined_login_warning
Refine warning for storing registry passwords
2019-04-16 10:36:24 +02:00
Daniel Hiltgen 5b3f171482 Add unit test coverage for token auth
Signed-off-by: Daniel Hiltgen <daniel.hiltgen@docker.com>
2019-04-15 16:13:55 -07:00
Silvin LubeckiandGitHub f02d94afbb Merge pull request #1825 from thaJeztah/bump_gotest_2.3.0
bump gotest.tools v2.3.0
2019-04-15 11:56:37 +02:00
Vincent DemeesterandGitHub c61435b9c7 Merge pull request #1834 from thaJeztah/end_of_upstream_packages
vendor.conf: reserve space for downstream projects
2019-04-15 09:49:07 +02:00
Sebastiaan van StijnandGitHub d043ab5993 Merge pull request #1823 from simonferquel/refactor-kubernetes-extras
Regroup all kubernetes extra-fields under x-kubernetes
2019-04-14 22:59:41 +02:00
Daniel Hiltgen 80d2496f99 Refine warning for storing registry passwords
This change refines the warning message returned during docker login to
only warn for unencrypted storage when the users password is being stored.
If the remote registry supports identity tokens, omit the warning,
since those tokens can be independently managed and revoked.

Signed-off-by: Daniel Hiltgen <daniel.hiltgen@docker.com>
2019-04-14 08:33:53 -07:00
Sebastiaan van Stijn 337a9611e2 bump gotestsum v0.3.4
https://github.com/gotestyourself/gotestsum/releases/tag/v0.3.4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-14 16:51:12 +02:00
Sebastiaan van Stijn 8c5460a2cc vendor.conf: reserve space for downstream projects
This helps merge conflicts in situations where downstream
projects have additional dependencies.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-14 16:21:12 +02:00
Sebastiaan van Stijn cf47bb2cc2 Bump Golang 1.12.4
go1.12.4 (released 2019/04/11) fixes an issue where using the prebuilt
binary releases on older versions of GNU/Linux led to failures when linking
programs that used cgo. Only Linux users who hit this issue need to update.

See golang/go#31293 for details

Full diff: https://github.com/golang/go/compare/go1.12.3...go1.12.4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-14 02:19:16 +02:00
Sebastiaan van Stijn acb24f5164 Switch to google/shlex
The github.com/flynn-archive/go-shlex package is a fork of Google/shlex,
and the repository is now archived, so let's switch to the maintained
version.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 17:51:15 +02:00
Sebastiaan van Stijn c30e94533c bump golang.org/x/sys 4b34438f7a67ee5f45cc6132e2bad873a20324e9
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:42 +02:00
Sebastiaan van Stijn 767fafdb32 bump golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:36 +02:00
Sebastiaan van Stijn b6cee4567c bump golang.org/x/net eb5bcb51f2a31c7d5141d810b70815c05d9c9146
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:33 +02:00
Sebastiaan van Stijn 34806a8b4c bump golang.org/x/crypto 38d8ce5564a5b71b2e3a00553993f1b9a7ae852f
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:30 +02:00
Sebastiaan van Stijn 058f4337a4 bump opencontainers/runc v1.0.0-rc7-6-g029124da
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:27 +02:00
Sebastiaan van Stijn a9c26efc3c bump moby/buildkit b3028967ae6259c9a31c1a1deeccd30fe3469cce
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:24 +02:00
Sebastiaan van Stijn 9d37657f34 bump konsorten/go-windows-terminal-sequences 1.0.2
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:21 +02:00
Sebastiaan van Stijn 34e119e571 bump containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:18 +02:00
Sebastiaan van Stijn f07e16d42c bump docker/docker ed07e1152879a4d156dff2e86abca3c4c811e743
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:09:15 +02:00
Sebastiaan van Stijn 40968111cc bump github.com/google/shlex c34317bd91bf98fab745d77b03933cf8769299fe
full diff: https://github.com/google/shlex/compare/6f45313302b9c56850fc17f99e40caebce98c716...c34317bd91bf98fab745d77b03933cf8769299fe

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 03:00:54 +02:00
Sebastiaan van Stijn c8d685457b bump gotest.tools v2.3.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-13 01:47:37 +02:00
Sebastiaan van Stijn 25e6a64e2a bump google.golang.org/grpc v1.12.2
full diff: https://github.com/grpc/grpc-go/compare/v1.12.0...v1.12.2

- grpc/grpc-go#2074 transport/server: fix race between writing status and header
  - fix grpc/grpc-go#1972 Possible race sending headers from server while receiving message over size limit
- grpc/grpc-go#2074 transport: account for user configured small io write buffer
  - fix grpc/grpc-go#2089 Server abruptly terminates connections if write buffer is small enough

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-12 20:46:34 +02:00
Brian GoffandGitHub 58ec72afca Merge pull request #1781 from dperny/swarm-credentialspec
Support using swarm Configs as CredentialSpecs in Services.
2019-04-12 09:35:03 -07:00
Drew Erny 42ec51e1ae add support for config credentialspecs to compose
Signed-off-by: Drew Erny <drew.erny@docker.com>
2019-04-12 11:17:34 -05:00
Drew Erny 4cacd1304a Add CredentialSpec tests
Adds tests for setting and updating swarm service CredentialSpecs,
especially when using a Config as a credential spec.

Signed-off-by: Drew Erny <drew.erny@docker.com>
2019-04-12 11:17:34 -05:00
Drew Erny 01f4f2e80a Update CredentialSpec code to allow using configs
Updates the CredentialSpec handling code for services to allow using
swarm Configs.

Additionally, fixes a bug where the `--credential-spec` flag would not
be respected on service updates.

Signed-off-by: Drew Erny <drew.erny@docker.com>
2019-04-12 11:17:33 -05:00
Sebastiaan van StijnandDrew Erny 6511da877f Add support for using Configs as CredentialSpecs in services
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-12 11:17:29 -05:00
Sebastiaan van StijnandGitHub 8b9cdab4e6 Merge pull request #1783 from sirlatrom/stack_compose_secret_driver
Add driver field to top-level secret object
2019-04-12 18:15:36 +02:00
Simon Ferquel e0f20fd86a Regroup all kubernetes extra-fields under x-kubernetes
This regroup all Kubernetes extra fields for compose-on-kubernetes
v1alpha3 in a single x-kubernetes object.
Also use the same naming scheme as cap_add etc. for fiels inside this
object.

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
2019-04-12 15:46:11 +02:00
Sebastiaan van StijnandGitHub 409c590fcf Merge pull request #1815 from simonferquel/expose-to-internal-ports
Support internal Load Balancing for Kubernetes stacks
2019-04-12 14:02:15 +02:00
Simon Ferquel cad20c759f Support internal Load Balancing for Kubernetes stacks
On the server v0.4.21 has introduced a better way of dealing with
intra-stack networking: if the user can specify a list of endpoints
exposed internally, we now can setup a ClusterIP for this to avoid the
pitfalls of DNS-based load balancing.
This exposes the feature using the "Expose" compose field, and adds an
extra x-internal-service-type field to explicitly define how intra-stack
networking is handled on a service.

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
2019-04-12 11:43:30 +02:00
Vincent DemeesterandGitHub a125283e01 Merge pull request #1822 from thaJeztah/format_vendor
Reformat vendor.conf and pin all deps by git-sha
2019-04-12 09:14:26 +02:00
Vincent DemeesterandGitHub 893f4a1194 Merge pull request #1818 from tao12345666333/bump-golang-1.12.3
Bump Golang 1.12.3
2019-04-12 09:10:23 +02:00
Sebastiaan van Stijn 9aa0d553c0 Sort vendor.conf alphabetically
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-12 01:33:10 +02:00
Sebastiaan van Stijn 6026ce4a8b Reformat vendor.conf and pin all deps by git-sha
To make it better readable, and to encourage pinning
by sha, but "align" to a tagged release.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-12 01:31:04 +02:00
Jintao Zhang c55c801faf Bump Golang 1.12.3
Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
2019-04-11 10:44:16 +08:00
Sebastiaan van StijnandGitHub ac758d9f80 Merge pull request #1817 from simonferquel/docker-host-context-warning
Add warnings when DOCKER_HOST conflicts with contexts
2019-04-10 15:01:20 +02:00
Simon Ferquel 1cefe057cd Add warnings when DOCKER_HOST conflicts with contexts
For clarity, on `docker context use` or `docker context ls`, this adds a
warning if the DOCKER_HOST variable is set because it overrides the
active context.

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
2019-04-10 10:14:47 +02:00
Sebastiaan van StijnandGitHub d6af3e143e Merge pull request #1773 from zappy-shu/create-context-from-current
add --from flag to context create
2019-04-09 16:38:46 +02:00
Brian GoffandGitHub f019bdcace Merge pull request #1816 from thaJeztah/bump_golang_1.12.2
Bump Golang 1.12.2
2019-04-08 10:22:07 -07:00
Sebastiaan van Stijn ed8733a940 Bump Golang 1.12.2
go1.12.2 (released 2019/04/05) includes fixes to the compiler, the go
command, the runtime, and the doc, net, net/http/httputil, and os packages.
See the Go 1.12.2 milestone on our issue tracker for details:

https://github.com/golang/go/issues?q=milestone%3AGo1.12.2

Full diff: https://github.com/golang/go/compare/go1.12.1...go1.12.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-04-08 18:53:12 +02:00
Harald Albers 7945010874 Add support for BuildKit specific options to bash completion
Signed-off-by: Harald Albers <github@albersweb.de>
2019-04-05 23:27:12 +02:00
Mårten Cassel 5bc9f490a9 add cli integration for unconfined systempaths with unit test, implement suggested changes
Signed-off-by: Mårten Cassel <marten.cassel@gmail.com>
2019-04-05 15:46:15 +02:00
Sune KellerandSune Keller ed838bff1f Add test case
Signed-off-by: Sune Keller <absukl@almbrand.dk>
2019-04-05 12:01:21 +02:00
Sune KellerandSune Keller c662ba03de Make use of driver and driver_opts fields in secrets
Signed-off-by: Sune Keller <absukl@almbrand.dk>
2019-04-05 12:01:21 +02:00
Sune KellerandSune Keller 89f9d806ff Add driver and driver_opts to secret in compose schema 3.8
Signed-off-by: Sune Keller <absukl@almbrand.dk>
2019-04-05 12:01:21 +02:00
Nick Adcock 8bb152d967 add --from option to context create
--from creates a context from a named context.
By default `context create` will create a context from the current context.
Replaced "from-current=" docker/kubernetes option with "from=" to allow specifying which context to copy the settings from.

Signed-off-by: Nick Adcock <nick.adcock@docker.com>
2019-04-02 13:41:47 +01:00
Akihiro Suda 62a15c16fc commandconn: set SysProcAttr.Setsid
Setting `Setsid` is needed for SSH connection helper with `ProxyCommand`
config, so as to detach TTY.

e.g.

  $ cat ~/.ssh/config
  Host foo
    Hostname foo
    ProxyCommand ssh -W %h:%p bastion
  $ DOCKER_HOST=ssh://foo docker run -it --rm alpine
  / #

Fix #1707

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
2019-03-06 13:22:54 +09:00
721 changed files with 37031 additions and 16090 deletions
+5 -1
View File
@@ -1,2 +1,6 @@
.dockerignore
.git
build
.gitignore
appveyor.yml
build
circle.yml
+83
View File
@@ -0,0 +1,83 @@
linters:
enable:
- bodyclose
- deadcode
- dogsled
- gocyclo
- goimports
- golint
- gosec
- gosimple
- govet
- ineffassign
- interfacer
- lll
- megacheck
- misspell
- nakedret
- staticcheck
- structcheck
- typecheck
- unconvert
- unparam
- unused
- varcheck
disable:
- errcheck
run:
timeout: 5m
skip-dirs:
- cli/command/stack/kubernetes/api/openapi
- cli/command/stack/kubernetes/api/client
skip-files:
- cli/compose/schema/bindata.go
- .*generated.*
linters-settings:
gocyclo:
min-complexity: 16
govet:
check-shadowing: false
lll:
line-length: 200
nakedret:
command: nakedret
pattern: ^(?P<path>.*?\\.go):(?P<line>\\d+)\\s*(?P<message>.*)$
issues:
# The default exclusion rules are a bit too permissive, so copying the relevant ones below
exclude-use-default: false
exclude:
- parameter .* always receives
exclude-rules:
# These are copied from the default exclude rules, except for "ineffective break statement"
# and GoDoc checks.
# https://github.com/golangci/golangci-lint/blob/0cc87df732aaf1d5ad9ce9ca538d38d916918b36/pkg/config/config.go#L36
- text: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked"
linters:
- errcheck
- text: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this"
linters:
- golint
- text: "G103: Use of unsafe calls should be audited"
linters:
- gosec
- text: "G104: Errors unhandled"
linters:
- gosec
- text: "G204: Subprocess launch(ed with (variable|function call)|ing should be audited)"
linters:
- gosec
- text: "(G301|G302): (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)"
linters:
- gosec
- text: "G304: Potential file inclusion via variable"
linters:
- gosec
- text: "(G201|G202): SQL string (formatting|concatenation)"
linters:
- gosec
+5
View File
@@ -44,6 +44,7 @@ Antonio Murdaca <antonio.murdaca@gmail.com> <runcom@users.noreply.github.com>
Anuj Bahuguna <anujbahuguna.dev@gmail.com>
Anuj Bahuguna <anujbahuguna.dev@gmail.com> <abahuguna@fiberlink.com>
Anusha Ragunathan <anusha.ragunathan@docker.com> <anusha@docker.com>
Ao Li <la9249@163.com>
Arnaud Porterie <arnaud.porterie@docker.com>
Arnaud Porterie <arnaud.porterie@docker.com> <icecrime@gmail.com>
Arthur Gautier <baloo@gandi.net> <superbaloo+registrations.github@superbaloo.net>
@@ -394,6 +395,8 @@ Stefan Berger <stefanb@linux.vnet.ibm.com>
Stefan Berger <stefanb@linux.vnet.ibm.com> <stefanb@us.ibm.com>
Stefan J. Wernli <swernli@microsoft.com> <swernli@ntdev.microsoft.com>
Stefan S. <tronicum@user.github.com>
Stefan Scherer <stefan.scherer@docker.com>
Stefan Scherer <stefan.scherer@docker.com> <scherer_stefan@icloud.com>
Stephen Day <stevvooe@gmail.com>
Stephen Day <stevvooe@gmail.com> <stephen.day@docker.com>
Stephen Day <stevvooe@gmail.com> <stevvooe@users.noreply.github.com>
@@ -402,6 +405,8 @@ Steve Richards <steve.richards@docker.com> stevejr <>
Sun Gengze <690388648@qq.com>
Sun Jianbo <wonderflow.sun@gmail.com>
Sun Jianbo <wonderflow.sun@gmail.com> <wonderflow@zju.edu.cn>
Sunny Gogoi <indiasuny000@gmail.com>
Sunny Gogoi <indiasuny000@gmail.com> <me@darkowlzz.space>
Sven Dowideit <SvenDowideit@home.org.au>
Sven Dowideit <SvenDowideit@home.org.au> <sven@t440s.home.gateway>
Sven Dowideit <SvenDowideit@home.org.au> <SvenDowideit@docker.com>
+8 -1
View File
@@ -58,6 +58,7 @@ Anton Polonskiy <anton.polonskiy@gmail.com>
Antonio Murdaca <antonio.murdaca@gmail.com>
Antonis Kalipetis <akalipetis@gmail.com>
Anusha Ragunathan <anusha.ragunathan@docker.com>
Ao Li <la9249@163.com>
Arash Deshmeh <adeshmeh@ca.ibm.com>
Arnaud Porterie <arnaud.porterie@docker.com>
Ashwini Oruganti <ashwini.oruganti@gmail.com>
@@ -158,6 +159,7 @@ David Cramer <davcrame@cisco.com>
David Dooling <dooling@gmail.com>
David Gageot <david@gageot.net>
David Lechner <david@lechnology.com>
David Scott <dave@recoil.org>
David Sheets <dsheets@docker.com>
David Williamson <david.williamson@docker.com>
David Xia <dxia@spotify.com>
@@ -300,6 +302,7 @@ Jim Galasyn <jim.galasyn@docker.com>
Jimmy Leger <jimmy.leger@gmail.com>
Jimmy Song <rootsongjc@gmail.com>
jimmyxian <jimmyxian2004@yahoo.com.cn>
Jintao Zhang <zhangjintao9020@gmail.com>
Joao Fernandes <joao.fernandes@docker.com>
Joe Doliner <jdoliner@pachyderm.io>
Joe Gordon <joe.gordon0@gmail.com>
@@ -471,9 +474,11 @@ Mrunal Patel <mrunalp@gmail.com>
muicoder <muicoder@gmail.com>
Muthukumar R <muthur@gmail.com>
Máximo Cuadros <mcuadros@gmail.com>
Mårten Cassel <marten.cassel@gmail.com>
Nace Oroz <orkica@gmail.com>
Nahum Shalman <nshalman@omniti.com>
Nalin Dahyabhai <nalin@redhat.com>
Nao YONASHIRO <owan.orisano@gmail.com>
Nassim 'Nass' Eddequiouaq <eddequiouaq.nassim@gmail.com>
Natalie Parker <nparker@omnifone.com>
Nate Brennand <nate.brennand@clever.com>
@@ -595,7 +600,7 @@ Spencer Brown <spencer@spencerbrown.org>
squeegels <1674195+squeegels@users.noreply.github.com>
Srini Brahmaroutu <srbrahma@us.ibm.com>
Stefan S. <tronicum@user.github.com>
Stefan Scherer <scherer_stefan@icloud.com>
Stefan Scherer <stefan.scherer@docker.com>
Stefan Weil <sw@weilnetz.de>
Stephane Jeandeaux <stephane.jeandeaux@gmail.com>
Stephen Day <stevvooe@gmail.com>
@@ -605,7 +610,9 @@ Steve Richards <steve.richards@docker.com>
Steven Burgess <steven.a.burgess@hotmail.com>
Subhajit Ghosh <isubuz.g@gmail.com>
Sun Jianbo <wonderflow.sun@gmail.com>
Sune Keller <absukl@almbrand.dk>
Sungwon Han <sungwon.han@navercorp.com>
Sunny Gogoi <indiasuny000@gmail.com>
Sven Dowideit <SvenDowideit@home.org.au>
Sylvain Baubeau <sbaubeau@redhat.com>
Sébastien HOUZÉ <cto@verylastroom.com>
Vendored
+2 -1
View File
@@ -5,8 +5,9 @@ wrappedNode(label: 'linux && x86_64', cleanWorkspace: true) {
stage "Run end-to-end test suite"
sh "docker version"
sh "docker info"
sh "E2E_UNIQUE_ID=clie2e${BUILD_NUMBER} \
IMAGE_TAG=clie2e${BUILD_NUMBER} \
make -f docker.Makefile test-e2e"
DOCKER_BUILDKIT=1 make -f docker.Makefile test-e2e"
}
}
+2 -1
View File
@@ -1,4 +1,5 @@
[![build status](https://circleci.com/gh/docker/cli.svg?style=shield)](https://circleci.com/gh/docker/cli/tree/master) [![Build Status](https://jenkins.dockerproject.org/job/docker/job/cli/job/master/badge/icon)](https://jenkins.dockerproject.org/job/docker/job/cli/job/master/)
[![build status](https://circleci.com/gh/docker/cli.svg?style=shield)](https://circleci.com/gh/docker/cli/tree/master)
[![Build Status](https://ci.docker.com/public/job/cli/job/master/badge/icon)](https://ci.docker.com/public/job/cli/job/master)
docker/cli
==========
+2 -2
View File
@@ -4,7 +4,7 @@ clone_folder: c:\gopath\src\github.com\docker\cli
environment:
GOPATH: c:\gopath
GOVERSION: 1.12.1
GOVERSION: 1.12.17
DEPVERSION: v0.4.1
install:
@@ -20,4 +20,4 @@ build_script:
- ps: .\scripts\make.ps1 -Binary
test_script:
- ps: .\scripts\make.ps1 -TestUnit
- ps: .\scripts\make.ps1 -TestUnit
+76 -38
View File
@@ -4,35 +4,64 @@ jobs:
lint:
working_directory: /work
docker: [{image: 'docker:18.03-git'}]
docker: [{image: 'docker:18.09-git'}]
environment:
DOCKER_BUILDKIT: 1
steps:
- checkout
- setup_remote_docker:
version: 18.03.1-ce
reusable: true
exclusive: false
version: 18.09.3
reusable: true
exclusive: false
- run:
name: "Docker version"
command: docker version
- run:
name: "Docker info"
command: docker info
- run:
name: "Shellcheck - build image"
command: |
docker build --progress=plain -f dockerfiles/Dockerfile.shellcheck --tag cli-validator:$CIRCLE_BUILD_NUM .
- run:
name: "Shellcheck"
command: |
docker run --rm cli-validator:$CIRCLE_BUILD_NUM \
make shellcheck
- run:
name: "Lint - build image"
command: |
docker build --progress=plain -f dockerfiles/Dockerfile.lint --tag cli-linter:$CIRCLE_BUILD_NUM .
- run:
name: "Lint"
command: |
docker build -f dockerfiles/Dockerfile.lint --tag cli-linter:$CIRCLE_BUILD_NUM .
docker run --rm cli-linter:$CIRCLE_BUILD_NUM
cross:
working_directory: /work
docker: [{image: 'docker:18.03-git'}]
docker: [{image: 'docker:18.09-git'}]
environment:
DOCKER_BUILDKIT: 1
parallelism: 3
steps:
- checkout
- setup_remote_docker:
version: 18.03.1-ce
reusable: true
exclusive: false
version: 18.09.3
reusable: true
exclusive: false
- run:
name: "Docker version"
command: docker version
- run:
name: "Docker info"
command: docker info
- run:
name: "Cross - build image"
command: |
docker build --progress=plain -f dockerfiles/Dockerfile.cross --tag cli-builder:$CIRCLE_BUILD_NUM .
- run:
name: "Cross"
command: |
docker build -f dockerfiles/Dockerfile.cross --tag cli-builder:$CIRCLE_BUILD_NUM .
name=cross-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
docker run \
-e CROSS_GROUP=$CIRCLE_NODE_INDEX \
@@ -46,18 +75,29 @@ jobs:
test:
working_directory: /work
docker: [{image: 'docker:18.03-git'}]
docker: [{image: 'docker:18.09-git'}]
environment:
DOCKER_BUILDKIT: 1
steps:
- checkout
- setup_remote_docker:
version: 18.03.1-ce
reusable: true
exclusive: false
version: 18.09.3
reusable: true
exclusive: false
- run:
name: "Docker version"
command: docker version
- run:
name: "Docker info"
command: docker info
- run:
name: "Unit Test with Coverage - build image"
command: |
mkdir -p test-results/unit-tests
docker build --progress=plain -f dockerfiles/Dockerfile.dev --tag cli-builder:$CIRCLE_BUILD_NUM .
- run:
name: "Unit Test with Coverage"
command: |
mkdir -p test-results/unit-tests
docker build -f dockerfiles/Dockerfile.dev --tag cli-builder:$CIRCLE_BUILD_NUM .
docker run \
-e GOTESTSUM_JUNITFILE=/tmp/junit.xml \
--name \
@@ -77,39 +117,38 @@ jobs:
echo 'Codecov failed to upload'
- store_test_results:
path: test-results
- store_artifacts:
path: test-results
validate:
working_directory: /work
docker: [{image: 'docker:18.03-git'}]
docker: [{image: 'docker:18.09-git'}]
environment:
DOCKER_BUILDKIT: 1
steps:
- checkout
- setup_remote_docker:
version: 18.03.1-ce
reusable: true
exclusive: false
version: 18.09.3
reusable: true
exclusive: false
- run:
name: "Docker version"
command: docker version
- run:
name: "Docker info"
command: docker info
- run:
name: "Validate - build image"
command: |
rm -f .dockerignore # include .git
docker build --progress=plain -f dockerfiles/Dockerfile.dev --tag cli-builder-with-git:$CIRCLE_BUILD_NUM .
- run:
name: "Validate Vendor, Docs, and Code Generation"
command: |
rm -f .dockerignore # include .git
docker build -f dockerfiles/Dockerfile.dev --tag cli-builder-with-git:$CIRCLE_BUILD_NUM .
docker run --rm cli-builder-with-git:$CIRCLE_BUILD_NUM \
make ci-validate
no_output_timeout: 15m
shellcheck:
working_directory: /work
docker: [{image: 'docker:18.03-git'}]
steps:
- checkout
- setup_remote_docker:
version: 18.03.1-ce
reusable: true
exclusive: false
- run:
name: "Run shellcheck"
command: |
docker build -f dockerfiles/Dockerfile.shellcheck --tag cli-validator:$CIRCLE_BUILD_NUM .
docker run --rm cli-validator:$CIRCLE_BUILD_NUM \
make shellcheck
workflows:
version: 2
ci:
@@ -118,4 +157,3 @@ workflows:
- cross
- test
- validate
- shellcheck
+1
View File
@@ -101,5 +101,6 @@ func main() {
SchemaVersion: "0.1.0",
Vendor: "Docker Inc.",
Version: "testing",
Experimental: os.Getenv("HELLO_EXPERIMENTAL") != "",
})
}
+40 -32
View File
@@ -12,9 +12,10 @@ import (
)
type fakeCandidate struct {
path string
exec bool
meta string
path string
exec bool
meta string
allowExperimental bool
}
func (c *fakeCandidate) Path() string {
@@ -35,9 +36,10 @@ func TestValidateCandidate(t *testing.T) {
builtinName = NamePrefix + "builtin"
builtinAlias = NamePrefix + "alias"
badPrefixPath = "/usr/local/libexec/cli-plugins/wobble"
badNamePath = "/usr/local/libexec/cli-plugins/docker-123456"
goodPluginPath = "/usr/local/libexec/cli-plugins/" + goodPluginName
badPrefixPath = "/usr/local/libexec/cli-plugins/wobble"
badNamePath = "/usr/local/libexec/cli-plugins/docker-123456"
goodPluginPath = "/usr/local/libexec/cli-plugins/" + goodPluginName
metaExperimental = `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true}`
)
fakeroot := &cobra.Command{Use: "docker"}
@@ -49,40 +51,46 @@ func TestValidateCandidate(t *testing.T) {
})
for _, tc := range []struct {
c *fakeCandidate
name string
c *fakeCandidate
// Either err or invalid may be non-empty, but not both (both can be empty for a good plugin).
err string
invalid string
}{
/* Each failing one of the tests */
{c: &fakeCandidate{path: ""}, err: "plugin candidate path cannot be empty"},
{c: &fakeCandidate{path: badPrefixPath}, err: fmt.Sprintf("does not have %q prefix", NamePrefix)},
{c: &fakeCandidate{path: badNamePath}, invalid: "did not match"},
{c: &fakeCandidate{path: builtinName}, invalid: `plugin "builtin" duplicates builtin command`},
{c: &fakeCandidate{path: builtinAlias}, invalid: `plugin "alias" duplicates an alias of builtin command "builtin"`},
{c: &fakeCandidate{path: goodPluginPath, exec: false}, invalid: fmt.Sprintf("failed to fetch metadata: faked a failure to exec %q", goodPluginPath)},
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `xyzzy`}, invalid: "invalid character"},
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{}`}, invalid: `plugin SchemaVersion "" is not valid`},
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "xyzzy"}`}, invalid: `plugin SchemaVersion "xyzzy" is not valid`},
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0"}`}, invalid: "plugin metadata does not define a vendor"},
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": ""}`}, invalid: "plugin metadata does not define a vendor"},
{name: "empty path", c: &fakeCandidate{path: ""}, err: "plugin candidate path cannot be empty"},
{name: "bad prefix", c: &fakeCandidate{path: badPrefixPath}, err: fmt.Sprintf("does not have %q prefix", NamePrefix)},
{name: "bad path", c: &fakeCandidate{path: badNamePath}, invalid: "did not match"},
{name: "builtin command", c: &fakeCandidate{path: builtinName}, invalid: `plugin "builtin" duplicates builtin command`},
{name: "builtin alias", c: &fakeCandidate{path: builtinAlias}, invalid: `plugin "alias" duplicates an alias of builtin command "builtin"`},
{name: "fetch failure", c: &fakeCandidate{path: goodPluginPath, exec: false}, invalid: fmt.Sprintf("failed to fetch metadata: faked a failure to exec %q", goodPluginPath)},
{name: "metadata not json", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `xyzzy`}, invalid: "invalid character"},
{name: "empty schemaversion", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{}`}, invalid: `plugin SchemaVersion "" is not valid`},
{name: "invalid schemaversion", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "xyzzy"}`}, invalid: `plugin SchemaVersion "xyzzy" is not valid`},
{name: "no vendor", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0"}`}, invalid: "plugin metadata does not define a vendor"},
{name: "empty vendor", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": ""}`}, invalid: "plugin metadata does not define a vendor"},
{name: "experimental required", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental}, invalid: "requires experimental CLI"},
// This one should work
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`}},
{name: "valid", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`}},
{name: "valid + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`, allowExperimental: true}},
{name: "experimental + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental, allowExperimental: true}},
} {
p, err := newPlugin(tc.c, fakeroot)
if tc.err != "" {
assert.ErrorContains(t, err, tc.err)
} else if tc.invalid != "" {
assert.NilError(t, err)
assert.Assert(t, cmp.ErrorType(p.Err, reflect.TypeOf(&pluginError{})))
assert.ErrorContains(t, p.Err, tc.invalid)
} else {
assert.NilError(t, err)
assert.Equal(t, NamePrefix+p.Name, goodPluginName)
assert.Equal(t, p.SchemaVersion, "0.1.0")
assert.Equal(t, p.Vendor, "e2e-testing")
}
t.Run(tc.name, func(t *testing.T) {
p, err := newPlugin(tc.c, fakeroot, tc.c.allowExperimental)
if tc.err != "" {
assert.ErrorContains(t, err, tc.err)
} else if tc.invalid != "" {
assert.NilError(t, err)
assert.Assert(t, cmp.ErrorType(p.Err, reflect.TypeOf(&pluginError{})))
assert.ErrorContains(t, p.Err, tc.invalid)
} else {
assert.NilError(t, err)
assert.Equal(t, NamePrefix+p.Name, goodPluginName)
assert.Equal(t, p.SchemaVersion, "0.1.0")
assert.Equal(t, p.Vendor, "e2e-testing")
}
})
}
}
+28 -4
View File
@@ -1,6 +1,7 @@
package manager
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
@@ -27,10 +28,23 @@ func (e errPluginNotFound) Error() string {
return "Error: No such CLI plugin: " + string(e)
}
type errPluginRequireExperimental string
// Note: errPluginRequireExperimental implements notFound so that the plugin
// is skipped when listing the plugins.
func (e errPluginRequireExperimental) NotFound() {}
func (e errPluginRequireExperimental) Error() string {
return fmt.Sprintf("plugin candidate %q: requires experimental CLI", string(e))
}
type notFound interface{ NotFound() }
// IsNotFound is true if the given error is due to a plugin not being found.
func IsNotFound(err error) bool {
if e, ok := err.(*pluginError); ok {
err = e.Cause()
}
_, ok := err.(notFound)
return ok
}
@@ -117,12 +131,14 @@ func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error
continue
}
c := &candidate{paths[0]}
p, err := newPlugin(c, rootcmd)
p, err := newPlugin(c, rootcmd, dockerCli.ClientInfo().HasExperimental)
if err != nil {
return nil, err
}
p.ShadowedPaths = paths[1:]
plugins = append(plugins, p)
if !IsNotFound(p.Err) {
p.ShadowedPaths = paths[1:]
plugins = append(plugins, p)
}
}
return plugins, nil
@@ -159,11 +175,19 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
}
c := &candidate{path: path}
plugin, err := newPlugin(c, rootcmd)
plugin, err := newPlugin(c, rootcmd, dockerCli.ClientInfo().HasExperimental)
if err != nil {
return nil, err
}
if plugin.Err != nil {
// TODO: why are we not returning plugin.Err?
err := plugin.Err.(*pluginError).Cause()
// if an experimental plugin was invoked directly while experimental mode is off
// provide a more useful error message than "not found".
if err, ok := err.(errPluginRequireExperimental); ok {
return nil, err
}
return nil, errPluginNotFound(name)
}
cmd := exec.Command(plugin.Path, args...)
+3
View File
@@ -22,4 +22,7 @@ type Metadata struct {
ShortDescription string `json:",omitempty"`
// URL is a pointer to the plugin's homepage.
URL string `json:",omitempty"`
// Experimental specifies whether the plugin is experimental.
// Experimental plugins are not displayed on non-experimental CLIs.
Experimental bool `json:",omitempty"`
}
+7 -2
View File
@@ -33,7 +33,9 @@ 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, rootcmd *cobra.Command) (Plugin, error) {
//
// nolint: gocyclo
func newPlugin(c Candidate, rootcmd *cobra.Command, allowExperimental bool) (Plugin, error) {
path := c.Path()
if path == "" {
return Plugin{}, errors.New("plugin candidate path cannot be empty")
@@ -94,7 +96,10 @@ func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) {
p.Err = wrapAsPluginError(err, "invalid metadata")
return p, nil
}
if p.Experimental && !allowExperimental {
p.Err = &pluginError{errPluginRequireExperimental(p.Name)}
return p, nil
}
if p.Metadata.SchemaVersion != "0.1.0" {
p.Err = NewPluginError("plugin SchemaVersion %q is not valid, must be 0.1.0", p.Metadata.SchemaVersion)
return p, nil
+8 -5
View File
@@ -114,11 +114,14 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta
fullname := manager.NamePrefix + name
cmd := &cobra.Command{
Use: fmt.Sprintf("docker [OPTIONS] %s [ARG...]", name),
Short: fullname + " is a Docker CLI plugin",
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRunE: PersistentPreRunE,
Use: fmt.Sprintf("docker [OPTIONS] %s [ARG...]", name),
Short: fullname + " is a Docker CLI plugin",
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// We can't use this as the hook directly since it is initialised later (in runPlugin)
return PersistentPreRunE(cmd, args)
},
TraverseChildren: true,
DisableFlagsInUseLine: true,
}
+2
View File
@@ -5,6 +5,7 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image"
)
// NewBuilderCommand returns a cobra command for `builder` subcommands
@@ -18,6 +19,7 @@ func NewBuilderCommand(dockerCli command.Cli) *cobra.Command {
}
cmd.AddCommand(
NewPruneCommand(dockerCli),
image.NewBuildCommand(dockerCli),
)
return cmd
}
+2 -2
View File
@@ -44,8 +44,8 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags()
flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images, not just dangling ones")
flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'unused-for=24h')")
flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused build cache, not just dangling ones")
flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'until=24h')")
flags.Var(&options.keepStorage, "keep-storage", "Amount of disk space to keep for cache")
return cmd
+27 -15
View File
@@ -14,7 +14,6 @@ import (
"github.com/docker/cli/cli/config/configfile"
dcontext "github.com/docker/cli/cli/context"
"github.com/docker/cli/cli/context/docker"
kubcontext "github.com/docker/cli/cli/context/kubernetes"
"github.com/docker/cli/cli/context/store"
"github.com/docker/cli/cli/debug"
cliflags "github.com/docker/cli/cli/flags"
@@ -210,11 +209,11 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize
cli.configFile = cliconfig.LoadDefaultConfigFile(cli.err)
baseContextSore := store.New(cliconfig.ContextStoreDir(), cli.contextStoreConfig)
baseContextStore := store.New(cliconfig.ContextStoreDir(), cli.contextStoreConfig)
cli.contextStore = &ContextStoreWithDefault{
Store: baseContextSore,
Store: baseContextStore,
Resolver: func() (*DefaultContext, error) {
return resolveDefaultContext(opts.Common, cli.ConfigFile(), cli.Err())
return ResolveDefaultContext(opts.Common, cli.ConfigFile(), cli.contextStoreConfig, cli.Err())
},
}
cli.currentContext, err = resolveContextName(opts.Common, cli.configFile, cli.contextStore)
@@ -259,10 +258,11 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize
// NewAPIClientFromFlags creates a new APIClient from command line flags
func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.ConfigFile) (client.APIClient, error) {
storeConfig := DefaultContextStoreConfig()
store := &ContextStoreWithDefault{
Store: store.New(cliconfig.ContextStoreDir(), defaultContextStoreConfig()),
Store: store.New(cliconfig.ContextStoreDir(), storeConfig),
Resolver: func() (*DefaultContext, error) {
return resolveDefaultContext(opts, configFile, ioutil.Discard)
return ResolveDefaultContext(opts, configFile, storeConfig, ioutil.Discard)
},
}
contextName, err := resolveContextName(opts, configFile, store)
@@ -290,8 +290,8 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
return client.NewClientWithOpts(clientOpts...)
}
func resolveDockerEndpoint(s store.Store, contextName string) (docker.Endpoint, error) {
ctxMeta, err := s.GetContextMetadata(contextName)
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
ctxMeta, err := s.GetMetadata(contextName)
if err != nil {
return docker.Endpoint{}, err
}
@@ -399,7 +399,7 @@ func (cli *DockerCli) CurrentContext() string {
// StackOrchestrator resolves which stack orchestrator is in use
func (cli *DockerCli) StackOrchestrator(flagValue string) (Orchestrator, error) {
currentContext := cli.CurrentContext()
ctxRaw, err := cli.ContextStore().GetContextMetadata(currentContext)
ctxRaw, err := cli.ContextStore().GetMetadata(currentContext)
if store.IsErrContextDoesNotExist(err) {
// case where the currentContext has been removed (CLI behavior is to fallback to using DOCKER_HOST based resolution)
return GetStackOrchestrator(flagValue, "", cli.ConfigFile().StackOrchestrator, cli.Err())
@@ -453,7 +453,7 @@ func NewDockerCli(ops ...DockerCliOption) (*DockerCli, error) {
WithContentTrustFromEnv(),
WithContainerizedClient(containerizedengine.NewClient),
}
cli.contextStoreConfig = defaultContextStoreConfig()
cli.contextStoreConfig = DefaultContextStoreConfig()
ops = append(defaultOps, ops...)
if err := cli.Apply(ops...); err != nil {
return nil, err
@@ -500,7 +500,7 @@ func UserAgent() string {
// - if DOCKER_CONTEXT is set, use this value
// - if Config file has a globally set "CurrentContext", use this value
// - fallbacks to default HOST, uses TLS config from flags/env vars
func resolveContextName(opts *cliflags.CommonOptions, config *configfile.ConfigFile, contextstore store.Store) (string, error) {
func resolveContextName(opts *cliflags.CommonOptions, config *configfile.ConfigFile, contextstore store.Reader) (string, error) {
if opts.Context != "" && len(opts.Hosts) > 0 {
return "", errors.New("Conflicting options: either specify --host or --context, not both")
}
@@ -517,7 +517,7 @@ func resolveContextName(opts *cliflags.CommonOptions, config *configfile.ConfigF
return ctxName, nil
}
if config != nil && config.CurrentContext != "" {
_, err := contextstore.GetContextMetadata(config.CurrentContext)
_, err := contextstore.GetMetadata(config.CurrentContext)
if store.IsErrContextDoesNotExist(err) {
return "", errors.Errorf("Current context %q is not found on the file system, please check your config file at %s", config.CurrentContext, config.Filename)
}
@@ -526,10 +526,22 @@ func resolveContextName(opts *cliflags.CommonOptions, config *configfile.ConfigF
return DefaultContextName, nil
}
func defaultContextStoreConfig() store.Config {
var defaultStoreEndpoints = []store.NamedTypeGetter{
store.EndpointTypeGetter(docker.DockerEndpoint, func() interface{} { return &docker.EndpointMeta{} }),
}
// RegisterDefaultStoreEndpoints registers a new named endpoint
// metadata type with the default context store config, so that
// endpoint will be supported by stores using the config returned by
// DefaultContextStoreConfig.
func RegisterDefaultStoreEndpoints(ep ...store.NamedTypeGetter) {
defaultStoreEndpoints = append(defaultStoreEndpoints, ep...)
}
// DefaultContextStoreConfig returns a new store.Config with the default set of endpoints configured.
func DefaultContextStoreConfig() store.Config {
return store.NewConfig(
func() interface{} { return &DockerContext{} },
store.EndpointTypeGetter(docker.DockerEndpoint, func() interface{} { return &docker.EndpointMeta{} }),
store.EndpointTypeGetter(kubcontext.KubernetesEndpoint, func() interface{} { return &kubcontext.EndpointMeta{} }),
defaultStoreEndpoints...,
)
}
+1 -2
View File
@@ -7,7 +7,6 @@ import (
"strconv"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/kubernetes"
"github.com/docker/cli/cli/context/store"
"github.com/docker/cli/cli/streams"
clitypes "github.com/docker/cli/types"
@@ -97,7 +96,7 @@ func WithContainerizedClient(containerizedFn func(string) (clitypes.Containerize
func WithContextEndpointType(endpointName string, endpointType store.TypeGetter) DockerCliOption {
return func(cli *DockerCli) error {
switch endpointName {
case docker.DockerEndpoint, kubernetes.KubernetesEndpoint:
case docker.DockerEndpoint:
return fmt.Errorf("cannot change %q endpoint type", endpointName)
}
cli.contextStoreConfig.SetEndpoint(endpointName, endpointType)
+24 -1
View File
@@ -6,6 +6,7 @@ import (
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
"os"
"runtime"
"testing"
@@ -79,6 +80,24 @@ func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
assert.Check(t, is.Equal(customVersion, apiclient.ClientVersion()))
}
func TestNewAPIClientFromFlagsWithHttpProxyEnv(t *testing.T) {
defer env.Patch(t, "HTTP_PROXY", "http://proxy.acme.com:1234")()
defer env.Patch(t, "DOCKER_HOST", "tcp://docker.acme.com:2376")()
opts := &flags.CommonOptions{}
configFile := &configfile.ConfigFile{}
apiclient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
transport, ok := apiclient.HTTPClient().Transport.(*http.Transport)
assert.Assert(t, ok)
assert.Assert(t, transport.Proxy != nil)
request, err := http.NewRequest(http.MethodGet, "tcp://docker.acme.com:2376", nil)
assert.NilError(t, err)
url, err := transport.Proxy(request)
assert.NilError(t, err)
assert.Check(t, is.Equal("http://proxy.acme.com:1234", url.String()))
}
type fakeClient struct {
client.Client
pingFunc func() (types.Ping, error)
@@ -133,6 +152,7 @@ func TestInitializeFromClient(t *testing.T) {
}
for _, testcase := range testcases {
testcase := testcase
t.Run(testcase.doc, func(t *testing.T) {
apiclient := &fakeClient{
pingFunc: testcase.pingFunc,
@@ -170,6 +190,7 @@ func TestExperimentalCLI(t *testing.T) {
}
for _, testcase := range testcases {
testcase := testcase
t.Run(testcase.doc, func(t *testing.T) {
dir := fs.NewDir(t, testcase.doc, fs.WithFile("config.json", testcase.configfile))
defer dir.Remove()
@@ -223,6 +244,7 @@ func TestGetClientWithPassword(t *testing.T) {
}
for _, testcase := range testcases {
testcase := testcase
t.Run(testcase.doc, func(t *testing.T) {
passRetriever := func(_, _ string, _ bool, attempts int) (passphrase string, giveup bool, err error) {
// Always return an invalid pass first to test iteration
@@ -275,11 +297,12 @@ func TestNewDockerCliAndOperators(t *testing.T) {
inbuf := bytes.NewBuffer([]byte("input"))
outbuf := bytes.NewBuffer(nil)
errbuf := bytes.NewBuffer(nil)
cli.Apply(
err = cli.Apply(
WithInputStream(ioutil.NopCloser(inbuf)),
WithOutputStream(outbuf),
WithErrorStream(errbuf),
)
assert.NilError(t, err)
// Check input stream
inputStream, err := ioutil.ReadAll(cli.In())
assert.NilError(t, err)
+1 -2
View File
@@ -7,10 +7,9 @@ import (
"time"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -2
View File
@@ -7,11 +7,10 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
"gotest.tools/golden"
+1 -9
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"net/http/httputil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@@ -103,10 +102,7 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
}
resp, errAttach := client.ContainerAttach(ctx, opts.container, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach returns an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection later
if errAttach != nil {
return errAttach
}
defer resp.Close()
@@ -142,10 +138,6 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
return err
}
if errAttach != nil {
return errAttach
}
return getExitStatus(errC, resultC)
}
+2
View File
@@ -151,6 +151,7 @@ func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
cli := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
hostConfig *container.HostConfig,
@@ -209,6 +210,7 @@ func TestNewCreateCommandWithWarnings(t *testing.T) {
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
+1 -2
View File
@@ -7,9 +7,8 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+34 -1
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"path"
"reflect"
"regexp"
"strconv"
"strings"
@@ -485,6 +486,8 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
return nil, err
}
securityOpts, maskedPaths, readonlyPaths := parseSystemPaths(securityOpts)
storageOpts, err := parseStorageOpts(copts.storageOpt.GetAll())
if err != nil {
return nil, err
@@ -635,6 +638,8 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
Sysctls: copts.sysctls.GetAll(),
Runtime: copts.runtime,
Mounts: mounts,
MaskedPaths: maskedPaths,
ReadonlyPaths: readonlyPaths,
}
if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() {
@@ -703,6 +708,15 @@ func parseNetworkOpts(copts *containerOptions) (map[string]*networktypes.Endpoin
if _, ok := endpoints[n.Target]; ok {
return nil, errdefs.InvalidParameter(errors.Errorf("network %q is specified multiple times", n.Target))
}
// For backward compatibility: if no custom options are provided for the network,
// and only a single network is specified, omit the endpoint-configuration
// on the client (the daemon will still create it when creating the container)
if i == 0 && len(copts.netMode.Value()) == 1 {
if ep == nil || reflect.DeepEqual(*ep, networktypes.EndpointSettings{}) {
continue
}
}
endpoints[n.Target] = ep
}
if hasUserDefined && hasNonUserDefined {
@@ -785,7 +799,7 @@ func parsePortOpts(publishOpts []string) ([]string, error) {
params[opt[0]] = opt[1]
}
optsList = append(optsList, fmt.Sprintf("%s:%s/%s", params["target"], params["published"], params["protocol"]))
optsList = append(optsList, fmt.Sprintf("%s:%s/%s", params["published"], params["target"], params["protocol"]))
}
return optsList, nil
}
@@ -825,6 +839,25 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) {
return securityOpts, nil
}
// parseSystemPaths checks if `systempaths=unconfined` security option is set,
// and returns the `MaskedPaths` and `ReadonlyPaths` accordingly. An updated
// list of security options is returned with this option removed, because the
// `unconfined` option is handled client-side, and should not be sent to the
// daemon.
func parseSystemPaths(securityOpts []string) (filtered, maskedPaths, readonlyPaths []string) {
filtered = securityOpts[:0]
for _, opt := range securityOpts {
if opt == "systempaths=unconfined" {
maskedPaths = []string{}
readonlyPaths = []string{}
} else {
filtered = append(filtered, opt)
}
}
return filtered, maskedPaths, readonlyPaths
}
// parses storage options per container into a map
func parseStorageOpts(storageOpts []string) (map[string]string, error) {
m := make(map[string]string)
+65 -5
View File
@@ -65,7 +65,7 @@ func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
}
func parseMustError(t *testing.T, args string) {
_, _, _, err := parseRun(strings.Split(args+" ubuntu bash", " "))
_, _, _, err := parseRun(strings.Split(args+" ubuntu bash", " ")) //nolint:dogsled
assert.ErrorContains(t, err, "", args)
}
@@ -401,13 +401,13 @@ func TestParseNetworkConfig(t *testing.T) {
{
name: "single-network-legacy",
flags: []string{"--network", "net1"},
expected: map[string]*networktypes.EndpointSettings{"net1": {}},
expected: map[string]*networktypes.EndpointSettings{},
expectedCfg: container.HostConfig{NetworkMode: "net1"},
},
{
name: "single-network-advanced",
flags: []string{"--network", "name=net1"},
expected: map[string]*networktypes.EndpointSettings{"net1": {}},
expected: map[string]*networktypes.EndpointSettings{},
expectedCfg: container.HostConfig{NetworkMode: "net1"},
},
{
@@ -539,7 +539,7 @@ func TestParseModes(t *testing.T) {
}
// uts ko
_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"})
_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"}) //nolint:dogsled
assert.ErrorContains(t, err, "--uts: invalid UTS mode")
// uts ok
@@ -600,7 +600,7 @@ func TestParseRestartPolicy(t *testing.T) {
func TestParseRestartPolicyAutoRemove(t *testing.T) {
expected := "Conflicting options: --restart and --rm"
_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"})
_, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"}) //nolint:dogsled
if err == nil || err.Error() != expected {
t.Fatalf("Expected error %v, but got none", expected)
}
@@ -800,3 +800,63 @@ func TestValidateDevice(t *testing.T) {
}
}
}
func TestParseSystemPaths(t *testing.T) {
tests := []struct {
doc string
in, out, masked, readonly []string
}{
{
doc: "not set",
in: []string{},
out: []string{},
},
{
doc: "not set, preserve other options",
in: []string{
"seccomp=unconfined",
"apparmor=unconfined",
"label=user:USER",
"foo=bar",
},
out: []string{
"seccomp=unconfined",
"apparmor=unconfined",
"label=user:USER",
"foo=bar",
},
},
{
doc: "unconfined",
in: []string{"systempaths=unconfined"},
out: []string{},
masked: []string{},
readonly: []string{},
},
{
doc: "unconfined and other options",
in: []string{"foo=bar", "bar=baz", "systempaths=unconfined"},
out: []string{"foo=bar", "bar=baz"},
masked: []string{},
readonly: []string{},
},
{
doc: "unknown option",
in: []string{"foo=bar", "systempaths=unknown", "bar=baz"},
out: []string{"foo=bar", "systempaths=unknown", "bar=baz"},
},
}
for _, tc := range tests {
securityOpts, maskedPaths, readonlyPaths := parseSystemPaths(tc.in)
assert.DeepEqual(t, securityOpts, tc.out)
assert.DeepEqual(t, maskedPaths, tc.masked)
assert.DeepEqual(t, readonlyPaths, tc.readonly)
}
}
func TestParsePortOpts(t *testing.T) {
parsed, err := parsePortOpts([]string{"published=1500,target=200", "target=80,published=90"})
assert.NilError(t, err)
assert.DeepEqual(t, []string{"1500:200/tcp", "90:80/tcp"}, parsed)
}
+1 -1
View File
@@ -35,7 +35,7 @@ func NewRmCommand(dockerCli command.Cli) *cobra.Command {
}
flags := cmd.Flags()
flags.BoolVarP(&opts.rmVolumes, "volumes", "v", false, "Remove the volumes associated with the container")
flags.BoolVarP(&opts.rmVolumes, "volumes", "v", false, "Remove anonymous volumes associated with the container")
flags.BoolVarP(&opts.rmLink, "link", "l", false, "Remove the specified link")
flags.BoolVarP(&opts.force, "force", "f", false, "Force the removal of a running container (uses SIGKILL)")
return cmd
+1 -10
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"net/http/httputil"
"os"
"runtime"
"strings"
@@ -115,11 +114,6 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
config.StdinOnce = false
}
// Disable sigProxy when in TTY mode
if config.Tty {
opts.sigProxy = false
}
// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
@@ -253,10 +247,7 @@ func attachContainer(
}
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, containerID, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach returns an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection later
if errAttach != nil {
return nil, errAttach
}
+2 -6
View File
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"io"
"net/http/httputil"
"strings"
"github.com/docker/cli/cli"
@@ -98,10 +97,7 @@ func runStart(dockerCli command.Cli, opts *startOptions) error {
}
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, c.ID, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach return an ErrPersistEOF (connection closed)
// means server met an error and already put it in Hijacked connection,
// we would keep the error and read the detailed error message from hijacked connection
if errAttach != nil {
return errAttach
}
defer resp.Close()
@@ -154,7 +150,7 @@ func runStart(dockerCli command.Cli, opts *startOptions) error {
}
}
if attachErr := <-cErr; attachErr != nil {
if _, ok := err.(term.EscapeError); ok {
if _, ok := attachErr.(term.EscapeError); ok {
// The user entered the detach escape sequence.
return nil
}
+3 -1
View File
@@ -208,7 +208,9 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
}
var err error
for range time.Tick(500 * time.Millisecond) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
cleanScreen()
ccstats := []StatsEntry{}
cStats.mu.Lock()
+1 -1
View File
@@ -13,7 +13,7 @@ type DockerContext struct {
}
// GetDockerContext extracts metadata from stored context metadata
func GetDockerContext(storeMetadata store.ContextMetadata) (DockerContext, error) {
func GetDockerContext(storeMetadata store.Metadata) (DockerContext, error) {
if storeMetadata.Metadata == nil {
// can happen if we save endpoints before assigning a context metadata
// it is totally valid, and we should return a default initialized value
+71 -13
View File
@@ -21,6 +21,7 @@ type CreateOptions struct {
DefaultStackOrchestrator string
Docker map[string]string
Kubernetes map[string]string
From string
}
func longCreateDescription() string {
@@ -63,6 +64,7 @@ func newCreateCommand(dockerCli command.Cli) *cobra.Command {
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
flags.StringVar(&opts.From, "from", "", "create context from a named context")
return cmd
}
@@ -76,17 +78,26 @@ func RunCreate(cli command.Cli, o *CreateOptions) error {
if err != nil {
return errors.Wrap(err, "unable to parse default-stack-orchestrator")
}
contextMetadata := store.ContextMetadata{
Endpoints: make(map[string]interface{}),
Metadata: command.DockerContext{
Description: o.Description,
StackOrchestrator: stackOrchestrator,
},
Name: o.Name,
switch {
case o.From == "" && o.Docker == nil && o.Kubernetes == nil:
err = createFromExistingContext(s, cli.CurrentContext(), stackOrchestrator, o)
case o.From != "":
err = createFromExistingContext(s, o.From, stackOrchestrator, o)
default:
err = createNewContext(o, stackOrchestrator, cli, s)
}
if err == nil {
fmt.Fprintln(cli.Out(), o.Name)
fmt.Fprintf(cli.Err(), "Successfully created context %q\n", o.Name)
}
return err
}
func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator, cli command.Cli, s store.Writer) error {
if o.Docker == nil {
return errors.New("docker endpoint configuration is required")
}
contextMetadata := newContextMetadata(stackOrchestrator, o)
contextTLSData := store.ContextTLSData{
Endpoints: make(map[string]store.EndpointTLSData),
}
@@ -116,22 +127,20 @@ func RunCreate(cli command.Cli, o *CreateOptions) error {
if err := validateEndpointsAndOrchestrator(contextMetadata); err != nil {
return err
}
if err := s.CreateOrUpdateContext(contextMetadata); err != nil {
if err := s.CreateOrUpdate(contextMetadata); err != nil {
return err
}
if err := s.ResetContextTLSMaterial(o.Name, &contextTLSData); err != nil {
if err := s.ResetTLSMaterial(o.Name, &contextTLSData); err != nil {
return err
}
fmt.Fprintln(cli.Out(), o.Name)
fmt.Fprintf(cli.Err(), "Successfully created context %q\n", o.Name)
return nil
}
func checkContextNameForCreation(s store.Store, name string) error {
func checkContextNameForCreation(s store.Reader, name string) error {
if err := validateContextName(name); err != nil {
return err
}
if _, err := s.GetContextMetadata(name); !store.IsErrContextDoesNotExist(err) {
if _, err := s.GetMetadata(name); !store.IsErrContextDoesNotExist(err) {
if err != nil {
return errors.Wrap(err, "error while getting existing contexts")
}
@@ -139,3 +148,52 @@ func checkContextNameForCreation(s store.Store, name string) error {
}
return nil
}
func createFromExistingContext(s store.ReaderWriter, fromContextName string, stackOrchestrator command.Orchestrator, o *CreateOptions) error {
if len(o.Docker) != 0 || len(o.Kubernetes) != 0 {
return errors.New("cannot use --docker or --kubernetes flags when --from is set")
}
reader := store.Export(fromContextName, &descriptionAndOrchestratorStoreDecorator{
Reader: s,
description: o.Description,
orchestrator: stackOrchestrator,
})
defer reader.Close()
return store.Import(o.Name, s, reader)
}
type descriptionAndOrchestratorStoreDecorator struct {
store.Reader
description string
orchestrator command.Orchestrator
}
func (d *descriptionAndOrchestratorStoreDecorator) GetMetadata(name string) (store.Metadata, error) {
c, err := d.Reader.GetMetadata(name)
if err != nil {
return c, err
}
typedContext, err := command.GetDockerContext(c)
if err != nil {
return c, err
}
if d.description != "" {
typedContext.Description = d.description
}
if d.orchestrator != command.Orchestrator("") {
typedContext.StackOrchestrator = d.orchestrator
}
c.Metadata = typedContext
return c, nil
}
func newContextMetadata(stackOrchestrator command.Orchestrator, o *CreateOptions) store.Metadata {
return store.Metadata{
Endpoints: make(map[string]interface{}),
Metadata: command.DockerContext{
Description: o.Description,
StackOrchestrator: stackOrchestrator,
},
Name: o.Name,
}
}
+181 -14
View File
@@ -1,6 +1,7 @@
package context
import (
"fmt"
"io/ioutil"
"os"
"testing"
@@ -27,7 +28,7 @@ func makeFakeCli(t *testing.T, opts ...func(*test.FakeCli)) (*test.FakeCli, func
Store: store.New(dir, storeConfig),
Resolver: func() (*command.DefaultContext, error) {
return &command.DefaultContext{
Meta: store.ContextMetadata{
Meta: store.Metadata{
Endpoints: map[string]interface{}{
docker.DockerEndpoint: docker.EndpointMeta{
Host: "unix:///var/run/docker.sock",
@@ -63,7 +64,7 @@ func withCliConfig(configFile *configfile.ConfigFile) func(*test.FakeCli) {
func TestCreateInvalids(t *testing.T) {
cli, cleanup := makeFakeCli(t)
defer cleanup()
assert.NilError(t, cli.ContextStore().CreateOrUpdateContext(store.ContextMetadata{Name: "existing-context"}))
assert.NilError(t, cli.ContextStore().CreateOrUpdate(store.Metadata{Name: "existing-context"}))
tests := []struct {
options CreateOptions
expecterErr string
@@ -105,13 +106,6 @@ func TestCreateInvalids(t *testing.T) {
},
expecterErr: `specified orchestrator "invalid" is invalid, please use either kubernetes, swarm or all`,
},
{
options: CreateOptions{
Name: "orchestrator-swarm-no-endpoint",
DefaultStackOrchestrator: "swarm",
},
expecterErr: `docker endpoint configuration is required`,
},
{
options: CreateOptions{
Name: "orchestrator-kubernetes-no-endpoint",
@@ -138,6 +132,11 @@ func TestCreateInvalids(t *testing.T) {
}
}
func assertContextCreateLogging(t *testing.T, cli *test.FakeCli, n string) {
assert.Equal(t, n+"\n", cli.OutBuffer().String())
assert.Equal(t, fmt.Sprintf("Successfully created context %q\n", n), cli.ErrBuffer().String())
}
func TestCreateOrchestratorSwarm(t *testing.T) {
cli, cleanup := makeFakeCli(t)
defer cleanup()
@@ -148,8 +147,7 @@ func TestCreateOrchestratorSwarm(t *testing.T) {
Docker: map[string]string{},
})
assert.NilError(t, err)
assert.Equal(t, "test\n", cli.OutBuffer().String())
assert.Equal(t, "Successfully created context \"test\"\n", cli.ErrBuffer().String())
assertContextCreateLogging(t, cli, "test")
}
func TestCreateOrchestratorEmpty(t *testing.T) {
@@ -161,11 +159,12 @@ func TestCreateOrchestratorEmpty(t *testing.T) {
Docker: map[string]string{},
})
assert.NilError(t, err)
assertContextCreateLogging(t, cli, "test")
}
func validateTestKubeEndpoint(t *testing.T, s store.Store, name string) {
func validateTestKubeEndpoint(t *testing.T, s store.Reader, name string) {
t.Helper()
ctxMetadata, err := s.GetContextMetadata(name)
ctxMetadata, err := s.GetMetadata(name)
assert.NilError(t, err)
kubeMeta := ctxMetadata.Endpoints[kubernetes.KubernetesEndpoint].(kubernetes.EndpointMeta)
kubeEP, err := kubeMeta.WithTLSData(s, name)
@@ -185,7 +184,7 @@ func createTestContextWithKube(t *testing.T, cli command.Cli) {
Name: "test",
DefaultStackOrchestrator: "all",
Kubernetes: map[string]string{
keyFromCurrent: "true",
keyFrom: "default",
},
Docker: map[string]string{},
})
@@ -196,5 +195,173 @@ func TestCreateOrchestratorAllKubernetesEndpointFromCurrent(t *testing.T) {
cli, cleanup := makeFakeCli(t)
defer cleanup()
createTestContextWithKube(t, cli)
assertContextCreateLogging(t, cli, "test")
validateTestKubeEndpoint(t, cli.ContextStore(), "test")
}
func TestCreateFromContext(t *testing.T) {
cases := []struct {
name string
description string
orchestrator string
expectedDescription string
docker map[string]string
kubernetes map[string]string
expectedOrchestrator command.Orchestrator
}{
{
name: "no-override",
expectedDescription: "original description",
expectedOrchestrator: command.OrchestratorSwarm,
},
{
name: "override-description",
description: "new description",
expectedDescription: "new description",
expectedOrchestrator: command.OrchestratorSwarm,
},
{
name: "override-orchestrator",
orchestrator: "kubernetes",
expectedDescription: "original description",
expectedOrchestrator: command.OrchestratorKubernetes,
},
}
cli, cleanup := makeFakeCli(t)
defer cleanup()
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
defer revert()
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "original",
Description: "original description",
Docker: map[string]string{
keyHost: "tcp://42.42.42.42:2375",
},
Kubernetes: map[string]string{
keyFrom: "default",
},
DefaultStackOrchestrator: "swarm",
}))
assertContextCreateLogging(t, cli, "original")
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "dummy",
Description: "dummy description",
Docker: map[string]string{
keyHost: "tcp://24.24.24.24:2375",
},
Kubernetes: map[string]string{
keyFrom: "default",
},
DefaultStackOrchestrator: "swarm",
}))
assertContextCreateLogging(t, cli, "dummy")
cli.SetCurrentContext("dummy")
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
cli.ResetOutputBuffers()
err := RunCreate(cli, &CreateOptions{
From: "original",
Name: c.name,
Description: c.description,
DefaultStackOrchestrator: c.orchestrator,
Docker: c.docker,
Kubernetes: c.kubernetes,
})
assert.NilError(t, err)
assertContextCreateLogging(t, cli, c.name)
newContext, err := cli.ContextStore().GetMetadata(c.name)
assert.NilError(t, err)
newContextTyped, err := command.GetDockerContext(newContext)
assert.NilError(t, err)
dockerEndpoint, err := docker.EndpointFromContext(newContext)
assert.NilError(t, err)
kubeEndpoint := kubernetes.EndpointFromContext(newContext)
assert.Check(t, kubeEndpoint != nil)
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
assert.Equal(t, newContextTyped.StackOrchestrator, c.expectedOrchestrator)
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
assert.Equal(t, kubeEndpoint.Host, "https://someserver")
})
}
}
func TestCreateFromCurrent(t *testing.T) {
cases := []struct {
name string
description string
orchestrator string
expectedDescription string
expectedOrchestrator command.Orchestrator
}{
{
name: "no-override",
expectedDescription: "original description",
expectedOrchestrator: command.OrchestratorSwarm,
},
{
name: "override-description",
description: "new description",
expectedDescription: "new description",
expectedOrchestrator: command.OrchestratorSwarm,
},
{
name: "override-orchestrator",
orchestrator: "kubernetes",
expectedDescription: "original description",
expectedOrchestrator: command.OrchestratorKubernetes,
},
}
cli, cleanup := makeFakeCli(t)
defer cleanup()
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
defer revert()
cli.ResetOutputBuffers()
assert.NilError(t, RunCreate(cli, &CreateOptions{
Name: "original",
Description: "original description",
Docker: map[string]string{
keyHost: "tcp://42.42.42.42:2375",
},
Kubernetes: map[string]string{
keyFrom: "default",
},
DefaultStackOrchestrator: "swarm",
}))
assertContextCreateLogging(t, cli, "original")
cli.SetCurrentContext("original")
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
cli.ResetOutputBuffers()
err := RunCreate(cli, &CreateOptions{
Name: c.name,
Description: c.description,
DefaultStackOrchestrator: c.orchestrator,
})
assert.NilError(t, err)
assertContextCreateLogging(t, cli, c.name)
newContext, err := cli.ContextStore().GetMetadata(c.name)
assert.NilError(t, err)
newContextTyped, err := command.GetDockerContext(newContext)
assert.NilError(t, err)
dockerEndpoint, err := docker.EndpointFromContext(newContext)
assert.NilError(t, err)
kubeEndpoint := kubernetes.EndpointFromContext(newContext)
assert.Check(t, kubeEndpoint != nil)
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
assert.Equal(t, newContextTyped.StackOrchestrator, c.expectedOrchestrator)
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
assert.Equal(t, kubeEndpoint.Host, "https://someserver")
})
}
}
+4 -4
View File
@@ -29,9 +29,9 @@ func TestExportImportWithFile(t *testing.T) {
cli.OutBuffer().Reset()
cli.ErrBuffer().Reset()
assert.NilError(t, RunImport(cli, "test2", contextFile))
context1, err := cli.ContextStore().GetContextMetadata("test")
context1, err := cli.ContextStore().GetMetadata("test")
assert.NilError(t, err)
context2, err := cli.ContextStore().GetContextMetadata("test2")
context2, err := cli.ContextStore().GetMetadata("test2")
assert.NilError(t, err)
assert.DeepEqual(t, context1.Endpoints, context2.Endpoints)
assert.DeepEqual(t, context1.Metadata, context2.Metadata)
@@ -57,9 +57,9 @@ func TestExportImportPipe(t *testing.T) {
cli.OutBuffer().Reset()
cli.ErrBuffer().Reset()
assert.NilError(t, RunImport(cli, "test2", "-"))
context1, err := cli.ContextStore().GetContextMetadata("test")
context1, err := cli.ContextStore().GetMetadata("test")
assert.NilError(t, err)
context2, err := cli.ContextStore().GetContextMetadata("test2")
context2, err := cli.ContextStore().GetMetadata("test2")
assert.NilError(t, err)
assert.DeepEqual(t, context1.Endpoints, context2.Endpoints)
assert.DeepEqual(t, context1.Metadata, context2.Metadata)
+1 -1
View File
@@ -80,7 +80,7 @@ func RunExport(dockerCli command.Cli, opts *ExportOptions) error {
if err := validateContextName(opts.ContextName); err != nil && opts.ContextName != command.DefaultContextName {
return err
}
ctxMeta, err := dockerCli.ContextStore().GetContextMetadata(opts.ContextName)
ctxMeta, err := dockerCli.ContextStore().GetMetadata(opts.ContextName)
if err != nil {
return err
}
+3 -1
View File
@@ -14,7 +14,7 @@ import (
func newImportCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "import CONTEXT FILE|-",
Short: "Import a context from a tar file",
Short: "Import a context from a tar or zip file",
Args: cli.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
return RunImport(dockerCli, args[0], args[1])
@@ -28,6 +28,7 @@ func RunImport(dockerCli command.Cli, name string, source string) error {
if err := checkContextNameForCreation(dockerCli.ContextStore(), name); err != nil {
return err
}
var reader io.Reader
if source == "-" {
reader = dockerCli.In()
@@ -43,6 +44,7 @@ func RunImport(dockerCli command.Cli, name string, source string) error {
if err := store.Import(name, dockerCli.ContextStore(), reader); err != nil {
return err
}
fmt.Fprintln(dockerCli.Out(), name)
fmt.Fprintf(dockerCli.Err(), "Successfully imported context %q\n", name)
return nil
+7 -7
View File
@@ -40,25 +40,25 @@ func newInspectCommand(dockerCli command.Cli) *cobra.Command {
func runInspect(dockerCli command.Cli, opts inspectOptions) error {
getRefFunc := func(ref string) (interface{}, []byte, error) {
c, err := dockerCli.ContextStore().GetContextMetadata(ref)
c, err := dockerCli.ContextStore().GetMetadata(ref)
if err != nil {
return nil, nil, err
}
tlsListing, err := dockerCli.ContextStore().ListContextTLSFiles(ref)
tlsListing, err := dockerCli.ContextStore().ListTLSFiles(ref)
if err != nil {
return nil, nil, err
}
return contextWithTLSListing{
ContextMetadata: c,
TLSMaterial: tlsListing,
Storage: dockerCli.ContextStore().GetContextStorageInfo(ref),
Metadata: c,
TLSMaterial: tlsListing,
Storage: dockerCli.ContextStore().GetStorageInfo(ref),
}, nil, nil
}
return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc)
}
type contextWithTLSListing struct {
store.ContextMetadata
store.Metadata
TLSMaterial map[string]store.EndpointFiles
Storage store.ContextStorageInfo
Storage store.StorageInfo
}
+1 -1
View File
@@ -17,7 +17,7 @@ func TestInspect(t *testing.T) {
refs: []string{"current"},
}))
expected := string(golden.Get(t, "inspect.golden"))
si := cli.ContextStore().GetContextStorageInfo("current")
si := cli.ContextStore().GetStorageInfo("current")
expected = strings.Replace(expected, "<METADATA_PATH>", strings.Replace(si.MetadataPath, `\`, `\\`, -1), 1)
expected = strings.Replace(expected, "<TLS_PATH>", strings.Replace(si.TLSPath, `\`, `\\`, -1), 1)
assert.Equal(t, cli.OutBuffer().String(), expected)
+10 -2
View File
@@ -2,6 +2,7 @@ package context
import (
"fmt"
"os"
"sort"
"github.com/docker/cli/cli"
@@ -41,7 +42,7 @@ func runList(dockerCli command.Cli, opts *listOptions) error {
opts.format = formatter.TableFormatKey
}
curContext := dockerCli.CurrentContext()
contextMap, err := dockerCli.ContextStore().ListContexts()
contextMap, err := dockerCli.ContextStore().List()
if err != nil {
return err
}
@@ -76,7 +77,14 @@ func runList(dockerCli command.Cli, opts *listOptions) error {
sort.Slice(contexts, func(i, j int) bool {
return sortorder.NaturalLess(contexts[i].Name, contexts[j].Name)
})
return format(dockerCli, opts, contexts)
if err := format(dockerCli, opts, contexts); err != nil {
return err
}
if os.Getenv("DOCKER_HOST") != "" {
fmt.Fprint(dockerCli.Err(), "Warning: DOCKER_HOST environment variable overrides the active context. "+
"To use a context, either set the global --context flag, or unset DOCKER_HOST environment variable.\n")
}
return nil
}
func format(dockerCli command.Cli, opts *listOptions, contexts []*formatter.ClientContext) error {
+1 -1
View File
@@ -17,7 +17,7 @@ func createTestContextWithKubeAndSwarm(t *testing.T, cli command.Cli, name strin
Name: name,
DefaultStackOrchestrator: orchestrator,
Description: "description of " + name,
Kubernetes: map[string]string{keyFromCurrent: "true"},
Kubernetes: map[string]string{keyFrom: "default"},
Docker: map[string]string{keyHost: "https://someswarmserver"},
})
assert.NilError(t, err)
+26 -28
View File
@@ -18,7 +18,7 @@ import (
)
const (
keyFromCurrent = "from-current"
keyFrom = "from"
keyHost = "host"
keyCA = "ca"
keyCert = "cert"
@@ -36,7 +36,7 @@ type configKeyDescription struct {
var (
allowedDockerConfigKeys = map[string]struct{}{
keyFromCurrent: {},
keyFrom: {},
keyHost: {},
keyCA: {},
keyCert: {},
@@ -44,15 +44,15 @@ var (
keySkipTLSVerify: {},
}
allowedKubernetesConfigKeys = map[string]struct{}{
keyFromCurrent: {},
keyFrom: {},
keyKubeconfig: {},
keyKubecontext: {},
keyKubenamespace: {},
}
dockerConfigKeysDescriptions = []configKeyDescription{
{
name: keyFromCurrent,
description: "Copy current Docker endpoint configuration",
name: keyFrom,
description: "Copy named context's Docker endpoint configuration",
},
{
name: keyHost,
@@ -77,8 +77,8 @@ var (
}
kubernetesConfigKeysDescriptions = []configKeyDescription{
{
name: keyFromCurrent,
description: "Copy current Kubernetes endpoint configuration",
name: keyFrom,
description: "Copy named context's Kubernetes endpoint configuration",
},
{
name: keyKubeconfig,
@@ -121,12 +121,15 @@ func getDockerEndpoint(dockerCli command.Cli, config map[string]string) (docker.
if err := validateConfig(config, allowedDockerConfigKeys); err != nil {
return docker.Endpoint{}, err
}
fromCurrent, err := parseBool(config, keyFromCurrent)
if err != nil {
return docker.Endpoint{}, err
}
if fromCurrent {
return dockerCli.DockerEndpoint(), nil
if contextName, ok := config[keyFrom]; ok {
metadata, err := dockerCli.ContextStore().GetMetadata(contextName)
if err != nil {
return docker.Endpoint{}, err
}
if ep, ok := metadata.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta); ok {
return docker.Endpoint{EndpointMeta: ep}, nil
}
return docker.Endpoint{}, errors.Errorf("unable to get endpoint from context %q", contextName)
}
tlsData, err := context.TLSDataFromFiles(config[keyCA], config[keyCert], config[keyKey])
if err != nil {
@@ -169,25 +172,20 @@ func getKubernetesEndpoint(dockerCli command.Cli, config map[string]string) (*ku
if len(config) == 0 {
return nil, nil
}
fromCurrent, err := parseBool(config, keyFromCurrent)
if err != nil {
return nil, err
}
if fromCurrent {
if dockerCli.CurrentContext() != "" {
ctxMeta, err := dockerCli.ContextStore().GetContextMetadata(dockerCli.CurrentContext())
if contextName, ok := config[keyFrom]; ok {
ctxMeta, err := dockerCli.ContextStore().GetMetadata(contextName)
if err != nil {
return nil, err
}
endpointMeta := kubernetes.EndpointFromContext(ctxMeta)
if endpointMeta != nil {
res, err := endpointMeta.WithTLSData(dockerCli.ContextStore(), dockerCli.CurrentContext())
if err != nil {
return nil, err
}
endpointMeta := kubernetes.EndpointFromContext(ctxMeta)
if endpointMeta != nil {
res, err := endpointMeta.WithTLSData(dockerCli.ContextStore(), dockerCli.CurrentContext())
if err != nil {
return nil, err
}
return &res, nil
}
return &res, nil
}
// fallback to env-based kubeconfig
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" {
+2 -2
View File
@@ -50,7 +50,7 @@ func RunRemove(dockerCli command.Cli, opts RemoveOptions, names []string) error
}
func doRemove(dockerCli command.Cli, name string, isCurrent, force bool) error {
if _, err := dockerCli.ContextStore().GetContextMetadata(name); err != nil {
if _, err := dockerCli.ContextStore().GetMetadata(name); err != nil {
return err
}
if isCurrent {
@@ -64,5 +64,5 @@ func doRemove(dockerCli command.Cli, name string, isCurrent, force bool) error {
return err
}
}
return dockerCli.ContextStore().RemoveContext(name)
return dockerCli.ContextStore().Remove(name)
}
+2 -2
View File
@@ -18,9 +18,9 @@ func TestRemove(t *testing.T) {
createTestContextWithKubeAndSwarm(t, cli, "current", "all")
createTestContextWithKubeAndSwarm(t, cli, "other", "all")
assert.NilError(t, RunRemove(cli, RemoveOptions{}, []string{"other"}))
_, err := cli.ContextStore().GetContextMetadata("current")
_, err := cli.ContextStore().GetMetadata("current")
assert.NilError(t, err)
_, err = cli.ContextStore().GetContextMetadata("other")
_, err = cli.ContextStore().GetMetadata("other")
assert.Check(t, store.IsErrContextDoesNotExist(err))
}
+4 -4
View File
@@ -72,7 +72,7 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
return err
}
s := cli.ContextStore()
c, err := s.GetContextMetadata(o.Name)
c, err := s.GetMetadata(o.Name)
if err != nil {
return err
}
@@ -118,11 +118,11 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
if err := validateEndpointsAndOrchestrator(c); err != nil {
return err
}
if err := s.CreateOrUpdateContext(c); err != nil {
if err := s.CreateOrUpdate(c); err != nil {
return err
}
for ep, tlsData := range tlsDataToReset {
if err := s.ResetContextEndpointTLSMaterial(o.Name, ep, tlsData); err != nil {
if err := s.ResetEndpointTLSMaterial(o.Name, ep, tlsData); err != nil {
return err
}
}
@@ -132,7 +132,7 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
return nil
}
func validateEndpointsAndOrchestrator(c store.ContextMetadata) error {
func validateEndpointsAndOrchestrator(c store.Metadata) error {
dockerContext, err := command.GetDockerContext(c)
if err != nil {
return err
+2 -2
View File
@@ -25,7 +25,7 @@ func TestUpdateDescriptionOnly(t *testing.T) {
Name: "test",
Description: "description",
}))
c, err := cli.ContextStore().GetContextMetadata("test")
c, err := cli.ContextStore().GetMetadata("test")
assert.NilError(t, err)
dc, err := command.GetDockerContext(c)
assert.NilError(t, err)
@@ -46,7 +46,7 @@ func TestUpdateDockerOnly(t *testing.T) {
keyHost: "tcp://some-host",
},
}))
c, err := cli.ContextStore().GetContextMetadata("test")
c, err := cli.ContextStore().GetMetadata("test")
assert.NilError(t, err)
dc, err := command.GetDockerContext(c)
assert.NilError(t, err)
+6 -1
View File
@@ -2,6 +2,7 @@ package context
import (
"fmt"
"os"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
@@ -25,7 +26,7 @@ func RunUse(dockerCli command.Cli, name string) error {
if err := validateContextName(name); err != nil && name != "default" {
return err
}
if _, err := dockerCli.ContextStore().GetContextMetadata(name); err != nil && name != "default" {
if _, err := dockerCli.ContextStore().GetMetadata(name); err != nil && name != "default" {
return err
}
configValue := name
@@ -39,5 +40,9 @@ func RunUse(dockerCli command.Cli, name string) error {
}
fmt.Fprintln(dockerCli.Out(), name)
fmt.Fprintf(dockerCli.Err(), "Current context is now %q\n", name)
if os.Getenv("DOCKER_HOST") != "" {
fmt.Fprintf(dockerCli.Err(), "Warning: DOCKER_HOST environment variable overrides the active context. "+
"To use %q, either set the global --context flag, or unset DOCKER_HOST environment variable.\n", name)
}
return nil
}
+70 -53
View File
@@ -3,15 +3,11 @@ package command
import (
"fmt"
"io"
"os"
"path/filepath"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/kubernetes"
"github.com/docker/cli/cli/context/store"
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/docker/pkg/homedir"
"github.com/pkg/errors"
)
@@ -20,9 +16,9 @@ const (
DefaultContextName = "default"
)
// DefaultContext contains the default context data for all enpoints
// DefaultContext contains the default context data for all endpoints
type DefaultContext struct {
Meta store.ContextMetadata
Meta store.Metadata
TLS store.ContextTLSData
}
@@ -35,8 +31,21 @@ type ContextStoreWithDefault struct {
Resolver DefaultContextResolver
}
// resolveDefaultContext creates a ContextMetadata for the current CLI invocation parameters
func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, stderr io.Writer) (*DefaultContext, error) {
// EndpointDefaultResolver is implemented by any EndpointMeta object
// which wants to be able to populate the store with whatever their default is.
type EndpointDefaultResolver interface {
// ResolveDefault returns values suitable for storing in store.Metadata.Endpoints
// and store.ContextTLSData.Endpoints.
//
// An error is only returned for something fatal, not simply
// the lack of a default (e.g. because the config file which
// would contain it is missing). If there is no default then
// returns nil, nil, nil.
ResolveDefault(Orchestrator) (interface{}, *store.EndpointTLSData, error)
}
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, storeconfig store.Config, stderr io.Writer) (*DefaultContext, error) {
stackOrchestrator, err := GetStackOrchestrator("", "", config.StackOrchestrator, stderr)
if err != nil {
return nil, err
@@ -44,7 +53,7 @@ func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf
contextTLSData := store.ContextTLSData{
Endpoints: make(map[string]store.EndpointTLSData),
}
contextMetadata := store.ContextMetadata{
contextMetadata := store.Metadata{
Endpoints: make(map[string]interface{}),
Metadata: DockerContext{
Description: "",
@@ -62,28 +71,36 @@ func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf
contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerEP.TLSData.ToStoreTLSData()
}
// Default context uses env-based kubeconfig for Kubernetes endpoint configuration
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" {
kubeconfig = filepath.Join(homedir.Get(), ".kube/config")
}
kubeEP, err := kubernetes.FromKubeConfig(kubeconfig, "", "")
if (stackOrchestrator == OrchestratorKubernetes || stackOrchestrator == OrchestratorAll) && err != nil {
return nil, errors.Wrapf(err, "default orchestrator is %s but kubernetes endpoint could not be found", stackOrchestrator)
}
if err == nil {
contextMetadata.Endpoints[kubernetes.KubernetesEndpoint] = kubeEP.EndpointMeta
if kubeEP.TLSData != nil {
contextTLSData.Endpoints[kubernetes.KubernetesEndpoint] = *kubeEP.TLSData.ToStoreTLSData()
if err := storeconfig.ForeachEndpointType(func(n string, get store.TypeGetter) error {
if n == docker.DockerEndpoint { // handled above
return nil
}
ep := get()
if i, ok := ep.(EndpointDefaultResolver); ok {
meta, tls, err := i.ResolveDefault(stackOrchestrator)
if err != nil {
return err
}
if meta == nil {
return nil
}
contextMetadata.Endpoints[n] = meta
if tls != nil {
contextTLSData.Endpoints[n] = *tls
}
}
// Nothing to be done
return nil
}); err != nil {
return nil, err
}
return &DefaultContext{Meta: contextMetadata, TLS: contextTLSData}, nil
}
// ListContexts implements store.Store's ListContexts
func (s *ContextStoreWithDefault) ListContexts() ([]store.ContextMetadata, error) {
contextList, err := s.Store.ListContexts()
// List implements store.Store's List
func (s *ContextStoreWithDefault) List() ([]store.Metadata, error) {
contextList, err := s.Store.List()
if err != nil {
return nil, err
}
@@ -94,52 +111,52 @@ func (s *ContextStoreWithDefault) ListContexts() ([]store.ContextMetadata, error
return append(contextList, defaultContext.Meta), nil
}
// CreateOrUpdateContext is not allowed for the default context and fails
func (s *ContextStoreWithDefault) CreateOrUpdateContext(meta store.ContextMetadata) error {
// CreateOrUpdate is not allowed for the default context and fails
func (s *ContextStoreWithDefault) CreateOrUpdate(meta store.Metadata) error {
if meta.Name == DefaultContextName {
return errors.New("default context cannot be created nor updated")
}
return s.Store.CreateOrUpdateContext(meta)
return s.Store.CreateOrUpdate(meta)
}
// RemoveContext is not allowed for the default context and fails
func (s *ContextStoreWithDefault) RemoveContext(name string) error {
// Remove is not allowed for the default context and fails
func (s *ContextStoreWithDefault) Remove(name string) error {
if name == DefaultContextName {
return errors.New("default context cannot be removed")
}
return s.Store.RemoveContext(name)
return s.Store.Remove(name)
}
// GetContextMetadata implements store.Store's GetContextMetadata
func (s *ContextStoreWithDefault) GetContextMetadata(name string) (store.ContextMetadata, error) {
// GetMetadata implements store.Store's GetMetadata
func (s *ContextStoreWithDefault) GetMetadata(name string) (store.Metadata, error) {
if name == DefaultContextName {
defaultContext, err := s.Resolver()
if err != nil {
return store.ContextMetadata{}, err
return store.Metadata{}, err
}
return defaultContext.Meta, nil
}
return s.Store.GetContextMetadata(name)
return s.Store.GetMetadata(name)
}
// ResetContextTLSMaterial is not implemented for default context and fails
func (s *ContextStoreWithDefault) ResetContextTLSMaterial(name string, data *store.ContextTLSData) error {
// ResetTLSMaterial is not implemented for default context and fails
func (s *ContextStoreWithDefault) ResetTLSMaterial(name string, data *store.ContextTLSData) error {
if name == DefaultContextName {
return errors.New("The default context store does not support ResetContextTLSMaterial")
return errors.New("The default context store does not support ResetTLSMaterial")
}
return s.Store.ResetContextTLSMaterial(name, data)
return s.Store.ResetTLSMaterial(name, data)
}
// ResetContextEndpointTLSMaterial is not implemented for default context and fails
func (s *ContextStoreWithDefault) ResetContextEndpointTLSMaterial(contextName string, endpointName string, data *store.EndpointTLSData) error {
// ResetEndpointTLSMaterial is not implemented for default context and fails
func (s *ContextStoreWithDefault) ResetEndpointTLSMaterial(contextName string, endpointName string, data *store.EndpointTLSData) error {
if contextName == DefaultContextName {
return errors.New("The default context store does not support ResetContextEndpointTLSMaterial")
return errors.New("The default context store does not support ResetEndpointTLSMaterial")
}
return s.Store.ResetContextEndpointTLSMaterial(contextName, endpointName, data)
return s.Store.ResetEndpointTLSMaterial(contextName, endpointName, data)
}
// ListContextTLSFiles implements store.Store's ListContextTLSFiles
func (s *ContextStoreWithDefault) ListContextTLSFiles(name string) (map[string]store.EndpointFiles, error) {
// ListTLSFiles implements store.Store's ListTLSFiles
func (s *ContextStoreWithDefault) ListTLSFiles(name string) (map[string]store.EndpointFiles, error) {
if name == DefaultContextName {
defaultContext, err := s.Resolver()
if err != nil {
@@ -155,11 +172,11 @@ func (s *ContextStoreWithDefault) ListContextTLSFiles(name string) (map[string]s
}
return tlsfiles, nil
}
return s.Store.ListContextTLSFiles(name)
return s.Store.ListTLSFiles(name)
}
// GetContextTLSData implements store.Store's GetContextTLSData
func (s *ContextStoreWithDefault) GetContextTLSData(contextName, endpointName, fileName string) ([]byte, error) {
// GetTLSData implements store.Store's GetTLSData
func (s *ContextStoreWithDefault) GetTLSData(contextName, endpointName, fileName string) ([]byte, error) {
if contextName == DefaultContextName {
defaultContext, err := s.Resolver()
if err != nil {
@@ -171,7 +188,7 @@ func (s *ContextStoreWithDefault) GetContextTLSData(contextName, endpointName, f
return defaultContext.TLS.Endpoints[endpointName].Files[fileName], nil
}
return s.Store.GetContextTLSData(contextName, endpointName, fileName)
return s.Store.GetTLSData(contextName, endpointName, fileName)
}
type noDefaultTLSDataError struct {
@@ -189,10 +206,10 @@ func (e *noDefaultTLSDataError) NotFound() {}
// IsTLSDataDoesNotExist satisfies github.com/docker/cli/cli/context/store.tlsDataDoesNotExist
func (e *noDefaultTLSDataError) IsTLSDataDoesNotExist() {}
// GetContextStorageInfo implements store.Store's GetContextStorageInfo
func (s *ContextStoreWithDefault) GetContextStorageInfo(contextName string) store.ContextStorageInfo {
// GetStorageInfo implements store.Store's GetStorageInfo
func (s *ContextStoreWithDefault) GetStorageInfo(contextName string) store.StorageInfo {
if contextName == DefaultContextName {
return store.ContextStorageInfo{MetadataPath: "<IN MEMORY>", TLSPath: "<IN MEMORY>"}
return store.StorageInfo{MetadataPath: "<IN MEMORY>", TLSPath: "<IN MEMORY>"}
}
return s.Store.GetContextStorageInfo(contextName)
return s.Store.GetStorageInfo(contextName)
}
+21 -24
View File
@@ -8,7 +8,6 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/kubernetes"
"github.com/docker/cli/cli/context/store"
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/go-connections/tlsconfig"
@@ -30,8 +29,8 @@ var testCfg = store.NewConfig(func() interface{} { return &testContext{} },
store.EndpointTypeGetter("ep2", func() interface{} { return &endpoint{} }),
)
func testDefaultMetadata() store.ContextMetadata {
return store.ContextMetadata{
func testDefaultMetadata() store.Metadata {
return store.Metadata{
Endpoints: map[string]interface{}{
"ep1": endpoint{Foo: "bar"},
},
@@ -40,7 +39,7 @@ func testDefaultMetadata() store.ContextMetadata {
}
}
func testStore(t *testing.T, meta store.ContextMetadata, tls store.ContextTLSData) (store.Store, func()) {
func testStore(t *testing.T, meta store.Metadata, tls store.ContextTLSData) (store.Store, func()) {
//meta := testDefaultMetadata()
testDir, err := ioutil.TempDir("", t.Name())
assert.NilError(t, err)
@@ -63,22 +62,20 @@ func TestDefaultContextInitializer(t *testing.T) {
cli, err := NewDockerCli()
assert.NilError(t, err)
defer env.Patch(t, "DOCKER_HOST", "ssh://someswarmserver")()
defer env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")()
cli.configFile = &configfile.ConfigFile{
StackOrchestrator: "all",
StackOrchestrator: "swarm",
}
ctx, err := resolveDefaultContext(&cliflags.CommonOptions{
ctx, err := ResolveDefaultContext(&cliflags.CommonOptions{
TLS: true,
TLSOptions: &tlsconfig.Options{
CAFile: "./testdata/ca.pem",
},
}, cli.ConfigFile(), cli.Err())
}, cli.ConfigFile(), DefaultContextStoreConfig(), cli.Err())
assert.NilError(t, err)
assert.Equal(t, "default", ctx.Meta.Name)
assert.Equal(t, OrchestratorAll, ctx.Meta.Metadata.(DockerContext).StackOrchestrator)
assert.Equal(t, OrchestratorSwarm, ctx.Meta.Metadata.(DockerContext).StackOrchestrator)
assert.DeepEqual(t, "ssh://someswarmserver", ctx.Meta.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta).Host)
golden.Assert(t, string(ctx.TLS.Endpoints[docker.DockerEndpoint].Files["ca.pem"]), "ca.pem")
assert.DeepEqual(t, "zoinx", ctx.Meta.Endpoints[kubernetes.KubernetesEndpoint].(kubernetes.EndpointMeta).DefaultNamespace)
}
func TestExportDefaultImport(t *testing.T) {
@@ -102,33 +99,33 @@ func TestExportDefaultImport(t *testing.T) {
err := store.Import("dest", s, r)
assert.NilError(t, err)
srcMeta, err := s.GetContextMetadata("default")
srcMeta, err := s.GetMetadata("default")
assert.NilError(t, err)
destMeta, err := s.GetContextMetadata("dest")
destMeta, err := s.GetMetadata("dest")
assert.NilError(t, err)
assert.DeepEqual(t, destMeta.Metadata, srcMeta.Metadata)
assert.DeepEqual(t, destMeta.Endpoints, srcMeta.Endpoints)
srcFileList, err := s.ListContextTLSFiles("default")
srcFileList, err := s.ListTLSFiles("default")
assert.NilError(t, err)
destFileList, err := s.ListContextTLSFiles("dest")
destFileList, err := s.ListTLSFiles("dest")
assert.NilError(t, err)
assert.Equal(t, 1, len(destFileList))
assert.Equal(t, 1, len(srcFileList))
assert.Equal(t, 2, len(destFileList["ep2"]))
assert.Equal(t, 2, len(srcFileList["ep2"]))
srcData1, err := s.GetContextTLSData("default", "ep2", "file1")
srcData1, err := s.GetTLSData("default", "ep2", "file1")
assert.NilError(t, err)
assert.DeepEqual(t, file1, srcData1)
srcData2, err := s.GetContextTLSData("default", "ep2", "file2")
srcData2, err := s.GetTLSData("default", "ep2", "file2")
assert.NilError(t, err)
assert.DeepEqual(t, file2, srcData2)
destData1, err := s.GetContextTLSData("dest", "ep2", "file1")
destData1, err := s.GetTLSData("dest", "ep2", "file1")
assert.NilError(t, err)
assert.DeepEqual(t, file1, destData1)
destData2, err := s.GetContextTLSData("dest", "ep2", "file2")
destData2, err := s.GetTLSData("dest", "ep2", "file2")
assert.NilError(t, err)
assert.DeepEqual(t, file2, destData2)
}
@@ -137,7 +134,7 @@ func TestListDefaultContext(t *testing.T) {
meta := testDefaultMetadata()
s, cleanup := testStore(t, meta, store.ContextTLSData{})
defer cleanup()
result, err := s.ListContexts()
result, err := s.List()
assert.NilError(t, err)
assert.Equal(t, 1, len(result))
assert.DeepEqual(t, meta, result[0])
@@ -146,7 +143,7 @@ func TestListDefaultContext(t *testing.T) {
func TestGetDefaultContextStorageInfo(t *testing.T) {
s, cleanup := testStore(t, testDefaultMetadata(), store.ContextTLSData{})
defer cleanup()
result := s.GetContextStorageInfo(DefaultContextName)
result := s.GetStorageInfo(DefaultContextName)
assert.Equal(t, "<IN MEMORY>", result.MetadataPath)
assert.Equal(t, "<IN MEMORY>", result.TLSPath)
}
@@ -155,7 +152,7 @@ func TestGetDefaultContextMetadata(t *testing.T) {
meta := testDefaultMetadata()
s, cleanup := testStore(t, meta, store.ContextTLSData{})
defer cleanup()
result, err := s.GetContextMetadata(DefaultContextName)
result, err := s.GetMetadata(DefaultContextName)
assert.NilError(t, err)
assert.Equal(t, DefaultContextName, result.Name)
assert.DeepEqual(t, meta.Metadata, result.Metadata)
@@ -166,7 +163,7 @@ func TestErrCreateDefault(t *testing.T) {
meta := testDefaultMetadata()
s, cleanup := testStore(t, meta, store.ContextTLSData{})
defer cleanup()
err := s.CreateOrUpdateContext(store.ContextMetadata{
err := s.CreateOrUpdate(store.Metadata{
Endpoints: map[string]interface{}{
"ep1": endpoint{Foo: "bar"},
},
@@ -180,7 +177,7 @@ func TestErrRemoveDefault(t *testing.T) {
meta := testDefaultMetadata()
s, cleanup := testStore(t, meta, store.ContextTLSData{})
defer cleanup()
err := s.RemoveContext("default")
err := s.Remove("default")
assert.Error(t, err, "default context cannot be removed")
}
@@ -188,6 +185,6 @@ func TestErrTLSDataError(t *testing.T) {
meta := testDefaultMetadata()
s, cleanup := testStore(t, meta, store.ContextTLSData{})
defer cleanup()
_, err := s.GetContextTLSData("default", "noop", "noop")
_, err := s.GetTLSData("default", "noop", "noop")
assert.Check(t, store.IsErrTLSDataDoesNotExist(err))
}
+2 -1
View File
@@ -304,7 +304,8 @@ func TestContainerContextWriteWithNoContainers(t *testing.T) {
}
for _, context := range contexts {
ContainerWrite(context.context, containers)
err := ContainerWrite(context.context, containers)
assert.NilError(t, err)
assert.Check(t, is.Equal(context.expected, out.String()))
// Clean buffer
out.Reset()
+2 -1
View File
@@ -348,7 +348,8 @@ func TestImageContextWriteWithNoImage(t *testing.T) {
}
for _, context := range contexts {
ImageWrite(context.context, images)
err := ImageWrite(context.context, images)
assert.NilError(t, err)
assert.Check(t, is.Equal(context.expected, out.String()))
// Clean buffer
out.Reset()
+3 -5
View File
@@ -1,16 +1,14 @@
package idresolver
import (
"context"
"testing"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
// Import builders to get the builder function as package function
"context"
. "github.com/docker/cli/internal/test/builders"
"github.com/pkg/errors"
)
func TestResolveError(t *testing.T) {
+14 -2
View File
@@ -120,28 +120,40 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags.VarP(&options.tags, "tag", "t", "Name and optionally a tag in the 'name:tag' format")
flags.Var(&options.buildArgs, "build-arg", "Set build-time variables")
flags.Var(options.ulimits, "ulimit", "Ulimit options")
flags.SetAnnotation("ulimit", "no-buildkit", nil)
flags.StringVarP(&options.dockerfileName, "file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
flags.VarP(&options.memory, "memory", "m", "Memory limit")
flags.SetAnnotation("memory", "no-buildkit", nil)
flags.Var(&options.memorySwap, "memory-swap", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap")
flags.SetAnnotation("memory-swap", "no-buildkit", nil)
flags.Var(&options.shmSize, "shm-size", "Size of /dev/shm")
flags.SetAnnotation("shm-size", "no-buildkit", nil)
flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)")
flags.SetAnnotation("cpu-shares", "no-buildkit", nil)
flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
flags.SetAnnotation("cpu-period", "no-buildkit", nil)
flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
flags.SetAnnotation("cpu-quota", "no-buildkit", nil)
flags.StringVar(&options.cpuSetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)")
flags.SetAnnotation("cpuset-cpus", "no-buildkit", nil)
flags.StringVar(&options.cpuSetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)")
flags.SetAnnotation("cpuset-mems", "no-buildkit", nil)
flags.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
flags.SetAnnotation("cgroup-parent", "no-buildkit", nil)
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")
flags.BoolVar(&options.rm, "rm", true, "Remove intermediate containers after a successful build")
flags.SetAnnotation("rm", "no-buildkit", nil)
flags.BoolVar(&options.forceRm, "force-rm", false, "Always remove intermediate containers")
flags.SetAnnotation("force-rm", "no-buildkit", nil)
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success")
flags.BoolVar(&options.pull, "pull", false, "Always attempt to pull a newer version of the image")
flags.StringSliceVar(&options.cacheFrom, "cache-from", []string{}, "Images to consider as cache sources")
flags.BoolVar(&options.compress, "compress", false, "Compress the build context using gzip")
flags.SetAnnotation("compress", "no-buildkit", nil)
flags.StringSliceVar(&options.securityOpt, "security-opt", []string{}, "Security options")
flags.SetAnnotation("security-opt", "no-buildkit", nil)
flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build")
flags.SetAnnotation("network", "version", []string{"1.25"})
flags.Var(&options.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
@@ -474,7 +486,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
// should be just the image ID and we'll print that to stdout.
if options.quiet {
imageID = fmt.Sprintf("%s", buildBuff)
fmt.Fprintf(dockerCli.Out(), imageID)
_, _ = fmt.Fprint(dockerCli.Out(), imageID)
}
if options.imageIDFile != "" {
+3 -3
View File
@@ -232,6 +232,7 @@ func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.Read
// getWithStatusError does an http.Get() and returns an error if the
// status code is 4xx or 5xx.
func getWithStatusError(url string) (resp *http.Response, err error) {
// #nosec G107
if resp, err = http.Get(url); err != nil {
return nil, err
}
@@ -242,9 +243,9 @@ func getWithStatusError(url string) (resp *http.Response, err error) {
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, errors.Wrapf(err, msg+": error reading body")
return nil, errors.Wrapf(err, "%s: error reading body", msg)
}
return nil, errors.Errorf(msg+": %s", bytes.TrimSpace(body))
return nil, errors.Errorf("%s: %s", msg, bytes.TrimSpace(body))
}
// GetContextFromLocalDir uses the given local directory as context for a
@@ -344,7 +345,6 @@ func getDockerfileRelPath(absContextDir, givenDockerfile string) (string, error)
absDockerfile, err = filepath.EvalSymlinks(absDockerfile)
if err != nil {
return "", errors.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err)
}
}
+22 -21
View File
@@ -24,12 +24,12 @@ var prepareEmpty = func(t *testing.T) (string, func()) {
}
var prepareNoFiles = func(t *testing.T) (string, func()) {
return createTestTempDir(t, "", "builder-context-test")
return createTestTempDir(t, "builder-context-test")
}
var prepareOneFile = func(t *testing.T) (string, func()) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
return contextDir, cleanup
}
@@ -42,7 +42,7 @@ func testValidateContextDirectory(t *testing.T, prepare func(t *testing.T) (stri
}
func TestGetContextFromLocalDirNoDockerfile(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
_, _, err := GetContextFromLocalDir(contextDir, "")
@@ -50,7 +50,7 @@ func TestGetContextFromLocalDirNoDockerfile(t *testing.T) {
}
func TestGetContextFromLocalDirNotExistingDir(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
fakePath := filepath.Join(contextDir, "fake")
@@ -60,7 +60,7 @@ func TestGetContextFromLocalDirNotExistingDir(t *testing.T) {
}
func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
fakePath := filepath.Join(contextDir, "fake")
@@ -70,10 +70,10 @@ func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) {
}
func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
contextDir, dirCleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, dirCleanup := createTestTempDir(t, "builder-context-test")
defer dirCleanup()
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
chdirCleanup := chdir(t, contextDir)
defer chdirCleanup()
@@ -86,10 +86,10 @@ func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
}
func TestGetContextFromLocalDirWithDockerfile(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "")
assert.NilError(t, err)
@@ -99,11 +99,11 @@ func TestGetContextFromLocalDirWithDockerfile(t *testing.T) {
}
func TestGetContextFromLocalDirLocalFile(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
testFilename := createTestTempFile(t, contextDir, "tmpTest", "test", 0777)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
testFilename := createTestTempFile(t, contextDir, "tmpTest", "test")
absContextDir, relDockerfile, err := GetContextFromLocalDir(testFilename, "")
@@ -121,13 +121,13 @@ func TestGetContextFromLocalDirLocalFile(t *testing.T) {
}
func TestGetContextFromLocalDirWithCustomDockerfile(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
chdirCleanup := chdir(t, contextDir)
defer chdirCleanup()
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, DefaultDockerfileName)
assert.NilError(t, err)
@@ -173,10 +173,10 @@ func TestGetContextFromReaderString(t *testing.T) {
}
func TestGetContextFromReaderTar(t *testing.T) {
contextDir, cleanup := createTestTempDir(t, "", "builder-context-test")
contextDir, cleanup := createTestTempDir(t, "builder-context-test")
defer cleanup()
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents)
tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
assert.NilError(t, err)
@@ -241,17 +241,18 @@ func TestValidateContextDirectoryWithOneFileExcludes(t *testing.T) {
// createTestTempDir creates a temporary directory for testing.
// It returns the created path and a cleanup function which is meant to be used as deferred call.
// When an error occurs, it terminates the test.
func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
path, err := ioutil.TempDir(dir, prefix)
//nolint: unparam
func createTestTempDir(t *testing.T, prefix string) (string, func()) {
path, err := ioutil.TempDir("", prefix)
assert.NilError(t, err)
return path, func() { assert.NilError(t, os.RemoveAll(path)) }
}
// createTestTempFile creates a temporary file within dir with specific contents and permissions.
// When an error occurs, it terminates the test
func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
func createTestTempFile(t *testing.T, dir, filename, contents string) string {
filePath := filepath.Join(dir, filename)
err := ioutil.WriteFile(filePath, []byte(contents), perm)
err := ioutil.WriteFile(filePath, []byte(contents), 0777)
assert.NilError(t, err)
return filePath
}
+15 -8
View File
@@ -14,6 +14,7 @@ import (
"strings"
"github.com/containerd/console"
"github.com/containerd/containerd/platforms"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image/build"
@@ -155,7 +156,8 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
}
w = f
}
s.Allow(filesync.NewFSSyncTarget(w))
output := func(map[string]string) (io.WriteCloser, error) { return w, nil }
s.Allow(filesync.NewFSSyncTarget(output))
}
}
@@ -173,7 +175,7 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
}))
}
s.Allow(authprovider.NewDockerAuthProvider())
s.Allow(authprovider.NewDockerAuthProvider(os.Stderr))
if len(options.secrets) > 0 {
sp, err := parseSecretSpecs(options.secrets)
if err != nil {
@@ -215,6 +217,14 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error {
})
}
if v := os.Getenv("BUILDKIT_PROGRESS"); v != "" && options.progress == "auto" {
options.progress = v
}
if strings.EqualFold(options.platform, "local") {
options.platform = platforms.DefaultString()
}
eg.Go(func() error {
defer func() { // make sure the Status ends cleanly on build errors
s.Close()
@@ -466,16 +476,13 @@ func parseSecret(value string) (*secretsprovider.FileSource, error) {
func parseSSHSpecs(sl []string) (session.Attachable, error) {
configs := make([]sshprovider.AgentConfig, 0, len(sl))
for _, v := range sl {
c, err := parseSSH(v)
if err != nil {
return nil, err
}
c := parseSSH(v)
configs = append(configs, *c)
}
return sshprovider.NewSSHAgentProvider(configs)
}
func parseSSH(value string) (*sshprovider.AgentConfig, error) {
func parseSSH(value string) *sshprovider.AgentConfig {
parts := strings.SplitN(value, "=", 2)
cfg := sshprovider.AgentConfig{
ID: parts[0],
@@ -483,5 +490,5 @@ func parseSSH(value string) (*sshprovider.AgentConfig, error) {
if len(parts) > 1 {
cfg.Paths = strings.Split(parts[1], ",")
}
return &cfg, nil
return &cfg
}
+9 -12
View File
@@ -35,16 +35,13 @@ func isSessionSupported(dockerCli command.Cli, forStream bool) bool {
}
func trySession(dockerCli command.Cli, contextDir string, forStream bool) (*session.Session, error) {
var s *session.Session
if isSessionSupported(dockerCli, forStream) {
sharedKey, err := getBuildSharedKey(contextDir)
if err != nil {
return nil, errors.Wrap(err, "failed to get build shared key")
}
s, err = session.NewSession(context.Background(), filepath.Base(contextDir), sharedKey)
if err != nil {
return nil, errors.Wrap(err, "failed to create session")
}
if !isSessionSupported(dockerCli, forStream) {
return nil, nil
}
sharedKey := getBuildSharedKey(contextDir)
s, err := session.NewSession(context.Background(), filepath.Base(contextDir), sharedKey)
if err != nil {
return nil, errors.Wrap(err, "failed to create session")
}
return s, nil
}
@@ -130,10 +127,10 @@ func (bw *bufferedWriter) String() string {
return fmt.Sprintf("%s", bw.Writer)
}
func getBuildSharedKey(dir string) (string, error) {
func getBuildSharedKey(dir string) string {
// build session is hash of build dir with node based randomness
s := sha256.Sum256([]byte(fmt.Sprintf("%s:%s", tryNodeIdentifier(), dir)))
return hex.EncodeToString(s[:]), nil
return hex.EncodeToString(s[:])
}
func tryNodeIdentifier() string {
+2 -6
View File
@@ -50,7 +50,6 @@ func TestNewPullCommandSuccess(t *testing.T) {
testCases := []struct {
name string
args []string
flags map[string]string
expectedTag string
}{
{
@@ -64,11 +63,8 @@ func TestNewPullCommandSuccess(t *testing.T) {
expectedTag: "image:latest",
},
{
name: "simple-quiet",
args: []string{"image"},
flags: map[string]string{
"quiet": "true",
},
name: "simple-quiet",
args: []string{"--quiet", "image"},
expectedTag: "image:latest",
},
}
@@ -1,2 +1 @@
Using default tag: latest
docker.io/library/image:latest
+1 -2
View File
@@ -5,11 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package functions
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
)
func TestNodeDemoteErrors(t *testing.T) {
+1 -2
View File
@@ -6,11 +6,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package functions
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -2
View File
@@ -6,14 +6,13 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
"gotest.tools/golden"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
)
func TestNodeListErrorOnAPIFailure(t *testing.T) {
+1 -2
View File
@@ -5,11 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
)
func TestNodePromoteErrors(t *testing.T) {
+1 -2
View File
@@ -8,11 +8,10 @@ import (
"time"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -2
View File
@@ -5,11 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
"gotest.tools/assert"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
)
func TestNodeUpdateErrors(t *testing.T) {
+3 -3
View File
@@ -58,7 +58,7 @@ func TestListErrors(t *testing.T) {
}
func TestList(t *testing.T) {
singlePluginListFunc := func(filter filters.Args) (types.PluginsListResponse, error) {
singlePluginListFunc := func(_ filters.Args) (types.PluginsListResponse, error) {
return types.PluginsListResponse{
{
ID: "id-foo",
@@ -113,7 +113,7 @@ func TestList(t *testing.T) {
"format": "{{ .ID }}",
},
golden: "plugin-list-with-no-trunc-option.golden",
listFunc: func(filter filters.Args) (types.PluginsListResponse, error) {
listFunc: func(_ filters.Args) (types.PluginsListResponse, error) {
return types.PluginsListResponse{
{
ID: "xyg4z2hiSLO5yTnBJfg4OYia9gKA6Qjd",
@@ -142,7 +142,7 @@ func TestList(t *testing.T) {
"format": "{{ .Name }}",
},
golden: "plugin-list-sort.golden",
listFunc: func(filter filters.Args) (types.PluginsListResponse, error) {
listFunc: func(_ filters.Args) (types.PluginsListResponse, error) {
return types.PluginsListResponse{
{
ID: "id-1",
+2 -1
View File
@@ -143,7 +143,8 @@ func runLogin(dockerCli command.Cli, opts loginOptions) error { //nolint: gocycl
creds := dockerCli.ConfigFile().GetCredentialsStore(serverAddress)
store, isDefault := creds.(isFileStore)
if isDefault {
// Display a warning if we're storing the users password (not a token)
if isDefault && authConfig.Password != "" {
err = displayUnencryptedWarning(dockerCli, store.GetFilename())
if err != nil {
return err
+23 -2
View File
@@ -24,6 +24,7 @@ var testAuthErrors = map[string]error{
}
var expiredPassword = "I_M_EXPIRED"
var useToken = "I_M_TOKEN"
type fakeClient struct {
client.Client
@@ -37,6 +38,11 @@ func (c fakeClient) RegistryLogin(ctx context.Context, auth types.AuthConfig) (r
if auth.Password == expiredPassword {
return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
}
if auth.Password == useToken {
return registrytypes.AuthenticateOKBody{
IdentityToken: auth.Password,
}, nil
}
err := testAuthErrors[auth.Username]
return registrytypes.AuthenticateOKBody{}, err
}
@@ -63,7 +69,7 @@ func TestLoginWithCredStoreCreds(t *testing.T) {
}
ctx := context.Background()
for _, tc := range testCases {
cli := (*test.FakeCli)(test.NewFakeCli(&fakeClient{}))
cli := test.NewFakeCli(&fakeClient{})
errBuf := new(bytes.Buffer)
cli.SetErr(errBuf)
loginWithCredStoreCreds(ctx, cli, &tc.inputAuthConfig)
@@ -90,6 +96,11 @@ func TestRunLogin(t *testing.T) {
Username: validUsername,
Password: expiredPassword,
}
validIdentityToken := configtypes.AuthConfig{
ServerAddress: storedServerAddress,
Username: validUsername,
IdentityToken: useToken,
}
testCases := []struct {
inputLoginOption loginOptions
inputStoredCred *configtypes.AuthConfig
@@ -134,6 +145,16 @@ func TestRunLogin(t *testing.T) {
inputStoredCred: &validAuthConfig,
expectedErr: testAuthErrMsg,
},
{
inputLoginOption: loginOptions{
serverAddress: storedServerAddress,
user: validUsername,
password: useToken,
},
inputStoredCred: &validIdentityToken,
expectedErr: "",
expectedSavedCred: validIdentityToken,
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
@@ -145,7 +166,7 @@ func TestRunLogin(t *testing.T) {
if tc.inputStoredCred != nil {
cred := *tc.inputStoredCred
configfile.GetCredentialsStore(cred.ServerAddress).Store(cred)
assert.NilError(t, configfile.GetCredentialsStore(cred.ServerAddress).Store(cred))
}
loginErr := runLogin(cli, tc.inputLoginOption)
if tc.expectedErr != "" {
+1 -1
View File
@@ -13,7 +13,7 @@ import (
)
const (
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}"
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}" // #nosec G101
secretIDHeader = "ID"
secretCreatedHeader = "CREATED"
secretUpdatedHeader = "UPDATED"
+1 -2
View File
@@ -7,10 +7,9 @@ import (
"time"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -2
View File
@@ -7,11 +7,10 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
"gotest.tools/golden"
+1 -2
View File
@@ -3,11 +3,10 @@ package service
import (
"context"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
)
type fakeClient struct {
+46 -8
View File
@@ -8,7 +8,9 @@ import (
"github.com/docker/cli/cli/command"
cliopts "github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/client"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@@ -95,14 +97,8 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
service.TaskTemplate.ContainerSpec.Secrets = secrets
}
specifiedConfigs := opts.configs.Value()
if len(specifiedConfigs) > 0 {
// parse and validate configs
configs, err := ParseConfigs(apiClient, specifiedConfigs)
if err != nil {
return err
}
service.TaskTemplate.ContainerSpec.Configs = configs
if err := setConfigs(apiClient, &service, opts); err != nil {
return err
}
if err := resolveServiceImageDigestContentTrust(dockerCli, &service); err != nil {
@@ -141,3 +137,45 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
return waitOnService(ctx, dockerCli, response.ID, opts.quiet)
}
// setConfigs does double duty: it both sets the ConfigReferences of the
// service, and it sets the service CredentialSpec. This is because there is an
// interplay between the CredentialSpec and the Config it depends on.
func setConfigs(apiClient client.ConfigAPIClient, service *swarm.ServiceSpec, opts *serviceOptions) error {
specifiedConfigs := opts.configs.Value()
// if the user has requested to use a Config, for the CredentialSpec add it
// to the specifiedConfigs as a RuntimeTarget.
if cs := opts.credentialSpec.Value(); cs != nil && cs.Config != "" {
specifiedConfigs = append(specifiedConfigs, &swarm.ConfigReference{
ConfigName: cs.Config,
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
})
}
if len(specifiedConfigs) > 0 {
// parse and validate configs
configs, err := ParseConfigs(apiClient, specifiedConfigs)
if err != nil {
return err
}
service.TaskTemplate.ContainerSpec.Configs = configs
// if we have a CredentialSpec Config, find its ID and rewrite the
// field on the spec
//
// we check the opts instead of the service directly because there are
// a few layers of nullable objects in the service, which is a PITA
// to traverse, but the existence of the option implies that those are
// non-null.
if cs := opts.credentialSpec.Value(); cs != nil && cs.Config != "" {
for _, config := range configs {
if config.ConfigName == cs.Config {
service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config = config.ConfigID
// we've found the right config, no need to keep iterating
// through the rest of them.
break
}
}
}
}
return nil
}
+271
View File
@@ -0,0 +1,271 @@
package service
import (
"context"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
cliopts "github.com/docker/cli/opts"
)
// fakeConfigAPIClientList is used to let us pass a closure as a
// ConfigAPIClient, to use as ConfigList. for all the other methods in the
// interface, it does nothing, not even return an error, so don't use them
type fakeConfigAPIClientList func(context.Context, types.ConfigListOptions) ([]swarm.Config, error)
func (f fakeConfigAPIClientList) ConfigList(ctx context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
return f(ctx, opts)
}
func (f fakeConfigAPIClientList) ConfigCreate(_ context.Context, _ swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
return types.ConfigCreateResponse{}, nil
}
func (f fakeConfigAPIClientList) ConfigRemove(_ context.Context, _ string) error {
return nil
}
func (f fakeConfigAPIClientList) ConfigInspectWithRaw(_ context.Context, _ string) (swarm.Config, []byte, error) {
return swarm.Config{}, nil, nil
}
func (f fakeConfigAPIClientList) ConfigUpdate(_ context.Context, _ string, _ swarm.Version, _ swarm.ConfigSpec) error {
return nil
}
// TestSetConfigsWithCredSpecAndConfigs tests that the setConfigs function for
// create correctly looks up the right configs, and correctly handles the
// credentialSpec
func TestSetConfigsWithCredSpecAndConfigs(t *testing.T) {
// we can't directly access the internal fields of the ConfigOpt struct, so
// we need to let it do the parsing
configOpt := &cliopts.ConfigOpt{}
configOpt.Set("bar")
opts := &serviceOptions{
credentialSpec: credentialSpecOpt{
value: &swarm.CredentialSpec{
Config: "foo",
},
source: "config://foo",
},
configs: *configOpt,
}
// create a service spec. we need to be sure to fill in the nullable
// fields, like the code expects
service := &swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Privileges: &swarm.Privileges{
CredentialSpec: opts.credentialSpec.value,
},
},
},
}
// set up a function to use as the list function
var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
f := opts.Filters
// we're expecting the filter to have names "foo" and "bar"
names := f.Get("name")
assert.Equal(t, len(names), 2)
assert.Assert(t, is.Contains(names, "foo"))
assert.Assert(t, is.Contains(names, "bar"))
return []swarm.Config{
{
ID: "fooID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "foo",
},
},
}, {
ID: "barID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "bar",
},
},
},
}, nil
}
// now call setConfigs
err := setConfigs(fakeClient, service, opts)
// verify no error is returned
assert.NilError(t, err)
credSpecConfigValue := service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config
assert.Equal(t, credSpecConfigValue, "fooID")
configRefs := service.TaskTemplate.ContainerSpec.Configs
assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
ConfigID: "fooID",
ConfigName: "foo",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
}), "expected configRefs to contain foo config")
assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
ConfigID: "barID",
ConfigName: "bar",
File: &swarm.ConfigReferenceFileTarget{
Name: "bar",
// these are the default field values
UID: "0",
GID: "0",
Mode: 0444,
},
}), "expected configRefs to contain bar config")
}
// TestSetConfigsOnlyCredSpec tests that even if a CredentialSpec is the only
// config needed, setConfigs still works
func TestSetConfigsOnlyCredSpec(t *testing.T) {
opts := &serviceOptions{
credentialSpec: credentialSpecOpt{
value: &swarm.CredentialSpec{
Config: "foo",
},
source: "config://foo",
},
}
service := &swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Privileges: &swarm.Privileges{
CredentialSpec: opts.credentialSpec.value,
},
},
},
}
// set up a function to use as the list function
var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
f := opts.Filters
names := f.Get("name")
assert.Equal(t, len(names), 1)
assert.Assert(t, is.Contains(names, "foo"))
return []swarm.Config{
{
ID: "fooID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "foo",
},
},
},
}, nil
}
// now call setConfigs
err := setConfigs(fakeClient, service, opts)
// verify no error is returned
assert.NilError(t, err)
credSpecConfigValue := service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config
assert.Equal(t, credSpecConfigValue, "fooID")
configRefs := service.TaskTemplate.ContainerSpec.Configs
assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
ConfigID: "fooID",
ConfigName: "foo",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
}))
}
// TestSetConfigsOnlyConfigs verifies setConfigs when only configs (and not a
// CredentialSpec) is needed.
func TestSetConfigsOnlyConfigs(t *testing.T) {
configOpt := &cliopts.ConfigOpt{}
configOpt.Set("bar")
opts := &serviceOptions{
configs: *configOpt,
}
service := &swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{},
},
}
var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
f := opts.Filters
names := f.Get("name")
assert.Equal(t, len(names), 1)
assert.Assert(t, is.Contains(names, "bar"))
return []swarm.Config{
{
ID: "barID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "bar",
},
},
},
}, nil
}
// now call setConfigs
err := setConfigs(fakeClient, service, opts)
// verify no error is returned
assert.NilError(t, err)
configRefs := service.TaskTemplate.ContainerSpec.Configs
assert.Assert(t, is.Contains(configRefs, &swarm.ConfigReference{
ConfigID: "barID",
ConfigName: "bar",
File: &swarm.ConfigReferenceFileTarget{
Name: "bar",
// these are the default field values
UID: "0",
GID: "0",
Mode: 0444,
},
}))
}
// TestSetConfigsNoConfigs checks that setConfigs works when there are no
// configs of any kind needed
func TestSetConfigsNoConfigs(t *testing.T) {
// add a credentialSpec that isn't a config
opts := &serviceOptions{
credentialSpec: credentialSpecOpt{
value: &swarm.CredentialSpec{
File: "foo",
},
source: "file://foo",
},
}
service := &swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Privileges: &swarm.Privileges{
CredentialSpec: opts.credentialSpec.value,
},
},
},
}
var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
// assert false -- we should never call this function
assert.Assert(t, false, "we should not be listing configs")
return nil, nil
}
err := setConfigs(fakeClient, service, opts)
assert.NilError(t, err)
// ensure that the value of the credentialspec has not changed
assert.Equal(t, service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.File, "foo")
assert.Equal(t, service.TaskTemplate.ContainerSpec.Privileges.CredentialSpec.Config, "")
}
+16 -3
View File
@@ -16,8 +16,8 @@ import (
"github.com/docker/docker/client"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/api/defaults"
shlex "github.com/flynn-archive/go-shlex"
gogotypes "github.com/gogo/protobuf/types"
"github.com/google/shlex"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)
@@ -331,12 +331,25 @@ func (c *credentialSpecOpt) Set(value string) error {
c.source = value
c.value = &swarm.CredentialSpec{}
switch {
case strings.HasPrefix(value, "config://"):
// NOTE(dperny): we allow the user to specify the value of
// CredentialSpec Config using the Name of the config, but the API
// requires the ID of the config. For simplicity, we will parse
// whatever value is provided into the "Config" field, but before
// making API calls, we may need to swap the Config Name for the ID.
// Therefore, this isn't the definitive location for the value of
// Config that is passed to the API.
c.value.Config = strings.TrimPrefix(value, "config://")
case strings.HasPrefix(value, "file://"):
c.value.File = strings.TrimPrefix(value, "file://")
case strings.HasPrefix(value, "registry://"):
c.value.Registry = strings.TrimPrefix(value, "registry://")
case value == "":
// if the value of the flag is an empty string, that means there is no
// CredentialSpec needed. This is useful for removing a CredentialSpec
// during a service update.
default:
return errors.New("Invalid credential spec - value must be prefixed file:// or registry:// followed by a value")
return errors.New(`invalid credential spec: value must be prefixed with "config://", "file://", or "registry://"`)
}
return nil
@@ -663,7 +676,7 @@ func (options *serviceOptions) ToService(ctx context.Context, apiClient client.N
EndpointSpec: options.endpoint.ToEndpointSpec(),
}
if options.credentialSpec.Value() != nil {
if options.credentialSpec.String() != "" && options.credentialSpec.Value() != nil {
service.TaskTemplate.ContainerSpec.Privileges = &swarm.Privileges{
CredentialSpec: options.credentialSpec.Value(),
}
+57 -3
View File
@@ -14,6 +14,60 @@ import (
is "gotest.tools/assert/cmp"
)
func TestCredentialSpecOpt(t *testing.T) {
tests := []struct {
name string
in string
value swarm.CredentialSpec
expectedErr string
}{
{
name: "empty",
in: "",
value: swarm.CredentialSpec{},
},
{
name: "no-prefix",
in: "noprefix",
value: swarm.CredentialSpec{},
expectedErr: `invalid credential spec: value must be prefixed with "config://", "file://", or "registry://"`,
},
{
name: "config",
in: "config://0bt9dmxjvjiqermk6xrop3ekq",
value: swarm.CredentialSpec{Config: "0bt9dmxjvjiqermk6xrop3ekq"},
},
{
name: "file",
in: "file://somefile.json",
value: swarm.CredentialSpec{File: "somefile.json"},
},
{
name: "registry",
in: "registry://testing",
value: swarm.CredentialSpec{Registry: "testing"},
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
var cs credentialSpecOpt
err := cs.Set(tc.in)
if tc.expectedErr != "" {
assert.Error(t, err, tc.expectedErr)
} else {
assert.NilError(t, err)
}
assert.Equal(t, cs.String(), tc.in)
assert.DeepEqual(t, cs.Value(), &tc.value)
})
}
}
func TestMemBytesString(t *testing.T) {
var mem opts.MemBytes = 1048576
assert.Check(t, is.Equal("1MiB", mem.String()))
@@ -148,9 +202,9 @@ func TestToServiceNetwork(t *testing.T) {
}
nwo := opts.NetworkOpt{}
nwo.Set("zzz-network")
nwo.Set("mmm-network")
nwo.Set("aaa-network")
assert.NilError(t, nwo.Set("zzz-network"))
assert.NilError(t, nwo.Set("mmm-network"))
assert.NilError(t, nwo.Set("aaa-network"))
o := newServiceOptions()
o.mode = "replicated"
+42 -2
View File
@@ -70,16 +70,40 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes.
return []*swarmtypes.ConfigReference{}, nil
}
// the configRefs map has two purposes: it prevents duplication of config
// target filenames, and it it used to get all configs so we can resolve
// their IDs. unfortunately, there are other targets for ConfigReferences,
// besides just a File; specifically, the Runtime target, which is used for
// CredentialSpecs. Therefore, we need to have a list of ConfigReferences
// that are not File targets as well. at this time of writing, the only use
// for Runtime targets is CredentialSpecs. However, to future-proof this
// functionality, we should handle the case where multiple Runtime targets
// are in use for the same Config, and we should deduplicate
// such ConfigReferences, as no matter how many times the Config is used,
// it is only needed to be referenced once.
configRefs := make(map[string]*swarmtypes.ConfigReference)
runtimeRefs := make(map[string]*swarmtypes.ConfigReference)
ctx := context.Background()
for _, config := range requestedConfigs {
// copy the config, so we don't mutate the args
configRef := new(swarmtypes.ConfigReference)
*configRef = *config
if config.Runtime != nil {
// by assigning to a map based on ConfigName, if the same Config
// is required as a Runtime target for multiple purposes, we only
// include it once in the final set of configs.
runtimeRefs[config.ConfigName] = config
// continue, so we skip the logic below for handling file-type
// configs
continue
}
if _, exists := configRefs[config.File.Name]; exists {
return nil, errors.Errorf("duplicate config target for %s not allowed", config.ConfigName)
}
configRef := new(swarmtypes.ConfigReference)
*configRef = *config
configRefs[config.File.Name] = configRef
}
@@ -87,6 +111,9 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes.
for _, s := range configRefs {
args.Add("name", s.ConfigName)
}
for _, s := range runtimeRefs {
args.Add("name", s.ConfigName)
}
configs, err := client.ConfigList(ctx, types.ConfigListOptions{
Filters: args,
@@ -114,5 +141,18 @@ func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes.
addedConfigs = append(addedConfigs, ref)
}
// unfortunately, because the key of configRefs and runtimeRefs is different
// values that may collide, we can't just do some fancy trickery to
// concat maps, we need to do two separate loops
for _, ref := range runtimeRefs {
id, ok := foundConfigs[ref.ConfigName]
if !ok {
return nil, errors.Errorf("config not found: %s", ref.ConfigName)
}
ref.ConfigID = id
addedConfigs = append(addedConfigs, ref)
}
return addedConfigs, nil
}
+132 -10
View File
@@ -194,13 +194,18 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti
spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets
updatedConfigs, err := getUpdatedConfigs(apiClient, flags, spec.TaskTemplate.ContainerSpec.Configs)
updatedConfigs, err := getUpdatedConfigs(apiClient, flags, spec.TaskTemplate.ContainerSpec)
if err != nil {
return err
}
spec.TaskTemplate.ContainerSpec.Configs = updatedConfigs
// set the credential spec value after get the updated configs, because we
// might need the updated configs to set the correct value of the
// CredentialSpec.
updateCredSpecConfig(flags, spec.TaskTemplate.ContainerSpec)
// only send auth if flag was set
sendAuth, err := flags.GetBool(flagRegistryAuth)
if err != nil {
@@ -731,20 +736,56 @@ func getUpdatedSecrets(apiClient client.SecretAPIClient, flags *pflag.FlagSet, s
return newSecrets, nil
}
func getUpdatedConfigs(apiClient client.ConfigAPIClient, flags *pflag.FlagSet, configs []*swarm.ConfigReference) ([]*swarm.ConfigReference, error) {
newConfigs := []*swarm.ConfigReference{}
func getUpdatedConfigs(apiClient client.ConfigAPIClient, flags *pflag.FlagSet, spec *swarm.ContainerSpec) ([]*swarm.ConfigReference, error) {
var (
// credSpecConfigName stores the name of the config specified by the
// credential-spec flag. if a Runtime target Config with this name is
// already in the containerSpec, then this value will be set to
// emptystring in the removeConfigs stage. otherwise, a ConfigReference
// will be created to pass to ParseConfigs to get the ConfigID.
credSpecConfigName string
// credSpecConfigID stores the ID of the credential spec config if that
// config is being carried over from the old set of references
credSpecConfigID string
)
toRemove := buildToRemoveSet(flags, flagConfigRemove)
for _, config := range configs {
if _, exists := toRemove[config.ConfigName]; !exists {
newConfigs = append(newConfigs, config)
if flags.Changed(flagCredentialSpec) {
credSpec := flags.Lookup(flagCredentialSpec).Value.(*credentialSpecOpt).Value()
credSpecConfigName = credSpec.Config
} else {
// if the credential spec flag has not changed, then check if there
// already is a credentialSpec. if there is one, and it's for a Config,
// then it's from the old object, and its value is the config ID. we
// need this so we don't remove the config if the credential spec is
// not being updated.
if spec.Privileges != nil && spec.Privileges.CredentialSpec != nil {
if config := spec.Privileges.CredentialSpec.Config; config != "" {
credSpecConfigID = config
}
}
}
if flags.Changed(flagConfigAdd) {
values := flags.Lookup(flagConfigAdd).Value.(*opts.ConfigOpt).Value()
newConfigs := removeConfigs(flags, spec, credSpecConfigName, credSpecConfigID)
addConfigs, err := ParseConfigs(apiClient, values)
// resolveConfigs is a slice of any new configs that need to have the ID
// resolved
resolveConfigs := []*swarm.ConfigReference{}
if flags.Changed(flagConfigAdd) {
resolveConfigs = append(resolveConfigs, flags.Lookup(flagConfigAdd).Value.(*opts.ConfigOpt).Value()...)
}
// if credSpecConfigNameis non-empty at this point, it means its a new
// config, and we need to resolve its ID accordingly.
if credSpecConfigName != "" {
resolveConfigs = append(resolveConfigs, &swarm.ConfigReference{
ConfigName: credSpecConfigName,
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
})
}
if len(resolveConfigs) > 0 {
addConfigs, err := ParseConfigs(apiClient, resolveConfigs)
if err != nil {
return nil, err
}
@@ -754,6 +795,42 @@ func getUpdatedConfigs(apiClient client.ConfigAPIClient, flags *pflag.FlagSet, c
return newConfigs, nil
}
// removeConfigs figures out which configs in the existing spec should be kept
// after the update.
func removeConfigs(flags *pflag.FlagSet, spec *swarm.ContainerSpec, credSpecName, credSpecID string) []*swarm.ConfigReference {
keepConfigs := []*swarm.ConfigReference{}
toRemove := buildToRemoveSet(flags, flagConfigRemove)
// all configs in spec.Configs should have both a Name and ID, because
// they come from an already-accepted spec.
for _, config := range spec.Configs {
// if the config is a Runtime target, make sure it's still in use right
// now, the only use for Runtime target is credential specs. if, in
// the future, more uses are added, then this check will need to be
// made more intelligent.
if config.Runtime != nil {
// if we're carrying over a credential spec explicitly (because the
// user passed --credential-spec with the same config name) then we
// should match on credSpecName. if we're carrying over a
// credential spec implicitly (because the user did not pass any
// --credential-spec flag) then we should match on credSpecID. in
// either case, we're keeping the config that already exists.
if config.ConfigName == credSpecName || config.ConfigID == credSpecID {
keepConfigs = append(keepConfigs, config)
}
// continue the loop, to skip the part where we check if the config
// is in toRemove.
continue
}
if _, exists := toRemove[config.ConfigName]; !exists {
keepConfigs = append(keepConfigs, config)
}
}
return keepConfigs
}
func envKey(value string) string {
kv := strings.SplitN(value, "=", 2)
return kv[0]
@@ -1220,3 +1297,48 @@ func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flag
spec.TaskTemplate.Networks = newNetworks
return nil
}
// updateCredSpecConfig updates the value of the credential spec Config field
// to the config ID if the credential spec has changed. it mutates the passed
// spec. it does not handle the case where the credential spec specifies a
// config that does not exist -- that case is handled as part of
// getUpdatedConfigs
func updateCredSpecConfig(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec) {
if flags.Changed(flagCredentialSpec) {
credSpecOpt := flags.Lookup(flagCredentialSpec)
// if the flag has changed, and the value is empty string, then we
// should remove any credential spec that might be present
if credSpecOpt.Value.String() == "" {
if containerSpec.Privileges != nil {
containerSpec.Privileges.CredentialSpec = nil
}
return
}
// otherwise, set the credential spec to be the parsed value
credSpec := credSpecOpt.Value.(*credentialSpecOpt).Value()
// if this is a Config credential spec, we we still need to replace the
// value of credSpec.Config with the config ID instead of Name.
if credSpec.Config != "" {
for _, config := range containerSpec.Configs {
// if the config name matches, then set the config ID. we do
// not need to worry about if this is a Runtime target or not.
// even if it is not a Runtime target, getUpdatedConfigs
// ensures that a Runtime target for this config exists, and
// the Name is unique so the ID is correct no matter the
// target.
if config.ConfigName == credSpec.Config {
credSpec.Config = config.ConfigID
break
}
}
}
if containerSpec.Privileges == nil {
containerSpec.Privileges = &swarm.Privileges{}
}
containerSpec.Privileges.CredentialSpec = credSpec
}
}
+333 -10
View File
@@ -28,7 +28,7 @@ func TestUpdateServiceArgs(t *testing.T) {
cspec := spec.TaskTemplate.ContainerSpec
cspec.Args = []string{"old", "args"}
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.DeepEqual([]string{"the", "new args"}, cspec.Args))
}
@@ -532,18 +532,18 @@ func TestUpdateReadOnly(t *testing.T) {
// Update with --read-only=true, changed to true
flags := newUpdateCommand(nil).Flags()
flags.Set("read-only", "true")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, cspec.ReadOnly)
// Update without --read-only, no change
flags = newUpdateCommand(nil).Flags()
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, cspec.ReadOnly)
// Update with --read-only=false, changed to false
flags = newUpdateCommand(nil).Flags()
flags.Set("read-only", "false")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, !cspec.ReadOnly)
}
@@ -558,18 +558,18 @@ func TestUpdateInit(t *testing.T) {
// Update with --init=true
flags := newUpdateCommand(nil).Flags()
flags.Set("init", "true")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal(true, *cspec.Init))
// Update without --init, no change
flags = newUpdateCommand(nil).Flags()
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal(true, *cspec.Init))
// Update with --init=false
flags = newUpdateCommand(nil).Flags()
flags.Set("init", "false")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal(false, *cspec.Init))
}
@@ -584,18 +584,18 @@ func TestUpdateStopSignal(t *testing.T) {
// Update with --stop-signal=SIGUSR1
flags := newUpdateCommand(nil).Flags()
flags.Set("stop-signal", "SIGUSR1")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal("SIGUSR1", cspec.StopSignal))
// Update without --stop-signal, no change
flags = newUpdateCommand(nil).Flags()
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal("SIGUSR1", cspec.StopSignal))
// Update with --stop-signal=SIGWINCH
flags = newUpdateCommand(nil).Flags()
flags.Set("stop-signal", "SIGWINCH")
updateService(nil, nil, flags, spec)
updateService(context.TODO(), nil, flags, spec)
assert.Check(t, is.Equal("SIGWINCH", cspec.StopSignal))
}
@@ -925,3 +925,326 @@ func TestUpdateSysCtls(t *testing.T) {
})
}
}
func TestUpdateGetUpdatedConfigs(t *testing.T) {
// cannedConfigs is a set of configs that we'll use over and over in the
// tests. it's a map of Name to Config
cannedConfigs := map[string]*swarm.Config{
"bar": {
ID: "barID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "bar",
},
},
},
"cred": {
ID: "credID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "cred",
},
},
},
"newCred": {
ID: "newCredID",
Spec: swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: "newCred",
},
},
},
}
// cannedConfigRefs is the same thing, but with config references instead
// instead of ID, however, it just maps an arbitrary string value. this is
// so we could have multiple config refs using the same config
cannedConfigRefs := map[string]*swarm.ConfigReference{
"fooRef": {
ConfigID: "fooID",
ConfigName: "foo",
File: &swarm.ConfigReferenceFileTarget{
Name: "foo",
UID: "0",
GID: "0",
Mode: 0444,
},
},
"barRef": {
ConfigID: "barID",
ConfigName: "bar",
File: &swarm.ConfigReferenceFileTarget{
Name: "bar",
UID: "0",
GID: "0",
Mode: 0444,
},
},
"bazRef": {
ConfigID: "bazID",
ConfigName: "baz",
File: &swarm.ConfigReferenceFileTarget{
Name: "baz",
UID: "0",
GID: "0",
Mode: 0444,
},
},
"credRef": {
ConfigID: "credID",
ConfigName: "cred",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
},
"newCredRef": {
ConfigID: "newCredID",
ConfigName: "newCred",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
},
}
type flagVal [2]string
type test struct {
// the name of the subtest
name string
// flags are the flags we'll be setting
flags []flagVal
// oldConfigs are the configs that would already be on the service
// it is a slice of strings corresponding to the the key of
// cannedConfigRefs
oldConfigs []string
// oldCredSpec is the credentialSpec being carried over from the old
// object
oldCredSpec *swarm.CredentialSpec
// lookupConfigs are the configs we're expecting to be listed. it is a
// slice of strings corresponding to the key of cannedConfigs
lookupConfigs []string
// expected is the configs we should get as a result. it is a slice of
// strings corresponding to the key in cannedConfigRefs
expected []string
}
testCases := []test{
{
name: "no configs added or removed",
oldConfigs: []string{"fooRef"},
expected: []string{"fooRef"},
}, {
name: "add a config",
flags: []flagVal{{"config-add", "bar"}},
oldConfigs: []string{"fooRef"},
lookupConfigs: []string{"bar"},
expected: []string{"fooRef", "barRef"},
}, {
name: "remove a config",
flags: []flagVal{{"config-rm", "bar"}},
oldConfigs: []string{"fooRef", "barRef"},
expected: []string{"fooRef"},
}, {
name: "include an old credential spec",
oldConfigs: []string{"credRef"},
oldCredSpec: &swarm.CredentialSpec{Config: "credID"},
expected: []string{"credRef"},
}, {
name: "add a credential spec",
oldConfigs: []string{"fooRef"},
flags: []flagVal{{"credential-spec", "config://cred"}},
lookupConfigs: []string{"cred"},
expected: []string{"fooRef", "credRef"},
}, {
name: "change a credential spec",
oldConfigs: []string{"fooRef", "credRef"},
oldCredSpec: &swarm.CredentialSpec{Config: "credID"},
flags: []flagVal{{"credential-spec", "config://newCred"}},
lookupConfigs: []string{"newCred"},
expected: []string{"fooRef", "newCredRef"},
}, {
name: "credential spec no longer config",
oldConfigs: []string{"fooRef", "credRef"},
oldCredSpec: &swarm.CredentialSpec{Config: "credID"},
flags: []flagVal{{"credential-spec", "file://someFile"}},
lookupConfigs: []string{},
expected: []string{"fooRef"},
}, {
name: "credential spec becomes config",
oldConfigs: []string{"fooRef"},
oldCredSpec: &swarm.CredentialSpec{File: "someFile"},
flags: []flagVal{{"credential-spec", "config://cred"}},
lookupConfigs: []string{"cred"},
expected: []string{"fooRef", "credRef"},
}, {
name: "remove credential spec",
oldConfigs: []string{"fooRef", "credRef"},
oldCredSpec: &swarm.CredentialSpec{Config: "credID"},
flags: []flagVal{{"credential-spec", ""}},
lookupConfigs: []string{},
expected: []string{"fooRef"},
}, {
name: "just frick my stuff up",
// a more complicated test. add barRef, remove bazRef, keep fooRef,
// change credentialSpec from credRef to newCredRef
oldConfigs: []string{"fooRef", "bazRef", "credRef"},
oldCredSpec: &swarm.CredentialSpec{Config: "cred"},
flags: []flagVal{
{"config-add", "bar"},
{"config-rm", "baz"},
{"credential-spec", "config://newCred"},
},
lookupConfigs: []string{"bar", "newCred"},
expected: []string{"fooRef", "barRef", "newCredRef"},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
flags := newUpdateCommand(nil).Flags()
for _, f := range tc.flags {
flags.Set(f[0], f[1])
}
// fakeConfigAPIClientList is actually defined in create_test.go,
// but we'll use it here as well
var fakeClient fakeConfigAPIClientList = func(_ context.Context, opts types.ConfigListOptions) ([]swarm.Config, error) {
names := opts.Filters.Get("name")
assert.Equal(t, len(names), len(tc.lookupConfigs))
configs := []swarm.Config{}
for _, lookup := range tc.lookupConfigs {
assert.Assert(t, is.Contains(names, lookup))
cfg, ok := cannedConfigs[lookup]
assert.Assert(t, ok)
configs = append(configs, *cfg)
}
return configs, nil
}
// build the actual set of old configs and the container spec
oldConfigs := []*swarm.ConfigReference{}
for _, config := range tc.oldConfigs {
cfg, ok := cannedConfigRefs[config]
assert.Assert(t, ok)
oldConfigs = append(oldConfigs, cfg)
}
containerSpec := &swarm.ContainerSpec{
Configs: oldConfigs,
Privileges: &swarm.Privileges{
CredentialSpec: tc.oldCredSpec,
},
}
finalConfigs, err := getUpdatedConfigs(fakeClient, flags, containerSpec)
assert.NilError(t, err)
// ensure that the finalConfigs consists of all of the expected
// configs
assert.Equal(t, len(finalConfigs), len(tc.expected),
"%v final configs, %v expected",
len(finalConfigs), len(tc.expected),
)
for _, expected := range tc.expected {
assert.Assert(t, is.Contains(finalConfigs, cannedConfigRefs[expected]))
}
})
}
}
func TestUpdateCredSpec(t *testing.T) {
type testCase struct {
// name is the name of the subtest
name string
// flagVal is the value we're setting flagCredentialSpec to
flagVal string
// spec is the existing serviceSpec with its configs
spec *swarm.ContainerSpec
// expected is the expected value of the credential spec after the
// function. it may be nil
expected *swarm.CredentialSpec
}
testCases := []testCase{
{
name: "add file credential spec",
flagVal: "file://somefile",
spec: &swarm.ContainerSpec{},
expected: &swarm.CredentialSpec{File: "somefile"},
}, {
name: "remove a file credential spec",
flagVal: "",
spec: &swarm.ContainerSpec{
Privileges: &swarm.Privileges{
CredentialSpec: &swarm.CredentialSpec{
File: "someFile",
},
},
},
expected: nil,
}, {
name: "remove when no CredentialSpec exists",
flagVal: "",
spec: &swarm.ContainerSpec{},
expected: nil,
}, {
name: "add a config credenital spec",
flagVal: "config://someConfigName",
spec: &swarm.ContainerSpec{
Configs: []*swarm.ConfigReference{
{
ConfigName: "someConfigName",
ConfigID: "someConfigID",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
},
},
},
expected: &swarm.CredentialSpec{
Config: "someConfigID",
},
}, {
name: "remove a config credential spec",
flagVal: "",
spec: &swarm.ContainerSpec{
Privileges: &swarm.Privileges{
CredentialSpec: &swarm.CredentialSpec{
Config: "someConfigID",
},
},
},
expected: nil,
}, {
name: "update a config credential spec",
flagVal: "config://someConfigName",
spec: &swarm.ContainerSpec{
Configs: []*swarm.ConfigReference{
{
ConfigName: "someConfigName",
ConfigID: "someConfigID",
Runtime: &swarm.ConfigReferenceRuntimeTarget{},
},
},
Privileges: &swarm.Privileges{
CredentialSpec: &swarm.CredentialSpec{
Config: "someDifferentConfigID",
},
},
},
expected: &swarm.CredentialSpec{
Config: "someConfigID",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
flags := newUpdateCommand(nil).Flags()
flags.Set(flagCredentialSpec, tc.flagVal)
updateCredSpecConfig(flags, tc.spec)
// handle the case where tc.spec.Privileges is nil
if tc.expected == nil {
assert.Assert(t, tc.spec.Privileges == nil || tc.spec.Privileges.CredentialSpec == nil)
return
}
assert.Assert(t, tc.spec.Privileges != nil)
assert.DeepEqual(t, tc.spec.Privileges.CredentialSpec, tc.expected)
})
}
}
+117 -52
View File
@@ -14,16 +14,17 @@ import (
latest "github.com/docker/compose-on-kubernetes/api/compose/v1alpha3"
"github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
"github.com/docker/go-connections/nat"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
// pullSecretExtraField is an extra field on ServiceConfigs usable to reference a pull secret
pullSecretExtraField = "x-pull-secret"
// pullPolicyExtraField is an extra field on ServiceConfigs usable to specify a pull policy
pullPolicyExtraField = "x-pull-policy"
// kubernatesExtraField is an extra field on ServiceConfigs containing kubernetes-specific extensions to compose format
kubernatesExtraField = "x-kubernetes"
)
// NewStackConverter returns a converter from types.Config (compose) to the specified
@@ -245,10 +246,8 @@ func fromComposeConfigs(s map[string]composeTypes.ConfigObjConfig) map[string]la
func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities composeCapabilities) (latest.ServiceConfig, error) {
var (
userID *int64
pullSecret string
pullPolicy string
err error
userID *int64
err error
)
if s.User != "" {
numerical, err := strconv.Atoi(s.User)
@@ -257,20 +256,22 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose
userID = &unixUserID
}
}
pullSecret, err = resolveServiceExtra(s, pullSecretExtraField)
kubeExtra, err := resolveServiceExtra(s)
if err != nil {
return latest.ServiceConfig{}, err
}
pullPolicy, err = resolveServiceExtra(s, pullPolicyExtraField)
if kubeExtra.PullSecret != "" && !capabilities.hasPullSecrets {
return latest.ServiceConfig{}, errors.Errorf(`stack API version %s does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`, capabilities.apiVersion)
}
if kubeExtra.PullPolicy != "" && !capabilities.hasPullPolicies {
return latest.ServiceConfig{}, errors.Errorf(`stack API version %s does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`, capabilities.apiVersion)
}
internalPorts, err := setupIntraStackNetworking(s, kubeExtra, capabilities)
if err != nil {
return latest.ServiceConfig{}, err
}
if pullSecret != "" && !capabilities.hasPullSecrets {
return latest.ServiceConfig{}, errors.Errorf("stack API version %s does not support pull secrets (field %q), please use version v1alpha3 or higher", capabilities.apiVersion, pullSecretExtraField)
}
if pullPolicy != "" && !capabilities.hasPullPolicies {
return latest.ServiceConfig{}, errors.Errorf("stack API version %s does not support pull policies (field %q), please use version v1alpha3 or higher", capabilities.apiVersion, pullPolicyExtraField)
}
return latest.ServiceConfig{
Name: s.Name,
CapAdd: s.CapAdd,
@@ -286,40 +287,96 @@ func fromComposeServiceConfig(s composeTypes.ServiceConfig, capabilities compose
RestartPolicy: fromComposeRestartPolicy(s.Deploy.RestartPolicy),
Placement: fromComposePlacement(s.Deploy.Placement),
},
Entrypoint: s.Entrypoint,
Environment: s.Environment,
ExtraHosts: s.ExtraHosts,
Hostname: s.Hostname,
HealthCheck: fromComposeHealthcheck(s.HealthCheck),
Image: s.Image,
Ipc: s.Ipc,
Labels: s.Labels,
Pid: s.Pid,
Ports: fromComposePorts(s.Ports),
Privileged: s.Privileged,
ReadOnly: s.ReadOnly,
Secrets: fromComposeServiceSecrets(s.Secrets),
StdinOpen: s.StdinOpen,
StopGracePeriod: composetypes.ConvertDurationPtr(s.StopGracePeriod),
Tmpfs: s.Tmpfs,
Tty: s.Tty,
User: userID,
Volumes: fromComposeServiceVolumeConfig(s.Volumes),
WorkingDir: s.WorkingDir,
PullSecret: pullSecret,
PullPolicy: pullPolicy,
Entrypoint: s.Entrypoint,
Environment: s.Environment,
ExtraHosts: s.ExtraHosts,
Hostname: s.Hostname,
HealthCheck: fromComposeHealthcheck(s.HealthCheck),
Image: s.Image,
Ipc: s.Ipc,
Labels: s.Labels,
Pid: s.Pid,
Ports: fromComposePorts(s.Ports),
Privileged: s.Privileged,
ReadOnly: s.ReadOnly,
Secrets: fromComposeServiceSecrets(s.Secrets),
StdinOpen: s.StdinOpen,
StopGracePeriod: composetypes.ConvertDurationPtr(s.StopGracePeriod),
Tmpfs: s.Tmpfs,
Tty: s.Tty,
User: userID,
Volumes: fromComposeServiceVolumeConfig(s.Volumes),
WorkingDir: s.WorkingDir,
PullSecret: kubeExtra.PullSecret,
PullPolicy: kubeExtra.PullPolicy,
InternalServiceType: kubeExtra.InternalServiceType,
InternalPorts: internalPorts,
}, nil
}
func resolveServiceExtra(s composeTypes.ServiceConfig, field string) (string, error) {
if iface, ok := s.Extras[field]; ok {
value, ok := iface.(string)
if !ok {
return "", errors.Errorf("field %q: value %v type is %T, should be a string", field, iface, iface)
}
return value, nil
func setupIntraStackNetworking(s composeTypes.ServiceConfig, kubeExtra kubernetesExtra, capabilities composeCapabilities) ([]latest.InternalPort, error) {
if kubeExtra.InternalServiceType != latest.InternalServiceTypeAuto && !capabilities.hasIntraStackLoadBalancing {
return nil,
errors.Errorf(`stack API version %s does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`,
capabilities.apiVersion)
}
return "", nil
if !capabilities.hasIntraStackLoadBalancing {
return nil, nil
}
if err := validateInternalServiceType(kubeExtra.InternalServiceType); err != nil {
return nil, err
}
internalPorts, err := toInternalPorts(s.Expose)
if err != nil {
return nil, err
}
return internalPorts, nil
}
func validateInternalServiceType(internalServiceType latest.InternalServiceType) error {
switch internalServiceType {
case latest.InternalServiceTypeAuto, latest.InternalServiceTypeClusterIP, latest.InternalServiceTypeHeadless:
default:
return errors.Errorf(`invalid value %q for field "x-kubernetes.internal_service_type", valid values are %q or %q`, internalServiceType,
latest.InternalServiceTypeClusterIP,
latest.InternalServiceTypeHeadless)
}
return nil
}
func toInternalPorts(expose []string) ([]latest.InternalPort, error) {
var internalPorts []latest.InternalPort
for _, sourcePort := range expose {
proto, port := nat.SplitProtoPort(sourcePort)
start, end, err := nat.ParsePortRange(port)
if err != nil {
return nil, errors.Errorf("invalid format for expose: %q, error: %s", sourcePort, err)
}
for i := start; i <= end; i++ {
k8sProto := v1.Protocol(strings.ToUpper(proto))
switch k8sProto {
case v1.ProtocolSCTP, v1.ProtocolTCP, v1.ProtocolUDP:
default:
return nil, errors.Errorf("invalid protocol for expose: %q, supported values are %q, %q and %q", sourcePort, v1.ProtocolSCTP, v1.ProtocolTCP, v1.ProtocolUDP)
}
internalPorts = append(internalPorts, latest.InternalPort{
Port: int32(i),
Protocol: k8sProto,
})
}
}
return internalPorts, nil
}
func resolveServiceExtra(s composeTypes.ServiceConfig) (kubernetesExtra, error) {
if iface, ok := s.Extras[kubernatesExtraField]; ok {
var result kubernetesExtra
if err := mapstructure.Decode(iface, &result); err != nil {
return kubernetesExtra{}, err
}
return result, nil
}
return kubernetesExtra{}, nil
}
func fromComposePorts(ports []composeTypes.ServicePortConfig) []latest.ServicePortConfig {
@@ -489,14 +546,22 @@ var (
apiVersion: "v1beta2",
}
v1alpha3Capabilities = composeCapabilities{
apiVersion: "v1alpha3",
hasPullSecrets: true,
hasPullPolicies: true,
apiVersion: "v1alpha3",
hasPullSecrets: true,
hasPullPolicies: true,
hasIntraStackLoadBalancing: true,
}
)
type composeCapabilities struct {
apiVersion string
hasPullSecrets bool
hasPullPolicies bool
apiVersion string
hasPullSecrets bool
hasPullPolicies bool
hasIntraStackLoadBalancing bool
}
type kubernetesExtra struct {
PullSecret string `mapstructure:"pull_secret"`
PullPolicy string `mapstructure:"pull_policy"`
InternalServiceType latest.InternalServiceType `mapstructure:"internal_service_type"`
}
+116 -4
View File
@@ -13,6 +13,7 @@ import (
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
"gotest.tools/assert"
is "gotest.tools/assert/cmp"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -188,12 +189,13 @@ func TestHandlePullSecret(t *testing.T) {
version string
err string
}{
{version: "v1beta1", err: `stack API version v1beta1 does not support pull secrets (field "x-pull-secret"), please use version v1alpha3 or higher`},
{version: "v1beta2", err: `stack API version v1beta2 does not support pull secrets (field "x-pull-secret"), please use version v1alpha3 or higher`},
{version: "v1beta1", err: `stack API version v1beta1 does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`},
{version: "v1beta2", err: `stack API version v1beta2 does not support pull secrets (field "x-kubernetes.pull_secret"), please use version v1alpha3 or higher`},
{version: "v1alpha3"},
}
for _, c := range cases {
c := c
t.Run(c.version, func(t *testing.T) {
conv, err := NewStackConverter(c.version)
assert.NilError(t, err)
@@ -215,12 +217,13 @@ func TestHandlePullPolicy(t *testing.T) {
version string
err string
}{
{version: "v1beta1", err: `stack API version v1beta1 does not support pull policies (field "x-pull-policy"), please use version v1alpha3 or higher`},
{version: "v1beta2", err: `stack API version v1beta2 does not support pull policies (field "x-pull-policy"), please use version v1alpha3 or higher`},
{version: "v1beta1", err: `stack API version v1beta1 does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`},
{version: "v1beta2", err: `stack API version v1beta2 does not support pull policies (field "x-kubernetes.pull_policy"), please use version v1alpha3 or higher`},
{version: "v1alpha3"},
}
for _, c := range cases {
c := c
t.Run(c.version, func(t *testing.T) {
conv, err := NewStackConverter(c.version)
assert.NilError(t, err)
@@ -235,3 +238,112 @@ func TestHandlePullPolicy(t *testing.T) {
})
}
}
func TestHandleInternalServiceType(t *testing.T) {
cases := []struct {
name string
value string
caps composeCapabilities
err string
expected v1alpha3.InternalServiceType
}{
{
name: "v1beta1",
value: "ClusterIP",
caps: v1beta1Capabilities,
err: `stack API version v1beta1 does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`,
},
{
name: "v1beta2",
value: "ClusterIP",
caps: v1beta2Capabilities,
err: `stack API version v1beta2 does not support intra-stack load balancing (field "x-kubernetes.internal_service_type"), please use version v1alpha3 or higher`,
},
{
name: "v1alpha3",
value: "ClusterIP",
caps: v1alpha3Capabilities,
expected: v1alpha3.InternalServiceTypeClusterIP,
},
{
name: "v1alpha3-invalid",
value: "invalid",
caps: v1alpha3Capabilities,
err: `invalid value "invalid" for field "x-kubernetes.internal_service_type", valid values are "ClusterIP" or "Headless"`,
},
}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
res, err := fromComposeServiceConfig(composetypes.ServiceConfig{
Name: "test",
Image: "test",
Extras: map[string]interface{}{
"x-kubernetes": map[string]interface{}{
"internal_service_type": c.value,
},
},
}, c.caps)
if c.err == "" {
assert.NilError(t, err)
assert.Equal(t, res.InternalServiceType, c.expected)
} else {
assert.ErrorContains(t, err, c.err)
}
})
}
}
func TestIgnoreExpose(t *testing.T) {
testData := loadTestStackWith(t, "expose")
for _, version := range []string{"v1beta1", "v1beta2"} {
conv, err := NewStackConverter(version)
assert.NilError(t, err)
s, err := conv.FromCompose(ioutil.Discard, "test", testData)
assert.NilError(t, err)
assert.Equal(t, len(s.Spec.Services[0].InternalPorts), 0)
}
}
func TestParseExpose(t *testing.T) {
testData := loadTestStackWith(t, "expose")
conv, err := NewStackConverter("v1alpha3")
assert.NilError(t, err)
s, err := conv.FromCompose(ioutil.Discard, "test", testData)
assert.NilError(t, err)
expected := []v1alpha3.InternalPort{
{
Port: 1,
Protocol: v1.ProtocolTCP,
},
{
Port: 2,
Protocol: v1.ProtocolTCP,
},
{
Port: 3,
Protocol: v1.ProtocolTCP,
},
{
Port: 4,
Protocol: v1.ProtocolTCP,
},
{
Port: 5,
Protocol: v1.ProtocolUDP,
},
{
Port: 6,
Protocol: v1.ProtocolUDP,
},
{
Port: 7,
Protocol: v1.ProtocolUDP,
},
{
Port: 8,
Protocol: v1.ProtocolUDP,
},
}
assert.DeepEqual(t, s.Spec.Services[0].InternalPorts, expected)
}
+8 -8
View File
@@ -56,16 +56,16 @@ func TestCreateChildResourcesV1Beta1(t *testing.T) {
secrets))
c, err := configs.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, c.ObjectMeta, "test", v1beta1.SchemeGroupVersion.String())
checkOwnerReferences(t, c.ObjectMeta, v1beta1.SchemeGroupVersion.String())
s, err := secrets.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, s.ObjectMeta, "test", v1beta1.SchemeGroupVersion.String())
checkOwnerReferences(t, s.ObjectMeta, v1beta1.SchemeGroupVersion.String())
}
func checkOwnerReferences(t *testing.T, objMeta metav1.ObjectMeta, stackName, stackVersion string) {
func checkOwnerReferences(t *testing.T, objMeta metav1.ObjectMeta, stackVersion string) {
t.Helper()
assert.Equal(t, len(objMeta.OwnerReferences), 1)
assert.Equal(t, objMeta.OwnerReferences[0].Name, stackName)
assert.Equal(t, objMeta.OwnerReferences[0].Name, "test")
assert.Equal(t, objMeta.OwnerReferences[0].Kind, "Stack")
assert.Equal(t, objMeta.OwnerReferences[0].APIVersion, stackVersion)
}
@@ -82,10 +82,10 @@ func TestCreateChildResourcesV1Beta2(t *testing.T) {
secrets))
c, err := configs.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, c.ObjectMeta, "test", v1beta2.SchemeGroupVersion.String())
checkOwnerReferences(t, c.ObjectMeta, v1beta2.SchemeGroupVersion.String())
s, err := secrets.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, s.ObjectMeta, "test", v1beta2.SchemeGroupVersion.String())
checkOwnerReferences(t, s.ObjectMeta, v1beta2.SchemeGroupVersion.String())
}
func TestCreateChildResourcesV1Alpha3(t *testing.T) {
@@ -100,10 +100,10 @@ func TestCreateChildResourcesV1Alpha3(t *testing.T) {
secrets))
c, err := configs.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, c.ObjectMeta, "test", v1alpha3.SchemeGroupVersion.String())
checkOwnerReferences(t, c.ObjectMeta, v1alpha3.SchemeGroupVersion.String())
s, err := secrets.Get("test", metav1.GetOptions{})
assert.NilError(t, err)
checkOwnerReferences(t, s.ObjectMeta, "test", v1alpha3.SchemeGroupVersion.String())
checkOwnerReferences(t, s.ObjectMeta, v1alpha3.SchemeGroupVersion.String())
}
func TestCreateChildResourcesWithStackCreationErrorV1Beta1(t *testing.T) {
+1 -1
View File
@@ -29,7 +29,7 @@ func GetStacks(kubeCli *KubeCli, opts options.List) ([]*formatter.Stack, error)
}
func isAllNamespacesDisabled(kubeCliConfig *configfile.KubernetesConfig) bool {
return kubeCliConfig == nil || kubeCliConfig != nil && kubeCliConfig.AllNamespaces != "disabled"
return kubeCliConfig == nil || kubeCliConfig.AllNamespaces != "disabled"
}
func getStacks(kubeCli *KubeCli, opts options.List) ([]*formatter.Stack, error) {
@@ -0,0 +1,9 @@
version: "3.7"
services:
test:
image: "some-image"
expose:
- "1" # default protocol, single port
- "2-4" # default protocol, port range
- "5/udp" # specific protocol, single port
- "6-8/udp" # specific protocol, port range
@@ -2,4 +2,5 @@ version: "3.7"
services:
test:
image: "some-image"
x-pull-policy: "Never"
x-kubernetes:
pull_policy: "Never"
@@ -2,4 +2,5 @@ version: "3.7"
services:
test:
image: "some-private-image"
x-pull-secret: "some-secret"
x-kubernetes:
pull_secret: "some-secret"
@@ -41,11 +41,13 @@ func newTestPodAndStackRepository(initialPods []apiv1.Pod, initialStacks []apiv1
o := k8stesting.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range initialPods {
obj := obj
if err := o.Add(&obj); err != nil {
panic(err)
}
}
for _, obj := range initialStacks {
obj := obj
if err := o.Add(&obj); err != nil {
panic(err)
}
+1 -2
View File
@@ -6,8 +6,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/test"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
+1 -2
View File
@@ -7,8 +7,7 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
+1 -2
View File
@@ -6,8 +6,7 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
+1 -2
View File
@@ -6,11 +6,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -2
View File
@@ -6,11 +6,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+1 -3
View File
@@ -7,12 +7,10 @@ import (
"time"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"gotest.tools/assert"
"gotest.tools/golden"
)
+2 -6
View File
@@ -88,9 +88,7 @@ func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error
func prettyPrintInfo(dockerCli command.Cli, info info) error {
fmt.Fprintln(dockerCli.Out(), "Client:")
if info.ClientInfo != nil {
if err := prettyPrintClientInfo(dockerCli, *info.ClientInfo); err != nil {
info.ClientErrors = append(info.ClientErrors, err.Error())
}
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
}
for _, err := range info.ClientErrors {
fmt.Fprintln(dockerCli.Out(), "ERROR:", err)
@@ -113,7 +111,7 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
return nil
}
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) error {
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
if len(info.Plugins) > 0 {
@@ -134,8 +132,6 @@ func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) error {
if len(info.Warnings) > 0 {
fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n"))
}
return nil
}
// nolint: gocyclo
+2 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/docker/cli/cli/version"
"github.com/docker/cli/kubernetes"
"github.com/docker/cli/templates"
kubeapi "github.com/docker/compose-on-kubernetes/api"
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -243,7 +244,7 @@ func getKubernetesVersion(dockerCli command.Cli, kubeConfig string) *kubernetesV
err error
)
if dockerCli.CurrentContext() == "" {
clientConfig = kubernetes.NewKubernetesConfig(kubeConfig)
clientConfig = kubeapi.NewKubernetesConfig(kubeConfig)
} else {
clientConfig, err = kubecontext.ConfigFromContext(dockerCli.CurrentContext(), dockerCli.ContextStore())
}
+1 -2
View File
@@ -8,8 +8,7 @@ import (
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/command/idresolver"
"github.com/docker/cli/internal/test"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"gotest.tools/assert"
-5
View File
@@ -393,11 +393,6 @@ func TestGetSignerRolesWithKeyIDs(t *testing.T) {
"bob": {"key71", "key72"},
}
var roleWithSigs []client.RoleWithSignatures
for _, role := range roles {
roleWithSig := client.RoleWithSignatures{Role: role, Signatures: nil}
roleWithSigs = append(roleWithSigs, roleWithSig)
}
signerRoleToKeyIDs := getDelegationRoleToKeyMap(roles)
assert.Check(t, is.DeepEqual(expectedSignerRoleToKeyIDs, signerRoleToKeyIDs))
}
+2 -3
View File
@@ -88,7 +88,7 @@ func validateAndGenerateKey(streams command.Streams, keyName string, workingDir
pubPEM, err := generateKeyAndOutputPubPEM(keyName, privKeyFileStore)
if err != nil {
fmt.Fprintf(streams.Out(), err.Error())
fmt.Fprint(streams.Out(), err.Error())
return errors.Wrapf(err, "failed to generate key for %s", keyName)
}
@@ -108,8 +108,7 @@ func generateKeyAndOutputPubPEM(keyName string, privKeyStore trustmanager.KeySto
return pem.Block{}, err
}
privKeyStore.AddKey(trustmanager.KeyInfo{Role: data.RoleName(keyName)}, privKey)
if err != nil {
if err := privKeyStore.AddKey(trustmanager.KeyInfo{Role: data.RoleName(keyName)}, privKey); err != nil {
return pem.Block{}, err
}
+9 -6
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"io/ioutil"
"os"
"runtime"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@@ -69,12 +70,14 @@ func loadPrivKey(streams command.Streams, keyPath string, options keyLoadOptions
}
func getPrivKeyBytesFromPath(keyPath string) ([]byte, error) {
fileInfo, err := os.Stat(keyPath)
if err != nil {
return nil, err
}
if fileInfo.Mode()&nonOwnerReadWriteMask != 0 {
return nil, fmt.Errorf("private key file %s must not be readable or writable by others", keyPath)
if runtime.GOOS != "windows" {
fileInfo, err := os.Stat(keyPath)
if err != nil {
return nil, err
}
if fileInfo.Mode()&nonOwnerReadWriteMask != 0 {
return nil, fmt.Errorf("private key file %s must not be readable or writable by others", keyPath)
}
}
from, err := os.OpenFile(keyPath, os.O_RDONLY, notary.PrivExecPerms)
+2
View File
@@ -117,6 +117,7 @@ var testKeys = map[string][]byte{
func TestLoadKeyFromPath(t *testing.T) {
skip.If(t, runtime.GOOS == "windows")
for keyID, keyBytes := range testKeys {
keyID, keyBytes := keyID, keyBytes
t.Run(fmt.Sprintf("load-key-id-%s-from-path", keyID), func(t *testing.T) {
testLoadKeyFromPath(t, keyID, keyBytes)
})
@@ -172,6 +173,7 @@ func testLoadKeyFromPath(t *testing.T, privKeyID string, privKeyFixture []byte)
func TestLoadKeyTooPermissive(t *testing.T) {
skip.If(t, runtime.GOOS == "windows")
for keyID, keyBytes := range testKeys {
keyID, keyBytes := keyID, keyBytes
t.Run(fmt.Sprintf("load-key-id-%s-too-permissive", keyID), func(t *testing.T) {
testLoadKeyTooPermissive(t, keyBytes)
})
+1 -1
View File
@@ -116,7 +116,7 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
assert.Check(t, is.DeepEqual(rootKeyA.Public(), rootKeyB.Public()))
// Now also try with a delegation key
releasesKey, err := getOrGenerateNotaryKey(notaryRepo, data.RoleName(trust.ReleasesRole))
releasesKey, err := getOrGenerateNotaryKey(notaryRepo, trust.ReleasesRole)
assert.NilError(t, err)
assert.Check(t, releasesKey != nil)

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