Compare commits

...

179 Commits

Author SHA1 Message Date
Victor Vieux
1f9b3ef9e9 bump version to 1.13.0-rc2
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 21:23:23 -08:00
Victor Vieux
dba611d0f1 Merge pull request #28729 from aluzzardi/1.13.x-swarmkit-revendor-1109c363ce9d6400d42908ead944df4f7f788860
1.13.x: revendor swarmkit to 1109c363ce9d6400d42908ead944df4f7f788860
2016-11-22 20:34:10 -08:00
Andrea Luzzardi
2a80a863ca 1.13.x: revendor swarmkit to 1109c363ce9d6400d42908ead944df4f7f788860
Includes:
- https://github.com/docker/swarmkit/pull/1766
- https://github.com/docker/swarmkit/pull/1770

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
2016-11-22 18:50:46 -08:00
Evan Hazlett
01807b785f update secret inspect to support IDs
This updates secret inspect to support inspect by ID in addition to name
as well as inspecting multiple secrets.  This also cleans up the
help text for consistency.

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
(cherry picked from commit 70d2cefd51)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 18:43:53 -08:00
yupeng
b82be871ab context.Context should be the first parameter of a function
Signed-off-by: yupeng <yu.peng36@zte.com.cn>
(cherry picked from commit aff5dacec1)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 18:43:29 -08:00
Darren Stahl
00fd466e00 Swap usage of LazyDLL and LoadDLL to LazySystemDLL.
Signed-off-by: Darren Stahl <darst@microsoft.com>
(cherry picked from commit 22c83c567f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 18:40:35 -08:00
John Howard
f9f8a94f42 Windows: Native autogen
Signed-off-by: John Howard <jhoward@microsoft.com>
(cherry picked from commit 64cc7677bf)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 18:40:19 -08:00
Sebastiaan van Stijn
f531a8f06b Use official fedora 25 image
Fedora 25 was released today, and the official
image will be available soon.

This removes the temporary override, so that
we can build using the official image.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 545a2f009e)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 18:39:58 -08:00
Victor Vieux
44fe761b35 Merge pull request #28674 from vieux/1.13.0-rc2-cherrypicks
1.13.0-rc2 cherry-picks : part 3
2016-11-22 18:39:06 -08:00
cyli
38b0c93954 Update docs to reflect no longer displaying secret digest or size.
Signed-off-by: cyli <cyli@twistedmatrix.com>
(cherry picked from commit fe127b7eae)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:54:55 -08:00
cyli
aa6211e153 Do not display the digest or size of swarm secrets
Signed-off-by: cyli <cyli@twistedmatrix.com>
(cherry picked from commit 2c0613540a)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:54:50 -08:00
Ben Firshman
fad605e8c5 Add documentation for working on Engine API
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
(cherry picked from commit 109c54c481)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:52:48 -08:00
Ben Firshman
8738566853 Update swagger.yaml with changes to API
Up to and including 673c5ee559

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
(cherry picked from commit 44c50807c6)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:52:40 -08:00
Ben Firshman
f67b380325 Add version information to swagger.yaml
- Tidied up copy
- API version is now mandatory
- Links to previous API versions

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
(cherry picked from commit c97f67dbab)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:51:14 -08:00
Ben Firshman
520e601dc2 Rename Remote API to Engine API
Implementation of https://github.com/docker/docker/issues/28319

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
(cherry picked from commit f0d55cd081)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:49:58 -08:00
Ben Firshman
2ac34851ec Move API reference to new location
See: https://github.com/docker/docker.github.io/pull/606

Also:
- Add missing redirects to API reference pages
- Remove v1.25 and 1.26, because they are being replaced with
  swagger generated docs.
- Remove all other docs which aren't reference material, because
  this can live in docker/docker.github.io

Signed-off-by: Ben Firshman <ben@firshman.co.uk>
(cherry picked from commit 993854f58f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:48:38 -08:00
Jacob Tomlinson
a4aabe7286 Add concurrent uploads/downloads section
Document and link to the concurrent uploads/downloads daemon option.

Signed-off-by: Jacob Tomlinson <jacob@tom.linson.uk>
(cherry picked from commit b303381a4d)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:20:19 -08:00
Sebastiaan van Stijn
e8b27e7dc7 add note that windows does not support managed plugins
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f885463b58)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:19:48 -08:00
Antonio Murdaca
54518a214d hack/dockerfile/binaries-commits: use full commit hash for docker info
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
(cherry picked from commit fa15d5ed0f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:19:18 -08:00
yupeng
1053fdf27e error strings should not be capitalized or end with punctuation
Signed-off-by: yupeng <yu.peng36@zte.com.cn>
(cherry picked from commit fc11efa2db)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:18:49 -08:00
Andrea Luzzardi
43e6479fd4 service logs: Support no-follow mode
Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
(cherry picked from commit c2d435e4f0)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:18:09 -08:00
Darren Stahl
af08f44640 Revendor go-winio to v0.3.7
Signed-off-by: Darren Stahl <darst@microsoft.com>
(cherry picked from commit 873a26697d)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:17:33 -08:00
Tibor Vass
faab09c1aa plugins: misc fixes
Rename variable to reflect manifest -> config renaming
Populate Description fields when computing privileges.
Refactor/reuse code from daemon/oci_linux.go

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 6547609870)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:39 -08:00
Tibor Vass
561f2b27cb plugins: support for devices
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 53b9b99e5c)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:33 -08:00
Tibor Vass
63277b0aff vendor go-connections to error out if unix socket path is too long
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit e2e7ab655f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:24 -08:00
Tibor Vass
8f66c5e731 plugins: fix some tests
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit a08ffa0e93)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:16 -08:00
Tibor Vass
a275ca2093 plugins: support for host networking
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 99124c055a)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:10 -08:00
Tibor Vass
c28c63472a plugins: linux capabilities and device creation
In the plugin manifest, Capabilities has been moved to
Linux.Capabilities to avoid confusion with Interface.Types[i].Capability

A DeviceCreation boolean has also been added to the manifest. This could
be changed in the future to be specific to a major number.

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 9f239281b1)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:16:04 -08:00
Tibor Vass
fb3c3d7eea plugins: do not try to contact disabled plugin
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 84e58e2f89)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:15:58 -08:00
Darren Stahl
40a56f29e2 Ensure vmcompute.dll exists during daemon start
Signed-off-by: Darren Stahl <darst@microsoft.com>
(cherry picked from commit 000366f1a7)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:15:19 -08:00
Brian Goff
9e35dea991 Use container Mounts API for Swarm containers.
Instead of converting nicely typed service mounts into untyped `Binds`
when creating containers, use the new `Mounts` API which is a 1-1
mapping between service mounts and container mounts.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 821aeb6a6f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 16:13:28 -08:00
Victor Vieux
a65a2936ac Merge pull request #28676 from aboch/1.13.x-local
[1.13.x] Vendor libnetwork, netlink and libkv
2016-11-22 12:07:05 -08:00
Harald Albers
24628fd7a0 Fix typo in docs (Copmose)
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 2e12055687)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:27:57 -08:00
Vincent Demeester
9302b0f59c Update aanand/compose-file to a3e58764f50597b6217fec07e9bff7225c4a1719
This fixes services networks list to be ignored when loading.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 01b70a95c9)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:27:28 -08:00
Andrew Hsu
3168635120 skip solaris and allow dry run control points
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit f60541069c)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:27:01 -08:00
Steve Durrheimer
f46b2fd604 Add zsh completion for 'docker image ls --filter reference'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
(cherry picked from commit 15134b8d36)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:26:33 -08:00
Steve Durrheimer
702b03b6fc Add zsh completion for 'dockerd --userland-proxy-path'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
(cherry picked from commit 97e1892922)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:26:03 -08:00
Tonis Tiigi
3f0aa9bceb Fix race on sending stdin close event
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 4e262f6387)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:25:33 -08:00
Kenfe-Mickael Laventure
3ab3f953d7 Add generate.sh for armhf deb Dockerfiles
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
(cherry picked from commit 3b3cf87478)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:25:01 -08:00
Kenfe-Mickael Laventure
bab6bf1d5e Add support for armhf ubuntu-yakkety deb
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
(cherry picked from commit b118056241)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:24:55 -08:00
Darren Stahl
8ebbeda5a8 Update hcsshim
Signed-off-by: Darren Stahl <darst@microsoft.com>
(cherry picked from commit baac0ef67f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:24:21 -08:00
Reficul
ca51b2bf2c fix incorrect ErrConnectFailed comparison
Signed-off-by: Reficul <xuzhenglun@gmail.com>
(cherry picked from commit d5dc9b8b1f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:23:49 -08:00
Anusha Ragunathan
0403addc5f Add HTTP client timeout.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit 83ca993c15)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:23:20 -08:00
allencloud
abc0eea899 update secret create url for consistency
Signed-off-by: allencloud <allen.sun@daocloud.io>
(cherry picked from commit 86d7682843)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:22:39 -08:00
Brian Goff
b4c0b07d89 Handle run --rm against older daemons on the cli
For previous versions of Docker, `--rm` was handled client side, as such
there was no support in the daemon for it.
Now it is handled daemon side, but we still need to handle the case of a
newer client talking to an older daemon.

Falls back to client-side removal when the daemon does not support it.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit f4bb8c51de)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:22:08 -08:00
Harald Albers
2d5f5287c3 Add bash completion for docker build --network
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit d48e70843f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:21:36 -08:00
Felix Ruess
41b92e6f36 build debian package for armhf ubuntu-xenial
Signed-off-by: Felix Ruess <felix.ruess@gmail.com>
(cherry picked from commit 015e83a8da)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:21:10 -08:00
Qiang Huang
8079cc8147 Add make deb support for aarch64
Fixes: #27045

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
(cherry picked from commit a532ff8cc3)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-22 11:20:32 -08:00
Sebastiaan van Stijn
309662d03f Merge pull request #28680 from cyli/1.13.0-rc2-swarmkit-reendor
Include swarmkik dek rotation fixes in re-vendor
2016-11-22 10:50:33 +01:00
Andrew Hsu
e285a304db allow replacing httpredir or deb mirror in jessie
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
(cherry picked from commit 060196ee4c)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 17:29:22 -08:00
Harald Albers
6f03b32968 Add bash completion for docker images --filter reference
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit e84d62f6cb)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 17:28:46 -08:00
Vincent Demeester
2fb6810841 Add documentation about templating support on…
… services creation/update.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 4571ad05db)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 17:28:06 -08:00
Sebastiaan van Stijn
7e2522ec9f Update service ps reference for "--no-trunc"
The "--no-trunc" option toggles between showing/hiding
digests.

This updates the reference to show this difference.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 90993640f0)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 17:26:38 -08:00
Daniel Nephin
95398c33cc Move docker stack out of experimental
Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit 6df5baf30f)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:47:24 -08:00
Brian Goff
fcb64b6e08 re-vendor syslog log driver
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 00caf03132)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:46:48 -08:00
allencloud
2ecc8cd4bd judge manager if locked before parsing key
Signed-off-by: allencloud <allen.sun@daocloud.io>
(cherry picked from commit 89100c162b)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:46:22 -08:00
Evan Hazlett
bdc378e781 lint fixes
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
(cherry picked from commit eb036ea4db)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:45:45 -08:00
Evan Hazlett
01aab8baa3 do not force target type for secret references
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>

use secret store interface instead of embedded secret data into container

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
(cherry picked from commit bebd472e40)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:45:39 -08:00
Antonio Murdaca
0a5732d1cf api: types: keep info.SecurityOptions a string slice
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
(cherry picked from commit 514ca09426)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:45:05 -08:00
Aaron Lehmann
2737519f9a cli: Add valid suffixes for remaining duration options
A recent PR added `(ns|us|ms|s|m|h)` to the descriptions of some
duration options, but not all. Add it to the remaining options for
consistency.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
(cherry picked from commit 32b12a28fc)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 14:44:33 -08:00
Alessandro Boch
5c684ba099 Vendoring libkv @1d84310
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-11-21 14:15:33 -08:00
cyli
ba9726350d Include swarmkik dek rotation fixes in re-vendor
Signed-off-by: cyli <cyli@twistedmatrix.com>
2016-11-21 16:43:55 -05:00
Vincent Demeester
05eb544ae2 Do not panic if network is nil
network is `nil` if the following case:

```
services:
  foo:
    image: nginx
    networks:
      mynetwork:
```

It's a valid compose so we should not panic.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 158388ef8d)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:24 -08:00
Vincent Demeester
040d4ebd58 Update cli reference for docker {,stack} deploy
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 88cdfc512b)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:24 -08:00
Zhang Wei
db8991c957 Bugfix: set cli.manualOverride when env var not empty
If env var "DOCKER_API_VERSION" is specified by user, we'll set
`cli.manualOverride`, before this, this field is always true due to
wrong logic.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
(cherry picked from commit 4d54d30477)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:24 -08:00
zhukj
20f3c552e0 close the file
Signed-off-by: zhukj <zhu.kunjia@zte.com.cn>
(cherry picked from commit cf3ef262b1)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:23 -08:00
Harald Albers
a20820b05c Add bash completion for dockerd --userland-proxy-path
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 0d573a62f7)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:23 -08:00
Derek McGowan
68e99239d3 Update deprecation notes about v1 registry
Adds section about the hub deprecating the v1 protocol.
Adds note about intent to disable by default and remove support.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
(cherry picked from commit c8f826f407)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:23 -08:00
bbayani
a47957d6f6 Clarify that ipmasq rules are not added when iptables is false
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
(cherry picked from commit db3f06fd97)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:23 -08:00
Nishant Totla
5b81d7e8b5 Suppressing digest for docker service ls/ps
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
(cherry picked from commit e7d83fdb9a)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:23 -08:00
Yanqiang Miao
4acf6aa456 The type of 'ExportdPorts' should be 'nat.PortSet'
Signed-off-by: Yanqiang Miao <miao.yanqiang@zte.com.cn>
(cherry picked from commit c44c542d95)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 13:23:16 -08:00
Tom Denham
c707468415 Update tests to handle bug fix from libnetwork
Signed-off-by: Tom Denham <tom@tomdee.co.uk>
2016-11-21 13:21:02 -08:00
Alessandro Boch
a6e1ed7a51 Vendoring libnetwork @dd0ddde
Signed-off-by: Alessandro Boch <aboch@docker.com>
2016-11-21 13:20:57 -08:00
Tom Denham
2c832d7d66 Update netlink library (required for libnetwork)
Signed-off-by: Tom Denham <tom@tomdee.co.uk>
2016-11-21 11:58:37 -08:00
Vincent Demeester
f44e2dca56 Update compose-file to bc280351b9589b05c6da031d9f93c5c5d22db922
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit b0903c9db0)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 11:48:27 -08:00
Vincent Demeester
c8e2552827 Add support for healthcheck in composefile v3
`docker stack deploy` now supports a composefile v3 format that have a
healthcheck.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 3bd64de7a9)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 11:48:22 -08:00
Daniel Nephin
a0df810219 Default parallelism to 1.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit 7c1b399235)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 11:48:16 -08:00
Boaz Shuster
c050ee1917 Return an empty stats if the container is restarting
In case, a container is restarting indefinitely running
"docker stats --no-stream <restarting_container>" is suspended.

To fix this, the daemon makes sure the container is either not
running or restarting if `--no-stream` is set to true and if so
returns an empty stats.

Should fix #27772.

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
(cherry picked from commit 786a95493d)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-21 11:45:57 -08:00
Vincent Demeester
cbff9474d2 Merge pull request #28604 from aluzzardi/1.13-swarmkit-revendor
1.13.x: Re-vendor swarmkit to a2080913b9cf2cac309845a28902896d65d3f527
2016-11-21 15:09:35 +01:00
Brian Goff
f7ae8204cb Merge pull request #28489 from vieux/1.13.0-rc2-cherrypicks
1.13.0-rc2 cherry-picks : part 2
2016-11-20 10:43:55 -05:00
Sean McIntyre
2d632c34ce Add HostConfig.Tmpfs to docs for container creation remote API
Signed-off-by: Sean McIntyre <s.mcintyre@xverba.ca>
(cherry picked from commit 2c38d43eb5)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:52:14 -08:00
Victor Vieux
4edaaeb671 fix a few golint errors
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit 9c559e6d0b)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:50:06 -08:00
Brian Goff
d63582c131 Allow graphdriver plugins to use v2
Currently the plugin initialization is too late for a loaded v2 plugin
to be usable as a graph driver.

This moves the initialization up before we create the graph driver.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 020b051dfb)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:49:03 -08:00
Victor Vieux
e773e0e654 error on cli when trying to use experimental feature with non experimental daemon
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit 98bb08fe38)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:48:19 -08:00
yupeng
fe8e347741 Fix the typo
Signed-off-by: yupeng <yu.peng36@zte.com.cn>
(cherry picked from commit 9551dd03cf)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:47:44 -08:00
Andrea Luzzardi
0d94260458 router: Return explicit error rather than 404 for experimental.
Instead of not adding experimental routes at all, fail with an explicit
message if the daemon is not running in experimental mode.

Added the `router.Experimental` which does this automatically.

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
(cherry picked from commit 3976a33c1a)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:47:12 -08:00
Vincent Demeester
cdfde9ecc1 Use Container.Config.Shell instead of hardcoded…
… for healthcheck. It make the code a little cleaner and more
future/usage proof.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit 5f81cf11f6)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-19 23:45:58 -08:00
Victor Vieux
8e21480106 skip api/types/container/ (like golint) and fix one pkg
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit 79a891efb7)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 18:41:43 -08:00
Victor Vieux
fd75cc462f fix gofmt in master
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit 9f348d5625)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 15:22:42 -08:00
Sebastiaan van Stijn
c4fd597ab3 swap position of "host" and "ip"
the service definition uses the format as defined
in  http://man7.org/linux/man-pages/man5/hosts.5.html
(IP_address canonical_hostname [aliases...])

This format is the _reverse_ of the format used in
the container API.

Commit f32869d956
inadvertently used the incorrect order.

This fixes the order, and correctly sets it to;

    IP-Address hostname

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit f1b9df9172)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 15:15:51 -08:00
Kenfe-Mickael Laventure
47ccfcc09f Update containerd & runc
containerd: 03e5862ec0d8d3b3f750e19fca3ee367e13c090e
runc: 51371867a01c467f08af739783b8beafc15

Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
(cherry picked from commit 8b1aeb22fe)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 15:15:19 -08:00
Yong Tang
e3c24caf7a Fix several issues with go vet and go fmt
For some reason, `go vet` and `go fmt` validate does not capture
several issues.

The following was the output of `go vet`:
```
ubuntu@ubuntu:~/docker$ go vet ./... 2>&1 | grep -v ^vendor | grep -v '^exit status 1$'
cli/command/formatter/container_test.go:393: possible formatting directive in Log call
volume/volume_test.go:257: arg mp.RW for printf verb %s of wrong type: bool
```

The following was the output of `go fmt -s`:
```
ubuntu@ubuntu:~/docker$ gofmt -s -l . | grep -v ^vendor
cli/command/stack/list.go
daemon/commit.go
```

