Compare commits
33 Commits
v18.04.0-c
...
v18.02.0-c
| Author | SHA1 | Date | |
|---|---|---|---|
| fc4de447b5 | |||
| b89c843589 | |||
| 58dddd3699 | |||
| 1c6c49f915 | |||
| f968a2cc55 | |||
| 80e6ea3db6 | |||
| d055e4b6d9 | |||
| bbc43ecc52 | |||
| 51e5449bfa | |||
| 65553aa3a5 | |||
| 7a876b5739 | |||
| 6f67a5601a | |||
| b97aef8f2a | |||
| f25c14edf2 | |||
| 8bc38e16b2 | |||
| 30849d8ad6 | |||
| 24653a880d | |||
| f30580f501 | |||
| d3c944e007 | |||
| ba58fe58e7 | |||
| 9651b006e6 | |||
| 97eb7b67a3 | |||
| fcc1ab290b | |||
| 9849fadfbe | |||
| 49bb088afe | |||
| 3fba076ef0 | |||
| 5e1d90afd7 | |||
| f903039853 | |||
| 1dcf6652c8 | |||
| 3b28f86d44 | |||
| 1a2098cecf | |||
| 9d7b9c23f5 | |||
| ffef3ad3d7 |
118
CHANGELOG.md
118
CHANGELOG.md
@ -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)
|
||||
|
||||
8
components/cli/.gitignore
vendored
8
components/cli/.gitignore
vendored
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1 +1 @@
|
||||
18.04.0-ce
|
||||
18.02.0-ce
|
||||
|
||||
@ -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
|
||||
@ -128,7 +128,7 @@ Examples:
|
||||
{{ .Example }}
|
||||
|
||||
{{- end}}
|
||||
{{- if .HasAvailableFlags}}
|
||||
{{- if .HasFlags}}
|
||||
|
||||
Options:
|
||||
{{ wrappedFlagUsages . | trimRightSpace}}
|
||||
|
||||
@ -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"
|
||||
]`))
|
||||
]`)
|
||||
}
|
||||
|
||||
@ -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()))
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()))
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
@ -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())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
@ -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, ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
c1 c1
|
||||
c2 c2
|
||||
@ -1,2 +0,0 @@
|
||||
c1 value
|
||||
c2
|
||||
@ -1,2 +0,0 @@
|
||||
c1 busybox:latest some.label=value
|
||||
c2 busybox:latest foo=bar
|
||||
@ -1,2 +0,0 @@
|
||||
c1 busybox:latest some.label=value
|
||||
c2 busybox:latest foo=bar
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"))
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
})
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
IMAGE CREATED AT CREATED BY SIZE COMMENT
|
||||
abcdef 2017-01-01T12:00:03Z rose 0 new history item!
|
||||
@ -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 {
|
||||
|
||||
@ -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 := ®istrytypes.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")
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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()))
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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
Reference in New Issue
Block a user