Compare commits

..

33 Commits

Author SHA1 Message Date
fc4de447b5 Merge pull request #413 from jose-bigio/18.02_versionBump
[18.02] bump version to 18.02.0-ce
2018-02-07 11:17:37 -08:00
b89c843589 Merge pull request #414 from jose-bigio/18.02_changelog
[18.02] changelog update
2018-02-07 11:17:14 -08:00
58dddd3699 Update Changelog
Signed-off-by: jose-bigio <jose.bigio@docker.com>
2018-02-05 13:19:01 -08:00
1c6c49f915 bump version to 18.02.0-ce
Signed-off-by: jose-bigio <jose.bigio@docker.com>
2018-02-05 11:13:21 -08:00
f968a2cc55 Merge pull request #403 from jose-bigio/18.02_bumpVersion
[18.02]  bump version to 18.02.0-ce-rc2
2018-01-31 15:57:19 -08:00
80e6ea3db6 Merge pull request #411 from andrewhsu/cl
[18.02] more adjustments to changelog for 18.02.0-ce-rc2
2018-01-31 15:56:05 -08:00
d055e4b6d9 Merge pull request #409 from andrewhsu/fix1
[18.02] Annotate "stack" commands to be "swarm" and "kubernetes"
2018-01-31 15:34:42 -08:00
bbc43ecc52 Merge pull request #410 from andrewhsu/fix2
[18.02] Using Flags instead of PersistentFlags, as Kubernetes flags seem not …
2018-01-31 14:43:59 -08:00
51e5449bfa more adjustments to changelog for 18.02.0-ce-rc2
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-31 13:41:47 -08:00
65553aa3a5 Using Flags instead of PersistentFlags, as Kubernetes flags seem not to be defined in the "persistent space".
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
(cherry picked from commit 14fcadffb1)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-31 13:15:19 -08:00
7a876b5739 Annotate "stack" commands to be "swarm" and "kubernetes"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 93c36eb228)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-31 13:06:40 -08:00
6f67a5601a Merge pull request #407 from andrewhsu/cl
[18.02] update changelog for 18.02.0-ce-rc2
2018-01-31 11:24:47 -08:00
b97aef8f2a update changelog for 18.02.0-ce-rc2
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-31 10:55:34 -08:00
f25c14edf2 Merge pull request #405 from thaJeztah/18.02-backport-fix-plural-singular-node-generic-resources
[18.02] Fix "--node-generic-resource" singular/plural
2018-01-31 10:39:51 -08:00
8bc38e16b2 Merge pull request #400 from thaJeztah/18.02-backport-bump-moby
[18.02] Bump moby and dependencies
2018-01-31 10:39:17 -08:00
30849d8ad6 Merge pull request #401 from thaJeztah/18.02-backport-bump-golang-1.9.3
[18.02] Bump Go to 1.9.3
2018-01-31 10:38:12 -08:00
24653a880d Merge pull request #406 from andrewhsu/qq
[18.02] revert attach: Use ContainerWait instead of Inspect
2018-01-30 21:42:36 -08:00
f30580f501 Revert "attach: Use ContainerWait instead of Inspect"
This reverts commit 1a65d7d84f.

Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-30 18:44:28 -08:00
d3c944e007 Revert "Fix TestAttachExitCode"
This reverts commit 3acd4904bf.

Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-30 18:44:24 -08:00
ba58fe58e7 Fix "--node-generic-resource" singular/plural
Daemon flags that can be specified multiple times use
singlar names for flags, but plural names for the configuration
file.

To make the daemon configuration know how to correlate
the flag with the corresponding configuration option,
`opt.NewNamedListOptsRef()` should be used instead of
`opt.NewListOptsRef()`.

Commit 6702ac590e6148cb3f606388dde93a011cb14931 attempted
to fix the daemon not corresponding the flag with the configuration
file option, but did so by changing the name of the flag
to plural.

This patch reverts that change, and uses `opt.NewNamedListOptsRef()`
instead.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 6e7715d65ba892a47d355e16bf9ad87fb537a2d0)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-30 14:50:06 -08:00
9651b006e6 bump version to 18.02.0-ce-rc2
Signed-off-by: jose-bigio <jose.bigio@docker.com>
2018-01-30 10:41:29 -08:00
97eb7b67a3 Bump Go to 1.9.3
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit ffc7648322)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-26 15:19:09 -08:00
fcc1ab290b bump swarmkit to 713d79dc8799b33465c58ed120b870c52eb5eb4f
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a6a51aadcb)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-26 11:55:49 -08:00
9849fadfbe Update runc and image-spec
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 8707bde082)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-26 11:55:42 -08:00
49bb088afe Bump go-winio to 0.4.6
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 2bf989e129)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-26 11:55:35 -08:00
3fba076ef0 Bump moby/moby to e11bf870a3170a1d2b1e177a0d7ccc66200bd643
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit a3be7a6720)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2018-01-26 11:55:28 -08:00
5e1d90afd7 Merge pull request #396 from andrewhsu/v
[18.02] bump version to 18.02.0-ce-rc1
2018-01-24 16:29:46 -08:00
f903039853 Merge pull request #394 from jose-bigio/18.02_changelog
[18.02] Create 18.02 Changelog
2018-01-24 16:29:30 -08:00
1dcf6652c8 Create 18.02 Changelog
Signed-off-by: jose-bigio <jose.bigio@docker.com>
2018-01-24 16:28:30 -08:00
3b28f86d44 Merge pull request #397 from andrewhsu/fix-tests
[18.02] skip DockerTrustSuite tests for 18.02
2018-01-24 13:08:12 -08:00
1a2098cecf update integration-cli tests for stderr output
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit 250b84ee88)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit d256539bf4)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit 5742bd3ccf)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-24 11:06:02 -08:00
9d7b9c23f5 Blacklist tests, will be rewritten later on
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
(cherry picked from commit 4e81e4fa4e)
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit ec6b0a1a4a)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit fbfecebc0a)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit e3571070d5)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-24 11:06:02 -08:00
ffef3ad3d7 bump version to 18.02.0-ce-rc1
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2018-01-24 10:55:26 -08:00
2847 changed files with 31361 additions and 50556 deletions

View File