Fixed above issues with `go vet` and `go fmt -s`

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
(cherry picked from commit ace786e9d5)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 15:14:49 -08:00
Aaron Lehmann
d4392659f7 Return warnings from service create and service update when digest pinning fails
Modify the service update and create APIs to return optional warning
messages as part of the response. Populate these messages with an
informative reason when digest resolution fails.

This is a small API change, but significantly improves the UX. The user
can now get immediate feedback when they've specified a nonexistent
image or unreachable registry.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
(cherry picked from commit 948e60691e)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:57:11 -08:00
He Xin
649445a206 fix bugs 'fatal error: concurrent map read and map write' to change VolumeStore.globalLock type from Mutex to RWMutex, and add globalLock.RLock() for the read of names, refs, labels and options in VolumeStore
Signed-off-by: He Xin <he_xinworld@126.com>
(cherry picked from commit 19bd1cee23)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:54:40 -08:00
Yanqiang Miao
df8a5e48de Fix a comment error
Signed-off-by: Yanqiang Miao <miao.yanqiang@zte.com.cn>
(cherry picked from commit 19e2c9177a)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:54:23 -08:00
Michael Crosby
c0ea2c8498 Fix cfs period calculation
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
(cherry picked from commit aff99136b4)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:45:58 -08:00
Stephen J Day
ce22bc39dc api/server/httputils: service unavailable for disable swarm
When swarm-mode is disabled, we need to return an error indicating this.
406 was chosen for the "Not Acceptable" verbiage, but this code has
specific semantics in relation to the `Accept` header, which aren't
applicable here.

We now use a 503 for this case. While it is not a perfect match, it does
make it clear that the particular "service" (read: API endpoint) is not
available. The body of the message provides the user with enough
information to take action on it by enabling swarm-mode and ensuring the
service is available.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 1d90d76048)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:44:36 -08:00
Yong Tang
3e9dd55695 Use map[string]bool for preProcessor to ignore unknwon field
This fix is an attempt to address the issue raised in 28339. In
`docker ps`, the formatter needs to expose all fields of `types.Container`
to `preProcessor` so that template could be executed.

This direct exposing is unreliable and could cause issues as user may incorrectly
assume all fields in `types.Container` will be available for templating.

However, the purpose of `preProcessor` is to only find out if `.Size`
is defined (so that opts.size could be set accordingly).

This fix defines `preProcessor` as `map[string]bool` with a func `Size()`.
In this way, any unknown fields will be ignored.

This fix adds several test cases to the existing `TestBuildContainerListOptions`.

This fix fixes 28339.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
(cherry picked from commit 312cc7eebd)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:42:21 -08:00
Boaz Shuster
19d2e68fb8 Change the docker-tag usage text to be clearer
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
(cherry picked from commit 039aca05c2)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:41:48 -08:00
John Howard
530b7cb4a0 Windows: Allow user in builder
Signed-off-by: John Howard <jhoward@microsoft.com>
(cherry picked from commit a3c4ab9b65)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:41:13 -08:00
Nishant Totla
902774c871 Refactoring code for pinning image by digest
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
(cherry picked from commit dc1b6341b9)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:40:13 -08:00
Nishant Totla
1af49192e4 Updating docker/distribution vendoring
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
(cherry picked from commit d910781c66)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:40:06 -08:00
Andrea Luzzardi
0be7359265 1.13.x: Re-vendor swarmkit to a2080913b9cf2cac309845a28902896d65d3f527
Includes:
- https://github.com/docker/swarmkit/pull/1749
- https://github.com/docker/swarmkit/pull/1753
- https://github.com/docker/swarmkit/pull/1760
- https://github.com/docker/swarmkit/pull/1762
- https://github.com/docker/swarmkit/pull/1764
- https://github.com/docker/swarmkit/pull/1765

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
2016-11-18 13:39:53 -08:00
Yong Tang
e013d7c543 Fix error messages for --cpus from daemon
This fix fixes error messages for `--cpus` from daemon.

When `docker run` takes `--cpus`, it will translate into NanoCPUs
and pass the value to daemon. The `NanoCPU` is not visible to the user.
The error message generated from daemon used 'NanoCPU' which may cause
some confusion to the user.

This fix fixes this issue by returning the error in CPUs instead.

This fix fixes 28456.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
(cherry picked from commit d22ac2f3a0)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:38:21 -08:00
Tonis Tiigi
5e7e260bac Fix deadlock on cancelling healthcheck
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 89b1234737)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:37:44 -08:00
Vincent Demeester
20dd2d1e4e Update images cli reference with reference filter
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
(cherry picked from commit a0d7b34d9c)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:37:07 -08:00
John Howard
3d43caf6f6 Windows: Revert 27884
Signed-off-by: John Howard <jhoward@microsoft.com>
(cherry picked from commit 7e03ce3f13)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:36:37 -08:00
Anusha Ragunathan
3f6e6b3f2d Cleanup after plugin install.
During error cases, we dont cleanup correctly. This commit takes care
of removing the plugin, if there are errors after the pull passed. It
also shuts down the plugin, if there are errors after the plugin in the
enable path.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit 1144f8f1d4)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:36:09 -08:00
Aaron Lehmann
48c2da3cd5 api: Remove omitempty tag on Parallelism
It doesn't make sense to use omitempty here. 0 is a meaningful value and
it's different from the default. If someone sets Parallelism to 0, we
want to show that Parallelism is 0, not hide the field.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
(cherry picked from commit d8b8b12994)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:35:33 -08:00
Yong Tang
7ef4feaf38 Fix crash caused by docker service inspect --pretty
This fix tries to fix the crash caused by `docker service inspect --pretty`,
by performing necessary nil pointer check.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
(cherry picked from commit b6857e91c1)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:34:35 -08:00
Stephen J Day
8b9b8bd930 api/server/httputils: ensure consistent status code
Error code resolution is powered by string matching. Not the greatest
thing in the world and I hope no one is proud of this code, but it
works. However, because a map is used, the iteration order of the map is
random, such that if an error matches two of the snippets, it may return
a different error code depending on the seed of the hashmap. This change
converts it to use a slice instead.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit 3484e02590)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:34:05 -08:00
allencloud
cd587419d0 judge manager before unlocking
Signed-off-by: allencloud <allen.sun@daocloud.io>
(cherry picked from commit 972a246c67)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:33:07 -08:00
Brian Goff
10ce88227d Reduce spew data dumped
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 4130eb24e9)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:32:26 -08:00
Tom Wilkie
9f3c9209d0 s/bCap/bLen/
Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
(cherry picked from commit 3a05545851)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:31:39 -08:00
Tom Wilkie
f02e4e1900 Fix use of cap in MultiReadSeeker
Signed-off-by: Tom Wilkie <tom.wilkie@gmail.com>
(cherry picked from commit 158bb9bbd5)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:31:33 -08:00
Victor Vieux
411e0bdc8e refactor help func in CLI
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
(cherry picked from commit bf95472105)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:30:44 -08:00
Vincent Demeester
51dc584445 Update Tini to fix photon build-rpm compilation errors
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-11-18 13:29:20 -08:00
Akshay Karle
78fe91c31c fix a typo
Signed-off-by: Akshay Karle <akshay.a.karle@gmail.com>
2016-11-18 13:28:11 -08:00
allencloud
0b8f8876b9 fix typo
Signed-off-by: allencloud <allen.sun@daocloud.io>
(cherry picked from commit 1f039a66ac)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:27:01 -08:00
Justin Cormack
c125c131d7 Fix check config script on 4.8 kernels
DEVPTS_MULTIPLE_INSTANCES is no longer an option, it is always set, so
do not check for this post 4.8.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
(cherry picked from commit 228ee16df3)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:26:03 -08:00
Felipe Oliveira
0a9521d321 fix infinite recursion
Signed-off-by: Felipe Oliveira <felipeweb.programador@gmail.com>
(cherry picked from commit 271b1f2756)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-18 13:25:29 -08:00
Aaron Lehmann
88a45c4a1b Merge pull request #28525 from aluzzardi/swarmkit-revendor
1.13.x: Re-vendor SwarmKit to 577d6bf89a474d3f459804efc5f160ba9fff2b5d
2016-11-17 11:08:33 -08:00
Sebastiaan van Stijn
22f0055e18 Merge pull request #28433 from thaJeztah/docker-1.13-changelog-updates
Docker 1.13 changelog updates
2016-11-17 10:01:50 +01:00
Andrea Luzzardi
73bf1ec999 1.13.x: Re-vendor SwarmKit to 577d6bf89a474d3f459804efc5f160ba9fff2b5d
Includes https://github.com/docker/swarmkit/pull/1746

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
2016-11-16 18:10:07 -08:00
Tonis Tiigi
0269ac0494 Skip cli initialization for daemon command
Cli initialization pings back to remote API and
creates a deadlock if socket is already being
listened by systemd.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2016-11-16 17:10:48 -08:00
Victor Vieux
f2eeaed8a3 explicitly show plugins as unsupported on !linux
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2016-11-16 17:10:40 -08:00
Noah Treuhaft
43f1682cef Disable v1 protocol for the default registry
All images in the default registry (AKA docker.io, index.docker.io, and
registry-1.docker.io) are available via the v2 protocol, so there's no
reason to use the v1 protocol.  Disabling it prevents useless fallbacks.

Signed-off-by: Noah Treuhaft <noah.treuhaft@docker.com>
2016-11-16 17:10:33 -08:00
Riyaz Faizullabhoy
94c4cfc209 Edits to plugin docs after building authz plugin
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
2016-11-16 17:10:24 -08:00
Sebastiaan van Stijn
dc71b1425e Changelog updates
This adds some missing entries to the changelog,
and some smal fixes / inconsistencies.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-11-17 01:42:56 +01:00
Vincent Demeester
a51fe6b056 Update stats cli reference documentation
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2016-11-16 11:11:52 -08:00
Steve Durrheimer
1841986d17 Add zsh completion for 'docker system df'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-16 11:11:45 -08:00
Yanqiang Miao
0d815d9bb7 Remove redundant 'if' statement
Signed-off-by: Yanqiang Miao <miao.yanqiang@zte.com.cn>

update

Signed-off-by: Yanqiang Miao <miao.yanqiang@zte.com.cn>
2016-11-16 11:11:39 -08:00
Brian Goff
3b93497fdb Don't validate platform-dep tmpfs opts on client
Daemon still does validation and errors out on incorrect options.

Fixes an issue where non-Linux clients attempting to pass tmpfs options
on `docker run` to a Linux daemon will incorrectly error out.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-11-16 11:11:32 -08:00
Victor Vieux
44bb0bb7f2 update tini to a87614212b3a51a9cad57ff7989103a841546745
Signed-off-by: Victor Vieux <vieux@docker.com>
2016-11-16 11:11:22 -08:00
Yong Tang
896e4f2d75 Fix missing versions in example requests of api docs
It is not required to have version prefix for all the remote
APIs. Though there are still quite a few example requests
in api docs that does not have the version prefix.

This fix update the remote api docs to address this issue.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2016-11-16 11:07:38 -08:00
Yong Tang
7154093e59 Update docs for docker info for most recent changes.
This fix updates docs for `docker info` for most recent changes.
It also made several chagnes:
1. Replace 0.12.0-dev to 0.13.0 for api docs v1.24.
2. Replace 0.13.0-dev to 0.13.0 for api docs v1.25

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2016-11-16 11:06:12 -08:00
John Howard
dbf1900e8c Windows: Use sequential file access
Signed-off-by: John Howard <jhoward@microsoft.com>
2016-11-16 11:05:23 -08:00
allencloud
d1b1dea80f allow node update api receive node name and id prefix
Signed-off-by: allencloud <allen.sun@daocloud.io>
2016-11-16 10:59:21 -08:00
Victor Vieux
2dfa08bc50 Merge pull request #28408 from vieux/1.13.0-rc2-cherrypicks
1.13.0 rc2 cherrypicks
2016-11-16 10:50:34 -08:00
Tõnis Tiigi
f5afe63eb6 Merge pull request #28463 from aluzzardi/swarmkit-revendor
1.13.x: Revendor swarmkit to 3076318ec0327e22c837c2bfdfacea08124dc755
2016-11-15 21:41:12 -08:00
Andrea Luzzardi
7a457451f6 Revendor swarmkit to 3076318ec0327e22c837c2bfdfacea08124dc755
Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
2016-11-15 19:04:09 -08:00
Sebastiaan van Stijn
5c69e4fa94 Revert reference docs for ambient capabilities
This feature was reverted for docker 1.13
in c5251f7116,
so removing the documentation as well.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-11-15 13:59:39 -08:00
Jonathan Boulle
c102ab8711 man/docker: wrap lines consistently
Quite a few changes, as it seems like previous wrapping was done
manually, so it's all over the place.

As noted in #28424

Signed-off-by: Jonathan Boulle <jonathanboulle@gmail.com>
2016-11-15 13:58:43 -08:00
Jonathan Boulle
44b5bcd744 man page: consistent indents for flag descriptions
Signed-off-by: Jonathan Boulle <jonathanboulle@gmail.com>
2016-11-15 13:57:57 -08:00
yuexiao-wang
0f254ab8b9 Remove inexistent link and add related links
Signed-off-by: yuexiao-wang <wang.yuexiao@zte.com.cn>
2016-11-15 13:57:10 -08:00
bbayani
4d850bd49a Updated daemon documentation to clarify that live-restore is not suppoted on windows
Review comment implementation

Signed-off-by: bbayani <bhumikabayani@gmail.com>
2016-11-15 13:55:14 -08:00
John Howard
7346a6aebd Gitignore dockerversion\version_autogen_unix.go
Signed-off-by: John Howard <jhoward@microsoft.com>
2016-11-14 17:32:44 -08:00
Anusha Ragunathan
846b198dd7 Perform graceful shutdown during plugin disable.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
2016-11-14 17:31:00 -08:00
Steve Durrheimer
6c3744f4fc Add zsh completion for 'docker image build --network'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 17:04:08 -08:00
lixiaobing10051267
6e10c4c8b2 fix the wrong title with docker swarm
Signed-off-by: lixiaobing10051267 <li.xiaobing1@zte.com.cn>
2016-11-14 17:02:42 -08:00
Brian Goff
a9bbf92b3f Fix issue with missing fields for ps template
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-11-14 14:25:27 -08:00
Muayyad Alsadi
02c7b6ffad remove "starting with /"
Signed-off-by: Muayyad Alsadi <alsadi@gmail.com>
2016-11-14 14:22:24 -08:00
Muayyad Alsadi
d3ae1d7bd6 fixes #17734, clear message for host volumes not starting with /
Signed-off-by: Muayyad Alsadi <alsadi@gmail.com>
2016-11-14 14:22:22 -08:00
Steve Durrheimer
b1c96a73a3 Add zsh completion for 'docker service {create,update} --secret'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 14:18:12 -08:00
Steve Durrheimer
d114b7dc48 Add zsh completion for the new 'docker secret' command
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 14:17:36 -08:00
Steve Durrheimer
fd04a2db51 Add zsh completion for 'docker service' DNS settings
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 14:16:57 -08:00
Yong Tang
2c61e9c3bd Fix a small typo in docs/deprecated.md
A small typo in `docs/deprecated.md`.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2016-11-14 14:16:19 -08:00
Yong Tang
9ed0bb2d0a Update bash completion dns-options-add/rm -> dns-option-add/rm
In 28186, `dns-options-add/rm` has been changed to `dns-option-add/rm`
in `docker service create/update`, for the purpose of consistency.

This fix updates bash completion to remove extra `s`.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2016-11-14 14:15:31 -08:00
Harald Albers
ba5d2331d5 Add bash completion for DNS settings in services
Signed-off-by: Harald Albers <github@albersweb.de>
2016-11-14 14:14:52 -08:00
Harald Albers
6ec7c7a89c Add bash completion for docker service ps --all
Signed-off-by: Harald Albers <github@albersweb.de>
2016-11-14 14:13:10 -08:00
Steve Durrheimer
a2575eb741 Add zsh completion for 'docker service {create --port, update --port-{add,rm}}'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 14:12:08 -08:00
Harald Albers
4b003634bc Fix bash completion for docker ps --filter is-task
Signed-off-by: Harald Albers <github@albersweb.de>
2016-11-14 14:11:27 -08:00
Steve Durrheimer
580343247e Add zsh completion for 'docker image build --cache-from'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2016-11-14 14:10:44 -08:00
Harald Albers
261958bfa8 Add bash completion for managing ports in services
Bash completion for

- `docker service create --port`
- `docker service update --port-{add,rm}`

Signed-off-by: Harald Albers <github@albersweb.de>
2016-11-14 14:10:03 -08:00
Harald Albers
2da971cf06 Add bash completion for docker build --cache-from
Signed-off-by: Harald Albers <github@albersweb.de>
2016-11-14 14:09:02 -08:00
Brian Goff
285915755c Move StreamConfig out of runconfig
`StreamConfig` carries with it a dep on libcontainerd, which is used by
other projects, but libcontainerd doesn't compile on all platforms, so
move it to `github.com/docker/docker/container/stream`

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-11-14 14:03:05 -08:00
allencloud
9798cdd632 fix typo in node update docs
Signed-off-by: allencloud <allen.sun@daocloud.io>
2016-11-14 13:30:51 -08:00
yuexiao-wang
5060ff0d8d Remove duplicated document
Signed-off-by: yuexiao-wang <wang.yuexiao@zte.com.cn>
2016-11-14 13:29:51 -08:00
John Howard
4bfd3643da Extra v1.25 in API docs
Signed-off-by: John Howard <jhoward@microsoft.com>
2016-11-14 12:00:24 -08:00
Alexander Morozov
f3d628129e dockerversion: add other binaries to _lib.go
Otherwise it's impossible to build without autogen tag

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
2016-11-14 11:59:08 -08:00
Shayne Wang
19c16fd95e Change reading order of tailfile
change reading order from beginning at the end to beginning at a buffer start
added intergration tests for boundary cases
Removed whitespace
Signed-off-by: Shayne Wang <shaynexwang@gmail.com>
2016-11-14 11:58:01 -08:00
allencloud
89c4410799 judge manager before getting secret
Signed-off-by: allencloud <allen.sun@daocloud.io>
2016-11-14 11:54:29 -08:00
Kenfe-Mickael Laventure
70e7fcc595 Remove extra binaries commit variables from windows build
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
2016-11-14 11:52:45 -08:00
Kenfe-Mickael Laventure
03c8f0cda1 Fix version detection for docker-init
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
2016-11-14 11:52:39 -08:00
Tonis Tiigi
22c09cf902 Skip plugin tests if not in amd64
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2016-11-14 11:50:20 -08:00
Evan Hazlett
8ac6b97189 only check secrets for service create if requested
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
2016-11-14 11:48:48 -08:00
Anusha Ragunathan
a7a8fa0e6b Add docs for plugin push
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
2016-11-14 11:34:28 -08:00
John Stephens
16d4e6395e Show experimental flags and subcommands if enabled
Signed-off-by: John Stephens <johnstep@docker.com>
2016-11-14 11:34:17 -08:00
Victor Vieux
75fd88ba89 bump version to 1.13.0-rc1
Signed-off-by: Victor Vieux <vieux@docker.com>
2016-11-11 02:27:33 -08:00
348 changed files with 5865 additions and 9018 deletions

1
.gitignore vendored
View File

@@ -17,6 +17,7 @@ bundles/
cmd/dockerd/dockerd
cmd/docker/docker
dockerversion/version_autogen.go
dockerversion/version_autogen_unix.go
docs/AWS_S3_BUCKET
docs/GITCOMMIT
docs/GIT_BRANCH

View File

@@ -20,8 +20,9 @@ be found.
- Fix builder cache issue on Windows [#27805](https://github.com/docker/docker/pull/27805)
### Contrib
+ Add support for building docker debs for Ubuntu Xenial on PPC64 [#23438](https://github.com/docker/docker/pull/23438)
+ Add support for building docker debs for Ubuntu Xenial on s390x [#26104](https://github.com/docker/docker/pull/26104)
+ Add support for building docker debs for Ubuntu 16.04 Xenial on PPC64LE [#23438](https://github.com/docker/docker/pull/23438)
+ Add support for building docker debs for Ubuntu 16.04 Xenial on s390x [#26104](https://github.com/docker/docker/pull/26104)
+ Add support for building docker debs for Ubuntu 16.10 Yakkety Yak on PPC64LE [#28046](https://github.com/docker/docker/pull/28046)
- Add RPM builder for VMWare Photon OS [#24116](https://github.com/docker/docker/pull/24116)
+ Add shell completions to tgz [#27735](https://github.com/docker/docker/pull/27735)
* Update the install script to allow using the mirror in China [#27005](https://github.com/docker/docker/pull/27005)
@@ -52,6 +53,7 @@ be found.
+ Unix socket support for fluentd [#26088](https://github.com/docker/docker/pull/26088)
* Enable fluentd logging driver on Windows [#28189](https://github.com/docker/docker/pull/28189)
- Sanitize docker labels when used as journald field names [#23725](https://github.com/docker/docker/pull/23725)
- Fix an issue where `docker logs --tail` returned less lines than expected [#28203](https://github.com/docker/docker/pull/28203)
### Networking
@@ -132,7 +134,7 @@ be found.
- Fix a race condition between device deferred removal and resume device, when using the devicemapper graphdriver [#23497](https://github.com/docker/docker/pull/23497)
- Add `docker stats` support in Windows [#25737](https://github.com/docker/docker/pull/25737)
- Allow using `--pid=host` and `--net=host` when `--userns=host` [#25771](https://github.com/docker/docker/pull/25771)
+ (experimental) Add metrics output [#25820](https://github.com/docker/docker/pull/25820)
+ (experimental) Add metrics (Prometheus) output for basic `container`, `image`, and `daemon` operations [#25820](https://github.com/docker/docker/pull/25820)
- Fix issue in `docker stats` with `NetworkDisabled=true` [#25905](https://github.com/docker/docker/pull/25905)
+ Add `docker top` support in Windows [#25891](https://github.com/docker/docker/pull/25891)
+ Record pid of exec'd process [#27470](https://github.com/docker/docker/pull/27470)
@@ -150,9 +152,10 @@ be found.
### Swarm Mode
+ Add secret management [#27794](https://github.com/docker/docker/pull/27794)
+ Add support for templating service options (hostname, mounts, and environment variables) [#28025](https://github.com/docker/docker/pull/28025)
* Display the endpoint mode in the output of `docker service inspect --pretty` [#26906](https://github.com/docker/docker/pull/26906)
* Make `docker service ps` output more bearable by shortening service IDs in task names [#28088](https://github.com/docker/docker/pull/28088)
* `docker node ps` now defaults to the current node [#25214](https://github.com/docker/docker/pull/25214)
* Make `docker node ps` default to the current node [#25214](https://github.com/docker/docker/pull/25214)
+ Add `-a`/`--all` flags to `docker service ps` and `docker node ps` to show all results [#25983](https://github.com/docker/docker/pull/25983)
+ Add `--dns`, -`-dns-opt`, and `--dns-search` to service create. [#27567](https://github.com/docker/docker/pull/27567)
+ Add `--force` to `docker service update` [#27596](https://github.com/docker/docker/pull/27596)
@@ -161,17 +164,19 @@ be found.
- Remove `--name` flag from `docker service update`. This flag is only functional on `docker service create`, so was removed from the `update` command [#26988](https://github.com/docker/docker/pull/26988)
- Fix worker nodes failing to recover because of transient networking issues [#26646](https://github.com/docker/docker/issues/26646)
* Add support for health aware load balancing and DNS records [#27279](https://github.com/docker/docker/pull/27279)
* Add `--hostname` to `docker service create` [#27857](https://github.com/docker/docker/pull/27857)
- Add `--tty` flag to `docker service create`/`update` [#28076](https://github.com/docker/docker/pull/28076)
+ Add `--hostname` to `docker service create` [#27857](https://github.com/docker/docker/pull/27857)
+ Add `--host` to `docker service create`, and `--host-add`, `--host-rm` to `docker service update` [#28031](https://github.com/docker/docker/pull/28031)
+ Add `--tty` flag to `docker service create`/`update` [#28076](https://github.com/docker/docker/pull/28076)
* Autodetect, store, and expose node IP address as seen by the manager [#27910](https://github.com/docker/docker/pull/27910)
* Encryption at rest of manager keys and raft data [#27967](https://github.com/docker/docker/pull/27967)
+ Add `--update-max-failure-ratio`, `--update-monitor` and `--rollback` flags to `docker service update` [#26421](https://github.com/docker/docker/pull/26421)
- Fix an issue with address autodiscovery on `docker swarm init` running inside a container [#26457](https://github.com/docker/docker/pull/26457)
+ (experimental) Add `docker service logs` command to view logs for a service [#28089](https://github.com/docker/docker/pull/28089)
- Pin images by digest for `docker service create` and `update` [#28173](https://github.com/docker/docker/pull/28173)
- Add short (`-f`) flag for `docker node rm --force` and `docker swarm leave --force` [#28196](https://github.com/docker/docker/pull/28196)
+ Don't repull image if pinned by digest [#28265](https://github.com/docker/docker/pull/28265)
+ swarm-mode support for indows [#27838](https://github.com/docker/docker/pull/27838)
+ Pin images by digest for `docker service create` and `update` [#28173](https://github.com/docker/docker/pull/28173)
* Add short (`-f`) flag for `docker node rm --force` and `docker swarm leave --force` [#28196](https://github.com/docker/docker/pull/28196)
+ Add options to customize Raft snapshots (`--max-snapshots`, `--snapshot-interval`) [#27997](https://github.com/docker/docker/pull/27997)
- Don't repull image if pinned by digest [#28265](https://github.com/docker/docker/pull/28265)
+ Swarm-mode support for Windows [#27838](https://github.com/docker/docker/pull/27838)
### Volume
@@ -193,9 +198,10 @@ be found.
- Remove Ubuntu 15.10 (Wily Werewolf) as supported platform. Ubuntu 15.10 is EOL, and no longer receives updates [#27042](https://github.com/docker/docker/pull/27042)
- Remove Fedora 22 as supported platform. Fedora 22 is EOL, and no longer receives updates [#27432](https://github.com/docker/docker/pull/27432)
- Deprecate the `repo:shortid` syntax on `docker pull` [#27207](https://github.com/docker/docker/pull/27207)
- Deprecate backing filesystem without d_type for overlay/overlay2 storage drivers [#27433](https://github.com/docker/docker/pull/27433)
- Deprecate MAINTAINER in Dockerfile [#25466](https://github.com/docker/docker/pull/25466)
- Deprecated filter param for endpoint `/images/json` [#27872](https://github.com/docker/docker/pull/27872)
- Deprecate backing filesystem without `d_type` for overlay and overlay2 storage drivers [#27433](https://github.com/docker/docker/pull/27433)
- Deprecate `MAINTAINER` in Dockerfile [#25466](https://github.com/docker/docker/pull/25466)
- Deprecate `filter` param for endpoint `/images/json` [#27872](https://github.com/docker/docker/pull/27872)
- Deprecate setting duplicate engine labels [#24533](https://github.com/docker/docker/pull/24533)
## 1.12.3 (2016-10-26)

View File

@@ -25,16 +25,15 @@
FROM debian:jessie
# allow replacing httpredir or deb mirror
ARG APT_MIRROR=deb.debian.org
RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
# Add zfs ppa
RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61 \
|| apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys E871F18B51E0147C77796AC81196BA81F6B0FC61
RUN echo deb http://ppa.launchpad.net/zfs-native/stable/ubuntu trusty main > /etc/apt/sources.list.d/zfs.list
# Allow replacing httpredir mirror
ARG APT_MIRROR=httpredir.debian.org
RUN sed -i s/httpredir.debian.org/$APT_MIRROR/g /etc/apt/sources.list
# Packaged dependencies
RUN apt-get update && apt-get install -y \
apparmor \

View File

@@ -17,6 +17,10 @@
FROM armhf/debian:jessie
# allow replacing httpredir or deb mirror
ARG APT_MIRROR=deb.debian.org
RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
# Packaged dependencies
RUN apt-get update && apt-get install -y \
apparmor \

View File

@@ -7,6 +7,10 @@
FROM debian:jessie
# allow replacing httpredir or deb mirror
ARG APT_MIRROR=deb.debian.org
RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
# Compile and runtime deps
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#build-dependencies
# https://github.com/docker/docker/blob/master/project/PACKAGERS.md#runtime-dependencies

View File

@@ -1 +1 @@
1.13.0-dev
1.13.0-rc2

View File

@@ -1,5 +1,42 @@
This directory contains code pertaining to the Docker API:
# Working on the Engine API
- Used by the docker client when communicating with the docker daemon
The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon.
- Used by third party tools wishing to interface with the docker daemon
It consists of various components in this repository:
- `api/swagger.yaml` A Swagger definition of the API.
- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this.
- `cli/` The command-line client.
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
- `daemon/` The daemon, which serves the API.
## Swagger definition
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
1. To automatically generate documentation.
2. To automatically generate the Go server and client. (A work-in-progress.)
3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc.
## Updating the API documentation
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, you'll need to edit this file to represent the change in the documentation.
The file is split into two main sections:
- `definitions`, which defines re-usable objects used in requests and responses
- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable)
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919)
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful for when you are making edits to ensure you are doing the right thing.
## Viewing the API documentation
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
All the documentation generation is done in the documentation repository, [docker/docker.github.io](https://github.com/docker/docker.github.io). The Swagger definition is vendored periodically into this repository, but you can manually copy over the Swagger definition to test changes.
Copy `api/swagger.yaml` in this repository to `engine/api/[VERSION_NUMBER]/swagger.yaml` in the documentation repository, overwriting what is already there. Then, run `docker-compose up` in the documentation repository and browse to [http://localhost:4000/engine/api/](http://localhost:4000/engine/api/) when it finishes rendering.

View File

@@ -28,7 +28,7 @@ type inputValidationError interface {
IsValidationError() bool
}
// GetHTTPErrorStatusCode retrieve status code from error message
// GetHTTPErrorStatusCode retrieves status code from error message
func GetHTTPErrorStatusCode(err error) int {
if err == nil {
logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling")
@@ -49,20 +49,23 @@ func GetHTTPErrorStatusCode(err error) int {
// If we need to differentiate between different possible error types,
// we should create appropriate error types that implement the httpStatusError interface.
errStr := strings.ToLower(errMsg)
for keyword, status := range map[string]int{
"not found": http.StatusNotFound,
"no such": http.StatusNotFound,
"bad parameter": http.StatusBadRequest,
"no command": http.StatusBadRequest,
"conflict": http.StatusConflict,
"impossible": http.StatusNotAcceptable,
"wrong login/password": http.StatusUnauthorized,
"unauthorized": http.StatusUnauthorized,
"hasn't been activated": http.StatusForbidden,
"this node": http.StatusNotAcceptable,
for _, status := range []struct {
keyword string
code int
}{
{"not found", http.StatusNotFound},
{"no such", http.StatusNotFound},
{"bad parameter", http.StatusBadRequest},
{"no command", http.StatusBadRequest},
{"conflict", http.StatusConflict},
{"impossible", http.StatusNotAcceptable},
{"wrong login/password", http.StatusUnauthorized},
{"unauthorized", http.StatusUnauthorized},
{"hasn't been activated", http.StatusForbidden},
{"this node", http.StatusServiceUnavailable},
} {
if strings.Contains(errStr, keyword) {
statusCode = status
if strings.Contains(errStr, status.keyword) {
statusCode = status.code
break
}
}

View File

@@ -29,8 +29,8 @@ func (r *checkpointRouter) Routes() []router.Route {
func (r *checkpointRouter) initRoutes() {
r.routes = []router.Route{
router.NewGetRoute("/containers/{name:.*}/checkpoints", r.getContainerCheckpoints),
router.NewPostRoute("/containers/{name:.*}/checkpoints", r.postContainerCheckpoint),
router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", r.deleteContainerCheckpoint),
router.Experimental(router.NewGetRoute("/containers/{name:.*}/checkpoints", r.getContainerCheckpoints)),
router.Experimental(router.NewPostRoute("/containers/{name:.*}/checkpoints", r.postContainerCheckpoint)),
router.Experimental(router.NewDeleteRoute("/containers/{name}/checkpoints/{checkpoint}", r.deleteContainerCheckpoint)),
}
}

View File

@@ -0,0 +1,67 @@
package router
import (
"errors"
"net/http"
"golang.org/x/net/context"
apierrors "github.com/docker/docker/api/errors"
"github.com/docker/docker/api/server/httputils"
)
var (
errExperimentalFeature = errors.New("This experimental feature is disabled by default. Start the Docker daemon with --experimental in order to enable it.")
)
// ExperimentalRoute defines an experimental API route that can be enabled or disabled.
type ExperimentalRoute interface {
Route
Enable()
Disable()
}
// experimentalRoute defines an experimental API route that can be enabled or disabled.
// It implements ExperimentalRoute
type experimentalRoute struct {
local Route
handler httputils.APIFunc
}
// Enable enables this experimental route
func (r *experimentalRoute) Enable() {
r.handler = r.local.Handler()
}
// Disable disables the experimental route
func (r *experimentalRoute) Disable() {
r.handler = experimentalHandler
}
func experimentalHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
return apierrors.NewErrorWithStatusCode(errExperimentalFeature, http.StatusNotImplemented)
}
// Handler returns returns the APIFunc to let the server wrap it in middlewares.
func (r *experimentalRoute) Handler() httputils.APIFunc {
return r.handler
}
// Method returns the http method that the route responds to.
func (r *experimentalRoute) Method() string {
return r.local.Method()
}
// Path returns the subpath where the route responds to.
func (r *experimentalRoute) Path() string {
return r.local.Path()
}
// Experimental will mark a route as experimental.
func Experimental(r Route) Route {
return &experimentalRoute{
local: r,
handler: experimentalHandler,
}
}

View File

@@ -11,7 +11,7 @@ import (
// Backend for Plugin
type Backend interface {
Disable(name string) error
Enable(name string) error
Enable(name string, config *enginetypes.PluginEnableConfig) error
List() ([]enginetypes.Plugin, error)
Inspect(name string) (enginetypes.Plugin, error)
Remove(name string, config *enginetypes.PluginRmConfig) error

View File

@@ -4,6 +4,7 @@ import (
"encoding/base64"
"encoding/json"
"net/http"
"strconv"
"strings"
"github.com/docker/docker/api/server/httputils"
@@ -56,7 +57,18 @@ func (pr *pluginRouter) createPlugin(ctx context.Context, w http.ResponseWriter,
}
func (pr *pluginRouter) enablePlugin(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
return pr.backend.Enable(vars["name"])
if err := httputils.ParseForm(r); err != nil {
return err
}
name := vars["name"]
timeout, err := strconv.Atoi(r.Form.Get("timeout"))
if err != nil {
return err
}
config := &types.PluginEnableConfig{Timeout: timeout}
return pr.backend.Enable(name, config)
}
func (pr *pluginRouter) disablePlugin(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {

View File

@@ -18,8 +18,8 @@ type Backend interface {
UnlockSwarm(req types.UnlockRequest) error
GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
GetService(string) (types.Service, error)
CreateService(types.ServiceSpec, string) (string, error)
UpdateService(string, uint64, types.ServiceSpec, string, string) error
CreateService(types.ServiceSpec, string) (*basictypes.ServiceCreateResponse, error)
UpdateService(string, uint64, types.ServiceSpec, string, string) (*basictypes.ServiceUpdateResponse, error)
RemoveService(string) error
ServiceLogs(context.Context, string, *backend.ContainerLogsConfig, chan struct{}) error
GetNodes(basictypes.NodeListOptions) ([]types.Node, error)

View File

@@ -1,9 +1,6 @@
package swarm
import (
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/daemon"
)
import "github.com/docker/docker/api/server/router"
// swarmRouter is a router to talk with the build controller
type swarmRouter struct {
@@ -12,14 +9,11 @@ type swarmRouter struct {
}
// NewRouter initializes a new build router
func NewRouter(d *daemon.Daemon, b Backend) router.Router {
func NewRouter(b Backend) router.Router {
r := &swarmRouter{
backend: b,
}
r.initRoutes()
if d.HasExperimental() {
r.addExperimentalRoutes()
}
return r
}
@@ -28,12 +22,6 @@ func (sr *swarmRouter) Routes() []router.Route {
return sr.routes
}
func (sr *swarmRouter) addExperimentalRoutes() {
sr.routes = append(sr.routes,
router.Cancellable(router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs)),
)
}
func (sr *swarmRouter) initRoutes() {
sr.routes = []router.Route{
router.NewPostRoute("/swarm/init", sr.initCluster),
@@ -48,6 +36,7 @@ func (sr *swarmRouter) initRoutes() {
router.NewPostRoute("/services/create", sr.createService),
router.NewPostRoute("/services/{id}/update", sr.updateService),
router.NewDeleteRoute("/services/{id}", sr.removeService),
router.Experimental(router.Cancellable(router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs))),
router.NewGetRoute("/nodes", sr.getNodes),
router.NewGetRoute("/nodes/{id}", sr.getNode),
router.NewDeleteRoute("/nodes/{id}", sr.removeNode),
@@ -55,7 +44,7 @@ func (sr *swarmRouter) initRoutes() {
router.NewGetRoute("/tasks", sr.getTasks),
router.NewGetRoute("/tasks/{id}", sr.getTask),
router.NewGetRoute("/secrets", sr.getSecrets),
router.NewPostRoute("/secrets", sr.createSecret),
router.NewPostRoute("/secrets/create", sr.createSecret),
router.NewDeleteRoute("/secrets/{id}", sr.removeSecret),
router.NewGetRoute("/secrets/{id}", sr.getSecret),
router.NewPostRoute("/secrets/{id}/update", sr.updateSecret),

View File

@@ -166,15 +166,13 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter,
// Get returns "" if the header does not exist
encodedAuth := r.Header.Get("X-Registry-Auth")
id, err := sr.backend.CreateService(service, encodedAuth)
resp, err := sr.backend.CreateService(service, encodedAuth)
if err != nil {
logrus.Errorf("Error creating service %s: %v", service.Name, err)
return err
}
return httputils.WriteJSON(w, http.StatusCreated, &basictypes.ServiceCreateResponse{
ID: id,
})
return httputils.WriteJSON(w, http.StatusCreated, resp)
}
func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -194,11 +192,12 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
registryAuthFrom := r.URL.Query().Get("registryAuthFrom")
if err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth, registryAuthFrom); err != nil {
resp, err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth, registryAuthFrom)
if err != nil {
logrus.Errorf("Error updating service %s: %v", vars["id"], err)
return err
}
return nil
return httputils.WriteJSON(w, http.StatusOK, resp)
}
func (sr *swarmRouter) removeService(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -238,10 +237,6 @@ func (sr *swarmRouter) getServiceLogs(ctx context.Context, w http.ResponseWriter
OutStream: w,
}
if !logsConfig.Follow {
return fmt.Errorf("Bad parameters: Only follow mode is currently supported")
}
if logsConfig.Details {
return fmt.Errorf("Bad parameters: details is not currently supported")
}

View File

@@ -16,7 +16,6 @@ import (
"github.com/docker/docker/api/types/registry"
timetypes "github.com/docker/docker/api/types/time"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/api/types/versions/v1p24"
"github.com/docker/docker/pkg/ioutils"
"golang.org/x/net/context"
)
@@ -42,16 +41,24 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") {
// TODO: handle this conversion in engine-api
oldInfo := &v1p24.Info{
InfoBase: info.InfoBase,
type oldInfo struct {
*types.Info
ExecutionDriver string
}
old := &oldInfo{
Info: info,
ExecutionDriver: "<not supported>",
}
for _, s := range info.SecurityOptions {
if s.Key == "Name" {
oldInfo.SecurityOptions = append(oldInfo.SecurityOptions, s.Value)
}
nameOnlySecurityOptions := []string{}
kvSecOpts, err := types.DecodeSecurityOptions(old.SecurityOptions)
if err != nil {
return err
}
return httputils.WriteJSON(w, http.StatusOK, oldInfo)
for _, s := range kvSecOpts {
nameOnlySecurityOptions = append(nameOnlySecurityOptions, s.Name)
}
old.SecurityOptions = nameOnlySecurityOptions
return httputils.WriteJSON(w, http.StatusOK, old)
}
return httputils.WriteJSON(w, http.StatusOK, info)
}

View File

@@ -102,7 +102,7 @@ func (s *Server) serveAPI() error {
}
// HTTPServer contains an instance of http server and the listener.
// srv *http.Server, contains configuration to create a http server and a mux router with all api end points.
// srv *http.Server, contains configuration to create an http server and a mux router with all api end points.
// l net.Listener, is a TCP or Socket listener that dispatches incoming request to the router.
type HTTPServer struct {
srv *http.Server

View File

@@ -10,18 +10,18 @@ consumes:
- "text/plain"
basePath: "/v1.25"
info:
title: "Docker Remote API"
title: "Docker Engine API"
version: "1.25"
x-logo:
url: "https://docs.docker.com/images/logo-docker-main.png"
description: |
The Docker API is an HTTP REST API served by Docker Engine. It is the API the Docker client uses to communicate with the Engine, so everything the Docker client can do can be done with the API.
The Engine API is an HTTP API served by Docker Engine. It is the API the Docker client uses to communicate with the Engine, so everything the Docker client can do can be done with the API.
Most of the client's commands map directly to API endpoints (e.g. `docker ps` is `GET /containers/json`). The notable exception is running containers, which consists of several API calls. [There is example of using `curl` to run a container in the SDK documentation.](#TODO)
Most of the client's commands map directly to API endpoints (e.g. `docker ps` is `GET /containers/json`). The notable exception is running containers, which consists of several API calls.
# Errors
The Remote API uses standard HTTP status codes to indicate the success or failure of the API call. The body of the response will be JSON in the following format:
The API uses standard HTTP status codes to indicate the success or failure of the API call. The body of the response will be JSON in the following format:
```
{
@@ -31,12 +31,28 @@ info:
# Versioning
The API is usually changed in each release of Docker. If you want to write a client that doesn't break when connecting to newer Docker releases, you can lock to a specific API version.
The API is usually changed in each release of Docker, so API calls are versioned to ensure that clients don't break.
For Docker 1.13, the API version is 1.25. To lock to this version, you prefix the URL with `/v1.25`. For example, calling `/info` is the same as calling `/v1.25/info`.
For Docker Engine 1.13, the API version is 1.25. To lock to this version, you prefix the URL with `/v1.25`. For example, calling `/info` is the same as calling `/v1.25/info`.
Engine releases in the near future should support this version of the API, so your client will continue to work even if it is talking to a newer Engine.
In previous versions of Docker, it was possible to access the API without providing a version. This behaviour is now deprecated will be removed in a future version of Docker.
The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons.
This documentation is for version 1.25 of the API, which was introduced with Docker 1.13. Use this table to find documentation for previous versions of the API:
Docker version | API version | Changes
----------------|-------------|---------
1.12.x | [1.24](/engine/api/v1.24/) | [API changes](/engine/api/version-history/#v1-24-api-changes)
1.11.x | [1.23](/engine/api/v1.23/) | [API changes](/engine/api/version-history/#v1-23-api-changes)
1.10.x | [1.22](/engine/api/v1.22/) | [API changes](/engine/api/version-history/#v1-22-api-changes)
1.9.x | [1.21](/engine/api/v1.21/) | [API changes](/engine/api/version-history/#v1-21-api-changes)
1.8.x | [1.20](/engine/api/v1.20/) | [API changes](/engine/api/version-history/#v1-20-api-changes)
1.7.x | [1.19](/engine/api/v1.19/) | [API changes](/engine/api/version-history/#v1-19-api-changes)
1.6.x | [1.18](/engine/api/v1.18/) | [API changes](/engine/api/version-history/#v1-18-api-changes)
# Authentication
Authentication for registries is handled client side. The client has to send authentication details to various endpoints that need to communicate with registries, such as `POST /images/(name)/push`. These are sent as `X-Registry-Auth` header as a Base64 encoded (JSON) string with the following structure:
@@ -543,7 +559,8 @@ definitions:
type: "string"
Tmpfs:
type: "object"
description: "List of tmpfs mounts for this container."
description: |
A map of container directories which should be replaced by tmpfs mounts, and their corresponding mount options. For example: `{ "/run": "rw,noexec,nosuid,size=65536k" }`.
additionalProperties:
type: "string"
UTSMode:
@@ -1262,7 +1279,7 @@ definitions:
x-nullable: false
Plugin:
description: "A plugin for the Remote API"
description: "A plugin for the Engine API"
type: "object"
required: [Settings, Enabled, Config, Name, Tag]
properties:
@@ -1311,9 +1328,8 @@ definitions:
- Entrypoint
- Workdir
- Network
- Capabilities
- Linux
- Mounts
- Devices
- Env
- Args
properties:
@@ -1361,18 +1377,26 @@ definitions:
Type:
x-nullable: false
type: "string"
Capabilities:
type: "array"
items:
type: "string"
Linux:
type: "object"
x-nullable: false
required: [Capabilities, DeviceCreation, Devices]
properties:
Capabilities:
type: "array"
items:
type: "string"
DeviceCreation:
type: "boolean"
x-nullable: false
Devices:
type: "array"
items:
$ref: "#/definitions/PluginDevice"
Mounts:
type: "array"
items:
$ref: "#/definitions/PluginMount"
Devices:
type: "array"
items:
$ref: "#/definitions/PluginDevice"
Env:
type: "array"
items:
@@ -1684,6 +1708,13 @@ definitions:
type: "object"
additionalProperties:
type: "string"
EncryptionConfig:
description: "Parameters related to encryption-at-rest."
type: "object"
properties:
AutoLockManagers:
description: "If set, generate a key and use it to lock data stored on the managers."
type: "boolean"
TaskDefaults:
description: "Defaults for creating tasks in this cluster."
type: "object"
@@ -1717,6 +1748,8 @@ definitions:
JoinTokens:
Worker: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx"
Manager: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
EncryptionConfig:
AutoLockManagers: false
# The Swarm information for `GET /info`. It is the same as `GET /swarm`, but
# without `JoinTokens`.
ClusterInfo:
@@ -1787,6 +1820,25 @@ definitions:
description: "Amount of time to wait for the container to terminate before forcefully killing it."
type: "integer"
format: "int64"
DNSConfig:
description: "Specification for DNS related configurations in resolver configuration file (`resolv.conf`)."
type: "object"
properties:
Nameservers:
description: "The IP addresses of the name servers."
type: "array"
items:
type: "string"
Search:
description: "A search list for host-name lookup."
type: "array"
items:
type: "string"
Options:
description: "A list of internal resolver variables to be modified (e.g., `debug`, `ndots:3`, etc.)."
type: "array"
items:
type: "string"
Resources:
description: "Resource requirements which apply to each individual container created as part of the service."
type: "object"
@@ -2218,6 +2270,16 @@ definitions:
Deleted:
description: "The image ID of an image that was deleted"
type: "string"
ServiceUpdateResponse:
type: "object"
properties:
Warnings:
description: "Optional warning messages"
type: "array"
items:
type: "string"
example:
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
ContainerSummary:
type: "array"
items:
@@ -2286,7 +2348,41 @@ definitions:
type: "array"
items:
$ref: "#/definitions/Mount"
SecretSpec:
type: "object"
properties:
Name:
description: "User-defined name of the secret."
type: "string"
Labels:
description: "User-defined key/value metadata."
type: "object"
additionalProperties:
type: "string"
Data:
description: "Base64-url-safe-encoded secret data"
type: "array"
items:
type: "string"
Secret:
type: "object"
properties:
ID:
type: "string"
Version:
type: "object"
properties:
Index:
type: "integer"
format: "int64"
CreatedAt:
type: "string"
format: "dateTime"
UpdatedAt:
type: "string"
format: "dateTime"
Spec:
$ref: "#/definitions/ServiceSpec"
paths:
/containers/json:
get:
@@ -3641,7 +3737,7 @@ paths:
Either the `stream` or `logs` parameter must be `true` for this endpoint to do anything.
See [the documentation for the `docker attach` command](https://docs.docker.com/engine/reference/commandline/attach/) for more details.
See [the documentation for the `docker attach` command](/engine/reference/commandline/attach/) for more details.
### Hijacking
@@ -4142,11 +4238,15 @@ paths:
default: false
- name: "filters"
in: "query"
description: "A JSON encoded value of the filters (a `map[string][]string`) to process on the containers list"
type: "string"
- name: "filter"
in: "query"
description: "Only return images with the specified name."
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list.
Available filters:
- `dangling=true`
- `label=key` or `label="key=value"` of an image label
- `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
- `reference`=(`<image-name>[:<tag>]`)
type: "string"
- name: "digests"
in: "query"
@@ -4161,7 +4261,7 @@ paths:
description: |
Build an image from a tar archive with a `Dockerfile` in it.
The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive's root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](https://docs.docker.com/engine/reference/builder/).
The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive's root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](/engine/reference/builder/).
The Docker daemon performs a preliminary validation of the `Dockerfile` before starting the build, and returns an error if the syntax is incorrect. After that, each instruction is run one-by-one until the ID of the new image is output.
@@ -4245,7 +4345,7 @@ paths:
type: "integer"
- name: "buildargs"
in: "query"
description: "JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker uses the buildargs as the environment context for commands run via the `Dockerfile` RUN instruction, or for variable expansion in other `Dockerfile` instructions. This is not meant for passing secret values. [Read more about the buildargs instruction.](https://docs.docker.com/engine/reference/builder/#arg)"
description: "JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker uses the buildargs as the environment context for commands run via the `Dockerfile` RUN instruction, or for variable expansion in other `Dockerfile` instructions. This is not meant for passing secret values. [Read more about the buildargs instruction.](/engine/reference/builder/#arg)"
type: "integer"
- name: "shmsize"
in: "query"
@@ -6297,7 +6397,7 @@ paths:
summary: "Install a plugin"
operationId: "PostPluginsPull"
description: |
Pulls and installs a plugin. After the plugin is installed, it can be enabled using the [`POST /plugins/{name}/enable` endpoint](#operation/PostPluginEnable).
Pulls and installs a plugin. After the plugin is installed, it can be enabled using the [`POST /plugins/{name}/enable` endpoint](#operation/PostPluginsEnable).
produces:
- "application/json"
responses:
@@ -6420,6 +6520,11 @@ paths:
description: "The name of the plugin. The `:latest` tag is optional, and is the default if omitted."
required: true
type: "string"
- name: "timeout"
in: "query"
description: "Set the HTTP client timeout (in seconds)"
type: "integer"
default: 0
tags:
- "Plugins"
/plugins/{name}/disable:
@@ -6468,6 +6573,31 @@ paths:
format: "binary"
tags:
- "Plugins"
/plugins/{name}/push:
post:
summary: "Push a plugin"
operationId: "PluginPush"
description: |
Push a plugin to the registry.
parameters:
- name: "name"
in: "path"
description: "The name of the plugin. The `:latest` tag is optional, and is the default if omitted."
required: true
type: "string"
responses:
200:
description: "no error"
404:
description: "plugin not installed"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
tags:
- "Plugins"
/plugins/{name}/set:
post:
summary: "Configure a plugin"
@@ -6523,9 +6653,10 @@ paths:
Available filters:
- `id=<node id>`
- `label=<engine label>`
- `membership=`(`accepted`|`pending`)`
- `name=<node name>`
- `membership=`(`pending`|`accepted`|`rejected`)`
- `role=`(`worker`|`manager`)`
- `role=`(`manager`|`worker`)`
type: "string"
tags:
- "Nodes"
@@ -6549,7 +6680,7 @@ paths:
parameters:
- name: "id"
in: "path"
description: "The ID of the node"
description: "The ID or name of the node"
type: "string"
required: true
tags:
@@ -6571,7 +6702,7 @@ paths:
parameters:
- name: "id"
in: "path"
description: "The ID of the node"
description: "The ID or name of the node"
type: "string"
required: true
- name: "force"
@@ -6651,6 +6782,8 @@ paths:
SnapshotInterval: 10000
ElectionTick: 3
TaskDefaults: {}
EncryptionConfig:
AutoLockManagers: false
Name: "default"
JoinTokens:
Worker: "SWMTKN-1-1h8aps2yszaiqmz2l3oc5392pgk8e49qhx2aj3nyv0ui0hez2a-6qmn92w6bu3jdvnglku58u11a"
@@ -6718,6 +6851,8 @@ paths:
Raft: {}
Dispatcher: {}
CAConfig: {}
EncryptionConfig:
AutoLockManagers: false
tags:
- "Swarm"
/swarm/join:
@@ -6731,14 +6866,14 @@ paths:
description: "bad parameter"
schema:
$ref: "#/definitions/ErrorResponse"
406:
description: "node is already part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
503:
description: "node is already part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "body"
in: "body"
@@ -6773,14 +6908,14 @@ paths:
responses:
200:
description: "no error"
406:
description: "node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
503:
description: "node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "force"
description: "Force leave swarm, even if this is the last manager or that it will break the cluster."
@@ -6800,14 +6935,14 @@ paths:
description: "bad parameter"
schema:
$ref: "#/definitions/ErrorResponse"
406:
description: "node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
503:
description: "node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "body"
in: "body"
@@ -6830,6 +6965,63 @@ paths:
description: "Rotate the manager join token."
type: "boolean"
default: false
- name: "rotateManagerUnlockKey"
in: "query"
description: "Rotate the manager unlock key."
type: "boolean"
default: false
tags:
- "Swarm"
/swarm/unlockkey:
get:
summary: "Get the unlock key"
operationId: "SwarmUnlockkey"
consumes:
- "application/json"
responses:
200:
description: "no error"
schema:
type: "object"
properties:
UnlockKey:
description: "The swarm's unlock key."
type: "string"
example:
UnlockKey: "SWMKEY-1-7c37Cc8654o6p38HnroywCi19pllOnGtbdZEgtKxZu8"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
tags:
- "Swarm"
/swarm/unlock:
post:
summary: "Unlock a locked manager"
operationId: "SwarmUnlock"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- name: "body"
in: "body"
required: true
schema:
type: "object"
properties:
UnlockKey:
description: "The swarm's unlock key."
type: "string"
example:
UnlockKey: "SWMKEY-1-7c37Cc8654o6p38HnroywCi19pllOnGtbdZEgtKxZu8"
responses:
200:
description: "no error"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
tags:
- "Swarm"
/services:
@@ -6854,8 +7046,9 @@ paths:
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the services list. Available filters:
- `id=<node id>`
- `name=<node name>`
- `id=<service id>`
- `name=<service name>`
- `label=<service label>`
tags:
- "Services"
/services/create:
@@ -6875,12 +7068,12 @@ paths:
ID:
description: "The ID of the created service."
type: "string"
Warning:
description: "Optional warning message"
type: "string"
example:
ID: "ak7w3gjqoa3kuz8xcpnyy0pvl"
406:
description: "server error or node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
409:
description: "name conflicts with an existing service"
schema:
@@ -6889,6 +7082,10 @@ paths:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
503:
description: "server error or node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "body"
in: "body"
@@ -6913,6 +7110,10 @@ paths:
Labels:
com.example.something: "something-value"
User: "33"
DNSConfig:
Nameservers: ["8.8.8.8"]
Search: ["example.org"]
Options: ["timeout:3"]
LogDriver:
Name: "json-file"
Options:
@@ -6998,10 +7199,14 @@ paths:
/services/{id}/update:
post:
summary: "Update a service"
operationId: "PostServicesUpdate"
operationId: "ServiceUpdate"
consumes: ["application/json"]
produces: ["application/json"]
responses:
200:
description: "no error"
schema:
$ref: "#/definitions/ImageDeleteResponse"
404:
description: "no such service"
schema:
@@ -7065,6 +7270,83 @@ paths:
description: "A base64-encoded auth configuration for pulling from private registries. [See the authentication section for details.](#section/Authentication)"
type: "string"
tags: ["Services"]
/services/{id}/logs:
get:
summary: "Get service logs"
description: |
Get `stdout` and `stderr` logs from a service.
**Note**: This endpoint works only for services with the `json-file` or `journald` logging drivers.
operationId: "ServiceLogs"
produces:
- "application/vnd.docker.raw-stream"
- "application/json"
responses:
101:
description: "logs returned as a stream"
schema:
type: "string"
format: "binary"
200:
description: "logs returned as a string in response body"
schema:
type: "string"
404:
description: "no such container"
schema:
$ref: "#/definitions/ErrorResponse"
examples:
application/json:
message: "No such container: c2ada9df5af8"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "id"
in: "path"
required: true
description: "ID or name of the container"
type: "string"
- name: "details"
in: "query"
description: "Show extra details provided to logs."
type: "boolean"
default: false
- name: "follow"
in: "query"
description: |
Return the logs as a stream.
This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/PostContainerAttach).
type: "boolean"
default: false
- name: "stdout"
in: "query"
description: "Return logs from `stdout`"
type: "boolean"
default: false
- name: "stderr"
in: "query"
description: "Return logs from `stderr`"
type: "boolean"
default: false
- name: "since"
in: "query"
description: "Only return logs since this time, as a UNIX timestamp"
type: "integer"
default: 0
- name: "timestamps"
in: "query"
description: "Add timestamps to every log line"
type: "boolean"
default: false
- name: "tail"
in: "query"
description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines."
type: "string"
default: "all"
tags:
- "Services"
/tasks:
@@ -7238,3 +7520,146 @@ paths:
type: "string"
tags:
- "Tasks"
/secrets:
get:
summary: "List secrets"
operationId: "SecretList"
produces:
- "application/json"
responses:
200:
description: "no error"
schema:
type: "array"
items:
$ref: "#/definitions/Secret"
example:
- ID: "ktnbjxoalbkvbvedmg1urrz8h"
Version:
Index: 11
CreatedAt: "2016-11-05T01:20:17.327670065Z"
UpdatedAt: "2016-11-05T01:20:17.327670065Z"
Spec:
Name: "app-dev.crt"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "filters"
in: "query"
type: "string"
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the secrets list. Available filters:
- `names=<secret name>`
tags:
- "Secrets"
/secrets/create:
post:
summary: "Create a secret"
operationId: "SecretCreate"
consumes:
- "application/json"
produces:
- "application/json"
responses:
201:
description: "no error"
schema:
type: "object"
properties:
ID:
description: "The ID of the created secret."
type: "string"
example:
ID: "ktnbjxoalbkvbvedmg1urrz8h"
406:
description: "server error or node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
409:
description: "name conflicts with an existing object"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "body"
in: "body"
schema:
allOf:
- $ref: "#/definitions/SecretSpec"
- type: "object"
example:
Name: "app-key.crt"
Labels:
foo: "bar"
Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg=="
tags:
- "Secrets"
/secrets/{id}:
get:
summary: "Inspect a secret"
operationId: "SecretsInspect"
produces:
- "application/json"
responses:
200:
description: "no error"
schema:
$ref: "#/definitions/Secret"
example:
ID: "ktnbjxoalbkvbvedmg1urrz8h"
Version:
Index: 11
CreatedAt: "2016-11-05T01:20:17.327670065Z"
UpdatedAt: "2016-11-05T01:20:17.327670065Z"
Spec:
Name: "app-dev.crt"
404:
description: "secret not found"
schema:
$ref: "#/definitions/ErrorResponse"
406:
description: "node is not part of a swarm"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "id"
in: "path"
required: true
type: "string"
description: "ID of the secret"
tags:
- "Secrets"
delete:
summary: "Delete a secret"
operationId: "SecretsDelete"
produces:
- "application/json"
responses:
204:
description: "no error"
404:
description: "secret not found"
schema:
$ref: "#/definitions/ErrorResponse"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
parameters:
- name: "id"
in: "path"
required: true
type: "string"
description: "ID of the secret"
tags:
- "Secrets"

View File

@@ -285,10 +285,12 @@ type ServiceCreateOptions struct {
}
// ServiceCreateResponse contains the information returned to a client
// on the creation of a new service.
// on the creation of a new service.
type ServiceCreateResponse struct {
// ID is the ID of the created service.
ID string
// Warnings is a set of non-fatal warning messages to pass on to the user.
Warnings []string `json:",omitempty"`
}
// Values for RegistryAuthFrom in ServiceUpdateOptions
@@ -330,6 +332,11 @@ type PluginRemoveOptions struct {
Force bool
}
// PluginEnableOptions holds parameters to enable plugins.
type PluginEnableOptions struct {
Timeout int
}
// PluginInstallOptions holds parameters to install a plugin.
type PluginInstallOptions struct {
Disabled bool
@@ -349,7 +356,7 @@ type SecretRequestOption struct {
Mode os.FileMode
}
// SwarmUnlockKeyResponse contains the response for Remote API:
// SwarmUnlockKeyResponse contains the response for Engine API:
// GET /swarm/unlockkey
type SwarmUnlockKeyResponse struct {
// UnlockKey is the unlock key in ASCII-armored format.

View File

@@ -59,3 +59,8 @@ type ExecConfig struct {
type PluginRmConfig struct {
ForceRemove bool
}
// PluginEnableConfig holds arguments for the plugin enable
type PluginEnableConfig struct {
Timeout int
}

View File

@@ -34,29 +34,29 @@ type HealthConfig struct {
// All fields added to this struct must be marked `omitempty` to keep getting
// predictable hashes from the old `v1Compatibility` configuration.
type Config struct {
Hostname string // Hostname
Domainname string // Domainname
User string // User that will run the command(s) inside the container, also support user:group
AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStdout bool // Attach the standard output
AttachStderr bool // Attach the standard error
ExposedPorts map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
Env []string // List of environment variable to set in the container
Cmd strslice.StrSlice // Command to run when starting the container
Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
Volumes map[string]struct{} // List of volumes (mounts) used for the container
WorkingDir string // Current directory (PWD) in the command will be launched
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
NetworkDisabled bool `json:",omitempty"` // Is network disabled
MacAddress string `json:",omitempty"` // Mac Address of the container
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string // List of labels set to this container
StopSignal string `json:",omitempty"` // Signal to stop a container
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
Hostname string // Hostname
Domainname string // Domainname
User string // User that will run the command(s) inside the container, also support user:group
AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStdout bool // Attach the standard output
AttachStderr bool // Attach the standard error
ExposedPorts nat.PortSet `json:",omitempty"` // List of exposed ports
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
Env []string // List of environment variable to set in the container
Cmd strslice.StrSlice // Command to run when starting the container
Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
Volumes map[string]struct{} // List of volumes (mounts) used for the container
WorkingDir string // Current directory (PWD) in the command will be launched
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
NetworkDisabled bool `json:",omitempty"` // Is network disabled
MacAddress string `json:",omitempty"` // Mac Address of the container
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string // List of labels set to this container
StopSignal string `json:",omitempty"` // Signal to stop a container
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
}

View File

@@ -1,14 +0,0 @@
package container
import "os"
// ContainerSecret represents a secret in a container. This gets realized
// in the container tmpfs
type ContainerSecret struct {
Name string
Target string
Data []byte
UID string
GID string
Mode os.FileMode
}

View File

@@ -3,7 +3,7 @@ package types
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// Plugin A plugin for the Remote API
// Plugin A plugin for the Engine API
// swagger:model Plugin
type Plugin struct {
@@ -39,18 +39,10 @@ type PluginConfig struct {
// Required: true
Args PluginConfigArgs `json:"Args"`
// capabilities
// Required: true
Capabilities []string `json:"Capabilities"`
// description
// Required: true
Description string `json:"Description"`
// devices
// Required: true
Devices []PluginDevice `json:"Devices"`
// documentation
// Required: true
Documentation string `json:"Documentation"`
@@ -67,6 +59,10 @@ type PluginConfig struct {
// Required: true
Interface PluginConfigInterface `json:"Interface"`
// linux
// Required: true
Linux PluginConfigLinux `json:"Linux"`
// mounts
// Required: true
Mounts []PluginMount `json:"Mounts"`
@@ -117,6 +113,23 @@ type PluginConfigInterface struct {
Types []PluginInterfaceType `json:"Types"`
}
// PluginConfigLinux plugin config linux
// swagger:model PluginConfigLinux
type PluginConfigLinux struct {
// capabilities
// Required: true
Capabilities []string `json:"Capabilities"`
// device creation
// Required: true
DeviceCreation bool `json:"DeviceCreation"`
// devices
// Required: true
Devices []PluginDevice `json:"Devices"`
}
// PluginConfigNetwork plugin config network
// swagger:model PluginConfigNetwork
type PluginConfigNetwork struct {

View File

@@ -5,7 +5,7 @@ import (
"fmt"
)
// PluginsListResponse contains the response for the remote API
// PluginsListResponse contains the response for the Engine API
type PluginsListResponse []*Plugin
const (

View File

@@ -0,0 +1,12 @@
package types
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// ServiceUpdateResponse service update response
// swagger:model ServiceUpdateResponse
type ServiceUpdateResponse struct {
// Optional warning messages
Warnings []string `json:"Warnings"`
}

View File

@@ -6,9 +6,7 @@ import "os"
type Secret struct {
ID string
Meta
Spec SecretSpec
Digest string
SecretSize int64
Spec SecretSpec
}
// SecretSpec represents a secret specification from a secret in swarm
@@ -27,7 +25,7 @@ type SecretReferenceFileTarget struct {
// SecretReference is a reference to a secret in swarm
type SecretReference struct {
File *SecretReferenceFileTarget
SecretID string
SecretName string
Target *SecretReferenceFileTarget
}

View File

@@ -74,7 +74,7 @@ const (
type UpdateConfig struct {
// Maximum number of tasks to be updated in one iteration.
// 0 means unlimited parallelism.
Parallelism uint64 `json:",omitempty"`
Parallelism uint64
// Amount of time between updates.
Delay time.Duration `json:",omitempty"`

View File

@@ -1,8 +1,11 @@
package types
import (
"errors"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/docker/docker/api/types/container"
@@ -14,14 +17,14 @@ import (
"github.com/docker/go-connections/nat"
)
// ContainerChange contains response of Remote API:
// ContainerChange contains response of Engine API:
// GET "/containers/{name:.*}/changes"
type ContainerChange struct {
Kind int
Path string
}
// ImageHistory contains response of Remote API:
// ImageHistory contains response of Engine API:
// GET "/images/{name:.*}/history"
type ImageHistory struct {
ID string `json:"Id"`
@@ -32,7 +35,7 @@ type ImageHistory struct {
Comment string
}
// ImageDelete contains response of Remote API:
// ImageDelete contains response of Engine API:
// DELETE "/images/{name:.*}"
type ImageDelete struct {
Untagged string `json:",omitempty"`
@@ -53,7 +56,7 @@ type RootFS struct {
BaseLayer string `json:",omitempty"`
}
// ImageInspect contains response of Remote API:
// ImageInspect contains response of Engine API:
// GET "/images/{name:.*}/json"
type ImageInspect struct {
ID string `json:"Id"`
@@ -76,7 +79,7 @@ type ImageInspect struct {
RootFS RootFS
}
// Container contains response of Remote API:
// Container contains response of Engine API:
// GET "/containers/json"
type Container struct {
ID string `json:"Id"`
@@ -98,7 +101,7 @@ type Container struct {
Mounts []MountPoint
}
// CopyConfig contains request body of Remote API:
// CopyConfig contains request body of Engine API:
// POST "/containers/"+containerID+"/copy"
type CopyConfig struct {
Resource string
@@ -115,28 +118,28 @@ type ContainerPathStat struct {
LinkTarget string `json:"linkTarget"`
}
// ContainerStats contains response of Remote API:
// ContainerStats contains response of Engine API:
// GET "/stats"
type ContainerStats struct {
Body io.ReadCloser `json:"body"`
OSType string `json:"ostype"`
}
// ContainerProcessList contains response of Remote API:
// ContainerProcessList contains response of Engine API:
// GET "/containers/{name:.*}/top"
type ContainerProcessList struct {
Processes [][]string
Titles []string
}
// Ping contains response of Remote API:
// Ping contains response of Engine API:
// GET "/_ping"
type Ping struct {
APIVersion string
Experimental bool
}
// Version contains response of Remote API:
// Version contains response of Engine API:
// GET "/version"
type Version struct {
Version string
@@ -158,9 +161,9 @@ type Commit struct {
Expected string
}
// InfoBase contains the base response of Remote API:
// Info contains response of Engine API:
// GET "/info"
type InfoBase struct {
type Info struct {
ID string
Containers int
ContainersRunning int
@@ -219,18 +222,49 @@ type InfoBase struct {
ContainerdCommit Commit
RuncCommit Commit
InitCommit Commit
SecurityOptions []string
}
// SecurityOpt holds key/value pair about a security option
type SecurityOpt struct {
// KeyValue holds a key/value pair
type KeyValue struct {
Key, Value string
}
// Info contains response of Remote API:
// GET "/info"
type Info struct {
*InfoBase
SecurityOptions []SecurityOpt
// SecurityOpt contains the name and options of a security option
type SecurityOpt struct {
Name string
Options []KeyValue
}
// DecodeSecurityOptions decodes a security options string slice to a type safe
// SecurityOpt
func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
so := []SecurityOpt{}
for _, opt := range opts {
// support output from a < 1.13 docker daemon
if !strings.Contains(opt, "=") {
so = append(so, SecurityOpt{Name: opt})
continue
}
secopt := SecurityOpt{}
split := strings.Split(opt, ",")
for _, s := range split {
kv := strings.SplitN(s, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("invalid security option %q", s)
}
if kv[0] == "" || kv[1] == "" {
return nil, errors.New("invalid empty security option")
}
if kv[0] == "name" {
secopt.Name = kv[1]
continue
}
secopt.Options = append(secopt.Options, KeyValue{Key: kv[0], Value: kv[1]})
}
so = append(so, secopt)
}
return so, nil
}
// PluginsInfo is a temp struct holding Plugins name
@@ -305,7 +339,7 @@ type ContainerNode struct {
Labels map[string]string
}
// ContainerJSONBase contains response of Remote API:
// ContainerJSONBase contains response of Engine API:
// GET "/containers/{name:.*}/json"
type ContainerJSONBase struct {
ID string `json:"Id"`
@@ -466,7 +500,7 @@ type Runtime struct {
Args []string `json:"runtimeArgs,omitempty"`
}
// DiskUsage contains response of Remote API:
// DiskUsage contains response of Engine API:
// GET "/system/df"
type DiskUsage struct {
LayersSize int64
@@ -475,49 +509,49 @@ type DiskUsage struct {
Volumes []*Volume
}
// ImagesPruneConfig contains the configuration for Remote API:
// ImagesPruneConfig contains the configuration for Engine API:
// POST "/images/prune"
type ImagesPruneConfig struct {
DanglingOnly bool
}
// ContainersPruneConfig contains the configuration for Remote API:
// ContainersPruneConfig contains the configuration for Engine API:
// POST "/images/prune"
type ContainersPruneConfig struct {
}
// VolumesPruneConfig contains the configuration for Remote API:
// VolumesPruneConfig contains the configuration for Engine API:
// POST "/images/prune"
type VolumesPruneConfig struct {
}
// NetworksPruneConfig contains the configuration for Remote API:
// NetworksPruneConfig contains the configuration for Engine API:
// POST "/networks/prune"
type NetworksPruneConfig struct {
}
// ContainersPruneReport contains the response for Remote API:
// ContainersPruneReport contains the response for Engine API:
// POST "/containers/prune"
type ContainersPruneReport struct {
ContainersDeleted []string
SpaceReclaimed uint64
}
// VolumesPruneReport contains the response for Remote API:
// VolumesPruneReport contains the response for Engine API:
// POST "/volumes/prune"
type VolumesPruneReport struct {
VolumesDeleted []string
SpaceReclaimed uint64
}
// ImagesPruneReport contains the response for Remote API:
// ImagesPruneReport contains the response for Engine API:
// POST "/images/prune"
type ImagesPruneReport struct {
ImagesDeleted []ImageDelete
SpaceReclaimed uint64
}
// NetworksPruneReport contains the response for Remote API:
// NetworksPruneReport contains the response for Engine API:
// POST "/networks/prune"
type NetworksPruneReport struct {
NetworksDeleted []string

View File

@@ -1,10 +0,0 @@
// Package v1p24 provides specific API types for the API version 1, patch 24.
package v1p24
import "github.com/docker/docker/api/types"
type Info struct {
*types.InfoBase
ExecutionDriver string
SecurityOptions []string
}

View File

@@ -11,7 +11,7 @@ type Volume struct {
// Required: true
Driver string `json:"Driver"`
// A mapping of abitrary key/value data set on this volume.
// User-defined key/value metadata.
// Required: true
Labels map[string]string `json:"Labels"`

View File

@@ -19,7 +19,7 @@ type VolumesCreateBody struct {
// Required: true
DriverOpts map[string]string `json:"DriverOpts"`
// A mapping of arbitrary key/value data to set on the volume.
// User-defined key/value metadata.
// Required: true
Labels map[string]string `json:"Labels"`

View File

@@ -6,7 +6,7 @@ import "fmt"
// a command not supported on the platform.
func platformSupports(command string) error {
switch command {
case "user", "stopsignal":
case "stopsignal":
return fmt.Errorf("The daemon on this platform does not support the command '%s'", command)
}
return nil

View File

@@ -12,11 +12,8 @@ func NewCheckpointCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "checkpoint",
Short: "Manage checkpoints",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
Tags: map[string]string{"experimental": "", "version": "1.25"},
RunE: dockerCli.ShowHelp,
Tags: map[string]string{"experimental": "", "version": "1.25"},
}
cmd.AddCommand(
newCreateCommand(dockerCli),

View File

@@ -20,6 +20,7 @@ import (
dopts "github.com/docker/docker/opts"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
@@ -73,6 +74,13 @@ func (cli *DockerCli) In() *InStream {
return cli.in
}
// ShowHelp shows the command help.
func (cli *DockerCli) ShowHelp(cmd *cobra.Command, args []string) error {
cmd.SetOutput(cli.err)
cmd.HelpFunc()(cmd, args)
return nil
}
// ConfigFile returns the ConfigFile
func (cli *DockerCli) ConfigFile() *configfile.ConfigFile {
return cli.configFile

View File

@@ -118,7 +118,7 @@ func runAttach(dockerCli *command.DockerCli, opts *attachOptions) error {
return errAttach
}
_, status, err := getExitCode(dockerCli, ctx, opts.container)
_, status, err := getExitCode(ctx, dockerCli, opts.container)
if err != nil {
return err
}

View File

@@ -13,10 +13,7 @@ func NewContainerCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "container",
Short: "Manage containers",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
NewAttachCommand(dockerCli),

View File

@@ -170,7 +170,7 @@ func getExecExitCode(ctx context.Context, client apiclient.ContainerAPIClient, e
resp, err := client.ContainerExecInspect(ctx, execID)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != apiclient.ErrConnectionFailed {
if !apiclient.IsErrConnectionFailed(err) {
return false, -1, err
}
return false, -1, nil

View File

@@ -59,21 +59,18 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cmd
}
type preProcessor struct {
types.Container
opts *types.ContainerListOptions
}
// listOptionsProcessor is used to set any container list options which may only
// be embedded in the format template.
// This is passed directly into tmpl.Execute in order to allow the preprocessor
// to set any list options that were not provided by flags (e.g. `.Size`).
// It is using a `map[string]bool` so that unknown fields passed into the
// template format do not cause errors. These errors will get picked up when
// running through the actual template processor.
type listOptionsProcessor map[string]bool
// Size sets the size option when called by a template execution.
func (p *preProcessor) Size() bool {
p.opts.Size = true
return true
}
// Networks does nothing but return true.
// It is needed to avoid the template check to fail as this field
// doesn't exist in `types.Container`
func (p *preProcessor) Networks() bool {
// Size sets the size of the map when called by a template execution.
func (o listOptionsProcessor) Size() bool {
o["size"] = true
return true
}
@@ -89,20 +86,20 @@ func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, er
options.Limit = 1
}
// Currently only used with Size, so we can determine if the user
// put {{.Size}} in their format.
pre := &preProcessor{opts: options}
tmpl, err := templates.Parse(opts.format)
if err != nil {
return nil, err
}
optionsProcessor := listOptionsProcessor{}
// This shouldn't error out but swallowing the error makes it harder
// to track down if preProcessor issues come up. Ref #24696
if err := tmpl.Execute(ioutil.Discard, pre); err != nil {
if err := tmpl.Execute(ioutil.Discard, optionsProcessor); err != nil {
return nil, err
}
// At the moment all we need is to capture .Size for preprocessor
options.Size = opts.size || optionsProcessor["size"]
return options, nil
}

View File

@@ -46,6 +46,57 @@ func TestBuildContainerListOptions(t *testing.T) {
expectedLimit: 1,
expectedFilters: make(map[string]string),
},
{
psOpts: &psOptions{
all: true,
size: false,
last: 5,
filter: filters,
// With .Size, size should be true
format: "{{.Size}}",
},
expectedAll: true,
expectedSize: true,
expectedLimit: 5,
expectedFilters: map[string]string{
"foo": "bar",
"baz": "foo",
},
},
{
psOpts: &psOptions{
all: true,
size: false,
last: 5,
filter: filters,
// With .Size, size should be true
format: "{{.Size}} {{.CreatedAt}} {{.Networks}}",
},
expectedAll: true,
expectedSize: true,
expectedLimit: 5,
expectedFilters: map[string]string{
"foo": "bar",
"baz": "foo",
},
},
{
psOpts: &psOptions{
all: true,
size: false,
last: 5,
filter: filters,
// Without .Size, size should be false
format: "{{.CreatedAt}} {{.Networks}}",
},
expectedAll: true,
expectedSize: false,
expectedLimit: 5,
expectedFilters: map[string]string{
"foo": "bar",
"baz": "foo",
},
},
}
for _, c := range contexts {

View File

@@ -211,7 +211,7 @@ func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions
})
}
statusChan := waitExitOrRemoved(dockerCli, ctx, createResponse.ID, hostConfig.AutoRemove)
statusChan := waitExitOrRemoved(ctx, dockerCli, createResponse.ID, hostConfig.AutoRemove)
//start the container
if err := client.ContainerStart(ctx, createResponse.ID, types.ContainerStartOptions{}); err != nil {

View File

@@ -111,7 +111,7 @@ func runStart(dockerCli *command.DockerCli, opts *startOptions) error {
// 3. We should open a channel for receiving status code of the container
// no matter it's detached, removed on daemon side(--rm) or exit normally.
statusChan := waitExitOrRemoved(dockerCli, ctx, c.ID, c.HostConfig.AutoRemove)
statusChan := waitExitOrRemoved(ctx, dockerCli, c.ID, c.HostConfig.AutoRemove)
startOptions := types.ContainerStartOptions{
CheckpointID: opts.checkpoint,
CheckpointDir: opts.checkpointDir,

View File

@@ -108,7 +108,7 @@ func runStats(dockerCli *command.DockerCli, opts *statsOptions) error {
s := formatter.NewContainerStats(container.ID[:12], daemonOSType)
if cStats.add(s) {
waitFirst.Add(1)
go collect(s, ctx, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
}
}
}
@@ -125,7 +125,7 @@ func runStats(dockerCli *command.DockerCli, opts *statsOptions) error {
s := formatter.NewContainerStats(e.ID[:12], daemonOSType)
if cStats.add(s) {
waitFirst.Add(1)
go collect(s, ctx, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
}
}
})
@@ -134,7 +134,7 @@ func runStats(dockerCli *command.DockerCli, opts *statsOptions) error {
s := formatter.NewContainerStats(e.ID[:12], daemonOSType)
if cStats.add(s) {
waitFirst.Add(1)
go collect(s, ctx, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
}
})
@@ -160,7 +160,7 @@ func runStats(dockerCli *command.DockerCli, opts *statsOptions) error {
s := formatter.NewContainerStats(name, daemonOSType)
if cStats.add(s) {
waitFirst.Add(1)
go collect(s, ctx, dockerCli.Client(), !opts.noStream, waitFirst)
go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst)
}
}

View File

@@ -53,7 +53,7 @@ func (s *stats) isKnownContainer(cid string) (int, bool) {
return -1, false
}
func collect(s *formatter.ContainerStats, ctx context.Context, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
func collect(ctx context.Context, s *formatter.ContainerStats, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
logrus.Debugf("collecting stats for %s", s.Container)
var (
getFirst bool

View File

@@ -9,21 +9,32 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/cli/command"
clientapi "github.com/docker/docker/client"
)
func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, containerID string, waitRemove bool) chan int {
func waitExitOrRemoved(ctx context.Context, dockerCli *command.DockerCli, containerID string, waitRemove bool) chan int {
if len(containerID) == 0 {
// containerID can never be empty
panic("Internal Error: waitExitOrRemoved needs a containerID as parameter")
}
var removeErr error
statusChan := make(chan int)
exitCode := 125
eventProcessor := func(e events.Message) bool {
// Get events via Events API
f := filters.NewArgs()
f.Add("type", "container")
f.Add("container", containerID)
options := types.EventsOptions{
Filters: f,
}
eventCtx, cancel := context.WithCancel(ctx)
eventq, errq := dockerCli.Client().Events(eventCtx, options)
eventProcessor := func(e events.Message) bool {
stopProcessing := false
switch e.Status {
case "die":
@@ -37,6 +48,18 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
}
if !waitRemove {
stopProcessing = true
} else {
// If we are talking to an older daemon, `AutoRemove` is not supported.
// We need to fall back to the old behavior, which is client-side removal
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.25") {
go func() {
removeErr = dockerCli.Client().ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{RemoveVolumes: true})
if removeErr != nil {
logrus.Errorf("error removing container: %v", removeErr)
cancel() // cancel the event Q
}
}()
}
}
case "detach":
exitCode = 0
@@ -44,39 +67,27 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
case "destroy":
stopProcessing = true
}
if stopProcessing {
statusChan <- exitCode
return true
}
return false
return stopProcessing
}
// Get events via Events API
f := filters.NewArgs()
f.Add("type", "container")
f.Add("container", containerID)
options := types.EventsOptions{
Filters: f,
}
eventCtx, cancel := context.WithCancel(ctx)
eventq, errq := dockerCli.Client().Events(eventCtx, options)
go func() {
defer cancel()
defer func() {
statusChan <- exitCode // must always send an exit code or the caller will block
cancel()
}()
for {
select {
case <-eventCtx.Done():
if removeErr != nil {
return
}
case evt := <-eventq:
if eventProcessor(evt) {
return
}
case err := <-errq:
logrus.Errorf("error getting events from daemon: %v", err)
statusChan <- exitCode
return
}
}
@@ -87,11 +98,11 @@ func waitExitOrRemoved(dockerCli *command.DockerCli, ctx context.Context, contai
// getExitCode performs an inspect on the container. It returns
// the running state and the exit code.
func getExitCode(dockerCli *command.DockerCli, ctx context.Context, containerID string) (bool, int, error) {
func getExitCode(ctx context.Context, dockerCli *command.DockerCli, containerID string) (bool, int, error) {
c, err := dockerCli.Client().ContainerInspect(ctx, containerID)
if err != nil {
// If we can't connect, then the daemon probably died.
if err != clientapi.ErrConnectionFailed {
if !clientapi.IsErrConnectionFailed(err) {
return false, -1, err
}
return false, -1, nil

View File

@@ -370,3 +370,29 @@ func TestContainerContextWriteJSONField(t *testing.T) {
assert.Equal(t, s, containers[i].ID)
}
}
func TestContainerBackCompat(t *testing.T) {
containers := []types.Container{{ID: "brewhaha"}}
cases := []string{
"ID",
"Names",
"Image",
"Command",
"CreatedAt",
"RunningFor",
"Ports",
"Status",
"Size",
"Labels",
"Mounts",
}
buf := bytes.NewBuffer(nil)
for _, c := range cases {
ctx := Context{Format: Format(fmt.Sprintf("{{ .%s }}", c)), Output: buf}
if err := ContainerWrite(ctx, containers); err != nil {
t.Logf("could not render template for field '%s': %v", c, err)
t.Fail()
}
buf.Reset()
}
}

View File

@@ -263,6 +263,9 @@ func (ctx *serviceInspectContext) HasResources() bool {
}
func (ctx *serviceInspectContext) HasResourceReservations() bool {
if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Reservations == nil {
return false
}
return ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes > 0
}
@@ -281,6 +284,9 @@ func (ctx *serviceInspectContext) ResourceReservationMemory() string {
}
func (ctx *serviceInspectContext) HasResourceLimits() bool {
if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Limits == nil {
return false
}
return ctx.Service.Spec.TaskTemplate.Resources.Limits.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes > 0
}

View File

@@ -13,10 +13,7 @@ func NewImageCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "image",
Short: "Manage images",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
NewBuildCommand(dockerCli),

View File

@@ -3,13 +3,13 @@ package image
import (
"fmt"
"io"
"os"
"golang.org/x/net/context"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/system"
"github.com/spf13/cobra"
)
@@ -43,7 +43,9 @@ func runLoad(dockerCli *command.DockerCli, opts loadOptions) error {
var input io.Reader = dockerCli.In()
if opts.input != "" {
file, err := os.Open(opts.input)
// We use system.OpenSequential to use sequential file access on Windows, avoiding
// depleting the standby list un-necessarily. On Linux, this equates to a regular os.Open.
file, err := system.OpenSequential(opts.input)
if err != nil {
return err
}

View File

@@ -18,8 +18,8 @@ func NewTagCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts tagOptions
cmd := &cobra.Command{
Use: "tag IMAGE[:TAG] IMAGE[:TAG]",
Short: "Tag an image into a repository",
Use: "tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]",
Short: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE",
Args: cli.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
opts.image = args[0]

View File

@@ -13,10 +13,7 @@ func NewNetworkCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "network",
Short: "Manage networks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newConnectCommand(dockerCli),

View File

@@ -14,10 +14,7 @@ func NewNodeCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "node",
Short: "Manage Swarm nodes",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newDemoteCommand(dockerCli),

View File

@@ -12,10 +12,7 @@ func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "plugin",
Short: "Manage plugins",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(

View File

@@ -3,6 +3,7 @@ package plugin
import (
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/reference"
@@ -10,20 +11,32 @@ import (
"golang.org/x/net/context"
)
type enableOpts struct {
timeout int
name string
}
func newEnableCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts enableOpts
cmd := &cobra.Command{
Use: "enable PLUGIN",
Short: "Enable a plugin",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runEnable(dockerCli, args[0])
opts.name = args[0]
return runEnable(dockerCli, &opts)
},
}
flags := cmd.Flags()
flags.IntVar(&opts.timeout, "timeout", 0, "HTTP client timeout (in seconds)")
return cmd
}
func runEnable(dockerCli *command.DockerCli, name string) error {
func runEnable(dockerCli *command.DockerCli, opts *enableOpts) error {
name := opts.name
named, err := reference.ParseNamed(name) // FIXME: validate
if err != nil {
return err
@@ -35,7 +48,11 @@ func runEnable(dockerCli *command.DockerCli, name string) error {
if !ok {
return fmt.Errorf("invalid name: %s", named.String())
}
if err := dockerCli.Client().PluginEnable(context.Background(), ref.String()); err != nil {
if opts.timeout < 0 {
return fmt.Errorf("negative timeout %d is invalid", opts.timeout)
}
if err := dockerCli.Client().PluginEnable(context.Background(), ref.String(), types.PluginEnableOptions{Timeout: opts.timeout}); err != nil {
return err
}
fmt.Fprintln(dockerCli.Out(), name)

View File

@@ -14,8 +14,8 @@ import (
func newPushCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := &cobra.Command{
Use: "push PLUGIN",
Short: "Push a plugin",
Use: "push NAME[:TAG]",
Short: "Push a plugin to a registry",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runPush(dockerCli, args[0])

View File

@@ -1,8 +1,6 @@
package secret
import (
"fmt"
"github.com/spf13/cobra"
"github.com/docker/docker/cli"
@@ -15,9 +13,7 @@ func NewSecretCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "secret",
Short: "Manage Docker secrets",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
fmt.Fprintf(dockerCli.Err(), "\n"+cmd.UsageString())
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newSecretListCommand(dockerCli),

View File

@@ -9,18 +9,18 @@ import (
)
type inspectOptions struct {
name string
names []string
format string
}
func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
opts := inspectOptions{}
cmd := &cobra.Command{
Use: "inspect [name]",
Use: "inspect SECRET [SECRET]",
Short: "Inspect a secret",
Args: cli.ExactArgs(1),
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.name = args[0]
opts.names = args
return runSecretInspect(dockerCli, opts)
},
}
@@ -33,23 +33,13 @@ func runSecretInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
client := dockerCli.Client()
ctx := context.Background()
// attempt to lookup secret by name
secrets, err := getSecretsByName(client, ctx, []string{opts.name})
ids, err := getCliRequestedSecretIDs(ctx, client, opts.names)
if err != nil {
return err
}
id := opts.name
for _, s := range secrets {
if s.Spec.Annotations.Name == opts.name {
id = s.ID
break
}
}
getRef := func(name string) (interface{}, []byte, error) {
getRef := func(id string) (interface{}, []byte, error) {
return client.SecretInspectWithRaw(ctx, id)
}
return inspect.Inspect(dockerCli.Out(), []string{id}, opts.format, getRef)
return inspect.Inspect(dockerCli.Out(), ids, opts.format, getRef)
}

View File

@@ -50,15 +50,14 @@ func runSecretList(dockerCli *command.DockerCli, opts listOptions) error {
fmt.Fprintf(w, "%s\n", s.ID)
}
} else {
fmt.Fprintf(w, "ID\tNAME\tCREATED\tUPDATED\tSIZE")
fmt.Fprintf(w, "ID\tNAME\tCREATED\tUPDATED")
fmt.Fprintf(w, "\n")
for _, s := range secrets {
created := units.HumanDuration(time.Now().UTC().Sub(s.Meta.CreatedAt)) + " ago"
updated := units.HumanDuration(time.Now().UTC().Sub(s.Meta.UpdatedAt)) + " ago"
size := units.HumanSizeWithPrecision(float64(s.SecretSize), 3)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", s.ID, s.Spec.Annotations.Name, created, updated, size)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", s.ID, s.Spec.Annotations.Name, created, updated)
}
}

View File

@@ -10,17 +10,17 @@ import (
)
type removeOptions struct {
ids []string
names []string
}
func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
return &cobra.Command{
Use: "rm [id]",
Use: "rm SECRET [SECRET]",
Short: "Remove a secret",
Args: cli.RequiresMinArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts := removeOptions{
ids: args,
names: args,
}
return runSecretRemove(dockerCli, opts)
},
@@ -31,32 +31,14 @@ func runSecretRemove(dockerCli *command.DockerCli, opts removeOptions) error {
client := dockerCli.Client()
ctx := context.Background()
// attempt to lookup secret by name
secrets, err := getSecretsByName(client, ctx, opts.ids)
ids, err := getCliRequestedSecretIDs(ctx, client, opts.names)
if err != nil {
return err
}
ids := opts.ids
names := make(map[string]int)
for _, id := range ids {
names[id] = 1
}
if len(secrets) > 0 {
ids = []string{}
for _, s := range secrets {
if _, ok := names[s.Spec.Annotations.Name]; ok {
ids = append(ids, s.ID)
}
}
}
for _, id := range ids {
if err := client.SecretRemove(ctx, id); err != nil {
return err
fmt.Fprintf(dockerCli.Out(), "WARN: %s\n", err)
}
fmt.Fprintln(dockerCli.Out(), id)

View File

@@ -8,7 +8,7 @@ import (
"golang.org/x/net/context"
)
func getSecretsByName(client client.APIClient, ctx context.Context, names []string) ([]swarm.Secret, error) {
func getSecretsByName(ctx context.Context, client client.APIClient, names []string) ([]swarm.Secret, error) {
args := filters.NewArgs()
for _, n := range names {
args.Add("names", n)
@@ -18,3 +18,30 @@ func getSecretsByName(client client.APIClient, ctx context.Context, names []stri
Filters: args,
})
}
func getCliRequestedSecretIDs(ctx context.Context, client client.APIClient, names []string) ([]string, error) {
ids := names
// attempt to lookup secret by name
secrets, err := getSecretsByName(ctx, client, ids)
if err != nil {
return nil, err
}
lookup := make(map[string]struct{})
for _, id := range ids {
lookup[id] = struct{}{}
}
if len(secrets) > 0 {
ids = []string{}
for _, s := range secrets {
if _, ok := lookup[s.Spec.Annotations.Name]; ok {
ids = append(ids, s.ID)
}
}
}
return ids, nil
}

View File

@@ -13,10 +13,7 @@ func NewServiceCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "service",
Short: "Manage services",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newCreateCommand(dockerCli),

View File

@@ -62,12 +62,16 @@ func runCreate(dockerCli *command.DockerCli, opts *serviceOptions) error {
return err
}
// parse and validate secrets
secrets, err := parseSecrets(apiClient, opts.secrets.Value())
if err != nil {
return err
specifiedSecrets := opts.secrets.Value()
if len(specifiedSecrets) > 0 {
// parse and validate secrets
secrets, err := parseSecrets(apiClient, specifiedSecrets)
if err != nil {
return err
}
service.TaskTemplate.ContainerSpec.Secrets = secrets
}
service.TaskTemplate.ContainerSpec.Secrets = secrets
ctx := context.Background()
@@ -86,6 +90,10 @@ func runCreate(dockerCli *command.DockerCli, opts *serviceOptions) error {
return err
}
for _, warning := range response.Warnings {
fmt.Fprintln(dockerCli.Err(), warning)
}
fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID)
return nil
}

View File

@@ -5,6 +5,7 @@ import (
"io"
"text/tabwriter"
distreference "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/swarm"
@@ -127,6 +128,16 @@ func printTable(out io.Writer, services []swarm.Service, running, tasksNoShutdow
mode = "global"
replicas = fmt.Sprintf("%d/%d", running[service.ID], tasksNoShutdown[service.ID])
}
image := service.Spec.TaskTemplate.ContainerSpec.Image
ref, err := distreference.ParseNamed(image)
if err == nil {
// update image string for display
namedTagged, ok := ref.(distreference.NamedTagged)
if ok {
image = namedTagged.Name() + ":" + namedTagged.Tag()
}
}
fmt.Fprintf(
writer,
listItemFmt,
@@ -134,7 +145,7 @@ func printTable(out io.Writer, services []swarm.Service, running, tasksNoShutdow
service.Spec.Name,
mode,
replicas,
service.Spec.TaskTemplate.ContainerSpec.Image)
image)
}
}

View File

@@ -575,14 +575,14 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
flags.Var(&opts.resources.limitMemBytes, flagLimitMemory, "Limit Memory")
flags.Var(&opts.resources.resCPU, flagReserveCPU, "Reserve CPUs")
flags.Var(&opts.resources.resMemBytes, flagReserveMemory, "Reserve Memory")
flags.Var(&opts.stopGrace, flagStopGracePeriod, "Time to wait before force killing a container")
flags.Var(&opts.stopGrace, flagStopGracePeriod, "Time to wait before force killing a container (ns|us|ms|s|m|h)")
flags.Var(&opts.replicas, flagReplicas, "Number of tasks")
flags.StringVar(&opts.restartPolicy.condition, flagRestartCondition, "", "Restart when condition is met (none, on-failure, or any)")
flags.Var(&opts.restartPolicy.delay, flagRestartDelay, "Delay between restart attempts")
flags.Var(&opts.restartPolicy.delay, flagRestartDelay, "Delay between restart attempts (ns|us|ms|s|m|h)")
flags.Var(&opts.restartPolicy.maxAttempts, flagRestartMaxAttempts, "Maximum number of restarts before giving up")
flags.Var(&opts.restartPolicy.window, flagRestartWindow, "Window used to evaluate the restart policy")
flags.Var(&opts.restartPolicy.window, flagRestartWindow, "Window used to evaluate the restart policy (ns|us|ms|s|m|h)")
flags.Uint64Var(&opts.update.parallelism, flagUpdateParallelism, 1, "Maximum number of tasks updated simultaneously (0 to update all at once)")
flags.DurationVar(&opts.update.delay, flagUpdateDelay, time.Duration(0), "Delay between updates (ns|us|ms|s|m|h) (default 0s)")
@@ -598,8 +598,8 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options")
flags.StringVar(&opts.healthcheck.cmd, flagHealthCmd, "", "Command to run to check health")
flags.Var(&opts.healthcheck.interval, flagHealthInterval, "Time between running the check")
flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run")
flags.Var(&opts.healthcheck.interval, flagHealthInterval, "Time between running the check (ns|us|ms|s|m|h)")
flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run (ns|us|ms|s|m|h)")
flags.IntVar(&opts.healthcheck.retries, flagHealthRetries, 0, "Consecutive failures needed to report unhealthy")
flags.BoolVar(&opts.healthcheck.noHealthcheck, flagNoHealthcheck, false, "Disable any container-specified HEALTHCHECK")

View File

@@ -17,19 +17,19 @@ func parseSecrets(client client.APIClient, requestedSecrets []*types.SecretReque
ctx := context.Background()
for _, secret := range requestedSecrets {
if _, exists := secretRefs[secret.Target]; exists {
return nil, fmt.Errorf("duplicate secret target for %s not allowed", secret.Source)
}
secretRef := &swarmtypes.SecretReference{
SecretName: secret.Source,
Target: &swarmtypes.SecretReferenceFileTarget{
File: &swarmtypes.SecretReferenceFileTarget{
Name: secret.Target,
UID: secret.UID,
GID: secret.GID,
Mode: secret.Mode,
},
SecretName: secret.Source,
}
if _, exists := secretRefs[secret.Target]; exists {
return nil, fmt.Errorf("duplicate secret target for %s not allowed", secret.Source)
}
secretRefs[secret.Target] = secretRef
}

View File

@@ -82,11 +82,15 @@ func runServiceScale(dockerCli *command.DockerCli, serviceID string, scale uint6
serviceMode.Replicated.Replicas = &scale
err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
response, err := client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{})
if err != nil {
return err
}
for _, warning := range response.Warnings {
fmt.Fprintln(dockerCli.Err(), warning)
}
fmt.Fprintf(dockerCli.Out(), "%s scaled to %d\n", serviceID, scale)
return nil
}

View File

@@ -133,11 +133,15 @@ func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, serviceID str
updateOpts.RegistryAuthFrom = types.RegistryAuthFromSpec
}
err = apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts)
response, err := apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts)
if err != nil {
return err
}
for _, warning := range response.Warnings {
fmt.Fprintln(dockerCli.Err(), warning)
}
fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)
return nil
}

View File

@@ -12,11 +12,8 @@ func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "stack",
Short: "Manage Docker stacks",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
Tags: map[string]string{"experimental": "", "version": "1.25"},
RunE: dockerCli.ShowHelp,
Tags: map[string]string{"version": "1.25"},
}
cmd.AddCommand(
newDeployCommand(dockerCli),
@@ -33,5 +30,6 @@ func NewTopLevelDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd := newDeployCommand(dockerCli)
// Remove the aliases at the top level
cmd.Aliases = []string{}
cmd.Tags = map[string]string{"experimental": "", "version": "1.25"}
return cmd
}

View File

@@ -6,6 +6,7 @@ import (
"os"
"sort"
"strings"
"time"
"github.com/spf13/cobra"
"golang.org/x/net/context"
@@ -13,6 +14,7 @@ import (
"github.com/aanand/compose-file/loader"
composetypes "github.com/aanand/compose-file/types"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm"
@@ -47,7 +49,6 @@ func newDeployCommand(dockerCli *command.DockerCli) *cobra.Command {
opts.namespace = args[0]
return runDeploy(dockerCli, opts)
},
Tags: map[string]string{"experimental": "", "version": "1.25"},
}
flags := cmd.Flags()
@@ -250,9 +251,13 @@ func convertServiceNetworks(
nets := []swarm.NetworkAttachmentConfig{}
for networkName, network := range networks {
var aliases []string
if network != nil {
aliases = network.Aliases
}
nets = append(nets, swarm.NetworkAttachmentConfig{
Target: namespace.scope(networkName),
Aliases: append(network.Aliases, name),
Aliases: append(aliases, name),
})
}
return nets
@@ -408,15 +413,20 @@ func deployServices(
if sendAuth {
updateOpts.EncodedRegistryAuth = encodedAuth
}
if err := apiClient.ServiceUpdate(
response, err := apiClient.ServiceUpdate(
ctx,
service.ID,
service.Version,
serviceSpec,
updateOpts,
); err != nil {
)
if err != nil {
return err
}
for _, warning := range response.Warnings {
fmt.Fprintln(dockerCli.Err(), warning)
}
} else {
fmt.Fprintf(out, "Creating service %s\n", name)
@@ -487,6 +497,11 @@ func convertService(
return swarm.ServiceSpec{}, err
}
healthcheck, err := convertHealthcheck(service.HealthCheck)
if err != nil {
return swarm.ServiceSpec{}, err
}
serviceSpec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: name,
@@ -499,6 +514,7 @@ func convertService(
Args: service.Command,
Hostname: service.Hostname,
Hosts: convertExtraHosts(service.ExtraHosts),
Healthcheck: healthcheck,
Env: convertEnvironment(service.Environment),
Labels: getStackLabels(namespace.name, service.Labels),
Dir: service.WorkingDir,
@@ -526,11 +542,52 @@ func convertService(
func convertExtraHosts(extraHosts map[string]string) []string {
hosts := []string{}
for host, ip := range extraHosts {
hosts = append(hosts, fmt.Sprintf("%s %s", host, ip))
hosts = append(hosts, fmt.Sprintf("%s %s", ip, host))
}
return hosts
}
func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container.HealthConfig, error) {
if healthcheck == nil {
return nil, nil
}
var (
err error
timeout, interval time.Duration
retries int
)
if healthcheck.Disable {
if len(healthcheck.Test) != 0 {
return nil, fmt.Errorf("command and disable key can't be set at the same time")
}
return &container.HealthConfig{
Test: []string{"NONE"},
}, nil
}
if healthcheck.Timeout != "" {
timeout, err = time.ParseDuration(healthcheck.Timeout)
if err != nil {
return nil, err
}
}
if healthcheck.Interval != "" {
interval, err = time.ParseDuration(healthcheck.Interval)
if err != nil {
return nil, err
}
}
if healthcheck.Retries != nil {
retries = int(*healthcheck.Retries)
}
return &container.HealthConfig{
Test: healthcheck.Test,
Timeout: timeout,
Interval: interval,
Retries: retries,
}, nil
}
func convertRestartPolicy(restart string, source *composetypes.RestartPolicy) (*swarm.RestartPolicy, error) {
// TODO: log if restart is being ignored
if source == nil {
@@ -566,8 +623,12 @@ func convertUpdateConfig(source *composetypes.UpdateConfig) *swarm.UpdateConfig
if source == nil {
return nil
}
parallel := uint64(1)
if source.Parallelism != nil {
parallel = *source.Parallelism
}
return &swarm.UpdateConfig{
Parallelism: source.Parallelism,
Parallelism: parallel,
Delay: source.Delay,
FailureAction: source.FailureAction,
Monitor: source.Monitor,

View File

@@ -72,7 +72,7 @@ func printTable(out io.Writer, stacks []*stack) {
type stack struct {
// Name is the name of the stack
Name string
Name string
// Services is the number of the services
Services int
}

View File

@@ -15,6 +15,7 @@ func addComposefileFlag(opt *string, flags *pflag.FlagSet) {
func addBundlefileFlag(opt *string, flags *pflag.FlagSet) {
flags.StringVar(opt, "bundle-file", "", "Path to a Distributed Application Bundle file")
flags.SetAnnotation("bundle-file", "experimental", nil)
}
func addRegistryAuthFlag(opt *bool, flags *pflag.FlagSet) {

View File

@@ -13,10 +13,7 @@ func NewSwarmCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "swarm",
Short: "Manage Swarm",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newInitCommand(dockerCli),

View File

@@ -13,10 +13,7 @@ func NewSystemCommand(dockerCli *command.DockerCli) *cobra.Command {
Use: "system",
Short: "Manage Docker",
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
NewEventsCommand(dockerCli),

View File

@@ -172,16 +172,21 @@ func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error {
fmt.Fprintf(dockerCli.Out(), "\n")
}
if len(info.SecurityOptions) != 0 {
kvs, err := types.DecodeSecurityOptions(info.SecurityOptions)
if err != nil {
return err
}
fmt.Fprintf(dockerCli.Out(), "Security Options:\n")
for _, o := range info.SecurityOptions {
switch o.Key {
case "Name":
fmt.Fprintf(dockerCli.Out(), " %s\n", o.Value)
case "Profile":
if o.Value != "default" {
fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n")
for _, so := range kvs {
fmt.Fprintf(dockerCli.Out(), " %s\n", so.Name)
for _, o := range so.Options {
switch o.Key {
case "profile":
if o.Value != "default" {
fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n")
}
fmt.Fprintf(dockerCli.Out(), " Profile: %s\n", o.Value)
}
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", o.Key, o.Value)
}
}
}

View File

@@ -10,6 +10,7 @@ import (
"golang.org/x/net/context"
distreference "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/idresolver"
@@ -118,11 +119,23 @@ func print(out io.Writer, ctx context.Context, tasks []swarm.Task, resolver *idr
taskErr = fmt.Sprintf("\"%s\"", taskErr)
}
image := task.Spec.ContainerSpec.Image
if !noTrunc {
ref, err := distreference.ParseNamed(image)
if err == nil {
// update image string for display
namedTagged, ok := ref.(distreference.NamedTagged)
if ok {
image = namedTagged.Name() + ":" + namedTagged.Tag()
}
}
}
fmt.Fprintf(
out,
psTaskItemFmt,
indentedName,
task.Spec.ContainerSpec.Image,
image,
nodeValue,
command.PrettyPrint(task.DesiredState),
command.PrettyPrint(task.Status.State),

View File

@@ -14,10 +14,7 @@ func NewVolumeCommand(dockerCli *command.DockerCli) *cobra.Command {
Short: "Manage volumes",
Long: volumeDescription,
Args: cli.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
},
RunE: dockerCli.ShowHelp,
}
cmd.AddCommand(
newCreateCommand(dockerCli),

View File

@@ -1,4 +1,4 @@
## Go client for the Docker Remote API
# Go client for the Docker Engine API
The `docker` command uses this package to communicate with the daemon. It can also be used by your own Go applications to do anything the command-line interface does  running containers, pulling images, managing swarms, etc.

View File

@@ -1,12 +1,12 @@
/*
Package client is a Go client for the Docker Remote API.
Package client is a Go client for the Docker Engine API.
The "docker" command uses this package to communicate with the daemon. It can also
be used by your own Go applications to do anything the command-line interface does
 running containers, pulling images, managing swarms, etc.
For more information about the Remote API, see the documentation:
https://docs.docker.com/engine/reference/api/docker_remote_api/
For more information about the Engine API, see the documentation:
https://docs.docker.com/engine/reference/api/
Usage
@@ -122,7 +122,7 @@ func NewEnvClient() (*Client, error) {
if err != nil {
return cli, err
}
if version != "" {
if os.Getenv("DOCKER_API_VERSION") != "" {
cli.manualOverride = true
}
return cli, nil

View File

@@ -1,18 +1,34 @@
package client
import (
"errors"
"fmt"
"github.com/docker/docker/api/types/versions"
"github.com/pkg/errors"
)
// ErrConnectionFailed is an error raised when the connection between the client and the server failed.
var ErrConnectionFailed = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
// errConnectionFailed implements an error returned when connection failed.
type errConnectionFailed struct {
host string
}
// Error returns a string representation of an errConnectionFailed
func (err errConnectionFailed) Error() string {
if err.host == "" {
return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?"
}
return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host)
}
// IsErrConnectionFailed returns true if the error is caused by connection failed.
func IsErrConnectionFailed(err error) bool {
_, ok := errors.Cause(err).(errConnectionFailed)
return ok
}
// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed.
func ErrorConnectionFailed(host string) error {
return fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host)
return errConnectionFailed{host: host}
}
type notFound interface {

View File

@@ -46,10 +46,8 @@ func TestInfo(t *testing.T) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
info := &types.Info{
InfoBase: &types.InfoBase{
ID: "daemonID",
Containers: 3,
},
ID: "daemonID",
Containers: 3,
}
b, err := json.Marshal(info)
if err != nil {

View File

@@ -109,7 +109,7 @@ type NodeAPIClient interface {
type PluginAPIClient interface {
PluginList(ctx context.Context) (types.PluginsListResponse, error)
PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error
PluginEnable(ctx context.Context, name string) error
PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error
PluginDisable(ctx context.Context, name string) error
PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error
PluginPush(ctx context.Context, name string, registryAuth string) error
@@ -124,7 +124,7 @@ type ServiceAPIClient interface {
ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error)
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
ServiceRemove(ctx context.Context, serviceID string) error
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)

View File

@@ -1,12 +1,19 @@
package client
import (
"net/url"
"strconv"
"github.com/docker/docker/api/types"
"golang.org/x/net/context"
)
// PluginEnable enables a plugin
func (cli *Client) PluginEnable(ctx context.Context, name string) error {
resp, err := cli.post(ctx, "/plugins/"+name+"/enable", nil, nil, nil)
func (cli *Client) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error {
query := url.Values{}
query.Set("timeout", strconv.Itoa(options.Timeout))
resp, err := cli.post(ctx, "/plugins/"+name+"/enable", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@@ -8,6 +8,7 @@ import (
"strings"
"testing"
"github.com/docker/docker/api/types"
"golang.org/x/net/context"
)
@@ -16,7 +17,7 @@ func TestPluginEnableError(t *testing.T) {
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.PluginEnable(context.Background(), "plugin_name")
err := client.PluginEnable(context.Background(), "plugin_name", types.PluginEnableOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
@@ -40,7 +41,7 @@ func TestPluginEnable(t *testing.T) {
}),
}
err := client.PluginEnable(context.Background(), "plugin_name")
err := client.PluginEnable(context.Background(), "plugin_name", types.PluginEnableOptions{})
if err != nil {
t.Fatal(err)
}

View File

@@ -10,7 +10,7 @@ import (
)
// PluginInstall installs a plugin
func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error {
func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (err error) {
// FIXME(vdemeester) name is a ref, we might want to parse/validate it here.
query := url.Values{}
query.Set("name", name)
@@ -27,6 +27,14 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
ensureReaderClosed(resp)
return err
}
defer func() {
if err != nil {
delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
ensureReaderClosed(delResp)
}
}()
var privileges types.PluginPrivileges
if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil {
ensureReaderClosed(resp)
@@ -40,8 +48,6 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
return err
}
if !accept {
resp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
ensureReaderClosed(resp)
return pluginPermissionDenied{name}
}
}
@@ -56,7 +62,7 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
return nil
}
return cli.PluginEnable(ctx, name)
return cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0})
}
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {

View File

@@ -13,7 +13,7 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t
var headers map[string][]string
var response types.SecretCreateResponse
resp, err := cli.post(ctx, "/secrets", nil, secret, headers)
resp, err := cli.post(ctx, "/secrets/create", nil, secret, headers)
if err != nil {
return response, err
}

View File

@@ -25,7 +25,7 @@ func TestSecretCreateError(t *testing.T) {
}
func TestSecretCreate(t *testing.T) {
expectedURL := "/secrets"
expectedURL := "/secrets/create"
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
@@ -41,7 +41,7 @@ func TestSecretCreate(t *testing.T) {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
StatusCode: http.StatusCreated,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}),

View File

@@ -1,6 +1,7 @@
package client
import (
"encoding/json"
"net/url"
"strconv"
@@ -10,7 +11,7 @@ import (
)
// ServiceUpdate updates a Service.
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) error {
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
var (
headers map[string][]string
query = url.Values{}
@@ -28,7 +29,13 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
query.Set("version", strconv.FormatUint(version.Index, 10))
var response types.ServiceUpdateResponse
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
if err != nil {
return response, err
}
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return err
return response, err
}

View File

@@ -19,7 +19,7 @@ func TestServiceUpdateError(t *testing.T) {
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
}
err := client.ServiceUpdate(context.Background(), "service_id", swarm.Version{}, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
_, err := client.ServiceUpdate(context.Background(), "service_id", swarm.Version{}, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
if err == nil || err.Error() != "Error response from daemon: Server error" {
t.Fatalf("expected a Server Error, got %v", err)
}
@@ -64,12 +64,12 @@ func TestServiceUpdate(t *testing.T) {
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader([]byte("body"))),
Body: ioutil.NopCloser(bytes.NewReader([]byte("{}"))),
}, nil
}),
}
err := client.ServiceUpdate(context.Background(), "service_id", updateCase.swarmVersion, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
_, err := client.ServiceUpdate(context.Background(), "service_id", updateCase.swarmVersion, swarm.ServiceSpec{}, types.ServiceUpdateOptions{})
if err != nil {
t.Fatal(err)
}

View File

@@ -1,6 +1,7 @@
package main
import (
"errors"
"fmt"
"os"
@@ -34,27 +35,37 @@ func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
showVersion()
return nil
}
cmd.SetOutput(dockerCli.Err())
cmd.HelpFunc()(cmd, args)
return nil
return dockerCli.ShowHelp(cmd, args)
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// daemon command is special, we redirect directly to another binary
if cmd.Name() == "daemon" {
return nil
}
// flags must be the top-level command flags, not cmd.Flags()
opts.Common.SetDefaultOptions(flags)
dockerPreRun(opts)
return dockerCli.Initialize(opts)
if err := dockerCli.Initialize(opts); err != nil {
return err
}
return isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental())
},
}
cli.SetupRootCommand(cmd)
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
if dockerCli.Client() == nil {
if dockerCli.Client() == nil { // when using --help, PersistenPreRun is not called, so initialization is needed.
// flags must be the top-level command flags, not cmd.Flags()
opts.Common.SetDefaultOptions(flags)
dockerPreRun(opts)
dockerCli.Initialize(opts)
}
if err := isSupported(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()); err != nil {
ccmd.Println(err)
return
}
hideUnsupportedFeatures(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental())
if err := ccmd.Help(); err != nil {
@@ -79,7 +90,7 @@ func noArgs(cmd *cobra.Command, args []string) error {
return nil
}
return fmt.Errorf(
"docker: '%s' is not a docker command.\nSee 'docker --help'.", args[0])
"docker: '%s' is not a docker command.\nSee 'docker --help'", args[0])
}
func main() {
@@ -126,8 +137,10 @@ func dockerPreRun(opts *cliflags.ClientOptions) {
func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperimental bool) {
cmd.Flags().VisitAll(func(f *pflag.Flag) {
// hide experimental flags
if _, ok := f.Annotations["experimental"]; ok {
f.Hidden = true
if !hasExperimental {
if _, ok := f.Annotations["experimental"]; ok {
f.Hidden = true
}
}
// hide flags not supported by the server
@@ -139,8 +152,10 @@ func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperi
for _, subcmd := range cmd.Commands() {
// hide experimental subcommands
if _, ok := subcmd.Tags["experimental"]; ok {
subcmd.Hidden = true
if !hasExperimental {
if _, ok := subcmd.Tags["experimental"]; ok {
subcmd.Hidden = true
}
}
// hide subcommands not supported by the server
@@ -149,3 +164,17 @@ func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperi
}
}
}
func isSupported(cmd *cobra.Command, clientVersion string, hasExperimental bool) error {
if !hasExperimental {
if _, ok := cmd.Tags["experimental"]; ok {
return errors.New("only supported with experimental daemon")
}
}
if cmdVersion, ok := cmd.Tags["version"]; ok && versions.LessThan(clientVersion, cmdVersion) {
return fmt.Errorf("only supported with daemon version >= %s", cmdVersion)
}
return nil
}

View File

@@ -17,6 +17,7 @@ import (
"github.com/docker/docker/api/server/middleware"
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/server/router/build"
checkpointrouter "github.com/docker/docker/api/server/router/checkpoint"
"github.com/docker/docker/api/server/router/container"
"github.com/docker/docker/api/server/router/image"
"github.com/docker/docker/api/server/router/network"
@@ -461,25 +462,32 @@ func loadDaemonCliConfig(opts daemonOptions) (*daemon.Config, error) {
func initRouter(s *apiserver.Server, d *daemon.Daemon, c *cluster.Cluster) {
decoder := runconfig.ContainerDecoder{}
routers := []router.Router{}
// we need to add the checkpoint router before the container router or the DELETE gets masked
routers = addExperimentalRouters(routers, d, decoder)
routers = append(routers, []router.Router{
routers := []router.Router{
// we need to add the checkpoint router before the container router or the DELETE gets masked
checkpointrouter.NewRouter(d, decoder),
container.NewRouter(d, decoder),
image.NewRouter(d, decoder),
systemrouter.NewRouter(d, c),
volume.NewRouter(d),
build.NewRouter(dockerfile.NewBuildManager(d)),
swarmrouter.NewRouter(d, c),
swarmrouter.NewRouter(c),
pluginrouter.NewRouter(plugin.GetManager()),
}...)
}
if d.NetworkControllerEnabled() {
routers = append(routers, network.NewRouter(d, c))
}
if d.HasExperimental() {
for _, r := range routers {
for _, route := range r.Routes() {
if experimental, ok := route.(router.ExperimentalRoute); ok {
experimental.Enable()
}
}
}
}
s.InitRouter(utils.IsDebugEnabled(), routers...)
}

View File

@@ -1,15 +0,0 @@
package main
import (
"github.com/docker/docker/api/server/httputils"
"github.com/docker/docker/api/server/router"
checkpointrouter "github.com/docker/docker/api/server/router/checkpoint"
"github.com/docker/docker/daemon"
)
func addExperimentalRouters(routers []router.Router, d *daemon.Daemon, decoder httputils.ContainerDecoder) []router.Router {
if !d.HasExperimental() {
return []router.Router{}
}
return append(routers, checkpointrouter.NewRouter(d, decoder))
}

View File

@@ -27,7 +27,7 @@ var (
flUnregisterService *bool
flRunService *bool
setStdHandle = syscall.NewLazyDLL("kernel32.dll").NewProc("SetStdHandle")
setStdHandle = windows.NewLazySystemDLL("kernel32.dll").NewProc("SetStdHandle")
oldStderr syscall.Handle
panicFile *os.File

View File

@@ -19,6 +19,8 @@ import (
containertypes "github.com/docker/docker/api/types/container"
mounttypes "github.com/docker/docker/api/types/mount"
networktypes "github.com/docker/docker/api/types/network"
swarmtypes "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/container/stream"
"github.com/docker/docker/daemon/exec"
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/daemon/logger/jsonfilelog"
@@ -40,6 +42,7 @@ import (
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/types"
agentexec "github.com/docker/swarmkit/agent/exec"
"github.com/opencontainers/runc/libcontainer/label"
)
@@ -65,9 +68,9 @@ func (DetachError) Error() string {
// CommonContainer holds the fields for a container which are
// applicable across all platforms supported by the daemon.
type CommonContainer struct {
*runconfig.StreamConfig
StreamConfig *stream.Config
// embed for Container to support states directly.
*State `json:"State"` // Needed for remote api version <= 1.11
*State `json:"State"` // Needed for Engine API version <= 1.11
Root string `json:"-"` // Path to the "home" of the container, including metadata.
BaseFS string `json:"-"` // Path to the graphdriver mountpoint
RWLayer layer.RWLayer `json:"-"`
@@ -89,9 +92,10 @@ type CommonContainer struct {
HasBeenStartedBefore bool
HasBeenManuallyStopped bool // used for unless-stopped restart policy
MountPoints map[string]*volume.MountPoint
HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable
ExecCommands *exec.Store `json:"-"`
Secrets []*containertypes.ContainerSecret `json:"-"` // do not serialize
HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable
ExecCommands *exec.Store `json:"-"`
SecretStore agentexec.SecretGetter `json:"-"`
SecretReferences []*swarmtypes.SecretReference
// logDriver for closing
LogDriver logger.Logger `json:"-"`
LogCopier *logger.Copier `json:"-"`
@@ -109,7 +113,7 @@ func NewBaseContainer(id, root string) *Container {
ExecCommands: exec.NewStore(),
Root: root,
MountPoints: make(map[string]*volume.MountPoint),
StreamConfig: runconfig.NewStreamConfig(),
StreamConfig: stream.NewConfig(),
attachContext: &attachContext{},
},
}
@@ -377,7 +381,7 @@ func (container *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr
// AttachStreams connects streams to a TTY.
// Used by exec too. Should this move somewhere else?
func AttachStreams(ctx context.Context, streamConfig *runconfig.StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer, keys []byte) chan error {
func AttachStreams(ctx context.Context, streamConfig *stream.Config, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer, keys []byte) chan error {
var (
cStdout, cStderr io.ReadCloser
cStdin io.WriteCloser
@@ -1064,6 +1068,26 @@ func (container *Container) startLogging() error {
return nil
}
// StdinPipe gets the stdin stream of the container
func (container *Container) StdinPipe() io.WriteCloser {
return container.StreamConfig.StdinPipe()
}
// StdoutPipe gets the stdout stream of the container
func (container *Container) StdoutPipe() io.ReadCloser {
return container.StreamConfig.StdoutPipe()
}
// StderrPipe gets the stderr stream of the container
func (container *Container) StderrPipe() io.ReadCloser {
return container.StreamConfig.StderrPipe()
}
// CloseStreams closes the container's stdio streams
func (container *Container) CloseStreams() error {
return container.StreamConfig.CloseStreams()
}
// InitializeStdio is called by libcontainerd to connect the stdio.
func (container *Container) InitializeStdio(iop libcontainerd.IOPipe) error {
if err := container.startLogging(); err != nil {
@@ -1073,7 +1097,7 @@ func (container *Container) InitializeStdio(iop libcontainerd.IOPipe) error {
container.StreamConfig.CopyToPipe(iop)
if container.Stdin() == nil && !container.Config.Tty {
if container.StreamConfig.Stdin() == nil && !container.Config.Tty {
if iop.Stdin != nil {
if err := iop.Stdin.Close(); err != nil {
logrus.Warnf("error closing stdin: %+v", err)

View File

@@ -258,7 +258,7 @@ func (container *Container) IpcMounts() []Mount {
// SecretMount returns the mount for the secret path
func (container *Container) SecretMount() *Mount {
if len(container.Secrets) > 0 {
if len(container.SecretReferences) > 0 {
return &Mount{
Source: container.SecretMountPath(),
Destination: containerSecretMountPath,

View File

@@ -42,10 +42,7 @@ func (s *Health) OpenMonitorChannel() chan struct{} {
func (s *Health) CloseMonitorChannel() {
if s.stop != nil {
logrus.Debug("CloseMonitorChannel: waiting for probe to stop")
// This channel does not buffer. Once the write succeeds, the monitor
// has read the stop request and will not make any further updates
// to c.State.Health.
s.stop <- struct{}{}
close(s.stop)
s.stop = nil
logrus.Debug("CloseMonitorChannel done")
}

View File

@@ -23,7 +23,7 @@ func (container *Container) Reset(lock bool) {
// Re-create a brand new stdin pipe once the container exited
if container.Config.OpenStdin {
container.NewInputPipes()
container.StreamConfig.NewInputPipes()
}
if container.LogDriver != nil {

View File

@@ -1,4 +1,4 @@
package runconfig
package stream
import (
"fmt"
@@ -14,16 +14,16 @@ import (
"github.com/docker/docker/pkg/pools"
)
// StreamConfig holds information about I/O streams managed together.
// Config holds information about I/O streams managed together.
//
// streamConfig.StdinPipe returns a WriteCloser which can be used to feed data
// config.StdinPipe returns a WriteCloser which can be used to feed data
// to the standard input of the streamConfig's active process.
// streamConfig.StdoutPipe and streamConfig.StderrPipe each return a ReadCloser
// config.StdoutPipe and streamConfig.StderrPipe each return a ReadCloser
// which can be used to retrieve the standard output (and error) generated
// by the container's active process. The output (and error) are actually
// copied and delivered to all StdoutPipe and StderrPipe consumers, using
// a kind of "broadcaster".
type StreamConfig struct {
type Config struct {
sync.WaitGroup
stdout *broadcaster.Unbuffered
stderr *broadcaster.Unbuffered
@@ -31,76 +31,76 @@ type StreamConfig struct {
stdinPipe io.WriteCloser
}
// NewStreamConfig creates a stream config and initializes
// NewConfig creates a stream config and initializes
// the standard err and standard out to new unbuffered broadcasters.
func NewStreamConfig() *StreamConfig {
return &StreamConfig{
func NewConfig() *Config {
return &Config{
stderr: new(broadcaster.Unbuffered),
stdout: new(broadcaster.Unbuffered),
}
}
// Stdout returns the standard output in the configuration.
func (streamConfig *StreamConfig) Stdout() *broadcaster.Unbuffered {
return streamConfig.stdout
func (c *Config) Stdout() *broadcaster.Unbuffered {
return c.stdout
}
// Stderr returns the standard error in the configuration.
func (streamConfig *StreamConfig) Stderr() *broadcaster.Unbuffered {
return streamConfig.stderr
func (c *Config) Stderr() *broadcaster.Unbuffered {
return c.stderr
}
// Stdin returns the standard input in the configuration.
func (streamConfig *StreamConfig) Stdin() io.ReadCloser {
return streamConfig.stdin
func (c *Config) Stdin() io.ReadCloser {
return c.stdin
}
// StdinPipe returns an input writer pipe as an io.WriteCloser.
func (streamConfig *StreamConfig) StdinPipe() io.WriteCloser {
return streamConfig.stdinPipe
func (c *Config) StdinPipe() io.WriteCloser {
return c.stdinPipe
}
// StdoutPipe creates a new io.ReadCloser with an empty bytes pipe.
// It adds this new out pipe to the Stdout broadcaster.
func (streamConfig *StreamConfig) StdoutPipe() io.ReadCloser {
func (c *Config) StdoutPipe() io.ReadCloser {
bytesPipe := ioutils.NewBytesPipe()
streamConfig.stdout.Add(bytesPipe)
c.stdout.Add(bytesPipe)
return bytesPipe
}
// StderrPipe creates a new io.ReadCloser with an empty bytes pipe.
// It adds this new err pipe to the Stderr broadcaster.
func (streamConfig *StreamConfig) StderrPipe() io.ReadCloser {
func (c *Config) StderrPipe() io.ReadCloser {
bytesPipe := ioutils.NewBytesPipe()
streamConfig.stderr.Add(bytesPipe)
c.stderr.Add(bytesPipe)
return bytesPipe
}
// NewInputPipes creates new pipes for both standard inputs, Stdin and StdinPipe.
func (streamConfig *StreamConfig) NewInputPipes() {
streamConfig.stdin, streamConfig.stdinPipe = io.Pipe()
func (c *Config) NewInputPipes() {
c.stdin, c.stdinPipe = io.Pipe()
}
// NewNopInputPipe creates a new input pipe that will silently drop all messages in the input.
func (streamConfig *StreamConfig) NewNopInputPipe() {
streamConfig.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard)
func (c *Config) NewNopInputPipe() {
c.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard)
}
// CloseStreams ensures that the configured streams are properly closed.
func (streamConfig *StreamConfig) CloseStreams() error {
func (c *Config) CloseStreams() error {
var errors []string
if streamConfig.stdin != nil {
if err := streamConfig.stdin.Close(); err != nil {
if c.stdin != nil {
if err := c.stdin.Close(); err != nil {
errors = append(errors, fmt.Sprintf("error close stdin: %s", err))
}
}
if err := streamConfig.stdout.Clean(); err != nil {
if err := c.stdout.Clean(); err != nil {
errors = append(errors, fmt.Sprintf("error close stdout: %s", err))
}
if err := streamConfig.stderr.Clean(); err != nil {
if err := c.stderr.Clean(); err != nil {
errors = append(errors, fmt.Sprintf("error close stderr: %s", err))
}
@@ -112,25 +112,25 @@ func (streamConfig *StreamConfig) CloseStreams() error {
}
// CopyToPipe connects streamconfig with a libcontainerd.IOPipe
func (streamConfig *StreamConfig) CopyToPipe(iop libcontainerd.IOPipe) {
func (c *Config) CopyToPipe(iop libcontainerd.IOPipe) {
copyFunc := func(w io.Writer, r io.Reader) {
streamConfig.Add(1)
c.Add(1)
go func() {
if _, err := pools.Copy(w, r); err != nil {
logrus.Errorf("stream copy error: %+v", err)
}
streamConfig.Done()
c.Done()
}()
}
if iop.Stdout != nil {
copyFunc(streamConfig.Stdout(), iop.Stdout)
copyFunc(c.Stdout(), iop.Stdout)
}
if iop.Stderr != nil {
copyFunc(streamConfig.Stderr(), iop.Stderr)
copyFunc(c.Stderr(), iop.Stderr)
}
if stdin := streamConfig.Stdin(); stdin != nil {
if stdin := c.Stdin(); stdin != nil {
if iop.Stdin != nil {
go func() {
pools.Copy(iop.Stdin, stdin)

View File

@@ -0,0 +1,10 @@
#!/bin/bash
set -e
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
set -x
./generate.sh
for d in */; do
docker build -t "dockercore/builder-deb:$(basename "$d")" "$d"
done

View File

@@ -0,0 +1,118 @@
#!/bin/bash
set -e
# This file is used to auto-generate Dockerfiles for making debs via 'make deb'
#
# usage: ./generate.sh [versions]
# ie: ./generate.sh
# to update all Dockerfiles in this directory
# or: ./generate.sh ubuntu-trusty
# to only update ubuntu-trusty/Dockerfile
# or: ./generate.sh ubuntu-newversion
# to create a new folder and a Dockerfile within it
#
# Note: non-LTS versions are not guaranteed to work.
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
versions=( "$@" )
if [ ${#versions[@]} -eq 0 ]; then
versions=( */ )
fi
versions=( "${versions[@]%/}" )
for version in "${versions[@]}"; do
echo "${versions[@]}"
distro="${version%-*}"
suite="${version##*-}"
from="aarch64/${distro}:${suite}"
mkdir -p "$version"
echo "$version -> FROM $from"
cat > "$version/Dockerfile" <<-EOF
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/deb/aarch64/generate.sh"!
#
FROM $from
EOF
dockerBuildTags='apparmor pkcs11 selinux'
runcBuildTags='apparmor selinux'
# this list is sorted alphabetically; please keep it that way
packages=(
apparmor # for apparmor_parser for testing the profile
bash-completion # for bash-completion debhelper integration
btrfs-tools # for "btrfs/ioctl.h" (and "version.h" if possible)
build-essential # "essential for building Debian packages"
cmake # tini dep
curl ca-certificates # for downloading Go
debhelper # for easy ".deb" building
dh-apparmor # for apparmor debhelper
dh-systemd # for systemd debhelper integration
git # for "git commit" info in "docker -v"
libapparmor-dev # for "sys/apparmor.h"
libdevmapper-dev # for "libdevmapper.h"
libltdl-dev # for pkcs11 "ltdl.h"
libsqlite3-dev # for "sqlite3.h"
pkg-config # for detecting things like libsystemd-journal dynamically
vim-common # tini dep
)
case "$suite" in
trusty)
packages+=( libsystemd-journal-dev )
# aarch64 doesn't have an official downloadable binary for go.
# And gccgo for trusty only includes Go 1.2 implementation which
# is too old to build current go source, fortunately trusty has
# golang-1.6-go package can be used as bootstrap.
packages+=( golang-1.6-go )
;;
xenial)
packages+=( libsystemd-dev )
packages+=( golang-go libseccomp-dev)
dockerBuildTags="$dockerBuildTags seccomp"
runcBuildTags="$runcBuildTags seccomp"
;;
*)
echo "Unsupported distro:" $distro:$suite
rm -fr "$version"
exit 1
;;
esac
# update and install packages
echo "RUN apt-get update && apt-get install -y ${packages[*]} --no-install-recommends && rm -rf /var/lib/apt/lists/*" >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
case "$suite" in
trusty)
echo 'RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
;;
*)
;;
esac
echo "# Install Go" >> "$version/Dockerfile"
echo "# aarch64 doesn't have official go binaries, so use the version of go installed from" >> "$version/Dockerfile"
echo "# the image to build go from source." >> "$version/Dockerfile"
awk '$1 == "ENV" && $2 == "GO_VERSION" { print; exit }' ../../../../Dockerfile.aarch64 >> "$version/Dockerfile"
echo 'RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \' >> "$version/Dockerfile"
echo ' && cd /usr/src/go/src \' >> "$version/Dockerfile"
echo ' && GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo 'ENV PATH $PATH:/usr/src/go/bin' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo "ENV AUTO_GOPATH 1" >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo "ENV DOCKER_BUILDTAGS $dockerBuildTags" >> "$version/Dockerfile"
echo "ENV RUNC_BUILDTAGS $runcBuildTags" >> "$version/Dockerfile"
done

View File

@@ -0,0 +1,24 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/deb/aarch64/generate.sh"!
#
FROM aarch64/ubuntu:trusty
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libsqlite3-dev pkg-config vim-common libsystemd-journal-dev golang-1.6-go --no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.7.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
ENV PATH $PATH:/usr/src/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux
ENV RUNC_BUILDTAGS apparmor selinux

View File

@@ -0,0 +1,22 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/deb/aarch64/generate.sh"!
#
FROM aarch64/ubuntu:xenial
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libsqlite3-dev pkg-config vim-common libsystemd-dev golang-go libseccomp-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.7.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash
ENV PATH $PATH:/usr/src/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS apparmor pkcs11 selinux seccomp
ENV RUNC_BUILDTAGS apparmor selinux seccomp

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