@ -1,85 +1,71 @@
# Changelog
For more information on the list of deprecated flags and APIs, have a look at
https://docs.docker.com/engine/deprecated/ where you can find the target removal dates
https://docs.docker.com/engine/deprecated/ where you can find target removal dates.
## 18.04.0-ce (2018-04-10)
## 18.02.0-ce (2018-02-07)
### Builder
- Fix typos in builder and client. [moby/moby#36424](https://github.com/moby/moby/pull/36424)
- Gitutils: fix checking out submodules [moby/moby#35737](https://github.com/moby/moby/pull/35737)
### Client
* Print Stack API and Kubernetes versions in version command. [docker/cli#898](https://github.com/docker/cli/pull/898)
- Fix Kubernetes duplication in version command. [docker/cli#953](https://github.com/docker/cli/pull/953)
* Use HasAvailableFlags instead of HasFlags for Options in help. [docker/cli#959](https://github.com/docker/cli/pull/959)
+ Add support for mandatory variables to stack deploy. [docker/cli#893](https://github.com/docker/cli/pull/893)
- Fix docker stack services command Port output. [docker/cli#943](https://github.com/docker/cli/pull/943)
* Deprecate unencrypted storage. [docker/cli#561](https://github.com/docker/cli/pull/561)
* Don't set a default filename for ConfigFile. [docker/cli#917](https://github.com/docker/cli/pull/917)
- Fix compose network name. [docker/cli#941](https://github.com/docker/cli/pull/941)
* Attach: Ensure attach exit code matches container's [docker/cli#696](https://github.com/docker/cli/pull/696)
+ Added support for tmpfs-mode in compose file [docker/cli#808](https://github.com/docker/cli/pull/808)
+ Adds a new compose file version 3.6 [docker/cli#808](https://github.com/docker/cli/pull/808)
- Fix issue of filter in `docker ps` where `health=starting` returns nothing [moby/moby#35940](https://github.com/moby/moby/pull/35940)
+ Improve presentation of published port ranges [docker/cli#581](https://github.com/docker/cli/pull/581)
* Bump Go to 1.9.3 [docker/cli#827](https://github.com/docker/cli/pull/827)
- Fix broken Kubernetes stack flags [docker/cli#831](https://github.com/docker/cli/pull/831)
* Annotate "stack" commands to be "swarm" and "kubernetes" [docker/cli#804](https://github.com/docker/cli/pull/804)
### Experimental
+ Add manifest command [docker/cli#138](https://github.com/docker/cli/pull/138)
* LCOW remotefs - return error in Read() implementation [moby/moby#36051](https://github.com/moby/moby/pull/36051)
+ LCOW: Coalesce daemon stores, allow dual LCOW and WCOW mode [moby/moby#34859](https://github.com/moby/moby/pull/34859)
- LCOW: Fix OpenFile parameters [moby/moby#36043](https://github.com/moby/moby/pull/36043)
* LCOW: Raise minimum requirement to Windows RS3 RTM build (16299) [moby/moby#36065](https://github.com/moby/moby/pull/36065)
### Logging
* Silent login: use credentials from cred store to login. [docker/cli#139](https://github.com/docker/cli/pull/139)
+ Add support for compressibility of log file. [moby/moby#29932](https://github.com/moby/moby/pull/29932)
- Fix empty LogPath with non-blocking logging mode. [moby/moby#36272](https://github.com/moby/moby/pull/36272)
* Improve daemon config reload; log active configuration [moby/moby#36019](https://github.com/moby/moby/pull/36019)
- Fixed error detection using IsErrNotFound and IsErrNotImplemented for the ContainerLogs method [moby/moby#36000](https://github.com/moby/moby/pull/36000)
+ Add journald tag as SYSLOG_IDENTIFIER [moby/moby#35570](https://github.com/moby/moby/pull/35570)
* Splunk: limit the reader size on error responses [moby/moby#35509](https://github.com/moby/moby/pull/35509)
### Networking
- Prevent explicit removal of ingress network. [moby/moby#36538](https://github.com/moby/moby/pull/36538)
* Disable service on release network results in zero-downtime deployments with rolling upgrades [moby/moby#35960](https://github.com/moby/moby/pull/35960)
- Fix services failing to start if multiple networks with the same name exist in different spaces [moby/moby#30897](https://github.com/moby/moby/pull/30897)
- Fix duplicate networks being added with `docker service update --network-add` [docker/cli#780](https://github.com/docker/cli/pull/780)
- Fixing ingress network when upgrading from 17.09 to 17.12. [moby/moby#36003](https://github.com/moby/moby/pull/36003)
- Fix ndots configuration [docker/libnetwork#1995](https://github.com/docker/libnetwork/pull/1995)
- Fix IPV6 networking being deconfigured if live-restore is enabled [docker/libnetwork#2043](https://github.com/docker/libnetwork/pull/2043)
+ Add support for MX type DNS queries in the embedded DNS server [docker/libnetwork#2041](https://github.com/docker/libnetwork/pull/2041)
### Packaging
+ Added packaging for Fedora 26, Fedora 27, and Centos 7 on aarch64 [docker/docker-ce-packaging#71](https://github.com/docker/docker-ce-packaging/pull/71)
- Removed support for Ubuntu Zesty [docker/docker-ce-packaging#73](https://github.com/docker/docker-ce-packaging/pull/73)
- Removed support for Fedora 25 [docker/docker-ce-packaging#72](https://github.com/docker/docker-ce-packaging/pull/72)
### Runtime
* Devmapper cleanup improvements. [moby/moby#36307](https://github.com/moby/moby/pull/36307)
* Devmapper.Mounted: remove. [moby/moby#36437](https://github.com/moby/moby/pull/36437)
* Devmapper/Remove(): use Rmdir, ignore errors. [moby/moby#36438](https://github.com/moby/moby/pull/36438)
* LCOW - Change platform parser directive to FROM statement flag. [moby/moby#35089](https://github.com/moby/moby/pull/35089)
* Split daemon service code to windows file. [moby/moby#36653](https://github.com/moby/moby/pull/36653)
* Windows: Block pulling uplevel images. [moby/moby#36327](https://github.com/moby/moby/pull/36327)
* Windows: Hyper-V containers are broken after 36586 was merged. [moby/moby#36610](https://github.com/moby/moby/pull/36610)
* Windows: Move kernel_windows to use golang registry functions. [moby/moby#36617](https://github.com/moby/moby/pull/36617)
* Windows: Pass back system errors on container exit. [moby/moby#35967](https://github.com/moby/moby/pull/35967)
* Windows: Remove servicing mode. [moby/moby#36267](https://github.com/moby/moby/pull/36267)
* Windows: Report Version and UBR. [moby/moby#36451](https://github.com/moby/moby/pull/36451)
* Bump Runc to 1.0.0-rc5. [moby/moby#36449](https://github.com/moby/moby/pull/36449)
* Mount failure indicates the path that failed. [moby/moby#36407](https://github.com/moby/moby/pull/36407)
* Change return for errdefs.getImplementer(). [moby/moby#36489](https://github.com/moby/moby/pull/36489)
* Client: fix hijackedconn reading from buffer. [moby/moby#36663](https://github.com/moby/moby/pull/36663)
* Content encoding negotiation added to archive request. [moby/moby#36164](https://github.com/moby/moby/pull/36164)
* Daemon/stats: more resilient cpu sampling. [moby/moby#36519](https://github.com/moby/moby/pull/36519)
* Daemon/stats: remove obnoxious types file. [moby/moby#36494](https://github.com/moby/moby/pull/36494)
* Daemon: use context error rather than inventing new one. [moby/moby#36670](https://github.com/moby/moby/pull/36670)
* Enable CRIU on non-amd64 architectures (v2). [moby/moby#36676](https://github.com/moby/moby/pull/36676)
- Fixes intermittent client hang after closing stdin to attached container [moby/moby#36517](https://github.com/moby/moby/pull/36517)
- Fix daemon panic on container export after restart [moby/moby#36586](https://github.com/moby/moby/pull/36586)
- Follow-up fixes on multi-stage moby's Dockerfile. [moby/moby#36425](https://github.com/moby/moby/pull/36425)
* Freeze busybox and latest glibc in Docker image. [moby/moby#36375](https://github.com/moby/moby/pull/36375)
* If container will run as non root user, drop permitted, effective caps early. [moby/moby#36587](https://github.com/moby/moby/pull/36587)
* Layer: remove metadata store interface. [moby/moby#36504](https://github.com/moby/moby/pull/36504)
* Minor optimizations to dockerd. [moby/moby#36577](https://github.com/moby/moby/pull/36577)
* Whitelist statx syscall. [moby/moby#36417](https://github.com/moby/moby/pull/36417)
+ Add missing error return for plugin creation. [moby/moby#36646](https://github.com/moby/moby/pull/36646)
- Fix AppArmor not being applied to Exec processes. [moby/moby#36466](https://github.com/moby/moby/pull/36466)
* Daemon/logger/ring.go: log error not instance. [moby/moby#36475](https://github.com/moby/moby/pull/36475)
- Fix stats collector spinning CPU if no stats are collected. [moby/moby#36609](https://github.com/moby/moby/pull/36609)
- Fix(distribution): digest cache should not be moved if it was an auth. [moby/moby#36509](https://github.com/moby/moby/pull/36509)
- Make sure plugin container is removed on failure. [moby/moby#36715](https://github.com/moby/moby/pull/36715)
* Bump to containerd 1.0.3. [moby/moby#36749](https://github.com/moby/moby/pull/36749)
* Don't sort plugin mount slice. [moby/moby#36711](https://github.com/moby/moby/pull/36711)
### Swarm Mode
* Fixes for synchronizing the dispatcher shutdown with in-progress rpcs. [moby/moby#36371](https://github.com/moby/moby/pull/36371)
* Increase raft ElectionTick to 10xHeartbeatTick. [moby/moby#36672](https://github.com/moby/moby/pull/36672)
* Make Swarm manager Raft quorum parameters configurable in daemon config. [moby/moby#36726](https://github.com/moby/moby/pull/36726)
* Ingress network should not be attachable. [docker/swarmkit#2523](https://github.com/docker/swarmkit/pull/2523)
* [manager/state] Add fernet as an option for raft encryption. [docker/swarmkit#2535](https://github.com/docker/swarmkit/pull/2535)
* Log GRPC server errors. [docker/swarmkit#2541](https://github.com/docker/swarmkit/pull/2541)
* Log leadership changes at the manager level. [docker/swarmkit#2542](https://github.com/docker/swarmkit/pull/2542)
* Remove the containerd executor. [docker/swarmkit#2568](https://github.com/docker/swarmkit/pull/2568)
* Agent: backoff session when no remotes are available. [docker/swarmkit#2570](https://github.com/docker/swarmkit/pull/2570)
* [ca/manager] Remove root CA key encryption support entirely. [docker/swarmkit#2573](https://github.com/docker/swarmkit/pull/2573)
- Fix agent logging race. [docker/swarmkit#2578](https://github.com/docker/swarmkit/pull/2578)
* Adding logic to restore networks in order. [docker/swarmkit#2571](https://github.com/docker/swarmkit/pull/2571)
- Fixes unexpected Docker Daemon shutdown based on pipe error [moby/moby#35968](https://github.com/moby/moby/pull/35968)
- Fix some occurrences of hcsshim::ImportLayer failed in Win32: The system cannot find the path specified [moby/moby#35924](https://github.com/moby/moby/pull/35924)
* Windows: increase the maximum layer size during build to 127GB [moby/moby#35925](https://github.com/moby/moby/pull/35925)
- Fix Devicemapper: Error running DeleteDevice dm_task_run failed [moby/moby#35919](https://github.com/moby/moby/pull/35919)
+ Introduce « exec_die » event [moby/moby#35744](https://github.com/moby/moby/pull/35744)
* Update API to version 1.36 [moby/moby#35744](https://github.com/moby/moby/pull/35744)
- Fix `docker update` not updating cpu quota, and cpu-period of a running container [moby/moby#36030](https://github.com/moby/moby/pull/36030)
* Make container shm parent unbindable [moby/moby#35830](https://github.com/moby/moby/pull/35830)
+ Make image (layer) downloads faster by using pigz [moby/moby#35697](https://github.com/moby/moby/pull/35697)
+ Protect the daemon from volume plugins that are slow or deadlocked [moby/moby#35441](https://github.com/moby/moby/pull/35441)
- Fix `DOCKER_RAMDISK` environment variable not being honoured [moby/moby#35957](https://github.com/moby/moby/pull/35957)
* Bump containerd to 1.0.1 (9b55aab90508bd389d7654c4baf173a981477d55) [moby/moby#35986](https://github.com/moby/moby/pull/35986)
* Update runc to fix hang during start and exec [moby/moby#36097](https://github.com/moby/moby/pull/36097)
- Fix "--node-generic-resource" singular/plural [moby/moby#36125](https://github.com/moby/moby/pull/36125)

View File

@ -1 +1 @@
18.04.0-ce
18.02.0-ce

View File

@ -1,12 +1,4 @@
# if you want to ignore files created by your editor/tools,
# please consider a global .gitignore https://help.github.com/articles/ignoring-files
*.exe
*.exe~
*.orig
.*.swp
.DS_Store
Thumbs.db
.editorconfig
/build/
cli/winresources/rsrc_386.syso
cli/winresources/rsrc_amd64.syso

View File

@ -232,7 +232,6 @@ Kai Qiang Wu (Kennan) <wkq5325@gmail.com>
Kai Qiang Wu (Kennan) <wkq5325@gmail.com> <wkqwu@cn.ibm.com>
Kamil Domański <kamil@domanski.co>
Kamjar Gerami <kami.gerami@gmail.com>
Kat Samperi <kat.samperi@gmail.com> <kizzie@users.noreply.github.com>
Ken Cochrane <kencochrane@gmail.com> <KenCochrane@gmail.com>
Ken Herner <kherner@progress.com> <chosenken@gmail.com>
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
@ -282,7 +281,6 @@ Martin Redmond <redmond.martin@gmail.com> <xgithub@redmond5.com>
Mary Anthony <mary.anthony@docker.com> <mary@docker.com>
Mary Anthony <mary.anthony@docker.com> <moxieandmore@gmail.com>
Mary Anthony <mary.anthony@docker.com> moxiegirl <mary@docker.com>
Mateusz Major <apkd@users.noreply.github.com>
Matt Bentley <matt.bentley@docker.com> <mbentley@mbentley.net>
Matt Schurenko <matt.schurenko@gmail.com>
Matt Williams <mattyw@me.com>
@ -399,7 +397,6 @@ Thatcher Peskens <thatcher@docker.com>
Thatcher Peskens <thatcher@docker.com> <thatcher@dotcloud.com>
Thatcher Peskens <thatcher@docker.com> <thatcher@gmx.net>
Thomas Gazagnaire <thomas@gazagnaire.org> <thomas@gazagnaire.com>
Thomas Krzero <thomas.kovatchitch@gmail.com>
Thomas Léveil <thomasleveil@gmail.com>
Thomas Léveil <thomasleveil@gmail.com> <thomasleveil@users.noreply.github.com>
Tibor Vass <teabee89@gmail.com> <tibor@docker.com>

View File

@ -17,7 +17,6 @@ Aidan Feldman <aidan.feldman@gmail.com>
Aidan Hobson Sayers <aidanhs@cantab.net>
AJ Bowen <aj@gandi.net>
Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Akim Demaille <akim.demaille@docker.com>
Alan Thompson <cloojure@gmail.com>
Albert Callarisa <shark234@gmail.com>
Aleksa Sarai <asarai@suse.de>
@ -108,7 +107,6 @@ Christophe Robin <crobin@nekoo.com>
Christophe Vidal <kriss@krizalys.com>
Christopher Biscardi <biscarch@sketcht.com>
Christopher Jones <tophj@linux.vnet.ibm.com>
Christy Perez <christy@linux.vnet.ibm.com>
Chun Chen <ramichen@tencent.com>
Clinton Kitson <clintonskitson@gmail.com>
Coenraad Loubser <coenraad@wish.org.za>
@ -180,7 +178,6 @@ Eric-Olivier Lamey <eo@lamey.me>
Erica Windisch <erica@windisch.us>
Erik Hollensbe <github@hollensbe.org>
Erik St. Martin <alakriti@gmail.com>
Ethan Haynes <ethanhaynes@alumni.harvard.edu>
Eugene Yakubovich <eugene.yakubovich@coreos.com>
Evan Allrich <evan@unguku.com>
Evan Hazlett <ejhazlett@gmail.com>
@ -237,7 +234,6 @@ Ilya Khlopotov <ilya.khlopotov@gmail.com>
Ilya Sotkov <ilya@sotkov.com>
Isabel Jimenez <contact.isabeljimenez@gmail.com>
Ivan Grcic <igrcic@gmail.com>
Ivan Markin <sw@nogoegst.net>
Jacob Atzen <jacob@jacobatzen.dk>
Jacob Tomlinson <jacob@tom.linson.uk>
Jaivish Kothari <janonymous.codevulture@gmail.com>
@ -318,7 +314,6 @@ Kai Qiang Wu (Kennan) <wkq5325@gmail.com>
Kara Alexandra <kalexandra@us.ibm.com>
Kareem Khazem <karkhaz@karkhaz.com>
Karthik Nayak <Karthik.188@gmail.com>
Kat Samperi <kat.samperi@gmail.com>
Katie McLaughlin <katie@glasnt.com>
Ke Xu <leonhartx.k@gmail.com>
Kei Ohmura <ohmura.kei@gmail.com>
@ -385,7 +380,6 @@ Mark Oates <fl0yd@me.com>
Martin Mosegaard Amdisen <martin.amdisen@praqma.com>
Mary Anthony <mary.anthony@docker.com>
Mason Malone <mason.malone@gmail.com>
Mateusz Major <apkd@users.noreply.github.com>
Matt Gucci <matt9ucci@gmail.com>
Matt Robenolt <matt@ydekproductions.com>
Matthew Heon <mheon@redhat.com>
@ -426,7 +420,6 @@ Moorthy RS <rsmoorthy@gmail.com>
Morgan Bauer <mbauer@us.ibm.com>
Moysés Borges <moysesb@gmail.com>
Mrunal Patel <mrunalp@gmail.com>
muicoder <muicoder@gmail.com>
Muthukumar R <muthur@gmail.com>
Máximo Cuadros <mcuadros@gmail.com>
Nace Oroz <orkica@gmail.com>
@ -527,7 +520,6 @@ Shukui Yang <yangshukui@huawei.com>
Sian Lerk Lau <kiawin@gmail.com>
Sidhartha Mani <sidharthamn@gmail.com>
sidharthamani <sid@rancher.com>
Silvin Lubecki <silvin.lubecki@docker.com>
Simei He <hesimei@zju.edu.cn>
Simon Ferquel <simon.ferquel@docker.com>
Sindhu S <sindhus@live.in>
@ -546,7 +538,6 @@ Steve Durrheimer <s.durrheimer@gmail.com>
Steven Burgess <steven.a.burgess@hotmail.com>
Subhajit Ghosh <isubuz.g@gmail.com>
Sun Jianbo <wonderflow.sun@gmail.com>
Sungwon Han <sungwon.han@navercorp.com>
Sven Dowideit <SvenDowideit@home.org.au>
Sylvain Baubeau <sbaubeau@redhat.com>
Sébastien HOUZÉ <cto@verylastroom.com>
@ -555,7 +546,6 @@ TAGOMORI Satoshi <tagomoris@gmail.com>
Taylor Jones <monitorjbl@gmail.com>
Thatcher Peskens <thatcher@docker.com>
Thomas Gazagnaire <thomas@gazagnaire.org>
Thomas Krzero <thomas.kovatchitch@gmail.com>
Thomas Leonard <thomas.leonard@docker.com>
Thomas Léveil <thomasleveil@gmail.com>
Thomas Riccardi <riccardi@systran.fr>
@ -604,7 +594,6 @@ Wang Long <long.wanglong@huawei.com>
Wang Ping <present.wp@icloud.com>
Wang Xing <hzwangxing@corp.netease.com>
Wang Yuexiao <wang.yuexiao@zte.com.cn>
Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
Wayne Song <wsong@docker.com>
Wen Cheng Ma <wenchma@cn.ibm.com>
Wenzhi Liang <wenzhi.liang@gmail.com>

View File

@ -1,6 +1,6 @@
# Docker maintainers file
#
# This file describes who runs the docker/cli project and how.
# This file describes who runs the docker/docker project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
@ -21,12 +21,23 @@
# a subsystem, they are responsible for doing so and holding the
# subsystem maintainers accountable. If ownership is unclear, they are the de facto owners.
# For each release (including minor releases), a "release captain" is assigned from the
# pool of core maintainers. Rotation is encouraged across all maintainers, to ensure
# the release process is clear and up-to-date.
people = [
"aaronlehmann",
"albers",
"aluzzardi",
"anusha",
"cpuguy83",
"crosbymichael",
"dnephin",
"ehazlett",
"johnstep",
"justincormack",
"mavenugo",
"mlaventure",
"stevvooe",
"tibor",
"tonistiigi",
@ -56,6 +67,7 @@
# - close an issue or pull request when it's inappropriate or off-topic
people = [
"ehazlett",
"programmerq",
"thajeztah"
]
@ -78,16 +90,41 @@
Email = "github@albersweb.de"
GitHub = "albers"
[people.aluzzardi]
Name = "Andrea Luzzardi"
Email = "al@docker.com"
GitHub = "aluzzardi"
[people.anusha]
Name = "Anusha Ragunathan"
Email = "anusha@docker.com"
GitHub = "anusha-ragunathan"
[people.cpuguy83]
Name = "Brian Goff"
Email = "cpuguy83@gmail.com"
GitHub = "cpuguy83"
[people.crosbymichael]
Name = "Michael Crosby"
Email = "crosbymichael@gmail.com"
GitHub = "crosbymichael"
[people.dnephin]
Name = "Daniel Nephin"
Email = "dnephin@gmail.com"
GitHub = "dnephin"
[people.ehazlett]
Name = "Evan Hazlett"
Email = "ejhazlett@gmail.com"
GitHub = "ehazlett"
[people.johnstep]
Name = "John Stephens"
Email = "johnstep@docker.com"
GitHub = "johnstep"
[people.justincormack]
Name = "Justin Cormack"
Email = "justin.cormack@docker.com"
@ -98,10 +135,15 @@
Email = "misty@docker.com"
GitHub = "mistyhacks"
[people.programmerq]
Name = "Jeff Anderson"
Email = "jeff@docker.com"
GitHub = "programmerq"
[people.mlaventure]
Name = "Kenfe-Mickaël Laventure"
Email = "mickael.laventure@docker.com"
GitHub = "mlaventure"
[people.shykes]
Name = "Solomon Hykes"
Email = "solomon@docker.com"
GitHub = "shykes"
[people.stevvooe]
Name = "Stephen Day"

View File

@ -51,8 +51,7 @@ watch: ## monitor file changes and run go test
./scripts/test/watch
vendor: vendor.conf ## check that vendor matches vendor.conf
rm -rf vendor
bash -c 'vndr |& grep -v -i clone'
vndr 2> /dev/null
scripts/validate/check-git-diff vendor
.PHONY: authors

View File

@ -1 +1 @@
18.04.0-ce
18.02.0-ce

View File

@ -1,23 +0,0 @@
version: "{build}"
clone_folder: c:\gopath\src\github.com\docker\cli
environment:
GOPATH: c:\gopath
GOVERSION: 1.10
DEPVERSION: v0.4.1
install:
- rmdir c:\go /s /q
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
- go version
- go env
deploy: false
build_script:
- ps: .\scripts\make.ps1 -Binary
test_script:
- ps: .\scripts\make.ps1 -TestUnit

View File

@ -128,7 +128,7 @@ Examples:
{{ .Example }}
{{- end}}
{{- if .HasAvailableFlags}}
{{- if .HasFlags}}
Options:
{{ wrappedFlagUsages . | trimRightSpace}}

View File

@ -5,8 +5,7 @@ import (
"strings"
"testing"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestLoadFileV01Success(t *testing.T) {
@ -26,9 +25,9 @@ func TestLoadFileV01Success(t *testing.T) {
}`)
bundle, err := LoadFile(reader)
assert.NilError(t, err)
assert.Check(t, is.Equal("0.1", bundle.Version))
assert.Check(t, is.Len(bundle.Services, 2))
assert.NoError(t, err)
assert.Equal(t, "0.1", bundle.Version)
assert.Len(t, bundle.Services, 2)
}
func TestLoadFileSyntaxError(t *testing.T) {
@ -38,7 +37,7 @@ func TestLoadFileSyntaxError(t *testing.T) {
}`)
_, err := LoadFile(reader)
assert.Error(t, err, "JSON syntax error at byte 37: invalid character 'u' looking for beginning of value")
assert.EqualError(t, err, "JSON syntax error at byte 37: invalid character 'u' looking for beginning of value")
}
func TestLoadFileTypeError(t *testing.T) {
@ -53,7 +52,7 @@ func TestLoadFileTypeError(t *testing.T) {
}`)
_, err := LoadFile(reader)
assert.Error(t, err, "Unexpected type at byte 94. Expected []string but received string.")
assert.EqualError(t, err, "Unexpected type at byte 94. Expected []string but received string.")
}
func TestPrint(t *testing.T) {
@ -67,12 +66,12 @@ func TestPrint(t *testing.T) {
},
},
}
assert.Check(t, Print(&buffer, bundle))
assert.NoError(t, Print(&buffer, bundle))
output := buffer.String()
assert.Check(t, is.Contains(output, "\"Image\": \"image\""))
assert.Check(t, is.Contains(output,
assert.Contains(t, output, "\"Image\": \"image\"")
assert.Contains(t, output,
`"Command": [
"echo",
"something"
]`))
]`)
}

View File

@ -6,10 +6,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestCheckpointCreateErrors(t *testing.T) {
@ -42,7 +42,7 @@ func TestCheckpointCreateErrors(t *testing.T) {
cmd := newCreateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -63,10 +63,10 @@ func TestCheckpointCreateWithOptions(t *testing.T) {
cmd.SetArgs([]string{"container-foo", checkpoint})
cmd.Flags().Set("leave-running", "true")
cmd.Flags().Set("checkpoint-dir", "/dir/foo")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("container-foo", containerID))
assert.Check(t, is.Equal(checkpoint, checkpointID))
assert.Check(t, is.Equal("/dir/foo", checkpointDir))
assert.Check(t, is.Equal(false, exit))
assert.Check(t, is.Equal(checkpoint, strings.TrimSpace(cli.OutBuffer().String())))
assert.NoError(t, cmd.Execute())
assert.Equal(t, "container-foo", containerID)
assert.Equal(t, checkpoint, checkpointID)
assert.Equal(t, "/dir/foo", checkpointDir)
assert.Equal(t, false, exit)
assert.Equal(t, checkpoint, strings.TrimSpace(cli.OutBuffer().String()))
}

View File

@ -5,11 +5,11 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestCheckpointListErrors(t *testing.T) {
@ -42,7 +42,7 @@ func TestCheckpointListErrors(t *testing.T) {
cmd := newListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -60,8 +60,8 @@ func TestCheckpointListWithOptions(t *testing.T) {
cmd := newListCommand(cli)
cmd.SetArgs([]string{"container-foo"})
cmd.Flags().Set("checkpoint-dir", "/dir/foo")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("container-foo", containerID))
assert.Check(t, is.Equal("/dir/foo", checkpointDir))
assert.NoError(t, cmd.Execute())
assert.Equal(t, "container-foo", containerID)
assert.Equal(t, "/dir/foo", checkpointDir)
golden.Assert(t, cli.OutBuffer().String(), "checkpoint-list-with-options.golden")
}

View File

@ -5,10 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestCheckpointRemoveErrors(t *testing.T) {
@ -41,7 +41,7 @@ func TestCheckpointRemoveErrors(t *testing.T) {
cmd := newRemoveCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -58,8 +58,8 @@ func TestCheckpointRemoveWithOptions(t *testing.T) {
cmd := newRemoveCommand(cli)
cmd.SetArgs([]string{"container-foo", "checkpoint-bar"})
cmd.Flags().Set("checkpoint-dir", "/dir/foo")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("container-foo", containerID))
assert.Check(t, is.Equal("checkpoint-bar", checkpointID))
assert.Check(t, is.Equal("/dir/foo", checkpointDir))
assert.NoError(t, cmd.Execute())
assert.Equal(t, "container-foo", containerID)
assert.Equal(t, "checkpoint-bar", checkpointID)
assert.Equal(t, "/dir/foo", checkpointDir)
}

View File

@ -22,6 +22,7 @@ import (
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/client"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -52,20 +53,18 @@ type Cli interface {
DefaultVersion() string
ManifestStore() manifeststore.Store
RegistryClient(bool) registryclient.RegistryClient
ContentTrustEnabled() bool
}
// DockerCli is an instance the docker command line client.
// Instances of the client can be returned from NewDockerCli.
type DockerCli struct {
configFile *configfile.ConfigFile
in *InStream
out *OutStream
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
contentTrust bool
configFile *configfile.ConfigFile
in *InStream
out *OutStream
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
}
// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified.
@ -123,12 +122,6 @@ func (cli *DockerCli) ClientInfo() ClientInfo {
return cli.clientInfo
}
// ContentTrustEnabled returns whether content trust has been enabled by an
// environment variable.
func (cli *DockerCli) ContentTrustEnabled() bool {
return cli.contentTrust
}
// ManifestStore returns a store for local manifests
func (cli *DockerCli) ManifestStore() manifeststore.Store {
// TODO: support override default location from config file
@ -245,8 +238,8 @@ func (c ClientInfo) HasKubernetes() bool {
}
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err.
func NewDockerCli(in io.ReadCloser, out, err io.Writer, isTrusted bool) *DockerCli {
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err, contentTrust: isTrusted}
func NewDockerCli(in io.ReadCloser, out, err io.Writer) *DockerCli {
return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err}
}
// NewAPIClientFromFlags creates a new APIClient from command line flags
@ -267,12 +260,12 @@ func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.
verStr = tmpStr
}
return client.NewClientWithOpts(
withHTTPClient(opts.TLSOptions),
client.WithHTTPHeaders(customHeaders),
client.WithVersion(verStr),
client.WithHost(host),
)
httpClient, err := newHTTPClient(host, opts.TLSOptions)
if err != nil {
return &client.Client{}, err
}
return client.NewClient(host, verStr, httpClient, customHeaders)
}
func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error) {
@ -289,32 +282,35 @@ func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error
return dopts.ParseHost(tlsOptions != nil, host)
}
func withHTTPClient(tlsOpts *tlsconfig.Options) func(*client.Client) error {
return func(c *client.Client) error {
if tlsOpts == nil {
// Use the default HTTPClient
return nil
}
opts := *tlsOpts
opts.ExclusiveRootPools = true
tlsConfig, err := tlsconfig.Client(opts)
if err != nil {
return err
}
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
DialContext: (&net.Dialer{
KeepAlive: 30 * time.Second,
Timeout: 30 * time.Second,
}).DialContext,
},
CheckRedirect: client.CheckRedirect,
}
return client.WithHTTPClient(httpClient)(c)
func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, error) {
if tlsOptions == nil {
// let the api client configure the default transport.
return nil, nil
}
opts := *tlsOptions
opts.ExclusiveRootPools = true
config, err := tlsconfig.Client(opts)
if err != nil {
return nil, err
}
tr := &http.Transport{
TLSClientConfig: config,
DialContext: (&net.Dialer{
KeepAlive: 30 * time.Second,
Timeout: 30 * time.Second,
}).DialContext,
}
proto, addr, _, err := client.ParseHost(host)
if err != nil {
return nil, err
}
sockets.ConfigureTransport(tr, proto, addr)
return &http.Client{
Transport: tr,
CheckRedirect: client.CheckRedirect,
}, nil
}
// UserAgent returns the user agent string used for making API requests

View File

@ -3,27 +3,24 @@ package command
import (
"crypto/x509"
"os"
"runtime"
"testing"
cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/flags"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/fs"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func TestNewAPIClientFromFlags(t *testing.T) {
host := "unix://path"
if runtime.GOOS == "windows" {
host = "npipe://./"
}
opts := &flags.CommonOptions{Hosts: []string{host}}
configFile := &configfile.ConfigFile{
HTTPHeaders: map[string]string{
@ -31,15 +28,15 @@ func TestNewAPIClientFromFlags(t *testing.T) {
},
}
apiclient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
assert.Check(t, is.Equal(host, apiclient.DaemonHost()))
require.NoError(t, err)
assert.Equal(t, host, apiclient.DaemonHost())
expectedHeaders := map[string]string{
"My-Header": "Custom-Value",
"User-Agent": UserAgent(),
}
assert.Check(t, is.DeepEqual(expectedHeaders, apiclient.(*client.Client).CustomHTTPHeaders()))
assert.Check(t, is.Equal(api.DefaultVersion, apiclient.ClientVersion()))
assert.Equal(t, expectedHeaders, apiclient.(*client.Client).CustomHTTPHeaders())
assert.Equal(t, api.DefaultVersion, apiclient.ClientVersion())
}
func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
@ -49,20 +46,20 @@ func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) {
opts := &flags.CommonOptions{}
configFile := &configfile.ConfigFile{}
apiclient, err := NewAPIClientFromFlags(opts, configFile)
assert.NilError(t, err)
assert.Check(t, is.Equal(customVersion, apiclient.ClientVersion()))
require.NoError(t, err)
assert.Equal(t, customVersion, apiclient.ClientVersion())
}
// TODO: use gotestyourself/env.Patch
func patchEnvVariable(t *testing.T, key, value string) func() {
oldValue, ok := os.LookupEnv(key)
assert.NilError(t, os.Setenv(key, value))
require.NoError(t, os.Setenv(key, value))
return func() {
if !ok {
assert.NilError(t, os.Unsetenv(key))
require.NoError(t, os.Unsetenv(key))
return
}
assert.NilError(t, os.Setenv(key, oldValue))
require.NoError(t, os.Setenv(key, oldValue))
}
}
@ -128,8 +125,8 @@ func TestInitializeFromClient(t *testing.T) {
cli := &DockerCli{client: apiclient}
cli.initializeFromClient()
assert.Check(t, is.DeepEqual(testcase.expectedServer, cli.serverInfo))
assert.Check(t, is.Equal(testcase.negotiated, apiclient.negotiated))
assert.Equal(t, testcase.expectedServer, cli.serverInfo)
assert.Equal(t, testcase.negotiated, apiclient.negotiated)
})
}
}
@ -167,8 +164,8 @@ func TestExperimentalCLI(t *testing.T) {
cli := &DockerCli{client: apiclient, err: os.Stderr}
cliconfig.SetDir(dir.Path())
err := cli.Initialize(flags.NewClientOptions())
assert.NilError(t, err)
assert.Check(t, is.Equal(testcase.expectedExperimentalCLI, cli.ClientInfo().HasExperimental))
assert.NoError(t, err)
assert.Equal(t, testcase.expectedExperimentalCLI, cli.ClientInfo().HasExperimental)
})
}
}
@ -270,9 +267,9 @@ func TestOrchestratorSwitch(t *testing.T) {
options.Common.Orchestrator = testcase.flagOrchestrator
}
err := cli.Initialize(options)
assert.NilError(t, err)
assert.Check(t, is.Equal(testcase.expectedKubernetes, cli.ClientInfo().HasKubernetes()))
assert.Check(t, is.Equal(testcase.expectedOrchestrator, string(cli.ClientInfo().Orchestrator)))
assert.NoError(t, err)
assert.Equal(t, testcase.expectedKubernetes, cli.ClientInfo().HasKubernetes())
assert.Equal(t, testcase.expectedOrchestrator, string(cli.ClientInfo().Orchestrator))
})
}
}
@ -334,11 +331,11 @@ func TestGetClientWithPassword(t *testing.T) {
_, err := getClientWithPassword(passRetriever, newClient)
if testcase.expectedErr != "" {
assert.ErrorContains(t, err, testcase.expectedErr)
testutil.ErrorContains(t, err, testcase.expectedErr)
return
}
assert.NilError(t, err)
assert.NoError(t, err)
})
}
}

View File

@ -16,10 +16,9 @@ import (
)
type createOptions struct {
name string
templateDriver string
file string
labels opts.ListOpts
name string
file string
labels opts.ListOpts
}
func newConfigCreateCommand(dockerCli command.Cli) *cobra.Command {
@ -39,8 +38,6 @@ func newConfigCreateCommand(dockerCli command.Cli) *cobra.Command {
}
flags := cmd.Flags()
flags.VarP(&createOpts.labels, "label", "l", "Config labels")
flags.StringVar(&createOpts.templateDriver, "template-driver", "", "Template driver")
flags.SetAnnotation("driver", "version", []string{"1.37"})
return cmd
}
@ -71,11 +68,7 @@ func runConfigCreate(dockerCli command.Cli, options createOptions) error {
},
Data: configData,
}
if options.templateDriver != "" {
spec.Templating = &swarm.Driver{
Name: options.templateDriver,
}
}
r, err := client.ConfigCreate(ctx, spec)
if err != nil {
return err

View File

@ -8,12 +8,12 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
const configDataFile = "config-create-with-name.golden"
@ -47,7 +47,7 @@ func TestConfigCreateErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -70,9 +70,9 @@ func TestConfigCreateWithName(t *testing.T) {
cmd := newConfigCreateCommand(cli)
cmd.SetArgs([]string{name, filepath.Join("testdata", configDataFile)})
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, string(actual), configDataFile)
assert.Check(t, is.Equal("ID-"+name, strings.TrimSpace(cli.OutBuffer().String())))
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
}
func TestConfigCreateWithLabels(t *testing.T) {
@ -82,21 +82,14 @@ func TestConfigCreateWithLabels(t *testing.T) {
}
name := "foo"
data, err := ioutil.ReadFile(filepath.Join("testdata", configDataFile))
assert.NilError(t, err)
expected := swarm.ConfigSpec{
Annotations: swarm.Annotations{
Name: name,
Labels: expectedLabels,
},
Data: data,
}
cli := test.NewFakeCli(&fakeClient{
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if !reflect.DeepEqual(spec, expected) {
return types.ConfigCreateResponse{}, errors.Errorf("expected %+v, got %+v", expected, spec)
if spec.Name != name {
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
if !reflect.DeepEqual(spec.Labels, expectedLabels) {
return types.ConfigCreateResponse{}, errors.Errorf("expected labels %v, got %v", expectedLabels, spec.Labels)
}
return types.ConfigCreateResponse{
@ -109,35 +102,6 @@ func TestConfigCreateWithLabels(t *testing.T) {
cmd.SetArgs([]string{name, filepath.Join("testdata", configDataFile)})
cmd.Flags().Set("label", "lbl1=Label-foo")
cmd.Flags().Set("label", "lbl2=Label-bar")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("ID-"+name, strings.TrimSpace(cli.OutBuffer().String())))
}
func TestConfigCreateWithTemplatingDriver(t *testing.T) {
expectedDriver := &swarm.Driver{
Name: "template-driver",
}
name := "foo"
cli := test.NewFakeCli(&fakeClient{
configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
if spec.Name != name {
return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
if spec.Templating.Name != expectedDriver.Name {
return types.ConfigCreateResponse{}, errors.Errorf("expected driver %v, got %v", expectedDriver, spec.Labels)
}
return types.ConfigCreateResponse{
ID: "ID-" + spec.Name,
}, nil
},
})
cmd := newConfigCreateCommand(cli)
cmd.SetArgs([]string{name, filepath.Join("testdata", configDataFile)})
cmd.Flags().Set("template-driver", expectedDriver.Name)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("ID-"+name, strings.TrimSpace(cli.OutBuffer().String())))
assert.NoError(t, cmd.Execute())
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
}

View File

@ -11,8 +11,9 @@ import (
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/docker/cli/internal/test/testutil"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestConfigInspectErrors(t *testing.T) {
@ -61,7 +62,7 @@ func TestConfigInspectErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -95,7 +96,7 @@ func TestConfigInspectWithoutFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{configInspectFunc: tc.configInspectFunc})
cmd := newConfigInspectCommand(cli)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-without-format.%s.golden", tc.name))
}
}
@ -132,7 +133,7 @@ func TestConfigInspectWithFormat(t *testing.T) {
cmd := newConfigInspectCommand(cli)
cmd.SetArgs(tc.args)
cmd.Flags().Set("format", tc.format)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-with-format.%s.golden", tc.name))
}
}
@ -166,7 +167,7 @@ func TestConfigInspectPretty(t *testing.T) {
cmd.SetArgs([]string{"configID"})
cmd.Flags().Set("pretty", "true")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-pretty.%s.golden", tc.name))
}
}

View File

@ -12,9 +12,9 @@ import (
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/docker/cli/internal/test/testutil"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestConfigListErrors(t *testing.T) {
@ -42,7 +42,7 @@ func TestConfigListErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -72,7 +72,7 @@ func TestConfigList(t *testing.T) {
},
})
cmd := newConfigListCommand(cli)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list-sort.golden")
}
@ -89,7 +89,7 @@ func TestConfigListWithQuietOption(t *testing.T) {
})
cmd := newConfigListCommand(cli)
cmd.Flags().Set("quiet", "true")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-quiet-option.golden")
}
@ -108,7 +108,7 @@ func TestConfigListWithConfigFormat(t *testing.T) {
ConfigFormat: "{{ .Name }} {{ .Labels }}",
})
cmd := newConfigListCommand(cli)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-config-format.golden")
}
@ -125,15 +125,15 @@ func TestConfigListWithFormat(t *testing.T) {
})
cmd := newConfigListCommand(cli)
cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-format.golden")
}
func TestConfigListWithFilter(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
assert.Check(t, is.Equal("foo", options.Filters.Get("name")[0]))
assert.Check(t, is.Equal("lbl1=Label-bar", options.Filters.Get("label")[0]))
assert.Equal(t, "foo", options.Filters.Get("name")[0])
assert.Equal(t, "lbl1=Label-bar", options.Filters.Get("label")[0])
return []swarm.Config{
*Config(ConfigID("ID-foo"),
ConfigName("foo"),
@ -153,6 +153,6 @@ func TestConfigListWithFilter(t *testing.T) {
cmd := newConfigListCommand(cli)
cmd.Flags().Set("filter", "name=foo")
cmd.Flags().Set("filter", "label=lbl1=Label-bar")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list-with-filter.golden")
}

View File

@ -6,9 +6,9 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/docker/cli/internal/test/testutil"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestConfigRemoveErrors(t *testing.T) {
@ -37,7 +37,7 @@ func TestConfigRemoveErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -52,9 +52,9 @@ func TestConfigRemoveWithName(t *testing.T) {
})
cmd := newConfigRemoveCommand(cli)
cmd.SetArgs(names)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.DeepEqual(names, strings.Split(strings.TrimSpace(cli.OutBuffer().String()), "\n")))
assert.Check(t, is.DeepEqual(names, removedConfigs))
assert.NoError(t, cmd.Execute())
assert.Equal(t, names, strings.Split(strings.TrimSpace(cli.OutBuffer().String()), "\n"))
assert.Equal(t, names, removedConfigs)
}
func TestConfigRemoveContinueAfterError(t *testing.T) {
@ -74,6 +74,6 @@ func TestConfigRemoveContinueAfterError(t *testing.T) {
cmd := newConfigRemoveCommand(cli)
cmd.SetArgs(names)
cmd.SetOutput(ioutil.Discard)
assert.Error(t, cmd.Execute(), "error removing config: foo")
assert.Check(t, is.DeepEqual(names, removedConfigs))
assert.EqualError(t, cmd.Execute(), "error removing config: foo")
assert.Equal(t, names, removedConfigs)
}

View File

@ -1,14 +1,12 @@
package container
import (
"fmt"
"io"
"net/http/httputil"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
@ -68,9 +66,6 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
ctx := context.Background()
client := dockerCli.Client()
// request channel to wait for client
resultC, errC := client.ContainerWait(ctx, opts.container, "")
c, err := inspectContainerAndCheckState(ctx, client, opts.container)
if err != nil {
return err
@ -145,24 +140,7 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
if errAttach != nil {
return errAttach
}
return getExitStatus(errC, resultC)
}
func getExitStatus(errC <-chan error, resultC <-chan container.ContainerWaitOKBody) error {
select {
case result := <-resultC:
if result.Error != nil {
return fmt.Errorf(result.Error.Message)
}
if result.StatusCode != 0 {
return cli.StatusError{StatusCode: int(result.StatusCode)}
}
case err := <-errC:
return err
}
return nil
return getExitStatus(ctx, dockerCli.Client(), opts.container)
}
func resizeTTY(ctx context.Context, dockerCli command.Cli, containerID string) {
@ -179,3 +157,19 @@ func resizeTTY(ctx context.Context, dockerCli command.Cli, containerID string) {
logrus.Debugf("Error monitoring TTY size: %s", err)
}
}
func getExitStatus(ctx context.Context, apiclient client.ContainerAPIClient, containerID string) error {
container, err := apiclient.ContainerInspect(ctx, containerID)
if err != nil {
// If we can't connect, then the daemon probably died.
if !client.IsErrConnectionFailed(err) {
return err
}
return cli.StatusError{StatusCode: -1}
}
status := container.State.ExitCode
if status != 0 {
return cli.StatusError{StatusCode: status}
}
return nil
}

View File

@ -1,16 +1,16 @@
package container
import (
"fmt"
"io/ioutil"
"testing"
"github.com/docker/cli/cli"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
func TestNewAttachCommandErrors(t *testing.T) {
@ -73,57 +73,45 @@ func TestNewAttachCommandErrors(t *testing.T) {
cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestGetExitStatus(t *testing.T) {
var (
expectedErr = fmt.Errorf("unexpected error")
errC = make(chan error, 1)
resultC = make(chan container.ContainerWaitOKBody, 1)
)
containerID := "the exec id"
expecatedErr := errors.New("unexpected error")
testcases := []struct {
result *container.ContainerWaitOKBody
err error
inspectError error
exitCode int
expectedError error
}{
{
result: &container.ContainerWaitOKBody{
StatusCode: 0,
},
inspectError: nil,
exitCode: 0,
},
{
err: expectedErr,
expectedError: expectedErr,
inspectError: expecatedErr,
expectedError: expecatedErr,
},
{
result: &container.ContainerWaitOKBody{
Error: &container.ContainerWaitOKBodyError{expectedErr.Error()},
},
expectedError: expectedErr,
},
{
result: &container.ContainerWaitOKBody{
StatusCode: 15,
},
exitCode: 15,
expectedError: cli.StatusError{StatusCode: 15},
},
}
for _, testcase := range testcases {
if testcase.err != nil {
errC <- testcase.err
}
if testcase.result != nil {
resultC <- *testcase.result
}
err := getExitStatus(errC, resultC)
if testcase.expectedError == nil {
assert.NilError(t, err)
} else {
assert.Error(t, err, testcase.expectedError.Error())
client := &fakeClient{
inspectFunc: func(id string) (types.ContainerJSON, error) {
assert.Equal(t, containerID, id)
return types.ContainerJSON{
ContainerJSONBase: &types.ContainerJSONBase{
State: &types.ContainerState{ExitCode: testcase.exitCode},
},
}, testcase.inspectError
},
}
err := getExitStatus(context.Background(), client, containerID)
assert.Equal(t, testcase.expectedError, err)
}
}

View File

@ -16,24 +16,15 @@ type fakeClient struct {
execInspectFunc func(execID string) (types.ContainerExecInspect, error)
execCreateFunc func(container string, config types.ExecConfig) (types.IDResponse, error)
createContainerFunc func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error)
containerStartFunc func(container string, options types.ContainerStartOptions) error
imageCreateFunc func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
infoFunc func() (types.Info, error)
containerStatPathFunc func(container, path string) (types.ContainerPathStat, error)
containerCopyFromFunc func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
logFunc func(string, types.ContainerLogsOptions) (io.ReadCloser, error)
waitFunc func(string) (<-chan container.ContainerWaitOKBody, <-chan error)
containerListFunc func(types.ContainerListOptions) ([]types.Container, error)
Version string
}
func (f *fakeClient) ContainerList(_ context.Context, options types.ContainerListOptions) ([]types.Container, error) {
if f.containerListFunc != nil {
return f.containerListFunc(options)
}
return []types.Container{}, nil
}
func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) {
if f.inspectFunc != nil {
return f.inspectFunc(containerID)
@ -117,10 +108,3 @@ func (f *fakeClient) ContainerWait(_ context.Context, container string, _ contai
}
return nil, nil
}
func (f *fakeClient) ContainerStart(_ context.Context, container string, options types.ContainerStartOptions) error {
if f.containerStartFunc != nil {
return f.containerStartFunc(container, options)
}
return nil
}

View File

@ -3,18 +3,18 @@ package container
import (
"io"
"io/ioutil"
"os"
"runtime"
"strings"
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/fs"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRunCopyWithInvalidArguments(t *testing.T) {
@ -43,7 +43,7 @@ func TestRunCopyWithInvalidArguments(t *testing.T) {
for _, testcase := range testcases {
t.Run(testcase.doc, func(t *testing.T) {
err := runCopy(test.NewFakeCli(nil), testcase.options)
assert.Error(t, err, testcase.expectedErr)
assert.EqualError(t, err, testcase.expectedErr)
})
}
}
@ -53,16 +53,16 @@ func TestRunCopyFromContainerToStdout(t *testing.T) {
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
assert.Equal(t, "container", container)
return ioutil.NopCloser(strings.NewReader(tarContent)), types.ContainerPathStat{}, nil
},
}
options := copyOptions{source: "container:/path", destination: "-"}
cli := test.NewFakeCli(fakeClient)
err := runCopy(cli, options)
assert.NilError(t, err)
assert.Check(t, is.Equal(tarContent, cli.OutBuffer().String()))
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
require.NoError(t, err)
assert.Equal(t, tarContent, cli.OutBuffer().String())
assert.Equal(t, "", cli.ErrBuffer().String())
}
func TestRunCopyFromContainerToFilesystem(t *testing.T) {
@ -72,7 +72,7 @@ func TestRunCopyFromContainerToFilesystem(t *testing.T) {
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
assert.Equal(t, "container", container)
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
return readCloser, types.ContainerPathStat{}, err
},
@ -80,13 +80,13 @@ func TestRunCopyFromContainerToFilesystem(t *testing.T) {
options := copyOptions{source: "container:/path", destination: destDir.Path()}
cli := test.NewFakeCli(fakeClient)
err := runCopy(cli, options)
assert.NilError(t, err)
assert.Check(t, is.Equal("", cli.OutBuffer().String()))
assert.Check(t, is.Equal("", cli.ErrBuffer().String()))
require.NoError(t, err)
assert.Equal(t, "", cli.OutBuffer().String())
assert.Equal(t, "", cli.ErrBuffer().String())
content, err := ioutil.ReadFile(destDir.Join("file1"))
assert.NilError(t, err)
assert.Check(t, is.Equal("content\n", string(content)))
require.NoError(t, err)
assert.Equal(t, "content\n", string(content))
}
func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.T) {
@ -96,7 +96,7 @@ func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.
fakeClient := &fakeClient{
containerCopyFromFunc: func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
assert.Check(t, is.Equal("container", container))
assert.Equal(t, "container", container)
readCloser, err := archive.TarWithOptions(destDir.Path(), &archive.TarOptions{})
return readCloser, types.ContainerPathStat{}, err
},
@ -108,39 +108,7 @@ func TestRunCopyFromContainerToFilesystemMissingDestinationDirectory(t *testing.
}
cli := test.NewFakeCli(fakeClient)
err := runCopy(cli, options)
assert.ErrorContains(t, err, destDir.Join("missing"))
}
func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
srcFile := fs.NewFile(t, t.Name())
defer srcFile.Remove()
options := copyOptions{
source: srcFile.Path() + string(os.PathSeparator),
destination: "container:/path",
}
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(cli, options)
expectedError := "not a directory"
if runtime.GOOS == "windows" {
expectedError = "The filename, directory name, or volume label syntax is incorrect"
}
assert.ErrorContains(t, err, expectedError)
}
func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) {
options := copyOptions{
source: "/does/not/exist",
destination: "container:/path",
}
cli := test.NewFakeCli(&fakeClient{})
err := runCopy(cli, options)
expected := "no such file or directory"
if runtime.GOOS == "windows" {
expected = "cannot find the file specified"
}
assert.ErrorContains(t, err, expected)
testutil.ErrorContains(t, err, destDir.Join("missing"))
}
func TestSplitCpArg(t *testing.T) {
@ -185,8 +153,8 @@ func TestSplitCpArg(t *testing.T) {
skip.IfCondition(t, testcase.os != "" && testcase.os != runtime.GOOS)
container, path := splitCpArg(testcase.path)
assert.Check(t, is.Equal(testcase.expectedContainer, container))
assert.Check(t, is.Equal(testcase.expectedPath, path))
assert.Equal(t, testcase.expectedContainer, container)
assert.Equal(t, testcase.expectedPath, path)
})
}
}

View File

@ -21,9 +21,8 @@ import (
)
type createOptions struct {
name string
platform string
untrusted bool
name string
platform string
}
// NewCreateCommand creates a new cobra.Command for `docker create`
@ -54,7 +53,7 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
flags.Bool("help", false, "Print usage")
command.AddPlatformFlag(flags, &opts.platform)
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
command.AddTrustVerificationFlags(flags)
copts = addFlags(flags)
return cmd
}
@ -65,7 +64,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *createOptions,
reportError(dockerCli.Err(), "create", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts)
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts.name, opts.platform)
if err != nil {
return err
}
@ -159,7 +158,7 @@ func newCIDFile(path string) (*cidFile, error) {
return &cidFile{path: path, file: f}, nil
}
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, opts *createOptions) (*container.ContainerCreateCreatedBody, error) {
func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, name string, platform string) (*container.ContainerCreateCreatedBody, error) {
config := containerConfig.Config
hostConfig := containerConfig.HostConfig
networkingConfig := containerConfig.NetworkingConfig
@ -183,7 +182,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
if named, ok := ref.(reference.Named); ok {
namedRef = reference.TagNameOnly(named)
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && !opts.untrusted {
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && command.IsTrusted() {
var err error
trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil)
if err != nil {
@ -194,7 +193,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
}
//create the container
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
//if image not found try to pull it
if err != nil {
@ -202,7 +201,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", reference.FamiliarString(namedRef))
// we don't want to write to stdout anything apart from container.ID
if err := pullImage(ctx, dockerCli, config.Image, opts.platform, stderr); err != nil {
if err := pullImage(ctx, dockerCli, config.Image, platform, stderr); err != nil {
return nil, err
}
if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil {
@ -212,7 +211,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig
}
// Retry
var retryErr error
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, opts.name)
response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
if retryErr != nil {
return nil, retryErr
}

View File

@ -2,7 +2,6 @@ package container
import (
"context"
"fmt"
"io"
"io/ioutil"
"os"
@ -11,24 +10,23 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/google/go-cmp/cmp"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/fs"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCIDFileNoOPWithNoFilename(t *testing.T) {
file, err := newCIDFile("")
assert.NilError(t, err)
assert.DeepEqual(t, &cidFile{}, file, cmp.AllowUnexported(cidFile{}))
require.NoError(t, err)
assert.Equal(t, &cidFile{}, file)
assert.NilError(t, file.Write("id"))
assert.NilError(t, file.Close())
assert.NoError(t, file.Write("id"))
assert.NoError(t, file.Close())
}
func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) {
@ -36,7 +34,7 @@ func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) {
defer tempfile.Remove()
_, err := newCIDFile(tempfile.Path())
assert.ErrorContains(t, err, "Container ID file found")
testutil.ErrorContains(t, err, "Container ID file found")
}
func TestCIDFileCloseWithNoWrite(t *testing.T) {
@ -45,12 +43,12 @@ func TestCIDFileCloseWithNoWrite(t *testing.T) {
path := tempdir.Join("cidfile")
file, err := newCIDFile(path)
assert.NilError(t, err)
assert.Check(t, is.Equal(file.path, path))
require.NoError(t, err)
assert.Equal(t, file.path, path)
assert.NilError(t, file.Close())
assert.NoError(t, file.Close())
_, err = os.Stat(path)
assert.Check(t, os.IsNotExist(err))
assert.True(t, os.IsNotExist(err))
}
func TestCIDFileCloseWithWrite(t *testing.T) {
@ -59,18 +57,18 @@ func TestCIDFileCloseWithWrite(t *testing.T) {
path := tempdir.Join("cidfile")
file, err := newCIDFile(path)
assert.NilError(t, err)
require.NoError(t, err)
content := "id"
assert.NilError(t, file.Write(content))
assert.NoError(t, file.Write(content))
actual, err := ioutil.ReadFile(path)
assert.NilError(t, err)
assert.Check(t, is.Equal(content, string(actual)))
require.NoError(t, err)
assert.Equal(t, content, string(actual))
assert.NilError(t, file.Close())
assert.NoError(t, file.Close())
_, err = os.Stat(path)
assert.NilError(t, err)
require.NoError(t, err)
}
func TestCreateContainerPullsImageIfMissing(t *testing.T) {
@ -109,61 +107,12 @@ func TestCreateContainerPullsImageIfMissing(t *testing.T) {
},
HostConfig: &container.HostConfig{},
}
body, err := createContainer(context.Background(), cli, config, &createOptions{
name: "name",
platform: runtime.GOOS,
untrusted: true,
})
assert.NilError(t, err)
body, err := createContainer(context.Background(), cli, config, "name", runtime.GOOS)
require.NoError(t, err)
expected := container.ContainerCreateCreatedBody{ID: containerID}
assert.Check(t, is.DeepEqual(expected, *body))
assert.Equal(t, expected, *body)
stderr := cli.ErrBuffer().String()
assert.Check(t, is.Contains(stderr, "Unable to find image 'does-not-exist-locally:latest' locally"))
}
func TestNewCreateCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
hostConfig *container.HostConfig,
networkingConfig *network.NetworkingConfig,
containerName string,
) (container.ContainerCreateCreatedBody, error) {
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
},
}, test.EnableContentTrust)
cli.SetNotaryClient(tc.notaryFunc)
cmd := NewCreateCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)
}
assert.Contains(t, stderr, "Unable to find image 'does-not-exist-locally:latest' locally")
}
type fakeNotFound struct{}

View File

@ -7,11 +7,11 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
@ -106,7 +106,7 @@ func TestParseExec(t *testing.T) {
for _, testcase := range testcases {
execConfig := parseExec(testcase.options, &testcase.configFile)
assert.Check(t, is.DeepEqual(testcase.expected, *execConfig))
assert.Equal(t, testcase.expected, *execConfig)
}
}
@ -150,14 +150,14 @@ func TestRunExec(t *testing.T) {
err := runExec(cli, testcase.options)
if testcase.expectedError != "" {
assert.ErrorContains(t, err, testcase.expectedError)
testutil.ErrorContains(t, err, testcase.expectedError)
} else {
if !assert.Check(t, err) {
if !assert.NoError(t, err) {
return
}
}
assert.Check(t, is.Equal(testcase.expectedOut, cli.OutBuffer().String()))
assert.Check(t, is.Equal(testcase.expectedErr, cli.ErrBuffer().String()))
assert.Equal(t, testcase.expectedOut, cli.OutBuffer().String())
assert.Equal(t, testcase.expectedErr, cli.ErrBuffer().String())
})
}
}
@ -192,12 +192,12 @@ func TestGetExecExitStatus(t *testing.T) {
for _, testcase := range testcases {
client := &fakeClient{
execInspectFunc: func(id string) (types.ContainerExecInspect, error) {
assert.Check(t, is.Equal(execID, id))
assert.Equal(t, execID, id)
return types.ContainerExecInspect{ExitCode: testcase.exitCode}, testcase.inspectError
},
}
err := getExecExitStatus(context.Background(), client, execID)
assert.Check(t, is.Equal(testcase.expectedError, err))
assert.Equal(t, testcase.expectedError, err)
}
}
@ -222,6 +222,6 @@ func TestNewExecCommandErrors(t *testing.T) {
cmd := NewExecCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -1,164 +0,0 @@
package container
import (
"fmt"
"io/ioutil"
"testing"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/golden"
)
func TestContainerListErrors(t *testing.T) {
testCases := []struct {
args []string
flags map[string]string
containerListFunc func(types.ContainerListOptions) ([]types.Container, error)
expectedError string
}{
{
flags: map[string]string{
"format": "{{invalid}}",
},
expectedError: `function "invalid" not defined`,
},
{
flags: map[string]string{
"format": "{{join}}",
},
expectedError: `wrong number of args for join`,
},
{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return nil, fmt.Errorf("error listing containers")
},
expectedError: "error listing containers",
},
}
for _, tc := range testCases {
cmd := newListCommand(
test.NewFakeCli(&fakeClient{
containerListFunc: tc.containerListFunc,
}),
)
cmd.SetArgs(tc.args)
for key, value := range tc.flags {
cmd.Flags().Set(key, value)
}
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestContainerListWithoutFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1"),
*Container("c2", WithName("foo")),
*Container("c3", WithPort(80, 80, TCP), WithPort(81, 81, TCP), WithPort(82, 82, TCP)),
*Container("c4", WithPort(81, 81, UDP)),
*Container("c5", WithPort(82, 82, IP("8.8.8.8"), TCP)),
}, nil
},
})
cmd := newListCommand(cli)
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format.golden")
}
func TestContainerListNoTrunc(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1"),
*Container("c2", WithName("foo/bar")),
}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("no-trunc", "true")
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-without-format-no-trunc.golden")
}
// Test for GitHub issue docker/docker#21772
func TestContainerListNamesMultipleTime(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1"),
*Container("c2", WithName("foo/bar")),
}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", "{{.Names}} {{.Names}}")
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-name-name.golden")
}
// Test for GitHub issue docker/docker#30291
func TestContainerListFormatTemplateWithArg(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1", WithLabel("some.label", "value")),
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", `{{.Names}} {{.Label "some.label"}}`)
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-format-with-arg.golden")
}
func TestContainerListFormatSizeSetsOption(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(options types.ContainerListOptions) ([]types.Container, error) {
assert.Check(t, options.Size)
return []types.Container{}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", `{{.Size}}`)
assert.NilError(t, cmd.Execute())
}
func TestContainerListWithConfigFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1", WithLabel("some.label", "value")),
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
}, nil
},
})
cli.SetConfigFile(&configfile.ConfigFile{
PsFormat: "{{ .Names }} {{ .Image }} {{ .Labels }}",
})
cmd := newListCommand(cli)
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-config-format.golden")
}
func TestContainerListWithFormat(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
containerListFunc: func(_ types.ContainerListOptions) ([]types.Container, error) {
return []types.Container{
*Container("c1", WithLabel("some.label", "value")),
*Container("c2", WithName("foo/bar"), WithLabel("foo", "bar")),
}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", "{{ .Names }} {{ .Image }} {{ .Labels }}")
assert.NilError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "container-list-with-format.golden")
}

View File

@ -7,10 +7,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
var logFn = func(expectedOut string) func(string, types.ContainerLogsOptions) (io.ReadCloser, error) {
@ -49,14 +49,14 @@ func TestRunLogs(t *testing.T) {
err := runLogs(cli, testcase.options)
if testcase.expectedError != "" {
assert.ErrorContains(t, err, testcase.expectedError)
testutil.ErrorContains(t, err, testcase.expectedError)
} else {
if !assert.Check(t, err) {
if !assert.NoError(t, err) {
return
}
}
assert.Check(t, is.Equal(testcase.expectedOut, cli.OutBuffer().String()))
assert.Check(t, is.Equal(testcase.expectedErr, cli.ErrBuffer().String()))
assert.Equal(t, testcase.expectedOut, cli.OutBuffer().String())
assert.Equal(t, testcase.expectedErr, cli.ErrBuffer().String())
})
}
}

View File

@ -145,7 +145,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
expose: opts.NewListOpts(nil),
extraHosts: opts.NewListOpts(opts.ValidateExtraHost),
groupAdd: opts.NewListOpts(nil),
labels: opts.NewListOpts(nil),
labels: opts.NewListOpts(opts.ValidateEnv),
labelsFile: opts.NewListOpts(nil),
linkLocalIPs: opts.NewListOpts(nil),
links: opts.NewListOpts(opts.ValidateLink),
@ -410,7 +410,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
}
// collect all the environment variables for the container
envVariables, err := opts.ReadKVEnvStrings(copts.envFile.GetAll(), copts.env.GetAll())
envVariables, err := opts.ReadKVStrings(copts.envFile.GetAll(), copts.env.GetAll())
if err != nil {
return nil, err
}

View File

@ -9,13 +9,14 @@ import (
"testing"
"time"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types/container"
networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestValidateAttach(t *testing.T) {
@ -66,12 +67,12 @@ func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
func parseMustError(t *testing.T, args string) {
_, _, _, err := parseRun(strings.Split(args+" ubuntu bash", " "))
assert.ErrorContains(t, err, "", args)
assert.Error(t, err, args)
}
func mustParse(t *testing.T, args string) (*container.Config, *container.HostConfig) {
config, hostConfig, _, err := parseRun(append(strings.Split(args, " "), "ubuntu", "bash"))
assert.NilError(t, err)
assert.NoError(t, err)
return config, hostConfig
}
@ -235,23 +236,23 @@ func TestRunFlagsParseWithMemory(t *testing.T) {
flags, _ := setupRunFlags()
args := []string{"--memory=invalid", "img", "cmd"}
err := flags.Parse(args)
assert.ErrorContains(t, err, `invalid argument "invalid" for "-m, --memory" flag`)
testutil.ErrorContains(t, err, `invalid argument "invalid" for "-m, --memory" flag`)
_, hostconfig := mustParse(t, "--memory=1G")
assert.Check(t, is.Equal(int64(1073741824), hostconfig.Memory))
assert.Equal(t, int64(1073741824), hostconfig.Memory)
}
func TestParseWithMemorySwap(t *testing.T) {
flags, _ := setupRunFlags()
args := []string{"--memory-swap=invalid", "img", "cmd"}
err := flags.Parse(args)
assert.ErrorContains(t, err, `invalid argument "invalid" for "--memory-swap" flag`)
testutil.ErrorContains(t, err, `invalid argument "invalid" for "--memory-swap" flag`)
_, hostconfig := mustParse(t, "--memory-swap=1G")
assert.Check(t, is.Equal(int64(1073741824), hostconfig.MemorySwap))
assert.Equal(t, int64(1073741824), hostconfig.MemorySwap)
_, hostconfig = mustParse(t, "--memory-swap=-1")
assert.Check(t, is.Equal(int64(-1), hostconfig.MemorySwap))
assert.Equal(t, int64(-1), hostconfig.MemorySwap)
}
func TestParseHostname(t *testing.T) {
@ -372,24 +373,24 @@ func TestParseModes(t *testing.T) {
// pid ko
flags, copts := setupRunFlags()
args := []string{"--pid=container:", "img", "cmd"}
assert.NilError(t, flags.Parse(args))
require.NoError(t, flags.Parse(args))
_, err := parse(flags, copts)
assert.ErrorContains(t, err, "--pid: invalid PID mode")
testutil.ErrorContains(t, err, "--pid: invalid PID mode")
// pid ok
_, hostconfig, _, err := parseRun([]string{"--pid=host", "img", "cmd"})
assert.NilError(t, err)
require.NoError(t, err)
if !hostconfig.PidMode.Valid() {
t.Fatalf("Expected a valid PidMode, got %v", hostconfig.PidMode)
}
// uts ko
_, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"})
assert.ErrorContains(t, err, "--uts: invalid UTS mode")
testutil.ErrorContains(t, err, "--uts: invalid UTS mode")
// uts ok
_, hostconfig, _, err = parseRun([]string{"--uts=host", "img", "cmd"})
assert.NilError(t, err)
require.NoError(t, err)
if !hostconfig.UTSMode.Valid() {
t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode)
}
@ -401,11 +402,11 @@ func TestRunFlagsParseShmSize(t *testing.T) {
args := []string{"--shm-size=a128m", "img", "cmd"}
expectedErr := `invalid argument "a128m" for "--shm-size" flag: invalid size: 'a128m'`
err := flags.Parse(args)
assert.ErrorContains(t, err, expectedErr)
testutil.ErrorContains(t, err, expectedErr)
// shm-size ok
_, hostconfig, _, err := parseRun([]string{"--shm-size=128m", "img", "cmd"})
assert.NilError(t, err)
require.NoError(t, err)
if hostconfig.ShmSize != 134217728 {
t.Fatalf("Expected a valid ShmSize, got %d", hostconfig.ShmSize)
}

View File

@ -4,14 +4,13 @@ import (
"testing"
"github.com/docker/cli/opts"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestBuildContainerListOptions(t *testing.T) {
filters := opts.NewFilterOpt()
assert.NilError(t, filters.Set("foo=bar"))
assert.NilError(t, filters.Set("baz=foo"))
assert.NoError(t, filters.Set("foo=bar"))
assert.NoError(t, filters.Set("baz=foo"))
contexts := []struct {
psOpts *psOptions
@ -102,12 +101,12 @@ func TestBuildContainerListOptions(t *testing.T) {
for _, c := range contexts {
options, err := buildContainerListOptions(c.psOpts)
assert.NilError(t, err)
assert.NoError(t, err)
assert.Check(t, is.Equal(c.expectedAll, options.All))
assert.Check(t, is.Equal(c.expectedSize, options.Size))
assert.Check(t, is.Equal(c.expectedLimit, options.Limit))
assert.Check(t, is.Equal(len(c.expectedFilters), options.Filters.Len()))
assert.Equal(t, c.expectedAll, options.All)
assert.Equal(t, c.expectedSize, options.Size)
assert.Equal(t, c.expectedLimit, options.Limit)
assert.Equal(t, len(c.expectedFilters), options.Filters.Len())
for k, v := range c.expectedFilters {
f := options.Filters

View File

@ -25,10 +25,11 @@ import (
)
type runOptions struct {
createOptions
detach bool
sigProxy bool
name string
detachKeys string
platform string
}
// NewRunCommand create a new `docker run` command
@ -63,7 +64,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
flags.Bool("help", false, "Print usage")
command.AddPlatformFlag(flags, &opts.platform)
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
command.AddTrustVerificationFlags(flags)
copts = addFlags(flags)
return cmd
}
@ -161,7 +162,7 @@ func runContainer(dockerCli command.Cli, opts *runOptions, copts *containerOptio
ctx, cancelFun := context.WithCancel(context.Background())
createResponse, err := createContainer(ctx, dockerCli, containerConfig, &opts.createOptions)
createResponse, err := createContainer(ctx, dockerCli, containerConfig, opts.name, opts.platform)
if err != nil {
reportError(stderr, cmdPath, err.Error(), true)
return runStartContainerErr(err)

View File

@ -1,73 +0,0 @@
package container
import (
"fmt"
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
)
func TestRunLabel(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
createContainerFunc: func(_ *container.Config, _ *container.HostConfig, _ *network.NetworkingConfig, _ string) (container.ContainerCreateCreatedBody, error) {
return container.ContainerCreateCreatedBody{
ID: "id",
}, nil
},
Version: "1.36",
})
cmd := NewRunCommand(cli)
cmd.Flags().Set("detach", "true")
cmd.SetArgs([]string{"--label", "foo", "busybox"})
assert.NilError(t, cmd.Execute())
}
func TestRunCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{
createContainerFunc: func(config *container.Config,
hostConfig *container.HostConfig,
networkingConfig *network.NetworkingConfig,
containerName string,
) (container.ContainerCreateCreatedBody, error) {
return container.ContainerCreateCreatedBody{}, fmt.Errorf("shouldn't try to pull image")
},
}, test.EnableContentTrust)
cli.SetNotaryClient(tc.notaryFunc)
cmd := NewRunCommand(cli)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.Assert(t, err != nil)
assert.Assert(t, is.Contains(cli.ErrBuffer().String(), tc.expectedError))
}
}

View File

@ -1,11 +1,10 @@
package container
import (
"fmt"
"testing"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/stretchr/testify/assert"
)
func TestCalculateMemUsageUnixNoCache(t *testing.T) {
@ -16,7 +15,7 @@ func TestCalculateMemUsageUnixNoCache(t *testing.T) {
result := calculateMemUsageUnixNoCache(stats)
// Then
assert.Assert(t, inDelta(100.0, result, 1e-6))
assert.InDelta(t, 100.0, result, 1e-6)
}
func TestCalculateMemPercentUnixNoCache(t *testing.T) {
@ -28,20 +27,10 @@ func TestCalculateMemPercentUnixNoCache(t *testing.T) {
// When and Then
t.Run("Limit is set", func(t *testing.T) {
result := calculateMemPercentUnixNoCache(someLimit, used)
assert.Assert(t, inDelta(70.0, result, 1e-6))
assert.InDelta(t, 70.0, result, 1e-6)
})
t.Run("No limit, no cgroup data", func(t *testing.T) {
result := calculateMemPercentUnixNoCache(noLimit, used)
assert.Assert(t, inDelta(0.0, result, 1e-6))
assert.InDelta(t, 0.0, result, 1e-6)
})
}
func inDelta(x, y, delta float64) func() (bool, string) {
return func() (bool, string) {
diff := x - y
if diff < -delta || diff > delta {
return false, fmt.Sprintf("%f != %f within %f", x, y, delta)
}
return true, ""
}
}

View File

@ -1,2 +0,0 @@
c1 busybox:latest some.label=value
c2 busybox:latest foo=bar

View File

@ -1,2 +0,0 @@
c1 busybox:latest some.label=value
c2 busybox:latest foo=bar

View File

@ -1,3 +0,0 @@
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
container_id busybox:latest "top" Less than a second ago Up 1 second c1
container_id busybox:latest "top" Less than a second ago Up 1 second c2,foo/bar

View File

@ -1,6 +0,0 @@
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
container_id busybox:latest "top" Less than a second ago Up 1 second c1
container_id busybox:latest "top" Less than a second ago Up 1 second c2
container_id busybox:latest "top" Less than a second ago Up 1 second 80-82/tcp c3
container_id busybox:latest "top" Less than a second ago Up 1 second 81/udp c4
container_id busybox:latest "top" Less than a second ago Up 1 second 8.8.8.8:82->82/tcp c5

View File

@ -7,9 +7,8 @@ import (
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types/container"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
@ -65,6 +64,6 @@ func TestWaitExitOrRemoved(t *testing.T) {
for _, testcase := range testcases {
statusC := waitExitOrRemoved(context.Background(), client, testcase.cid, true)
exitCode := <-statusC
assert.Check(t, is.Equal(testcase.exitCode, exitCode))
assert.Equal(t, testcase.exitCode, exitCode)
}
}

View File

@ -5,7 +5,7 @@ import (
"testing"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/stretchr/testify/assert"
)
func TestCheckpointContextFormatWrite(t *testing.T) {
@ -46,7 +46,10 @@ checkpoint-3:
out := bytes.NewBufferString("")
testcase.context.Output = out
err := CheckpointWrite(testcase.context, checkpoints)
assert.NilError(t, err)
assert.Equal(t, out.String(), testcase.expected)
if err != nil {
assert.Error(t, err, testcase.expected)
} else {
assert.Equal(t, out.String(), testcase.expected)
}
}
}

View File

@ -6,8 +6,7 @@ import (
"time"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestConfigContextFormatWrite(t *testing.T) {
@ -56,9 +55,9 @@ id_rsa
out := bytes.NewBufferString("")
testcase.context.Output = out
if err := ConfigWrite(testcase.context, configs); err != nil {
assert.ErrorContains(t, err, testcase.expected)
assert.Error(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(out.String(), testcase.expected))
assert.Equal(t, out.String(), testcase.expected)
}
}
}

View File

@ -10,9 +10,9 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestContainerPsContext(t *testing.T) {
@ -244,9 +244,9 @@ size: 0B
testcase.context.Output = out
err := ContainerWrite(testcase.context, containers)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -305,7 +305,7 @@ func TestContainerContextWriteWithNoContainers(t *testing.T) {
for _, context := range contexts {
ContainerWrite(context.context, containers)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}
@ -359,8 +359,8 @@ func TestContainerContextWriteJSON(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var m map[string]interface{}
err := json.Unmarshal([]byte(line), &m)
assert.NilError(t, err, msg)
assert.Check(t, is.DeepEqual(expectedJSONs[i], m), msg)
require.NoError(t, err, msg)
assert.Equal(t, expectedJSONs[i], m, msg)
}
}
@ -378,8 +378,8 @@ func TestContainerContextWriteJSONField(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var s string
err := json.Unmarshal([]byte(line), &s)
assert.NilError(t, err, msg)
assert.Check(t, is.Equal(containers[i].ID, s), msg)
require.NoError(t, err, msg)
assert.Equal(t, containers[i].ID, s, msg)
}
}
@ -642,17 +642,14 @@ func TestDisplayablePorts(t *testing.T) {
PublicPort: 1024,
PrivatePort: 80,
Type: "udp",
}, {
PrivatePort: 12345,
Type: "sctp",
},
},
"80/tcp, 80/udp, 1024/tcp, 1024/udp, 12345/sctp, 1.1.1.1:1024->80/tcp, 1.1.1.1:1024->80/udp, 2.1.1.1:1024->80/tcp, 2.1.1.1:1024->80/udp, 1.1.1.1:80->1024/tcp, 1.1.1.1:80->1024/udp, 2.1.1.1:80->1024/tcp, 2.1.1.1:80->1024/udp",
"80/tcp, 80/udp, 1024/tcp, 1024/udp, 1.1.1.1:1024->80/tcp, 1.1.1.1:1024->80/udp, 2.1.1.1:1024->80/tcp, 2.1.1.1:1024->80/udp, 1.1.1.1:80->1024/tcp, 1.1.1.1:80->1024/udp, 2.1.1.1:80->1024/tcp, 2.1.1.1:80->1024/udp",
},
}
for _, port := range cases {
actual := DisplayablePorts(port.ports)
assert.Check(t, is.Equal(port.expected, actual))
assert.Equal(t, port.expected, actual)
}
}

View File

@ -4,8 +4,7 @@ import (
"strings"
"testing"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func compareMultipleValues(t *testing.T, value, expected string) {
@ -24,5 +23,5 @@ func compareMultipleValues(t *testing.T, value, expected string) {
keyval := strings.Split(expected, "=")
expMap[keyval[0]] = keyval[1]
}
assert.Check(t, is.DeepEqual(expMap, entriesMap))
assert.Equal(t, expMap, entriesMap)
}

View File

@ -6,8 +6,7 @@ import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestDiffContextFormatWrite(t *testing.T) {
@ -52,9 +51,9 @@ D: /usr/app/old_app.js
testcase.context.Output = out
err := DiffWrite(testcase.context, diffs)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}

View File

@ -4,9 +4,8 @@ import (
"bytes"
"testing"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestDiskUsageContextFormatWrite(t *testing.T) {
@ -102,9 +101,9 @@ Build Cache 0B
out := bytes.NewBufferString("")
testcase.context.Output = out
if err := testcase.context.Write(); err != nil {
assert.Check(t, is.Equal(testcase.expected, err.Error()))
assert.Equal(t, testcase.expected, err.Error())
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}

View File

@ -3,8 +3,7 @@ package formatter
import (
"testing"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestEllipsis(t *testing.T) {
@ -26,6 +25,6 @@ func TestEllipsis(t *testing.T) {
}
for _, testcase := range testcases {
assert.Check(t, is.Equal(testcase.expected, Ellipsis(testcase.source, testcase.width)))
assert.Equal(t, testcase.expected, Ellipsis(testcase.source, testcase.width))
}
}

View File

@ -1,16 +1,16 @@
package formatter
import (
"bytes"
"strconv"
"strings"
"testing"
"time"
"bytes"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
type historyCase struct {
@ -50,7 +50,6 @@ func TestHistoryContext_ID(t *testing.T) {
}
func TestHistoryContext_CreatedSince(t *testing.T) {
dateStr := "2009-11-10T23:00:00Z"
var ctx historyContext
cases := []historyCase{
{
@ -65,7 +64,7 @@ func TestHistoryContext_CreatedSince(t *testing.T) {
h: image.HistoryResponseItem{Created: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()},
trunc: false,
human: false,
}, dateStr, ctx.CreatedSince,
}, "2009-11-10T23:00:00Z", ctx.CreatedSince,
},
}
@ -219,7 +218,7 @@ imageID4 24 hours ago /bin/bash grep
for _, context := range contexts {
HistoryWrite(context.context, true, histories)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}

View File

@ -9,8 +9,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestImageContext(t *testing.T) {
@ -84,7 +83,7 @@ func TestImageContext(t *testing.T) {
if strings.Contains(v, ",") {
compareMultipleValues(t, v, c.expValue)
} else {
assert.Check(t, is.Equal(c.expValue, v))
assert.Equal(t, c.expValue, v)
}
}
}
@ -294,9 +293,9 @@ image_id: imageID3
testcase.context.Output = out
err := ImageWrite(testcase.context, images)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -349,7 +348,7 @@ func TestImageContextWriteWithNoImage(t *testing.T) {
for _, context := range contexts {
ImageWrite(context.context, images)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}

View File

@ -10,8 +10,8 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNetworkContext(t *testing.T) {
@ -162,9 +162,9 @@ foobar_bar 2017-01-01 00:00:00 +0000 UTC
testcase.context.Output = out
err := NetworkWrite(testcase.context, networks)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -188,8 +188,8 @@ func TestNetworkContextWriteJSON(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var m map[string]interface{}
err := json.Unmarshal([]byte(line), &m)
assert.NilError(t, err, msg)
assert.Check(t, is.DeepEqual(expectedJSONs[i], m), msg)
require.NoError(t, err, msg)
assert.Equal(t, expectedJSONs[i], m, msg)
}
}
@ -207,7 +207,7 @@ func TestNetworkContextWriteJSONField(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var s string
err := json.Unmarshal([]byte(line), &s)
assert.NilError(t, err, msg)
assert.Check(t, is.Equal(networks[i].ID, s), msg)
require.NoError(t, err, msg)
assert.Equal(t, networks[i].ID, s, msg)
}
}

View File

@ -14,7 +14,7 @@ import (
)
const (
defaultNodeTableFormat = "table {{.ID}} {{if .Self}}*{{else}} {{ end }}\t{{.Hostname}}\t{{.Status}}\t{{.Availability}}\t{{.ManagerStatus}}\t{{.EngineVersion}}"
defaultNodeTableFormat = "table {{.ID}} {{if .Self}}*{{else}} {{ end }}\t{{.Hostname}}\t{{.Status}}\t{{.Availability}}\t{{.ManagerStatus}}"
nodeInspectPrettyTemplate Format = `ID: {{.ID}}
{{- if .Name }}
Name: {{.Name}}
@ -75,7 +75,6 @@ TLS Info:
hostnameHeader = "HOSTNAME"
availabilityHeader = "AVAILABILITY"
managerStatusHeader = "MANAGER STATUS"
engineVersionHeader = "ENGINE VERSION"
tlsStatusHeader = "TLS STATUS"
)
@ -116,7 +115,6 @@ func NodeWrite(ctx Context, nodes []swarm.Node, info types.Info) error {
"Status": statusHeader,
"Availability": availabilityHeader,
"ManagerStatus": managerStatusHeader,
"EngineVersion": engineVersionHeader,
"TLSStatus": tlsStatusHeader,
}
nodeCtx := nodeContext{}
@ -178,10 +176,6 @@ func (c *nodeContext) TLSStatus() string {
return "Needs Rotation"
}
func (c *nodeContext) EngineVersion() string {
return c.n.Description.Engine.EngineVersion
}
// NodeInspectWrite renders the context for a list of nodes
func NodeInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error {
if ctx.Format != nodeInspectPrettyTemplate {

View File

@ -10,8 +10,8 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNodeContext(t *testing.T) {
@ -74,10 +74,10 @@ func TestNodeContextWrite(t *testing.T) {
// Table format
{
context: Context{Format: NewNodeFormat("table", false)},
expected: `ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
nodeID1 foobar_baz Foo Drain Leader 18.03.0-ce
nodeID2 foobar_bar Bar Active Reachable 1.2.3
nodeID3 foobar_boo Boo Active ` + "\n", // (to preserve whitespace)
expected: `ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
nodeID1 foobar_baz Foo Drain Leader
nodeID2 foobar_bar Bar Active Reachable
nodeID3 foobar_boo Boo Active ` + "\n", // (to preserve whitespace)
clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}},
},
{
@ -172,7 +172,6 @@ foobar_boo Unknown
Description: swarm.NodeDescription{
Hostname: "foobar_baz",
TLSInfo: swarm.TLSInfo{TrustRoot: "no"},
Engine: swarm.EngineDescription{EngineVersion: "18.03.0-ce"},
},
Status: swarm.NodeStatus{State: swarm.NodeState("foo")},
Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("drain")},
@ -183,7 +182,6 @@ foobar_boo Unknown
Description: swarm.NodeDescription{
Hostname: "foobar_bar",
TLSInfo: swarm.TLSInfo{TrustRoot: "hi"},
Engine: swarm.EngineDescription{EngineVersion: "1.2.3"},
},
Status: swarm.NodeStatus{State: swarm.NodeState("bar")},
Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("active")},
@ -203,9 +201,9 @@ foobar_boo Unknown
testcase.context.Output = out
err := NodeWrite(testcase.context, nodes, types.Info{Swarm: swarm.Info{Cluster: &testcase.clusterInfo}})
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -217,17 +215,17 @@ func TestNodeContextWriteJSON(t *testing.T) {
}{
{
expected: []map[string]interface{}{
{"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": "1.2.3"},
{"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": ""},
{"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": "18.03.0-ce"},
{"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"},
{"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"},
{"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"},
},
info: types.Info{},
},
{
expected: []map[string]interface{}{
{"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Ready", "EngineVersion": "1.2.3"},
{"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Needs Rotation", "EngineVersion": ""},
{"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown", "EngineVersion": "18.03.0-ce"},
{"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Ready"},
{"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Needs Rotation"},
{"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"},
},
info: types.Info{
Swarm: swarm.Info{
@ -242,9 +240,9 @@ func TestNodeContextWriteJSON(t *testing.T) {
for _, testcase := range cases {
nodes := []swarm.Node{
{ID: "nodeID1", Description: swarm.NodeDescription{Hostname: "foobar_baz", TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}, Engine: swarm.EngineDescription{EngineVersion: "1.2.3"}}},
{ID: "nodeID1", Description: swarm.NodeDescription{Hostname: "foobar_baz", TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}},
{ID: "nodeID2", Description: swarm.NodeDescription{Hostname: "foobar_bar", TLSInfo: swarm.TLSInfo{TrustRoot: "no"}}},
{ID: "nodeID3", Description: swarm.NodeDescription{Hostname: "foobar_boo", Engine: swarm.EngineDescription{EngineVersion: "18.03.0-ce"}}},
{ID: "nodeID3", Description: swarm.NodeDescription{Hostname: "foobar_boo"}},
}
out := bytes.NewBufferString("")
err := NodeWrite(Context{Format: "{{json .}}", Output: out}, nodes, testcase.info)
@ -255,8 +253,8 @@ func TestNodeContextWriteJSON(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var m map[string]interface{}
err := json.Unmarshal([]byte(line), &m)
assert.NilError(t, err, msg)
assert.Check(t, is.DeepEqual(testcase.expected[i], m), msg)
require.NoError(t, err, msg)
assert.Equal(t, testcase.expected[i], m, msg)
}
}
}
@ -275,8 +273,8 @@ func TestNodeContextWriteJSONField(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var s string
err := json.Unmarshal([]byte(line), &s)
assert.NilError(t, err, msg)
assert.Check(t, is.Equal(nodes[i].ID, s), msg)
require.NoError(t, err, msg)
assert.Equal(t, nodes[i].ID, s, msg)
}
}
@ -344,5 +342,5 @@ data
Issuer Subject: c3ViamVjdA==
Issuer Public Key: cHViS2V5
`
assert.Check(t, is.Equal(expected, out.String()))
assert.Equal(t, expected, out.String())
}

View File

@ -8,8 +8,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestPluginContext(t *testing.T) {
@ -132,9 +131,9 @@ foobar_bar
testcase.context.Output = out
err := PluginWrite(testcase.context, plugins)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -159,7 +158,7 @@ func TestPluginContextWriteJSON(t *testing.T) {
if err := json.Unmarshal([]byte(line), &m); err != nil {
t.Fatal(err)
}
assert.Check(t, is.DeepEqual(expectedJSONs[i], m))
assert.Equal(t, expectedJSONs[i], m)
}
}
@ -178,6 +177,6 @@ func TestPluginContextWriteJSONField(t *testing.T) {
if err := json.Unmarshal([]byte(line), &s); err != nil {
t.Fatal(err)
}
assert.Check(t, is.Equal(plugins[i].ID, s))
assert.Equal(t, plugins[i].ID, s)
}
}

View File

@ -7,9 +7,8 @@ import (
"testing"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestSearchContext(t *testing.T) {
@ -155,9 +154,9 @@ result2 5
testcase.context.Output = out
err := SearchWrite(testcase.context, results, false, 0)
if err != nil {
assert.Check(t, is.ErrorContains(err, testcase.expected))
assert.Error(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(out.String(), testcase.expected))
assert.Equal(t, out.String(), testcase.expected)
}
}
}
@ -192,9 +191,9 @@ result2
testcase.context.Output = out
err := SearchWrite(testcase.context, results, true, 0)
if err != nil {
assert.Check(t, is.ErrorContains(err, testcase.expected))
assert.Error(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(out.String(), testcase.expected))
assert.Equal(t, out.String(), testcase.expected)
}
}
}
@ -227,9 +226,9 @@ result1
testcase.context.Output = out
err := SearchWrite(testcase.context, results, false, 6)
if err != nil {
assert.Check(t, is.ErrorContains(err, testcase.expected))
assert.Error(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(out.String(), testcase.expected))
assert.Equal(t, out.String(), testcase.expected)
}
}
}
@ -255,7 +254,7 @@ func TestSearchContextWriteJSON(t *testing.T) {
if err := json.Unmarshal([]byte(line), &m); err != nil {
t.Fatal(err)
}
assert.Check(t, is.DeepEqual(m, expectedJSONs[i]))
assert.Equal(t, m, expectedJSONs[i])
}
}
@ -275,6 +274,6 @@ func TestSearchContextWriteJSONField(t *testing.T) {
if err := json.Unmarshal([]byte(line), &s); err != nil {
t.Fatal(err)
}
assert.Check(t, is.Equal(s, results[i].Name))
assert.Equal(t, s, results[i].Name)
}
}

View File

@ -6,8 +6,7 @@ import (
"time"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestSecretContextFormatWrite(t *testing.T) {
@ -56,9 +55,9 @@ id_rsa
out := bytes.NewBufferString("")
testcase.context.Output = out
if err := SecretWrite(testcase.context, secrets); err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}

View File

@ -8,9 +8,9 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestServiceContextWrite(t *testing.T) {
@ -126,9 +126,9 @@ bar
testcase.context.Output = out
err := ServiceListWrite(testcase.context, services, info)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -192,8 +192,8 @@ func TestServiceContextWriteJSON(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var m map[string]interface{}
err := json.Unmarshal([]byte(line), &m)
assert.NilError(t, err, msg)
assert.Check(t, is.DeepEqual(expectedJSONs[i], m), msg)
require.NoError(t, err, msg)
assert.Equal(t, expectedJSONs[i], m, msg)
}
}
func TestServiceContextWriteJSONField(t *testing.T) {
@ -220,8 +220,8 @@ func TestServiceContextWriteJSONField(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var s string
err := json.Unmarshal([]byte(line), &s)
assert.NilError(t, err, msg)
assert.Check(t, is.Equal(services[i].Spec.Name, s), msg)
require.NoError(t, err, msg)
assert.Equal(t, services[i].Spec.Name, s, msg)
}
}
@ -338,22 +338,10 @@ func TestServiceContext_Ports(t *testing.T) {
PublishedPort: 62,
PublishMode: "ingress",
},
{
Protocol: "sctp",
TargetPort: 97,
PublishedPort: 97,
PublishMode: "ingress",
},
{
Protocol: "sctp",
TargetPort: 98,
PublishedPort: 98,
PublishMode: "ingress",
},
},
},
},
}
assert.Check(t, is.Equal("*:97-98->97-98/sctp, *:60-61->60-61/tcp, *:62->61/tcp, *:80-81->80/tcp, *:90-95->90-95/tcp, *:90-96->90-96/udp", c.Ports()))
assert.Equal(t, "*:60-61->60-61/tcp, *:62->61/tcp, *:80-81->80/tcp, *:90-95->90-95/tcp, *:90-96->90-96/udp", c.Ports())
}

View File

@ -4,8 +4,7 @@ import (
"bytes"
"testing"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestStackContextWrite(t *testing.T) {
@ -57,9 +56,9 @@ bar
testcase.context.Output = out
err := StackWrite(testcase.context, stacks)
if err != nil {
assert.Check(t, is.ErrorContains(err, testcase.expected))
assert.Error(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(out.String(), testcase.expected))
assert.Equal(t, out.String(), testcase.expected)
}
}
}

View File

@ -5,8 +5,7 @@ import (
"testing"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestContainerStatsContext(t *testing.T) {
@ -117,9 +116,9 @@ container2 --
te.context.Output = &out
err := ContainerStatsWrite(te.context, stats, "linux", false)
if err != nil {
assert.Error(t, err, te.expected)
assert.EqualError(t, err, te.expected)
} else {
assert.Check(t, is.Equal(te.expected, out.String()))
assert.Equal(t, te.expected, out.String())
}
}
}
@ -183,9 +182,9 @@ container2 -- --
te.context.Output = &out
err := ContainerStatsWrite(te.context, stats, "windows", false)
if err != nil {
assert.Error(t, err, te.expected)
assert.EqualError(t, err, te.expected)
} else {
assert.Check(t, is.Equal(te.expected, out.String()))
assert.Equal(t, te.expected, out.String())
}
}
}
@ -222,7 +221,7 @@ func TestContainerStatsContextWriteWithNoStats(t *testing.T) {
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{}, "linux", false)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}
@ -260,7 +259,7 @@ func TestContainerStatsContextWriteWithNoStatsWindows(t *testing.T) {
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{}, "windows", false)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}
@ -294,7 +293,7 @@ func TestContainerStatsContextWriteTrunc(t *testing.T) {
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{{ID: "b95a83497c9161c9b444e3d70e1a9dfba0c1840d41720e146a95a08ebf938afc"}}, "linux", context.trunc)
assert.Check(t, is.Equal(context.expected, out.String()))
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}

View File

@ -7,9 +7,8 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestTaskContextWrite(t *testing.T) {
@ -75,9 +74,9 @@ foobar_bar foo2
testcase.context.Output = out
err := TaskWrite(testcase.context, tasks, names, nodes)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -101,6 +100,6 @@ func TestTaskContextWriteJSONField(t *testing.T) {
if err := json.Unmarshal([]byte(line), &s); err != nil {
t.Fatal(err)
}
assert.Check(t, is.Equal(tasks[i].ID, s))
assert.Equal(t, tasks[i].ID, s)
}
}

View File

@ -5,8 +5,7 @@ import (
"testing"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
)
func TestTrustTag(t *testing.T) {
@ -127,9 +126,9 @@ tag3 bbbbbbbb
testcase.context.Output = out
err := TrustTagWrite(testcase.context, signedTags)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -153,8 +152,8 @@ func TestTrustTagContextEmptyWrite(t *testing.T) {
out := bytes.NewBufferString("")
emptyCase.context.Output = out
err := TrustTagWrite(emptyCase.context, emptySignedTags)
assert.NilError(t, err)
assert.Check(t, is.Equal(emptyCase.expected, out.String()))
assert.NoError(t, err)
assert.Equal(t, emptyCase.expected, out.String())
}
func TestSignerInfoContextEmptyWrite(t *testing.T) {
@ -172,8 +171,8 @@ func TestSignerInfoContextEmptyWrite(t *testing.T) {
out := bytes.NewBufferString("")
emptyCase.context.Output = out
err := SignerInfoWrite(emptyCase.context, emptySignerInfo)
assert.NilError(t, err)
assert.Check(t, is.Equal(emptyCase.expected, out.String()))
assert.NoError(t, err)
assert.Equal(t, emptyCase.expected, out.String())
}
func TestSignerInfoContextWrite(t *testing.T) {
@ -231,9 +230,9 @@ eve foobarbazquxquux, key31, key32
testcase.context.Output = out
err := SignerInfoWrite(testcase.context, signerInfo)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}

View File

@ -9,8 +9,8 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestVolumeContext(t *testing.T) {
@ -133,9 +133,9 @@ foobar_bar
testcase.context.Output = out
err := VolumeWrite(testcase.context, volumes)
if err != nil {
assert.Error(t, err, testcase.expected)
assert.EqualError(t, err, testcase.expected)
} else {
assert.Check(t, is.Equal(testcase.expected, out.String()))
assert.Equal(t, testcase.expected, out.String())
}
}
}
@ -158,8 +158,8 @@ func TestVolumeContextWriteJSON(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var m map[string]interface{}
err := json.Unmarshal([]byte(line), &m)
assert.NilError(t, err, msg)
assert.Check(t, is.DeepEqual(expectedJSONs[i], m), msg)
require.NoError(t, err, msg)
assert.Equal(t, expectedJSONs[i], m, msg)
}
}
@ -177,7 +177,7 @@ func TestVolumeContextWriteJSONField(t *testing.T) {
msg := fmt.Sprintf("Output: line %d: %s", i, line)
var s string
err := json.Unmarshal([]byte(line), &s)
assert.NilError(t, err, msg)
assert.Check(t, is.Equal(volumes[i].Name, s), msg)
require.NoError(t, err, msg)
assert.Equal(t, volumes[i].Name, s, msg)
}
}

View File

@ -4,11 +4,10 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
@ -22,7 +21,7 @@ func TestResolveError(t *testing.T) {
idResolver := New(cli, false)
_, err := idResolver.Resolve(context.Background(), struct{}{}, "nodeID")
assert.Error(t, err, "unsupported type")
assert.EqualError(t, err, "unsupported type")
}
func TestResolveWithNoResolveOption(t *testing.T) {
@ -41,9 +40,9 @@ func TestResolveWithNoResolveOption(t *testing.T) {
idResolver := New(cli, true)
id, err := idResolver.Resolve(context.Background(), swarm.Node{}, "nodeID")
assert.NilError(t, err)
assert.Check(t, is.Equal("nodeID", id))
assert.Check(t, !resolved)
assert.NoError(t, err)
assert.Equal(t, "nodeID", id)
assert.False(t, resolved)
}
func TestResolveWithCache(t *testing.T) {
@ -60,11 +59,11 @@ func TestResolveWithCache(t *testing.T) {
ctx := context.Background()
for i := 0; i < 2; i++ {
id, err := idResolver.Resolve(ctx, swarm.Node{}, "nodeID")
assert.NilError(t, err)
assert.Check(t, is.Equal("node-foo", id))
assert.NoError(t, err)
assert.Equal(t, "node-foo", id)
}
assert.Check(t, is.Equal(1, inspectCounter))
assert.Equal(t, 1, inspectCounter)
}
func TestResolveNode(t *testing.T) {
@ -104,8 +103,8 @@ func TestResolveNode(t *testing.T) {
idResolver := New(cli, false)
id, err := idResolver.Resolve(ctx, swarm.Node{}, tc.nodeID)
assert.NilError(t, err)
assert.Check(t, is.Equal(tc.expectedID, id))
assert.NoError(t, err)
assert.Equal(t, tc.expectedID, id)
}
}
@ -139,7 +138,7 @@ func TestResolveService(t *testing.T) {
idResolver := New(cli, false)
id, err := idResolver.Resolve(ctx, swarm.Service{}, tc.serviceID)
assert.NilError(t, err)
assert.Check(t, is.Equal(tc.expectedID, id))
assert.NoError(t, err)
assert.Equal(t, tc.expectedID, id)
}
}

View File

@ -9,10 +9,8 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -67,7 +65,6 @@ type buildOptions struct {
imageIDFile string
stream bool
platform string
untrusted bool
}
// dockerfileFromStdin returns true when the user specified that the Dockerfile
@ -138,7 +135,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVar(&options.target, "target", "", "Set the target build stage to build.")
flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file")
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
command.AddTrustVerificationFlags(flags)
command.AddPlatformFlag(flags, &options.platform)
flags.BoolVar(&options.squash, "squash", false, "Squash newly built layers into a single new layer")
@ -209,14 +206,6 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
buildCtx, relDockerfile, err = build.GetContextFromReader(dockerCli.In(), options.dockerfileName)
case isLocalDir(specifiedContext):
contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, options.dockerfileName)
if err == nil && strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
// Dockerfile is outside of build-context; read the Dockerfile and pass it as dockerfileCtx
dockerfileCtx, err = os.Open(options.dockerfileName)
if err != nil {
return errors.Errorf("unable to open Dockerfile: %v", err)
}
defer dockerfileCtx.Close()
}
case urlutil.IsGitURL(specifiedContext):
tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, options.dockerfileName)
case urlutil.IsURL(specifiedContext):
@ -264,7 +253,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
}
}
// replace Dockerfile if it was added from stdin or a file outside the build-context, and there is archive context
// replace Dockerfile if it was added from stdin and there is archive context
if dockerfileCtx != nil && buildCtx != nil {
buildCtx, relDockerfile, err = build.AddDockerfileToBuildContext(dockerfileCtx, buildCtx)
if err != nil {
@ -272,7 +261,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
}
}
// if streaming and Dockerfile was not from stdin then read from file
// if streaming and dockerfile was not from stdin then read from file
// to the same reader that is usually stdin
if options.stream && dockerfileCtx == nil {
dockerfileCtx, err = os.Open(relDockerfile)
@ -286,7 +275,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
defer cancel()
var resolvedTags []*resolvedTag
if !options.untrusted {
if command.IsTrusted() {
translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
return TrustedReference(ctx, dockerCli, ref, nil)
}
@ -294,10 +283,10 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
if buildCtx != nil {
// Wrap the tar archive to replace the Dockerfile entry with the rewritten
// Dockerfile which uses trusted pulls.
buildCtx = replaceDockerfileForContentTrust(ctx, buildCtx, relDockerfile, translator, &resolvedTags)
buildCtx = replaceDockerfileTarWrapper(ctx, buildCtx, relDockerfile, translator, &resolvedTags)
} else if dockerfileCtx != nil {
// if there was not archive context still do the possible replacements in Dockerfile
newDockerfile, _, err := rewriteDockerfileFromForContentTrust(ctx, dockerfileCtx, translator)
newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator)
if err != nil {
return err
}
@ -461,7 +450,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
return err
}
}
if !options.untrusted {
if command.IsTrusted() {
// Since the build was successful, now we must tag any of the resolved
// images from the above Dockerfile rewrite.
for _, resolved := range resolvedTags {
@ -500,12 +489,11 @@ type resolvedTag struct {
tagRef reference.NamedTagged
}
// rewriteDockerfileFromForContentTrust rewrites the given Dockerfile by resolving images in
// rewriteDockerfileFrom rewrites the given Dockerfile by resolving images in
// "FROM <image>" instructions to a digest reference. `translator` is a
// function that takes a repository name and tag reference and returns a
// trusted digest reference.
// This should be called *only* when content trust is enabled
func rewriteDockerfileFromForContentTrust(ctx context.Context, dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
scanner := bufio.NewScanner(dockerfile)
buf := bytes.NewBuffer(nil)
@ -522,7 +510,7 @@ func rewriteDockerfileFromForContentTrust(ctx context.Context, dockerfile io.Rea
return nil, nil, err
}
ref = reference.TagNameOnly(ref)
if ref, ok := ref.(reference.NamedTagged); ok {
if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() {
trustedRef, err := translator(ctx, ref)
if err != nil {
return nil, nil, err
@ -545,10 +533,11 @@ func rewriteDockerfileFromForContentTrust(ctx context.Context, dockerfile io.Rea
return buf.Bytes(), resolvedTags, scanner.Err()
}
// replaceDockerfileForContentTrust wraps the given input tar archive stream and
// uses the translator to replace the Dockerfile which uses a trusted reference.
// Returns a new tar archive stream with the replaced Dockerfile.
func replaceDockerfileForContentTrust(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser {
// replaceDockerfileTarWrapper wraps the given input tar archive stream and
// replaces the entry with the given Dockerfile name with the contents of the
// new Dockerfile. Returns a new tar archive stream with the replaced
// Dockerfile.
func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser {
pipeReader, pipeWriter := io.Pipe()
go func() {
tarReader := tar.NewReader(inputTarStream)
@ -575,7 +564,7 @@ func replaceDockerfileForContentTrust(ctx context.Context, inputTarStream io.Rea
// generated from a directory on the local filesystem, the
// Dockerfile will only appear once in the archive.
var newDockerfile []byte
newDockerfile, *resolvedTags, err = rewriteDockerfileFromForContentTrust(ctx, content, translator)
newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator)
if err != nil {
pipeWriter.CloseWithError(err)
return

View File

@ -167,10 +167,6 @@ func GetContextFromGitURL(gitURL, dockerfileName string) (string, string, error)
return "", "", err
}
relDockerfile, err := getDockerfileRelPath(absContextDir, dockerfileName)
if err == nil && strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
return "", "", errors.Errorf("the Dockerfile (%s) must be within the build context", dockerfileName)
}
return absContextDir, relDockerfile, err
}
@ -322,6 +318,10 @@ func getDockerfileRelPath(absContextDir, givenDockerfile string) (string, error)
return "", errors.Errorf("unable to get relative Dockerfile path: %v", err)
}
if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
return "", errors.Errorf("the Dockerfile (%s) must be within the build context", givenDockerfile)
}
return relDockerfile, nil
}

View File

@ -11,9 +11,10 @@ import (
"strings"
"testing"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/pkg/archive"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const dockerfileContents = "FROM busybox"
@ -37,7 +38,7 @@ func testValidateContextDirectory(t *testing.T, prepare func(t *testing.T) (stri
defer cleanup()
err := ValidateContextDirectory(contextDir, excludes)
assert.NilError(t, err)
require.NoError(t, err)
}
func TestGetContextFromLocalDirNoDockerfile(t *testing.T) {
@ -45,7 +46,7 @@ func TestGetContextFromLocalDirNoDockerfile(t *testing.T) {
defer cleanup()
_, _, err := GetContextFromLocalDir(contextDir, "")
assert.ErrorContains(t, err, "Dockerfile")
testutil.ErrorContains(t, err, "Dockerfile")
}
func TestGetContextFromLocalDirNotExistingDir(t *testing.T) {
@ -55,7 +56,7 @@ func TestGetContextFromLocalDirNotExistingDir(t *testing.T) {
fakePath := filepath.Join(contextDir, "fake")
_, _, err := GetContextFromLocalDir(fakePath, "")
assert.ErrorContains(t, err, "fake")
testutil.ErrorContains(t, err, "fake")
}
func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) {
@ -65,7 +66,7 @@ func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) {
fakePath := filepath.Join(contextDir, "fake")
_, _, err := GetContextFromLocalDir(contextDir, fakePath)
assert.ErrorContains(t, err, "fake")
testutil.ErrorContains(t, err, "fake")
}
func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
@ -78,10 +79,10 @@ func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) {
defer chdirCleanup()
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "")
assert.NilError(t, err)
require.NoError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Equal(t, contextDir, absContextDir)
assert.Equal(t, DefaultDockerfileName, relDockerfile)
}
func TestGetContextFromLocalDirWithDockerfile(t *testing.T) {
@ -91,10 +92,10 @@ func TestGetContextFromLocalDirWithDockerfile(t *testing.T) {
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "")
assert.NilError(t, err)
require.NoError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Equal(t, contextDir, absContextDir)
assert.Equal(t, DefaultDockerfileName, relDockerfile)
}
func TestGetContextFromLocalDirLocalFile(t *testing.T) {
@ -129,10 +130,10 @@ func TestGetContextFromLocalDirWithCustomDockerfile(t *testing.T) {
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, DefaultDockerfileName)
assert.NilError(t, err)
require.NoError(t, err)
assert.Check(t, is.Equal(contextDir, absContextDir))
assert.Check(t, is.Equal(DefaultDockerfileName, relDockerfile))
assert.Equal(t, contextDir, absContextDir)
assert.Equal(t, DefaultDockerfileName, relDockerfile)
}
func TestGetContextFromReaderString(t *testing.T) {
@ -160,7 +161,7 @@ func TestGetContextFromReaderString(t *testing.T) {
t.Fatalf("Tar stream too long: %s", err)
}
assert.NilError(t, tarArchive.Close())
require.NoError(t, tarArchive.Close())
if dockerfileContents != contents {
t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents)
@ -178,15 +179,15 @@ func TestGetContextFromReaderTar(t *testing.T) {
createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777)
tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
assert.NilError(t, err)
require.NoError(t, err)
tarArchive, relDockerfile, err := GetContextFromReader(tarStream, DefaultDockerfileName)
assert.NilError(t, err)
require.NoError(t, err)
tarReader := tar.NewReader(tarArchive)
header, err := tarReader.Next()
assert.NilError(t, err)
require.NoError(t, err)
if header.Name != DefaultDockerfileName {
t.Fatalf("Dockerfile name should be: %s, got: %s", DefaultDockerfileName, header.Name)
@ -202,7 +203,7 @@ func TestGetContextFromReaderTar(t *testing.T) {
t.Fatalf("Tar stream too long: %s", err)
}
assert.NilError(t, tarArchive.Close())
require.NoError(t, tarArchive.Close())
if dockerfileContents != contents {
t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents)
@ -242,8 +243,8 @@ func TestValidateContextDirectoryWithOneFileExcludes(t *testing.T) {
// When an error occurs, it terminates the test.
func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
path, err := ioutil.TempDir(dir, prefix)
assert.NilError(t, err)
return path, func() { assert.NilError(t, os.RemoveAll(path)) }
require.NoError(t, err)
return path, func() { require.NoError(t, os.RemoveAll(path)) }
}
// createTestTempFile creates a temporary file within dir with specific contents and permissions.
@ -251,7 +252,7 @@ func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
filePath := filepath.Join(dir, filename)
err := ioutil.WriteFile(filePath, []byte(contents), perm)
assert.NilError(t, err)
require.NoError(t, err)
return filePath
}
@ -261,9 +262,9 @@ func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.Fi
// When an error occurs, it terminates the test.
func chdir(t *testing.T, dir string) func() {
workingDirectory, err := os.Getwd()
assert.NilError(t, err)
assert.NilError(t, os.Chdir(dir))
return func() { assert.NilError(t, os.Chdir(workingDirectory)) }
require.NoError(t, err)
require.NoError(t, os.Chdir(dir))
return func() { require.NoError(t, os.Chdir(workingDirectory)) }
}
func TestIsArchive(t *testing.T) {
@ -294,6 +295,6 @@ func TestIsArchive(t *testing.T) {
},
}
for _, testcase := range testcases {
assert.Check(t, is.Equal(testcase.expected, IsArchive(testcase.header)), testcase.doc)
assert.Equal(t, testcase.expected, IsArchive(testcase.header), testcase.doc)
}
}

View File

@ -1,66 +1,39 @@
package image
import (
"archive/tar"
"bytes"
"compress/gzip"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sort"
"syscall"
"testing"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/google/go-cmp/cmp"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/fs"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
buffer := new(bytes.Buffer)
fakeBuild := newFakeBuild()
fakeImageBuild := func(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
tee := io.TeeReader(context, buffer)
gzipReader, err := gzip.NewReader(tee)
assert.NilError(t, err)
return fakeBuild.build(ctx, gzipReader, options)
}
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
dockerfile := bytes.NewBufferString(`
FROM alpine:3.6
COPY foo /
`)
cli.SetIn(command.NewInStream(ioutil.NopCloser(dockerfile)))
dir := fs.NewDir(t, t.Name(),
fs.WithFile("foo", "some content"))
defer dir.Remove()
options := newBuildOptions()
options.compress = true
options.dockerfileName = "-"
options.context = dir.Path()
options.untrusted = true
assert.NilError(t, runBuild(cli, options))
expected := []string{fakeBuild.options.Dockerfile, ".dockerignore", "foo"}
assert.DeepEqual(t, expected, fakeBuild.filenames(t))
header := buffer.Bytes()[:10]
assert.Equal(t, archive.Gzip, archive.DetectCompression(header))
}
func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
skip.If(t, os.Getuid() != 0, "root is required to chown files")
fakeBuild := newFakeBuild()
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeBuild.build})
skip.IfCondition(t, runtime.GOOS == "windows", "uid and gid not relevant on windows")
dest := fs.NewDir(t, "test-build-context-dest")
defer dest.Remove()
fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
assert.NoError(t, archive.Untar(context, dest.Path(), nil))
body := new(bytes.Buffer)
return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil
}
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
dir := fs.NewDir(t, "test-build-context",
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
@ -73,60 +46,78 @@ func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
options := newBuildOptions()
options.context = dir.Path()
options.untrusted = true
assert.NilError(t, runBuild(cli, options))
headers := fakeBuild.headers(t)
expected := []*tar.Header{
{Name: "Dockerfile"},
{Name: "foo"},
err := runBuild(cli, options)
require.NoError(t, err)
files, err := ioutil.ReadDir(dest.Path())
require.NoError(t, err)
for _, fileInfo := range files {
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid)
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid)
}
var cmpTarHeaderNameAndOwner = cmp.Comparer(func(x, y tar.Header) bool {
return x.Name == y.Name && x.Uid == y.Uid && x.Gid == y.Gid
})
assert.DeepEqual(t, expected, headers, cmpTarHeaderNameAndOwner)
}
func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
dest, err := ioutil.TempDir("", "test-build-compress-dest")
require.NoError(t, err)
defer os.RemoveAll(dest)
func TestRunBuildDockerfileOutsideContext(t *testing.T) {
dir := fs.NewDir(t, t.Name(),
fs.WithFile("data", "data file"))
defer dir.Remove()
var dockerfileName string
fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
buffer := new(bytes.Buffer)
tee := io.TeeReader(context, buffer)
// Dockerfile outside of build-context
df := fs.NewFile(t, t.Name(),
fs.WithContent(`
FROM FOOBAR
COPY data /data
`),
)
defer df.Remove()
assert.NoError(t, archive.Untar(tee, dest, nil))
dockerfileName = options.Dockerfile
fakeBuild := newFakeBuild()
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeBuild.build})
header := buffer.Bytes()[:10]
assert.Equal(t, archive.Gzip, archive.DetectCompression(header))
body := new(bytes.Buffer)
return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil
}
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
dockerfile := bytes.NewBufferString(`
FROM alpine:3.6
COPY foo /
`)
cli.SetIn(command.NewInStream(ioutil.NopCloser(dockerfile)))
dir, err := ioutil.TempDir("", "test-build-compress")
require.NoError(t, err)
defer os.RemoveAll(dir)
ioutil.WriteFile(filepath.Join(dir, "foo"), []byte("some content"), 0644)
options := newBuildOptions()
options.context = dir.Path()
options.dockerfileName = df.Path()
options.untrusted = true
assert.NilError(t, runBuild(cli, options))
options.compress = true
options.dockerfileName = "-"
options.context = dir
expected := []string{fakeBuild.options.Dockerfile, ".dockerignore", "data"}
assert.DeepEqual(t, expected, fakeBuild.filenames(t))
err = runBuild(cli, options)
require.NoError(t, err)
files, err := ioutil.ReadDir(dest)
require.NoError(t, err)
actual := []string{}
for _, fileInfo := range files {
actual = append(actual, fileInfo.Name())
}
sort.Strings(actual)
assert.Equal(t, []string{dockerfileName, ".dockerignore", "foo"}, actual)
}
// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that build contexts
// starting with `github.com/` are special-cased, and the build command attempts
// to clone the remote repo.
// TODO: test "context selection" logic directly when runBuild is refactored
// to support testing (ex: docker/cli#294)
func TestRunBuildFromGitHubSpecialCase(t *testing.T) {
cmd := NewBuildCommand(test.NewFakeCli(nil))
// Clone a small repo that exists so git doesn't prompt for credentials
cmd.SetArgs([]string{"github.com/docker/for-win"})
cmd.SetArgs([]string{"github.com/docker/no-such-repository"})
cmd.SetOutput(ioutil.Discard)
err := cmd.Execute()
assert.ErrorContains(t, err, "unable to prepare context")
assert.ErrorContains(t, err, "docker-build-git")
assert.Error(t, err)
assert.Contains(t, err.Error(), "unable to prepare context: unable to 'git clone'")
}
// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that a local directory
@ -134,83 +125,19 @@ func TestRunBuildFromGitHubSpecialCase(t *testing.T) {
// case.
func TestRunBuildFromLocalGitHubDir(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "docker-build-from-local-dir-")
assert.NilError(t, err)
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
buildDir := filepath.Join(tmpDir, "github.com", "docker", "no-such-repository")
err = os.MkdirAll(buildDir, 0777)
assert.NilError(t, err)
require.NoError(t, err)
err = ioutil.WriteFile(filepath.Join(buildDir, "Dockerfile"), []byte("FROM busybox\n"), 0644)
assert.NilError(t, err)
require.NoError(t, err)
client := test.NewFakeCli(&fakeClient{})
cmd := NewBuildCommand(client)
cmd.SetArgs([]string{buildDir})
cmd.SetOutput(ioutil.Discard)
err = cmd.Execute()
assert.NilError(t, err)
}
func TestRunBuildWithSymlinkedContext(t *testing.T) {
dockerfile := `
FROM alpine:3.6
RUN echo hello world
`
tmpDir := fs.NewDir(t, t.Name(),
fs.WithDir("context",
fs.WithFile("Dockerfile", dockerfile)),
fs.WithSymlink("context-link", "context"))
defer tmpDir.Remove()
fakeBuild := newFakeBuild()
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeBuild.build})
options := newBuildOptions()
options.context = tmpDir.Join("context-link")
options.untrusted = true
assert.NilError(t, runBuild(cli, options))
assert.DeepEqual(t, fakeBuild.filenames(t), []string{"Dockerfile"})
}
type fakeBuild struct {
context *tar.Reader
options types.ImageBuildOptions
}
func newFakeBuild() *fakeBuild {
return &fakeBuild{}
}
func (f *fakeBuild) build(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
f.context = tar.NewReader(context)
f.options = options
body := new(bytes.Buffer)
return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil
}
func (f *fakeBuild) headers(t *testing.T) []*tar.Header {
t.Helper()
headers := []*tar.Header{}
for {
hdr, err := f.context.Next()
switch err {
case io.EOF:
return headers
case nil:
headers = append(headers, hdr)
default:
assert.NilError(t, err)
}
}
}
func (f *fakeBuild) filenames(t *testing.T) []string {
t.Helper()
names := []string{}
for _, header := range f.headers(t) {
names = append(names, header.Name)
}
sort.Strings(names)
return names
require.NoError(t, err)
}

View File

@ -7,11 +7,11 @@ import (
"time"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types/image"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewHistoryCommandErrors(t *testing.T) {
@ -39,20 +39,15 @@ func TestNewHistoryCommandErrors(t *testing.T) {
cmd := NewHistoryCommand(test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func notUTCTimezone() bool {
now := time.Now()
return now != now.UTC()
}
func TestNewHistoryCommandSuccess(t *testing.T) {
skip.If(t, notUTCTimezone, "expected output requires UTC timezone")
testCases := []struct {
name string
args []string
outputRegex string
imageHistoryFunc func(img string) ([]image.HistoryResponseItem, error)
}{
{
@ -69,17 +64,16 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
name: "quiet",
args: []string{"--quiet", "image:tag"},
},
// TODO: This test is failing since the output does not contain an RFC3339 date
//{
// name: "non-human",
// args: []string{"--human=false", "image:tag"},
// outputRegex: "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}", // RFC3339 date format match
//},
{
name: "non-human",
args: []string{"--human=false", "image:tag"},
imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) {
return []image.HistoryResponseItem{{
ID: "abcdef",
Created: time.Date(2017, 1, 1, 12, 0, 3, 0, time.UTC).Unix(),
CreatedBy: "rose",
Comment: "new history item!",
}}, nil
},
name: "non-human-header",
args: []string{"--human=false", "image:tag"},
outputRegex: "CREATED\\sAT",
},
{
name: "quiet-no-trunc",
@ -98,8 +92,12 @@ func TestNewHistoryCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
actual := cli.OutBuffer().String()
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
if tc.outputRegex == "" {
golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name))
} else {
assert.Regexp(t, tc.outputRegex, actual)
}
}
}

View File

@ -7,10 +7,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewImportCommandErrors(t *testing.T) {
@ -38,7 +38,7 @@ func TestNewImportCommandErrors(t *testing.T) {
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -46,7 +46,7 @@ func TestNewImportCommandInvalidFile(t *testing.T) {
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs([]string{"testdata/import-command-success.unexistent-file"})
assert.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file")
testutil.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file")
}
func TestNewImportCommandSuccess(t *testing.T) {
@ -67,7 +67,7 @@ func TestNewImportCommandSuccess(t *testing.T) {
name: "double",
args: []string{"-", "image:local"},
imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
assert.Check(t, is.Equal("image:local", ref))
assert.Equal(t, "image:local", ref)
return ioutil.NopCloser(strings.NewReader("")), nil
},
},
@ -75,7 +75,7 @@ func TestNewImportCommandSuccess(t *testing.T) {
name: "message",
args: []string{"--message", "test message", "-"},
imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
assert.Check(t, is.Equal("test message", options.Message))
assert.Equal(t, "test message", options.Message)
return ioutil.NopCloser(strings.NewReader("")), nil
},
},
@ -83,7 +83,7 @@ func TestNewImportCommandSuccess(t *testing.T) {
name: "change",
args: []string{"--change", "ENV DEBUG true", "-"},
imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
assert.Check(t, is.Equal("ENV DEBUG true", options.Changes[0]))
assert.Equal(t, "ENV DEBUG true", options.Changes[0])
return ioutil.NopCloser(strings.NewReader("")), nil
},
},
@ -92,6 +92,6 @@ func TestNewImportCommandSuccess(t *testing.T) {
cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}
}

View File

@ -6,10 +6,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestNewInspectCommandErrors(t *testing.T) {
@ -28,7 +28,7 @@ func TestNewInspectCommandErrors(t *testing.T) {
cmd := newInspectCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -46,7 +46,7 @@ func TestNewInspectCommandSuccess(t *testing.T) {
imageCount: 1,
imageInspectFunc: func(image string) (types.ImageInspect, []byte, error) {
imageInspectInvocationCount++
assert.Check(t, is.Equal("image", image))
assert.Equal(t, "image", image)
return types.ImageInspect{}, nil, nil
},
},
@ -66,9 +66,9 @@ func TestNewInspectCommandSuccess(t *testing.T) {
imageInspectFunc: func(image string) (types.ImageInspect, []byte, error) {
imageInspectInvocationCount++
if imageInspectInvocationCount == 1 {
assert.Check(t, is.Equal("image1", image))
assert.Equal(t, "image1", image)
} else {
assert.Check(t, is.Equal("image2", image))
assert.Equal(t, "image2", image)
}
return types.ImageInspect{}, nil, nil
},
@ -81,8 +81,8 @@ func TestNewInspectCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("inspect-command-success.%s.golden", tc.name))
assert.Check(t, is.Equal(imageInspectInvocationCount, tc.imageCount))
assert.Equal(t, imageInspectInvocationCount, tc.imageCount)
}
}

View File

@ -7,11 +7,11 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewImagesCommandErrors(t *testing.T) {
@ -38,7 +38,7 @@ func TestNewImagesCommandErrors(t *testing.T) {
cmd := NewImagesCommand(test.NewFakeCli(&fakeClient{imageListFunc: tc.imageListFunc}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -65,7 +65,7 @@ func TestNewImagesCommandSuccess(t *testing.T) {
name: "match-name",
args: []string{"image"},
imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) {
assert.Check(t, is.Equal("image", options.Filters.Get("reference")[0]))
assert.Equal(t, "image", options.Filters.Get("reference")[0])
return []types.ImageSummary{{}}, nil
},
},
@ -73,7 +73,7 @@ func TestNewImagesCommandSuccess(t *testing.T) {
name: "filters",
args: []string{"--filter", "name=value"},
imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) {
assert.Check(t, is.Equal("value", options.Filters.Get("name")[0]))
assert.Equal(t, "value", options.Filters.Get("name")[0])
return []types.ImageSummary{{}}, nil
},
},
@ -85,14 +85,14 @@ func TestNewImagesCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("list-command-success.%s.golden", tc.name))
}
}
func TestNewListCommandAlias(t *testing.T) {
cmd := newListCommand(test.NewFakeCli(&fakeClient{}))
assert.Check(t, cmd.HasAlias("images"))
assert.Check(t, cmd.HasAlias("list"))
assert.Check(t, !cmd.HasAlias("other"))
assert.True(t, cmd.HasAlias("images"))
assert.True(t, cmd.HasAlias("list"))
assert.False(t, cmd.HasAlias("other"))
}

View File

@ -8,10 +8,11 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewLoadCommandErrors(t *testing.T) {
@ -46,7 +47,7 @@ func TestNewLoadCommandErrors(t *testing.T) {
cmd := NewLoadCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -56,7 +57,7 @@ func TestNewLoadCommandInvalidInput(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs([]string{"--input", "*"})
err := cmd.Execute()
assert.ErrorContains(t, err, expectedError)
testutil.ErrorContains(t, err, expectedError)
}
func TestNewLoadCommandSuccess(t *testing.T) {
@ -95,7 +96,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("load-command-success.%s.golden", tc.name))
}
}

View File

@ -6,12 +6,12 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewPruneCommandErrors(t *testing.T) {
@ -41,7 +41,7 @@ func TestNewPruneCommandErrors(t *testing.T) {
}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -55,7 +55,7 @@ func TestNewPruneCommandSuccess(t *testing.T) {
name: "all",
args: []string{"--all"},
imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) {
assert.Check(t, is.Equal("false", pruneFilter.Get("dangling")[0]))
assert.Equal(t, "false", pruneFilter.Get("dangling")[0])
return types.ImagesPruneReport{}, nil
},
},
@ -63,7 +63,7 @@ func TestNewPruneCommandSuccess(t *testing.T) {
name: "force-deleted",
args: []string{"--force"},
imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) {
assert.Check(t, is.Equal("true", pruneFilter.Get("dangling")[0]))
assert.Equal(t, "true", pruneFilter.Get("dangling")[0])
return types.ImagesPruneReport{
ImagesDeleted: []types.ImageDeleteResponseItem{{Deleted: "image1"}},
SpaceReclaimed: 1,
@ -74,7 +74,7 @@ func TestNewPruneCommandSuccess(t *testing.T) {
name: "force-untagged",
args: []string{"--force"},
imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) {
assert.Check(t, is.Equal("true", pruneFilter.Get("dangling")[0]))
assert.Equal(t, "true", pruneFilter.Get("dangling")[0])
return types.ImagesPruneReport{
ImagesDeleted: []types.ImageDeleteResponseItem{{Untagged: "image1"}},
SpaceReclaimed: 2,
@ -88,7 +88,7 @@ func TestNewPruneCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("prune-command-success.%s.golden", tc.name))
}
}

View File

@ -14,10 +14,9 @@ import (
)
type pullOptions struct {
remote string
all bool
platform string
untrusted bool
remote string
all bool
platform string
}
// NewPullCommand creates a new `docker pull` command
@ -39,7 +38,7 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository")
command.AddPlatformFlag(flags, &opts.platform)
command.AddTrustVerificationFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
command.AddTrustVerificationFlags(flags)
return cmd
}
@ -59,14 +58,14 @@ func runPull(cli command.Cli, opts pullOptions) error {
}
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), distributionRef.String())
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
if err != nil {
return err
}
// Check if reference has a digest
_, isCanonical := distributionRef.(reference.Canonical)
if !opts.untrusted && !isCanonical {
if command.IsTrusted() && !isCanonical {
err = trustedPull(ctx, cli, imgRefAndAuth, opts.platform)
} else {
err = imagePullPrivileged(ctx, cli, imgRefAndAuth, opts.all, opts.platform)

View File

@ -8,11 +8,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/notary"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestNewPullCommandErrors(t *testing.T) {
@ -42,7 +41,7 @@ func TestNewPullCommandErrors(t *testing.T) {
cmd := NewPullCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -66,7 +65,7 @@ func TestNewPullCommandSuccess(t *testing.T) {
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{
imagePullFunc: func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
assert.Check(t, is.Equal(tc.expectedTag, ref), tc.name)
assert.Equal(t, tc.expectedTag, ref, tc.name)
return ioutil.NopCloser(strings.NewReader("")), nil
},
})
@ -74,48 +73,7 @@ func TestNewPullCommandSuccess(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.NilError(t, err)
assert.NoError(t, err)
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("pull-command-success.%s.golden", tc.name))
}
}
func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
notaryFunc test.NotaryClientFuncType
}{
{
name: "offline-notary-server",
notaryFunc: notary.GetOfflineNotaryRepository,
expectedError: "client is offline",
args: []string{"image:tag"},
},
{
name: "uninitialized-notary-server",
notaryFunc: notary.GetUninitializedNotaryRepository,
expectedError: "remote trust data does not exist",
args: []string{"image:tag"},
},
{
name: "empty-notary-server",
notaryFunc: notary.GetEmptyTargetsNotaryRepository,
expectedError: "No valid trust data for tag",
args: []string{"image:tag"},
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{
imagePullFunc: func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
return ioutil.NopCloser(strings.NewReader("")), fmt.Errorf("shouldn't try to pull image")
},
}, test.EnableContentTrust)
cli.SetNotaryClient(tc.notaryFunc)
cmd := NewPullCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.ErrorContains(t, err, tc.expectedError)
}
}

View File

@ -11,34 +11,26 @@ import (
"github.com/spf13/cobra"
)
type pushOptions struct {
remote string
untrusted bool
}
// NewPushCommand creates a new `docker push` command
func NewPushCommand(dockerCli command.Cli) *cobra.Command {
var opts pushOptions
cmd := &cobra.Command{
Use: "push [OPTIONS] NAME[:TAG]",
Short: "Push an image or a repository to a registry",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.remote = args[0]
return runPush(dockerCli, opts)
return runPush(dockerCli, args[0])
},
}
flags := cmd.Flags()
command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
command.AddTrustSigningFlags(flags)
return cmd
}
func runPush(dockerCli command.Cli, opts pushOptions) error {
ref, err := reference.ParseNormalizedNamed(opts.remote)
func runPush(dockerCli command.Cli, remote string) error {
ref, err := reference.ParseNormalizedNamed(remote)
if err != nil {
return err
}
@ -55,7 +47,7 @@ func runPush(dockerCli command.Cli, opts pushOptions) error {
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
if !opts.untrusted {
if command.IsTrusted() {
return TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)
}

View File

@ -7,9 +7,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestNewPushCommandErrors(t *testing.T) {
@ -37,13 +38,18 @@ func TestNewPushCommandErrors(t *testing.T) {
return ioutil.NopCloser(strings.NewReader("")), errors.Errorf("Failed to push")
},
},
{
name: "trust-error",
args: []string{"--disable-content-trust=false", "image:repo"},
expectedError: "you are not authorized to perform this operation: server returned 401.",
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{imagePushFunc: tc.imagePushFunc})
cmd := NewPushCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -66,6 +72,6 @@ func TestNewPushCommandSuccess(t *testing.T) {
cmd := NewPushCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}
}

View File

@ -6,11 +6,11 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
type notFound struct {
@ -27,9 +27,9 @@ func (n notFound) NotFound() bool {
func TestNewRemoveCommandAlias(t *testing.T) {
cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{}))
assert.Check(t, cmd.HasAlias("rmi"))
assert.Check(t, cmd.HasAlias("remove"))
assert.Check(t, !cmd.HasAlias("other"))
assert.True(t, cmd.HasAlias("rmi"))
assert.True(t, cmd.HasAlias("remove"))
assert.False(t, cmd.HasAlias("other"))
}
func TestNewRemoveCommandErrors(t *testing.T) {
@ -48,7 +48,7 @@ func TestNewRemoveCommandErrors(t *testing.T) {
args: []string{"-f", "image1"},
expectedError: "error removing image",
imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
assert.Check(t, is.Equal("image1", image))
assert.Equal(t, "image1", image)
return []types.ImageDeleteResponseItem{}, errors.Errorf("error removing image")
},
},
@ -57,8 +57,8 @@ func TestNewRemoveCommandErrors(t *testing.T) {
args: []string{"arg1"},
expectedError: "error removing image",
imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
assert.Check(t, !options.Force)
assert.Check(t, options.PruneChildren)
assert.False(t, options.Force)
assert.True(t, options.PruneChildren)
return []types.ImageDeleteResponseItem{}, errors.Errorf("error removing image")
},
},
@ -70,7 +70,7 @@ func TestNewRemoveCommandErrors(t *testing.T) {
}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
})
}
}
@ -86,7 +86,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
name: "Image Deleted",
args: []string{"image1"},
imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
assert.Check(t, is.Equal("image1", image))
assert.Equal(t, "image1", image)
return []types.ImageDeleteResponseItem{{Deleted: image}}, nil
},
},
@ -94,8 +94,8 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
name: "Image not found with force option",
args: []string{"-f", "image1"},
imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
assert.Check(t, is.Equal("image1", image))
assert.Check(t, is.Equal(true, options.Force))
assert.Equal(t, "image1", image)
assert.Equal(t, true, options.Force)
return []types.ImageDeleteResponseItem{}, notFound{"image1"}
},
expectedStderr: "Error: No such image: image1\n",
@ -105,7 +105,7 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
name: "Image Untagged",
args: []string{"image1"},
imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) {
assert.Check(t, is.Equal("image1", image))
assert.Equal(t, "image1", image)
return []types.ImageDeleteResponseItem{{Untagged: image}}, nil
},
},
@ -126,8 +126,8 @@ func TestNewRemoveCommandSuccess(t *testing.T) {
cmd := NewRemoveCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal(tc.expectedStderr, cli.ErrBuffer().String()))
assert.NoError(t, cmd.Execute())
assert.Equal(t, tc.expectedStderr, cli.ErrBuffer().String())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("remove-command-success.%s.golden", tc.name))
})
}

View File

@ -8,9 +8,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/docker/cli/internal/test/testutil"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewSaveCommandErrors(t *testing.T) {
@ -53,7 +54,7 @@ func TestNewSaveCommandErrors(t *testing.T) {
cmd := NewSaveCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -68,8 +69,8 @@ func TestNewSaveCommandSuccess(t *testing.T) {
args: []string{"-o", "save_tmp_file", "arg1"},
isTerminal: true,
imageSaveFunc: func(images []string) (io.ReadCloser, error) {
assert.Assert(t, is.Len(images, 1))
assert.Check(t, is.Equal("arg1", images[0]))
require.Len(t, images, 1)
assert.Equal(t, "arg1", images[0])
return ioutil.NopCloser(strings.NewReader("")), nil
},
deferredFunc: func() {
@ -80,9 +81,9 @@ func TestNewSaveCommandSuccess(t *testing.T) {
args: []string{"arg1", "arg2"},
isTerminal: false,
imageSaveFunc: func(images []string) (io.ReadCloser, error) {
assert.Assert(t, is.Len(images, 2))
assert.Check(t, is.Equal("arg1", images[0]))
assert.Check(t, is.Equal("arg2", images[1]))
require.Len(t, images, 2)
assert.Equal(t, "arg1", images[0])
assert.Equal(t, "arg2", images[1])
return ioutil.NopCloser(strings.NewReader("")), nil
},
},
@ -95,7 +96,7 @@ func TestNewSaveCommandSuccess(t *testing.T) {
}))
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
if tc.deferredFunc != nil {
tc.deferredFunc()
}

View File

@ -5,8 +5,8 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/docker/cli/internal/test/testutil"
"github.com/stretchr/testify/assert"
)
func TestCliNewTagCommandErrors(t *testing.T) {
@ -20,7 +20,7 @@ func TestCliNewTagCommandErrors(t *testing.T) {
cmd := NewTagCommand(test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), expectedError)
testutil.ErrorContains(t, cmd.Execute(), expectedError)
}
}
@ -28,14 +28,14 @@ func TestCliNewTagCommand(t *testing.T) {
cmd := NewTagCommand(
test.NewFakeCli(&fakeClient{
imageTagFunc: func(image string, ref string) error {
assert.Check(t, is.Equal("image1", image))
assert.Check(t, is.Equal("image2", ref))
assert.Equal(t, "image1", image)
assert.Equal(t, "image2", ref)
return nil
},
}))
cmd.SetArgs([]string{"image1", "image2"})
cmd.SetOutput(ioutil.Discard)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
value, _ := cmd.Flags().GetBool("interspersed")
assert.Check(t, !value)
assert.False(t, value)
}

View File

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

View File

@ -198,7 +198,7 @@ func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.Image
if err != nil {
return err
}
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, nil, AuthResolver(cli), trustedRef.String())
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
if err != nil {
return err
}
@ -293,24 +293,35 @@ func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth tru
// TrustedReference returns the canonical trusted reference for an image reference
func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) {
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, rs, AuthResolver(cli), ref.String())
var (
repoInfo *registry.RepositoryInfo
err error
)
if rs != nil {
repoInfo, err = rs.ResolveRepository(ref)
} else {
repoInfo, err = registry.ParseRepositoryInfo(ref)
}
if err != nil {
return nil, err
}
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, []string{"pull"})
// Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil {
return nil, errors.Wrap(err, "error establishing connection to trust repository")
}
t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return nil, trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), err)
return nil, trust.NotaryError(repoInfo.Name.Name(), err)
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return nil, trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), client.ErrNoSuchTarget(ref.Tag()))
return nil, trust.NotaryError(repoInfo.Name.Name(), client.ErrNoSuchTarget(ref.Tag()))
}
r, err := convertTarget(t.Target)
if err != nil {

View File

@ -7,7 +7,9 @@ import (
"github.com/docker/cli/cli/trust"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/docker/docker/registry"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/theupdateframework/notary/client"
"github.com/theupdateframework/notary/passphrase"
"github.com/theupdateframework/notary/trustpinning"
@ -46,8 +48,8 @@ func TestHTTPENVTrustServer(t *testing.T) {
func TestOfficialTrustServer(t *testing.T) {
indexInfo := &registrytypes.IndexInfo{Name: "testserver", Official: true}
output, err := trust.Server(indexInfo)
if err != nil || output != trust.NotaryServer {
t.Fatalf("Expected server to be %s, got %s", trust.NotaryServer, output)
if err != nil || output != registry.NotaryServer {
t.Fatalf("Expected server to be %s, got %s", registry.NotaryServer, output)
}
}
@ -62,12 +64,12 @@ func TestNonOfficialTrustServer(t *testing.T) {
func TestAddTargetToAllSignableRolesError(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NilError(t, err)
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
assert.NilError(t, err)
require.NoError(t, err)
target := client.Target{}
err = AddTargetToAllSignableRoles(notaryRepo, &target)
assert.Error(t, err, "client is offline")
assert.EqualError(t, err, "client is offline")
}

View File

@ -6,8 +6,8 @@ import (
"testing"
"github.com/docker/cli/templates"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type testElement struct {
@ -243,17 +243,17 @@ func TestTemplateInspectorRawFallbackNumber(t *testing.T) {
}
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.Size}} {{.Id}}")
assert.NilError(t, err)
require.NoError(t, err)
i := NewTemplateInspector(b, tmpl)
for _, tc := range testcases {
err = i.Inspect(typedElem, tc.raw)
assert.NilError(t, err)
require.NoError(t, err)
err = i.Flush()
assert.NilError(t, err)
require.NoError(t, err)
assert.Check(t, is.Equal(tc.exp, b.String()))
assert.Equal(t, tc.exp, b.String())
b.Reset()
}
}

View File

@ -5,9 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/docker/cli/internal/test/testutil"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestManifestAnnotateError(t *testing.T) {
@ -34,7 +35,7 @@ func TestManifestAnnotateError(t *testing.T) {
cmd := newAnnotateCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -47,13 +48,13 @@ func TestManifestAnnotate(t *testing.T) {
namedRef := ref(t, "alpine:3.0")
imageManifest := fullImageManifest(t, namedRef)
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
cmd := newAnnotateCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/fake:0.0"})
cmd.SetOutput(ioutil.Discard)
expectedError := "manifest for image example.com/fake:0.0 does not exist"
assert.ErrorContains(t, cmd.Execute(), expectedError)
testutil.ErrorContains(t, cmd.Execute(), expectedError)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.Flags().Set("os", "freebsd")
@ -61,17 +62,17 @@ func TestManifestAnnotate(t *testing.T) {
cmd.Flags().Set("os-features", "feature1")
cmd.Flags().Set("variant", "v7")
expectedError = "manifest entry for image has unsupported os/arch combination"
assert.ErrorContains(t, cmd.Execute(), expectedError)
testutil.ErrorContains(t, cmd.Execute(), expectedError)
cmd.Flags().Set("arch", "arm")
assert.NilError(t, cmd.Execute())
require.NoError(t, cmd.Execute())
cmd = newInspectCommand(cli)
err = cmd.Flags().Set("verbose", "true")
assert.NilError(t, err)
require.NoError(t, err)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
assert.NilError(t, cmd.Execute())
require.NoError(t, cmd.Execute())
actual := cli.OutBuffer()
expected := golden.Get(t, "inspect-annotate.golden")
assert.Check(t, is.Equal(string(expected), actual.String()))
assert.Equal(t, string(expected), actual.String())
}

View File

@ -10,6 +10,7 @@ import (
)
type fakeRegistryClient struct {
client.RegistryClient
getManifestFunc func(ctx context.Context, ref reference.Named) (manifesttypes.ImageManifest, error)
getManifestListFunc func(ctx context.Context, ref reference.Named) ([]manifesttypes.ImageManifest, error)
mountBlobFunc func(ctx context.Context, source reference.Canonical, target reference.Named) error
@ -43,5 +44,3 @@ func (c *fakeRegistryClient) PutManifest(ctx context.Context, ref reference.Name
}
return digest.Digest(""), nil
}
var _ client.RegistryClient = &fakeRegistryClient{}

View File

@ -6,11 +6,12 @@ import (
manifesttypes "github.com/docker/cli/cli/manifest/types"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/distribution/reference"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
@ -34,7 +35,7 @@ func TestManifestCreateErrors(t *testing.T) {
cmd := newCreateListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -49,28 +50,28 @@ func TestManifestCreateAmend(t *testing.T) {
namedRef := ref(t, "alpine:3.0")
imageManifest := fullImageManifest(t, namedRef)
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
namedRef = ref(t, "alpine:3.1")
imageManifest = fullImageManifest(t, namedRef)
err = store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
cmd := newCreateListCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.1"})
cmd.Flags().Set("amend", "true")
cmd.SetOutput(ioutil.Discard)
err = cmd.Execute()
assert.NilError(t, err)
require.NoError(t, err)
// make a new cli to clear the buffers
cli = test.NewFakeCli(nil)
cli.SetManifestStore(store)
inspectCmd := newInspectCommand(cli)
inspectCmd.SetArgs([]string{"example.com/list:v1"})
assert.NilError(t, inspectCmd.Execute())
require.NoError(t, inspectCmd.Execute())
actual := cli.OutBuffer()
expected := golden.Get(t, "inspect-manifest-list.golden")
assert.Check(t, is.Equal(string(expected), actual.String()))
assert.Equal(t, string(expected), actual.String())
}
// attempt to overwrite a saved manifest and get refused
@ -83,13 +84,13 @@ func TestManifestCreateRefuseAmend(t *testing.T) {
namedRef := ref(t, "alpine:3.0")
imageManifest := fullImageManifest(t, namedRef)
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
cmd := newCreateListCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.SetOutput(ioutil.Discard)
err = cmd.Execute()
assert.Error(t, err, "refusing to amend an existing manifest list with no --amend flag")
assert.EqualError(t, err, "refusing to amend an existing manifest list with no --amend flag")
}
// attempt to make a manifest list without valid images
@ -112,5 +113,5 @@ func TestManifestCreateNoManifest(t *testing.T) {
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
cmd.SetOutput(ioutil.Discard)
err := cmd.Execute()
assert.Error(t, err, "No such image: example.com/alpine:3.0")
assert.EqualError(t, err, "No such image: example.com/alpine:3.0")
}

View File

@ -12,24 +12,24 @@ import (
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/schema2"
"github.com/docker/distribution/reference"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func newTempManifestStore(t *testing.T) (store.Store, func()) {
tmpdir, err := ioutil.TempDir("", "test-manifest-storage")
assert.NilError(t, err)
require.NoError(t, err)
return store.NewStore(tmpdir), func() { os.RemoveAll(tmpdir) }
}
func ref(t *testing.T, name string) reference.Named {
named, err := reference.ParseNamed("example.com/" + name)
assert.NilError(t, err)
require.NoError(t, err)
return named
}
@ -49,7 +49,7 @@ func fullImageManifest(t *testing.T, ref reference.Named) types.ImageManifest {
},
},
})
assert.NilError(t, err)
require.NoError(t, err)
// TODO: include image data for verbose inspect
return types.NewImageManifest(ref, digest.Digest("sha256:7328f6f8b41890597575cbaadc884e7386ae0acc53b747401ebce5cf0d62abcd"), types.Image{OS: "linux", Architecture: "amd64"}, man)
}
@ -65,7 +65,7 @@ func TestInspectCommandLocalManifestNotFound(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
err := cmd.Execute()
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")
assert.EqualError(t, err, "No such manifest: example.com/alpine:3.0")
}
func TestInspectCommandNotFound(t *testing.T) {
@ -87,7 +87,7 @@ func TestInspectCommandNotFound(t *testing.T) {
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs([]string{"example.com/alpine:3.0"})
err := cmd.Execute()
assert.Error(t, err, "No such manifest: example.com/alpine:3.0")
assert.EqualError(t, err, "No such manifest: example.com/alpine:3.0")
}
func TestInspectCommandLocalManifest(t *testing.T) {
@ -99,14 +99,14 @@ func TestInspectCommandLocalManifest(t *testing.T) {
namedRef := ref(t, "alpine:3.0")
imageManifest := fullImageManifest(t, namedRef)
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
cmd := newInspectCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1", "example.com/alpine:3.0"})
assert.NilError(t, cmd.Execute())
require.NoError(t, cmd.Execute())
actual := cli.OutBuffer()
expected := golden.Get(t, "inspect-manifest.golden")
assert.Check(t, is.Equal(string(expected), actual.String()))
assert.Equal(t, string(expected), actual.String())
}
func TestInspectcommandRemoteManifest(t *testing.T) {
@ -124,8 +124,8 @@ func TestInspectcommandRemoteManifest(t *testing.T) {
cmd := newInspectCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs([]string{"example.com/alpine:3.0"})
assert.NilError(t, cmd.Execute())
require.NoError(t, cmd.Execute())
actual := cli.OutBuffer()
expected := golden.Get(t, "inspect-manifest.golden")
assert.Check(t, is.Equal(string(expected), actual.String()))
assert.Equal(t, string(expected), actual.String())
}

View File

@ -6,13 +6,16 @@ import (
manifesttypes "github.com/docker/cli/cli/manifest/types"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/distribution/reference"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func newFakeRegistryClient() *fakeRegistryClient {
func newFakeRegistryClient(t *testing.T) *fakeRegistryClient {
require.NoError(t, nil)
return &fakeRegistryClient{
getManifestFunc: func(_ context.Context, _ reference.Named) (manifesttypes.ImageManifest, error) {
return manifesttypes.ImageManifest{}, errors.New("")
@ -43,15 +46,16 @@ func TestManifestPushErrors(t *testing.T) {
cmd := newPushListCommand(cli)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
// store a one-image manifest list and puah it
func TestManifestPush(t *testing.T) {
store, sCleanup := newTempManifestStore(t)
defer sCleanup()
registry := newFakeRegistryClient()
registry := newFakeRegistryClient(t)
cli := test.NewFakeCli(nil)
cli.SetManifestStore(store)
@ -60,10 +64,10 @@ func TestManifestPush(t *testing.T) {
namedRef := ref(t, "alpine:3.0")
imageManifest := fullImageManifest(t, namedRef)
err := store.Save(ref(t, "list:v1"), namedRef, imageManifest)
assert.NilError(t, err)
require.NoError(t, err)
cmd := newPushListCommand(cli)
cmd.SetArgs([]string{"example.com/list:v1"})
err = cmd.Execute()
assert.NilError(t, err)
require.NoError(t, err)
}

View File

@ -5,10 +5,10 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types/network"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
@ -38,7 +38,7 @@ func TestNetworkConnectErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -54,7 +54,7 @@ func TestNetworkConnectWithFlags(t *testing.T) {
}
cli := test.NewFakeCli(&fakeClient{
networkConnectFunc: func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error {
assert.Check(t, is.DeepEqual(expectedOpts, config.IPAMConfig), "not expected driver error")
assert.Equal(t, expectedOpts, config.IPAMConfig, "not expected driver error")
return nil
},
})
@ -66,5 +66,5 @@ func TestNetworkConnectWithFlags(t *testing.T) {
cmd.Flags().Set("ip-range", "192.168.4.0/24")
cmd.Flags().Set("gateway", "192.168.4.1/24")
cmd.Flags().Set("subnet", "192.168.4.0/24")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}

View File

@ -6,11 +6,12 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/network"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
@ -135,10 +136,10 @@ func TestNetworkCreateErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
for key, value := range tc.flags {
assert.NilError(t, cmd.Flags().Set(key, value))
require.NoError(t, cmd.Flags().Set(key, value))
}
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -154,8 +155,8 @@ func TestNetworkCreateWithFlags(t *testing.T) {
}
cli := test.NewFakeCli(&fakeClient{
networkCreateFunc: func(ctx context.Context, name string, createBody types.NetworkCreate) (types.NetworkCreateResponse, error) {
assert.Check(t, is.Equal(expectedDriver, createBody.Driver), "not expected driver error")
assert.Check(t, is.DeepEqual(expectedOpts, createBody.IPAM.Config), "not expected driver error")
assert.Equal(t, expectedDriver, createBody.Driver, "not expected driver error")
assert.Equal(t, expectedOpts, createBody.IPAM.Config, "not expected driver error")
return types.NetworkCreateResponse{
ID: name,
}, nil
@ -169,6 +170,6 @@ func TestNetworkCreateWithFlags(t *testing.T) {
cmd.Flags().Set("ip-range", "192.168.4.0/24")
cmd.Flags().Set("gateway", "192.168.4.1/24")
cmd.Flags().Set("subnet", "192.168.4.0/24")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal("banana", strings.TrimSpace(cli.OutBuffer().String())))
assert.NoError(t, cmd.Execute())
assert.Equal(t, "banana", strings.TrimSpace(cli.OutBuffer().String()))
}

View File

@ -5,7 +5,7 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/docker/cli/internal/test/testutil"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -36,6 +36,6 @@ func TestNetworkDisconnectErrors(t *testing.T) {
)
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}

View File

@ -1,19 +1,20 @@
package network
import (
"io/ioutil"
"strings"
"testing"
"io/ioutil"
"strings"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/google/go-cmp/cmp"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
@ -37,18 +38,23 @@ func TestNetworkListErrors(t *testing.T) {
}),
)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestNetworkListWithFlags(t *testing.T) {
filterArgs := filters.NewArgs()
filterArgs.Add("image.name", "ubuntu")
expectedOpts := types.NetworkListOptions{
Filters: filters.NewArgs(filters.Arg("image.name", "ubuntu")),
Filters: filterArgs,
}
cli := test.NewFakeCli(&fakeClient{
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
assert.Check(t, is.DeepEqual(expectedOpts, options, cmp.AllowUnexported(filters.Args{})))
assert.Equal(t, expectedOpts, options, "not expected options error")
return []types.NetworkResource{*NetworkResource(NetworkResourceID("123454321"),
NetworkResourceName("network_1"),
NetworkResourceDriver("09.7.01"),
@ -58,6 +64,6 @@ func TestNetworkListWithFlags(t *testing.T) {
cmd := newListCommand(cli)
cmd.Flags().Set("filter", "image.name=ubuntu")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, strings.TrimSpace(cli.OutBuffer().String()), "network-list.golden")
}

View File

@ -6,10 +6,11 @@ import (
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/docker/cli/internal/test/testutil"
"github.com/stretchr/testify/assert"
)
func TestNodeDemoteErrors(t *testing.T) {
@ -45,7 +46,7 @@ func TestNodeDemoteErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -63,7 +64,7 @@ func TestNodeDemoteNoChange(t *testing.T) {
},
}))
cmd.SetArgs([]string{"nodeID"})
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}
func TestNodeDemoteMultipleNode(t *testing.T) {
@ -80,5 +81,5 @@ func TestNodeDemoteMultipleNode(t *testing.T) {
},
}))
cmd.SetArgs([]string{"nodeID1", "nodeID2"})
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}

View File

@ -11,8 +11,9 @@ import (
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/docker/cli/internal/test/testutil"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestNodeInspectErrors(t *testing.T) {
@ -75,7 +76,7 @@ func TestNodeInspectErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -112,7 +113,7 @@ func TestNodeInspectPretty(t *testing.T) {
cmd := newInspectCommand(cli)
cmd.SetArgs([]string{"nodeID"})
cmd.Flags().Set("pretty", "true")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-inspect-pretty.%s.golden", tc.name))
}
}

View File

@ -8,12 +8,11 @@ import (
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
is "github.com/gotestyourself/gotestyourself/assert/cmp"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/stretchr/testify/assert"
)
func TestNodeListErrorOnAPIFailure(t *testing.T) {
@ -49,7 +48,7 @@ func TestNodeListErrorOnAPIFailure(t *testing.T) {
})
cmd := newListCommand(cli)
cmd.SetOutput(ioutil.Discard)
assert.Error(t, cmd.Execute(), tc.expectedError)
assert.EqualError(t, cmd.Execute(), tc.expectedError)
}
}
@ -57,8 +56,8 @@ func TestNodeList(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
nodeListFunc: func() ([]swarm.Node, error) {
return []swarm.Node{
*Node(NodeID("nodeID1"), Hostname("node-2-foo"), Manager(Leader()), EngineVersion(".")),
*Node(NodeID("nodeID2"), Hostname("node-10-foo"), Manager(), EngineVersion("18.03.0-ce")),
*Node(NodeID("nodeID1"), Hostname("node-2-foo"), Manager(Leader())),
*Node(NodeID("nodeID2"), Hostname("node-10-foo"), Manager()),
*Node(NodeID("nodeID3"), Hostname("node-1-foo")),
}, nil
},
@ -72,7 +71,7 @@ func TestNodeList(t *testing.T) {
})
cmd := newListCommand(cli)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "node-list-sort.golden")
}
@ -86,8 +85,8 @@ func TestNodeListQuietShouldOnlyPrintIDs(t *testing.T) {
})
cmd := newListCommand(cli)
cmd.Flags().Set("quiet", "true")
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal(cli.OutBuffer().String(), "nodeID1\n"))
assert.NoError(t, cmd.Execute())
assert.Equal(t, cli.OutBuffer().String(), "nodeID1\n")
}
func TestNodeListDefaultFormatFromConfig(t *testing.T) {
@ -111,7 +110,7 @@ func TestNodeListDefaultFormatFromConfig(t *testing.T) {
NodesFormat: "{{.ID}}: {{.Hostname}} {{.Status}}/{{.ManagerStatus}}",
})
cmd := newListCommand(cli)
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "node-list-format-from-config.golden")
}
@ -136,6 +135,6 @@ func TestNodeListFormat(t *testing.T) {
})
cmd := newListCommand(cli)
cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}")
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "node-list-format-flag.golden")
}

View File

@ -6,10 +6,11 @@ import (
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/docker/cli/internal/test/testutil"
"github.com/stretchr/testify/assert"
)
func TestNodePromoteErrors(t *testing.T) {
@ -45,7 +46,7 @@ func TestNodePromoteErrors(t *testing.T) {
}))
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
@ -63,7 +64,7 @@ func TestNodePromoteNoChange(t *testing.T) {
},
}))
cmd.SetArgs([]string{"nodeID"})
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}
func TestNodePromoteMultipleNode(t *testing.T) {
@ -80,5 +81,5 @@ func TestNodePromoteMultipleNode(t *testing.T) {
},
}))
cmd.SetArgs([]string{"nodeID1", "nodeID2"})
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
}

View File

@ -12,8 +12,8 @@ import (
"github.com/pkg/errors"
// Import builders to get the builder function as package function
. "github.com/docker/cli/internal/test/builders"
"github.com/gotestyourself/gotestyourself/assert"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
func TestNodePsErrors(t *testing.T) {
@ -60,7 +60,7 @@ func TestNodePsErrors(t *testing.T) {
cmd.Flags().Set(key, value)
}
cmd.SetOutput(ioutil.Discard)
assert.Error(t, cmd.Execute(), tc.expectedError)
assert.EqualError(t, cmd.Execute(), tc.expectedError)
}
}
@ -122,7 +122,7 @@ func TestNodePs(t *testing.T) {
for key, value := range tc.flags {
cmd.Flags().Set(key, value)
}
assert.NilError(t, cmd.Execute())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-ps.%s.golden", tc.name))
}
}

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