Compare commits

..

421 Commits

Author SHA1 Message Date
f4ffd2511c Merge pull request #273 from andrewhsu/v
[17.10] bump version to 17.10.0-ce
2017-10-17 11:51:33 -07:00
ec6b6de1c8 Merge pull request #272 from andrewhsu/c
[17.10] update changelog for 17.10.0-ce
2017-10-17 11:51:16 -07:00
8bac3f632b update changelog for 17.10.0-ce
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-17 11:02:49 -07:00
646a76c31b bump version to 17.10.0-ce
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-13 14:37:20 -07:00
af94197a36 Merge pull request #268 from andrewhsu/v
[17.10] bump version to 17.10.0-ce-rc2
2017-10-11 17:38:08 -07:00
2f11502622 Merge pull request #269 from andrewhsu/cl
[17.10] update changelog for 17.10.0-ce-rc2
2017-10-11 17:37:59 -07:00
24ee573f35 Merge pull request #270 from andrewhsu/sk
[17.10] re-vndr swarmkit to 1d2bc2e
2017-10-11 17:37:36 -07:00
4d73e16a14 update changelog for 17.10.0-ce-rc2
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 16:28:26 -07:00
1311aaf76e Merge pull request #271 from andrewhsu/d
[17.10] backport doc fixes and shell completion script fixes
2017-10-11 16:10:39 -07:00
6f56735237 Merge pull request #266 from johnstep/windows-manifest-lists
[17.10] Backport version fix for Windows manifest lists
2017-10-11 16:08:09 -07:00
e274827392 Merge pull request #267 from seemethere/cherry_pick_cli_607
[17.10] Mutate image references where needed for trusted pulls
2017-10-11 16:03:47 -07:00
e7f51b183f Fix markdown link in service-create reference docs
Markdown nested in a HTML table doesn't work, so changing
the link to a plain HTML link.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 6b6511f191)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:32:32 -07:00
792e8f9a82 Fix dockerd reference heading levels
Commit ddadd3db49 changed
the heading levels of various sections, but as a result,
the "daemon configuration file" section (and other sections)
changed from a H2 to a H4, therefore no longer showing
up in the page's TOC / navigation bar.

This patch changes the heading level to a H3 for
sections that should show up in the page navigation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit aca0421eb8)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:31:37 -07:00
8b13940b3b Update rmi.md
Signed-off-by: Daniel Goosen <daniel.goosen@surveysampling.com>
(cherry picked from commit 9004495541)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:30:49 -07:00
550052ebae Add bash completion for secret create --driver
Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 1d7a31f87e)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:29:15 -07:00
b0596beda5 Add bash completion for stack deploy --resolve-image
Also adds minimal documentation for this flag.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 9559b9b7a8)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:28:15 -07:00
6fc2c6b8c5 Update deprecation for synchronous service updates
- The default was not changed in 17.09 but will be in 17.10
- `service scale` and `service rollback` are also affected.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 20d9ceca78)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:26:34 -07:00
f26232e8f6 Update bash completion for synchronous docker service commands
The default value for
`docker service create|update|scale|rollback --detach|-d` changed from
`true` to `false`.
This updates bash completion to complete just `--detach|-d`.

Signed-off-by: Harald Albers <github@albersweb.de>
(cherry picked from commit 60bfaba6fb)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 15:26:34 -07:00
018b6401f5 re-vndr swarmkit to 1d2bc2e
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 14:27:34 -07:00
56bd88c226 bump version to 17.10.0-ce-rc2
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-11 10:55:10 -07:00
fc8971da3b Merge pull request #265 from andrewhsu/olay
[17.10] Fallback to use naive diff driver if enable CONFIG_OVERLAY_FS_REDIREC…
2017-10-11 10:49:01 -07:00
9f566ba32b Update e2e test for image pull to check stdout
Also add TEST_DEBUG env variable for debugging E2E tests.
And change icmd environment helpers to fit the CmdOp interface os they
can be passed to 'icmd.RunCmd()'

Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit b11c11ea74)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
785d4378ad Refactor runPull to remove second GetImageReferencesAndAuth
Fix unit tests to catch the regression.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit e548861481)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
e9a538eda6 factor out rigging for pushing unsigned busybox image
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit 7dda6fc3c9)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
cdee6d83f4 update image pull tests
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit 46f3d8bb7f)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
c76d10969f get e2e working with notary service
Signed-off-by: Daniel Nephin <dnephin@docker.com>
(cherry picked from commit ade675d36c)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
02f6ddc6ae trust: update references when pulling
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit 067fff8b03)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
125ffb8b1b update e2e tests for content trust tests
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
(cherry picked from commit 6e3bafd06b)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-11 10:47:45 -07:00
9c61899f29 Merge pull request #264 from andrewhsu/v
[17.10] re-vndr libnetwork to 6c51292 and swarmkit to 872861d
2017-10-11 10:46:00 -07:00
76922d8690 Stop filtering Windows manifest lists by version
Signed-off-by: John Stephens <johnstep@docker.com>
(cherry picked from commit 8ed8f4a71d7e1a936fa077b4348b7375c81746a6)

Conflicts:
	components/engine/distribution/pull_v2_windows.go

Signed-off-by: John Stephens <johnstep@docker.com>
2017-10-10 21:42:19 -07:00
f437cf754f Add support for Windows version filtering on pull
Update logic to choose manifest from manifest list to check
for os version on Windows. Separate the logic for windows
and unix to keep unix logic the same.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
(cherry picked from commit 38aef56e1fcb8ea318df98c89cf002267b88a136)
Signed-off-by: John Stephens <johnstep@docker.com>
2017-10-10 21:10:00 -07:00
2adb51e303 Fallback to use naive diff driver if enable CONFIG_OVERLAY_FS_REDIRECT_DIR
When use overlay2 as the graphdriver and the kernel enable
`CONFIG_OVERLAY_FS_REDIRECT_DIR=y`, rename a dir in lower layer
will has a xattr to redirct its dir to source dir. This make the
image layer unportable. This patch fallback to use naive diff driver
when kernel enable CONFIG_OVERLAY_FS_REDIRECT_DIR

Signed-off-by: Lei Jitang <leijitang@huawei.com>
(cherry picked from commit 49c3a7c4bac2877265ef8c4eaf210159560f08b4)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-10 20:56:55 -07:00
a761ee3d4d Modifying swarm integration test
Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
(cherry picked from commit 7e6b2165ef58e68ad4eafd457e8de89dd4c2c6b1)
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-10 18:59:32 -07:00
e1484d2ff8 re-vndr swarmkit to 872861d
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-10 17:50:47 -07:00
d82f9fe3f3 re-vndr libnetwork to 6c51292
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-10-10 17:19:58 -07:00
73ecdcee10 Merge pull request #263 from seemethere/change_ubuntu_trusty_package_mirror
Switches ubuntu trusty mirror to one that works
2017-10-10 10:24:53 -07:00
c8e9afef61 Switches ubuntu trusty mirror to one that works
Was getting 404's with the old one, consider this one temporary until
canonical fixes their stuff.

Related:
https://bugs.launchpad.net/cloud-images/+bug/1711735

Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
(cherry picked from commit 8e177368d0a30614a7ba615f3c2f2ede1e21ff8e)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-10 10:22:06 -07:00
d866876d86 Merge pull request #259 from andrewhsu/v
[17.10] bump version to 17.10.0-ce-rc1
2017-10-04 14:11:32 -07:00
8ab000a5f4 Merge pull request #256 from vieux/17.10-changelog
[17.10] add 17.10 changelog
2017-10-04 14:08:52 -07:00
c8ede6fcc6 Merge pull request #260 from seemethere/fix_tests_for_1710_release
[17.10] Fix tests for 17.10 release
2017-10-04 14:07:13 -07:00
0d46b8e710 [integration-cli] fix s390x flaky test
s390x node-1 has kernel 4.6.0, kernel.CompareKernelVersion()
returns 0 if the kernels are equal, so include that.

Full logic for CompareKernelVersion() is
a > b ret 1,
a == b ret 0,
a < b ret -1

Signed-off-by: Christopher Jones <tophj@linux.vnet.ibm.com>
(cherry picked from commit aa5ea652c8864f014e1fa480d7e504f0d742c170)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-04 13:11:31 -07:00
58f592c0d9 Add note to test changes for rmi
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-10-04 10:43:27 -07:00
e58d3abea8 Switch from using lstat to stat in docker cp test. Use the first 12 characters of the ID for the stats test substring.
Signed-off-by: Corbin <corbin.coleman@docker.com>
2017-10-03 14:02:17 -07:00
4f818dd6f7 Add detach flag for scale tests
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-30 13:23:18 -07:00
d73806305a Changes error check form NotNil to IsNil
rmi -f always returns a 0 exit code so these tests needed to be changed
accordingly.

Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
(cherry picked from commit 5d1587e61e)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-30 13:23:18 -07:00
4e81e4fa4e Blacklist tests, will be rewritten later on
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-30 13:23:18 -07:00
8a6c4c93b6 Merge pull request #261 from seemethere/ensure_channel
[17.10] ensure channel is allocated
2017-09-30 09:36:10 -07:00
7b99808cac cli/command/container: ensure channel is allocated
Signed-off-by: Stephen J Day <stephen.day@docker.com>
(cherry picked from commit e78772af4d)
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-29 18:14:51 -07:00
fab4b40e38 bump version to 17.10.0-ce-rc1
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-09-29 16:12:03 -07:00
079f5eb5e5 removed deprecation line
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-09-29 15:56:26 -07:00
db0a220cda update punctuation and spacing
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
2017-09-29 15:47:47 -07:00
71bb1e8c44 add 17.10 changelog
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
2017-09-29 15:47:47 -07:00
328a5917ad Merge component 'engine' from git@github.com:moby/moby master 2017-09-29 22:30:27 +00:00
09bc512154 Merge component 'cli' from git@github.com:docker/cli master 2017-09-29 22:08:57 +00:00
4b8b813d22 Merge pull request #570 from thaJeztah/bump-moby-vendor
Bump moby vendor to 14ce1f1cf48e9859223c6311de58aec4dc
Upstream-commit: 31908a4b45
Component: cli
2017-09-29 23:08:16 +02:00
0e6592d05e Merge pull request #572 from thaJeztah/bump-vendor-for-powerpc
revendor logrus and x/crypto
Upstream-commit: 00cc728dfb
Component: cli
2017-09-29 13:58:38 -07:00
4c4e74cebe Merge pull request #35042 from pradipd/panic_fix
Fixing panic when sandbox is nil
Upstream-commit: ab2b03a0e139537376bbf66c1e1e9e897a403f06
Component: engine
2017-09-29 12:51:55 -07:00
28e35b96d0 Fixing panic when sandbox is nil
Signed-off-by: Pradip Dhara <pradipd@microsoft.com>
Upstream-commit: c4ad0747e929a41ecec7e8c2ae2bd0cc037401ed
Component: engine
2017-09-29 09:23:06 -07:00
c9fbb737e9 Fixes for updated dependencies
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 0082310aa5
Component: cli
2017-09-29 17:45:31 +02:00
c9e8020d97 bump moby/moby and dependencies to 14ce1f1cf48e9859223c6311de58aec4dc0f046c
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 98dbfeee76
Component: cli
2017-09-29 17:44:49 +02:00
0b195d3e47 Merge pull request #571 from thaJeztah/bump-vndr
Bump vndr to a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384
Upstream-commit: 107f6c6ab2
Component: cli
2017-09-29 17:39:21 +02:00
6230f06c47 revendor logrus and x/crypto
updates to the same version as is currently used
on moby/moby; this bump contains fixes for ppc64le.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: e3b7700fb9
Component: cli
2017-09-29 15:32:42 +02:00
5edb9ec08c Bump vndr to a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384
Includes a fix to cleanup unused vendor-directories

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 368b639e7e
Component: cli
2017-09-29 14:58:05 +02:00
907b966c7e Merge pull request #35029 from fntlnz/builder/cleaning
Cleaning dead code out of the builder
Upstream-commit: de6cb7ab848d6131634e40d21d30bf2fe183e9a3
Component: engine
2017-09-29 16:28:02 +09:00
4034b44eca Cleaning dead code out of the builder
Signed-off-by: Lorenzo Fontana <lo@linux.com>
Upstream-commit: dff2a23749a6b7c949146d7850f514cd74e3a8d7
Component: engine
2017-09-29 02:55:35 +02:00
80c3ad8db1 Merge pull request #35008 from yujuhong/cli-version
Fix version comparison when negotiating the the API version
Upstream-commit: 14ce1f1cf48e9859223c6311de58aec4dc0f046c
Component: engine
2017-09-28 11:58:50 -10:00
d62e09de17 Merge pull request #35025 from Microsoft/jjh/TestRunAttachFailedNoLeak
Windows: RS3: Temporarily disable TestRunAttachFailedNoLeak
Upstream-commit: 048ef0db6a75898aee57bf725ed64940744cd938
Component: engine
2017-09-28 21:59:32 +02:00
5fe53bab44 Merge pull request #565 from thaJeztah/change-stats-format
Change default stats format and add --no-trunc flag
Upstream-commit: 64d5c32b8e
Component: cli
2017-09-28 15:14:43 -04:00
ae273c63d1 Merge component 'engine' from git@github.com:moby/moby master 2017-09-28 10:34:35 -07:00
4330196b5a Windows: RS3: Temporarily disable TestRunAttachFailedNoLeak
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: 9e587fa72b8cc42895681efe3d0b9fdcdfe3b06d
Component: engine
2017-09-28 10:15:58 -07:00
e25514ef0c Merge pull request #35004 from thaJeztah/dont-warn-for-comment-only-lines
Warn on empty continuation lines only, not on comment-only lines
Upstream-commit: 94b987043ffd372aad49dfc51c3be2c2f6cff97f
Component: engine
2017-09-28 08:56:30 -07:00
d6eb3e21a4 Merge pull request #35007 from seemethere/fix_service_detach_tests
Explicitly add --detach to service CLI calls
Upstream-commit: 5a4841079bc247937e6ed1042ab24ffd01a8547c
Component: engine
2017-09-28 11:17:14 +02:00
747a47b477 Fix version comparison when negotiating the the API version
Signed-off-by: Yu-Ju Hong <yjhong@google.com>
Upstream-commit: 4b6ec10b07c14e7fff1cc51156b6d954147f826f
Component: engine
2017-09-27 18:42:02 -07:00
d7aeee3eda remove --detach on scale
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
Upstream-commit: 0ad0294124badebe0d9a73f1b7e2f030e4a24e2b
Component: engine
2017-09-27 17:47:51 -07:00
8d23cb5213 Merge pull request #34966 from AkihiroSuda/seccomp
Dockerfile: use seccomp provided by stretch
Upstream-commit: aa02e2b7bc1f5f4b921f64337e4f6d1cf7aa8fe4
Component: engine
2017-09-27 16:21:55 -07:00
ca5a5c5ca1 Explicitly add --detach to service CLI calls
The behavior of service (create/update/scale) was changed in a recent PR
to docker/cli. This commit serves to remedy test failures experienced
when attempting to use service calls.

Should not affect current behavior.

Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
Upstream-commit: e5b3ebbc649e4b1a10d4cdca342a153c301ec225
Component: engine
2017-09-27 16:17:55 -07:00
f6d296e26e Warn on empty continuation lines only, not for comments
Commit 8d1ae76dcbbb73d8e20c6a14a7d3fe2410b95f55 added
deprecation warnings for empty continuation lines,
but also treated comment-only lines as empty.

This patch distinguishes empty continuation lines
from comment-only lines, and only outputs warnings
for the former.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 2fd736ac10c1c46d1001373d887cb99b3d8ee824
Component: engine
2017-09-28 00:11:10 +02:00
00bb761ead Merge pull request #34990 from pradipd/update_field_name
Update field name
Upstream-commit: 853df8f32bf560428fdc39dfd9bfa7bb7c610346
Component: engine
2017-09-27 20:00:18 +02:00
747646833d Merge component 'engine' from git@github.com:moby/moby master 2017-09-27 10:25:04 -07:00
b4a6a3d358 Add --no-trunc option to docker container stats
This patch adds a `--no-trunc` option to `docker container stats`;

With this patch applied, the default output is:

    CONTAINER ID        NAME                                    CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    b95a83497c91        awesome_brattain                        0.28%               5.629MiB / 1.952GiB   0.28%               916B / 0B           147kB / 0B          9
    67b2525d8ad1        foobar                                  0.00%               1.727MiB / 1.952GiB   0.09%               2.48kB / 0B         4.11MB / 0B         2
    e5c383697914        test-1951.1.kay7x1lh1twk9c0oig50sd5tr   0.00%               196KiB / 1.952GiB     0.01%               71.2kB / 0B         770kB / 0B          1
    4bda148efbc0        random.1.vnc8on831idyr42slu578u3cr      0.00%               1.672MiB / 1.952GiB   0.08%               110kB / 0B          578kB / 0B          2
    84e3deaa45b2        registry                                0.01%               3.402MiB / 1.952GiB   0.17%               127kB / 378B        233kB / 0B          10
    2ed915778ceb        foo.1.lsmxrefn5yp9c9ijz1hzgdq4u         0.00%               1.727MiB / 1.952GiB   0.09%               166kB / 7.76kB      614kB / 0B          2

Addin the `--no-trunc` option, changes the output to:

    CONTAINER ID                                                       NAME                                    CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    b95a83497c9161c9b444e3d70e1a9dfba0c1840d41720e146a95a08ebf938afc   awesome_brattain                        0.25%               5.75MiB / 1.952GiB    0.29%               648B / 0B           147kB / 0B          10
    67b2525d8ad10bb236a49960e93c09993b0baabeef12c2d46cd5f4fbb6f4808c   foobar                                  0.00%               1.727MiB / 1.952GiB   0.09%               2.35kB / 0B         4.11MB / 0B         2
    e5c383697914b98b10cbbc9d0bd324b7b927099ac584f031057b8208d2fba9b1   test-1951.1.kay7x1lh1twk9c0oig50sd5tr   0.00%               196KiB / 1.952GiB     0.01%               71.1kB / 0B         770kB / 0B          1
    4bda148efbc006b0063373c3678083159af89f8cc83a6a28def14cb0dd171f70   random.1.vnc8on831idyr42slu578u3cr      0.00%               1.672MiB / 1.952GiB   0.08%               110kB / 0B          578kB / 0B          2
    84e3deaa45b2fc363e06167df9b90ab59f88d4f101e3f9b8df03a62a8f6783e1   registry                                0.00%               3.387MiB / 1.952GiB   0.17%               127kB / 378B        233kB / 0B          10
    2ed915778cebddf9ec69263a75cfdcf00962a5198d94d42cda75d5cd45bb82f2   foo.1.lsmxrefn5yp9c9ijz1hzgdq4u         0.00%               1.727MiB / 1.952GiB   0.09%               166kB / 7.76kB      614kB / 0B          2

Which is the same as the default before this patch was applied.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: e63417a9c0
Component: cli
2017-09-27 18:59:25 +02:00
915d4f9741 Merge component 'cli' from git@github.com:docker/cli master 2017-09-27 09:23:02 -07:00
a58b05b91c Update default output format for stats to include ID and Name
The `docker container stats` output has a column (`CONTAINER`), that shows either
the container _id_ or container _name_, depending on the arguments given.

For example, running `docker container stats foobar` shows:

    CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    foobar              0.00%               1.938MiB / 1.952GiB   0.10%               782B / 0B           4.11MB / 0B         2

Whereas `docker container stats 67b2525d8ad1` (`67b2525d8ad1` being the ID for
container `foobar`) shows:

    CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    67b2525d8ad1        0.00%               1.938MiB / 1.952GiB   0.10%               916B / 0B           4.11MB / 0B         2

This behavior is confusing.

This patch updates the default output format for `docker stats` to use separate
columns for container ID and container Name (similar to `docker container ls`).

With this patch applied, both commands show the same output:

    $ docker container stats foobar
    CONTAINER ID                                                       NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    67b2525d8ad10bb236a49960e93c09993b0baabeef12c2d46cd5f4fbb6f4808c   foobar              0.00%               1.938MiB / 1.952GiB   0.10%               1.25kB / 0B         4.11MB / 0B         2

    $ docker container stats 67b2525d8ad1
    CONTAINER ID                                                       NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
    67b2525d8ad10bb236a49960e93c09993b0baabeef12c2d46cd5f4fbb6f4808c   foobar              0.00%               1.938MiB / 1.952GiB   0.10%               1.31kB / 0B         4.11MB / 0B         2

Users that want to use the old format can configure a custom format in the
cli configuration file (`~/.docker/config.json`);

on Linux:

    {
      "statsFormat" : "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
    }

on Windows:

    {
      "statsFormat" : "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
    }

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 0a78472211
Component: cli
2017-09-27 18:05:51 +02:00
4d03073a2c Merge pull request #34811 from yongtang/runc
Update runc to 0351df1c5a66838d0c392b4ac4cf9450de844e2d
Upstream-commit: 502eddb9859dcd30ce46732b24cefe49cf1ccbd1
Component: engine
2017-09-27 08:44:43 -07:00
d14643fb47 Merge pull request #34792 from runcom/fix-relabel-symlinks
volume: evaluate symlinks before relabeling mount source
Upstream-commit: f60e7aac62a14907132aa5c3bc9d5cf5ca0e6ebc
Component: engine
2017-09-27 17:42:23 +02:00
240408899b Merge pull request #34928 from darrenstahlmsft/HnsRunning
Ensure Host Network Service exists
Upstream-commit: 6af60b3c6180817e06ce87d562643b442a866502
Component: engine
2017-09-27 17:35:08 +02:00
4262667057 Merge pull request #34985 from thaJeztah/remove-use-of-deprecated-filter-functions
Remove use of deprecated filter functions
Upstream-commit: a343cba40c25deb2893e13f9a81dbcc4d19d16e2
Component: engine
2017-09-27 17:34:07 +02:00
7ed1303eb4 Merge pull request #34881 from ityangchen/test-moby
"docker swarm init --force-new-cluster" use limit
Upstream-commit: 0b968f91958eea12c2fa82cec64790cb03367232
Component: engine
2017-09-27 14:11:46 +02:00
689b8ff233 Merge pull request #562 from dnephin/update-gometalinter
Update gometalinter
Upstream-commit: feb4d79935
Component: cli
2017-09-27 09:42:37 +02:00
5a67fa7a37 Merge pull request #563 from riyazdf/remove-extra-options
trust: remove extraneous OPTIONS from commands that do not use it
Upstream-commit: e27e07a8a9
Component: cli
2017-09-27 09:41:33 +02:00
bb1eca37a9 trust: remove extraneous OPTIONS from commands that do not use it
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 9ad0e8f223
Component: cli
2017-09-26 16:15:45 -07:00
e4f32567d3 Updating moby to correspond to naming convention used in https://github.com/docker/swarmkit/pull/2385
Signed-off-by: Pradip Dhara <pradipd@microsoft.com>
Upstream-commit: d00a07b1e6d46c3cc9ef95e8b6227115830e2701
Component: engine
2017-09-26 22:08:10 +00:00
fa385958f4 vndr swarmkit 941a01844b89c56aa61086fecb167ab3af1de22b
Signed-off-by: Pradip Dhara <pradipd@microsoft.com>
Upstream-commit: 8e15b1cffb95d1e82943a628353c6df7cd54f6c4
Component: engine
2017-09-26 22:08:10 +00:00
23c421f3c5 Merge pull request #557 from allencloud/add-more-event-filter-type
Add more event filters in doc: config, node, secret and service
Upstream-commit: 62d62ff513
Component: cli
2017-09-26 22:48:22 +02:00
de74f6b50c Merge pull request #34952 from allencloud/add-specific-event-filter
add node/service/secret/config specific event filter
Upstream-commit: afe31900915782daf67b40d405d8e7b8e01ab2dd
Component: engine
2017-09-26 22:46:41 +02:00
f99bd6dc82 Merge component 'engine' from git@github.com:moby/moby master 2017-09-26 12:50:25 -07:00
dead314452 Refactor image commands to make use of the new trust struct for trusted pull
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 4203b49431
Component: cli
2017-09-26 15:15:42 -04:00
8a5301f81b Merge pull request #34911 from dnephin/new-ci-entrypoint
Add a new entrypoint for CI
Upstream-commit: a971f9c9d7d1bdc69b197a82c3fb010681f5cd1f
Component: engine
2017-09-26 11:50:44 -07:00
1a654751d3 Merge component 'cli' from git@github.com:docker/cli master 2017-09-26 10:56:04 -07:00
7fd47ecc0d Merge pull request #34961 from fcrisciani/libnetwork-vendoring
Vendoring libnetwork
Upstream-commit: 37eb796ccb6de7def92f0ab3f18c686ae92ef29f
Component: engine
2017-09-26 10:50:32 -07:00
09b100cab2 Merge pull request #34973 from darrenstahlmsft/fixError
Fix error string about containers feature
Upstream-commit: 9feef9287474d0e9afe489d9ad0b71a986a012cb
Component: engine
2017-09-26 18:44:12 +02:00
6424aeb9fa Merge pull request #34918 from thaJeztah/update-copy-add-error
Improve error message for COPY missing destination
Upstream-commit: 76b5ab6f43aeffe4261e2b1f848476d36d332880
Component: engine
2017-09-26 18:43:36 +02:00
57c6d20473 Merge pull request #34358 from ripcurld0/fix_link_problem
Add an integration test for bug #31392 regression
Upstream-commit: 584ed9603b4cb79160d0dd8689cdbbdedb9fe00f
Component: engine
2017-09-26 18:41:08 +02:00
f321e1ed9d Update gometalinter
The update includes bug fixes in gometalinter and updates to linters, which
discovered more linter problems.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: d956386b2d
Component: cli
2017-09-26 12:33:35 -04:00
2a54e5d16e add node/service/secret/config specific event filter
Signed-off-by: Allen Sun <shlallen1990@gmail.com>
Upstream-commit: 4611ecd3cdc9b2738f58a136b79f752add223f3f
Component: engine
2017-09-27 00:23:51 +08:00
e3c3856028 Merge pull request #34908 from thaJeztah/bump-api-version-1.33
Bump API version to 1.33
Upstream-commit: 74a084162ce544fe995715ba47aa84d3d75b95c1
Component: engine
2017-09-26 18:09:50 +02:00
86f10d67d5 add more event filters in doc: config, node, secret and service
Signed-off-by: Allen Sun <shlallen1990@gmail.com>
Upstream-commit: fc98f8757a
Component: cli
2017-09-27 00:04:56 +08:00
399de7ee20 Merge pull request #551 from dnephin/set-local-constant
Use a local constant
Upstream-commit: 0856c20e04
Component: cli
2017-09-26 17:42:50 +02:00
57dd97eab1 Merge pull request #555 from joaofnfernandes/docs/advertise-addr
Add note about joining through a load balancer
Upstream-commit: b77f3fd5ac
Component: cli
2017-09-26 17:15:42 +02:00
671d46ed3d Merge pull request #34983 from thaJeztah/suppress-tmp-rename-warning
Suppress warning for renaming missing tmp directory
Upstream-commit: 65234597216d03866bc26bdad06cb1f25f832206
Component: engine
2017-09-26 16:53:28 +02:00
9e59512fe4 Merge pull request #451 from tych0/use-pass-backend
Use pass backend
Upstream-commit: be8dab26a3
Component: cli
2017-09-26 16:40:32 +02:00
1fe51e0bb7 document the pass backend and default behavior
Also add a big warning about cleartext passwords.

Signed-off-by: Tycho Andersen <tycho@docker.com>
Upstream-commit: a2f116733b
Component: cli
2017-09-26 08:31:02 -06:00
5dbfedf3f9 Replace uses of filters.ToParam(), FromParam() with filters.ToJSON(), FromJSON()
`filters.ToParam()` and `filters.FromParam()` were deprecated in favor of
`filters.ToJSON()` and `filters.FromJSON()` in 065118390a3ecaf0dbd2fa752d54d43f8f1e8ec6,
but still used in various locations.

This patch replaces uses of `filters.ToParam()` and  `filters.FromParam()` with
`filters.ToJSON()` and `filters.FromJSON()`.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: a4efe66cf2a7648dbcf5b9993bf351925b905b5b
Component: engine
2017-09-26 13:59:45 +02:00
c4c68bf819 Replace uses of filters.Include() with filters.Contains()
The `filters.Include()` method was deprecated in favor of `filters.Contains()`
in 065118390a3ecaf0dbd2fa752d54d43f8f1e8ec6, but still used in various
locations.

This patch replaces uses of `filters.Include()` with `filters.Contains()`.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 97c5ae25c4d857563acd1f3467afc760145b1d55
Component: engine
2017-09-26 13:39:56 +02:00
b987e63572 Update runc to 0351df1c5a66838d0c392b4ac4cf9450de844e2d
This fix updates runc to 0351df1c5a66838d0c392b4ac4cf9450de844e2d

With this fix the warnings generated by netgo and dlopen by go 1.9
are addressed.

See
- opencontainers/runc#1577
- opencontainers/runc#1579

This fix is part of the efforts for go 1.9 (#33892)

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Upstream-commit: e0ff1d147bc12234f1be25a620bf6b3bf3179d97
Component: engine
2017-09-26 11:07:27 +00:00
cbf8cc6faf Suppress warning for renaming missing tmp directory
When starting `dockerd` on a host that has no `/var/lib/docker/tmp` directory,
a warning was printed in the logs:

    $ dockerd --data-root=/no-such-directory
    ...
    WARN[2017-09-26T09:37:00.045153377Z] failed to rename /no-such-directory/tmp for background deletion: rename /no-such-directory/tmp /no-such-directory/tmp-old: no such file or directory. Deleting synchronously

Although harmless, the warning does not show any useful information, so can be
skipped.

This patch checks thetype of error, so that warning is not printed.
Other errors will still show up:

    $ touch /i-am-a-file
    $ dockerd --data-root=/i-am-a-file
    Unable to get the full path to root (/i-am-a-file): canonical path points to a file '/i-am-a-file'

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 2b50b14aebc12722f81db8d8f66415e1fa7b954a
Component: engine
2017-09-26 12:04:30 +02:00
b4098a4e18 Merge pull request #34968 from chris-crone/integration-test-docker-ee
Docker EE integration test fixes
Upstream-commit: 147443a42665419d8b3c2047a7d345440bfb63c0
Component: engine
2017-09-26 10:50:09 +02:00
48757849a4 Merge pull request #34946 from dnephin/fix-jsonlog
Move pkg/jsonlog to be a subpackage of the single consumer
Upstream-commit: 7d47823c22945bb24a609a7ef20c0559d78d96e4
Component: engine
2017-09-26 10:49:57 +02:00
ec4868350d Add an integration test for bug #31392 regression
This verifies that bug #31392 won't surface again.

To reproduce the bug:
1) docker run -dit --name a0 busybox sh
2) docker run -dit --name b0 --link a0 busybox sh
3) docker rename a0 a1
4) docker run -dit --name a0 busybox sh
5) docker rm -f b0
6) docker run -dit --name b0 --link a0 busybox sh

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
Upstream-commit: 48a26ba9e42f25ebc1ad732b4c0d31e77a7aaa55
Component: engine
2017-09-26 10:55:59 +03:00
fa79e0059e Merge pull request #34943 from tonistiigi/vendor-buildkit
vendor: update buildkit to aaff9d591
Upstream-commit: 4d48baacde3dd6bb9e4c4f8ef1319765ded031f4
Component: engine
2017-09-26 08:37:46 +02:00
3366e8951a Merge pull request #34965 from vdemeester/fix-pkg-mount-unit-test-under-selinux
Fix TestMount under a selinux system
Upstream-commit: 41313c87a25aec122fb43fdaf2433d1b121f1808
Component: engine
2017-09-26 08:37:22 +02:00
401172966f "docker swarm init --force-new-cluster" use limit
Signed-off-by: yangchenliang <yangchenliang@huawei.com>

When worker executor `docker swarm init
--force-new-cluster`,docker would hang.So only manager can process it.

Signed-off-by: yangchenliang <yangchenliang@huawei.com>
Upstream-commit: 12e947efdba5481020f6543514ade83d87c69a28
Component: engine
2017-09-26 12:05:19 +08:00
1608188995 Merge pull request #472 from riyazdf/docker-trust
docker trust: view, revoke, sign subcommands (experimental)
Upstream-commit: af3cdccf52
Component: cli
2017-09-25 17:26:52 -07:00
f367f50630 Move jsonlog to a subpackage of jsonfilelog
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 035604cca6d6bd9a432268caf7515a35023908ed
Component: engine
2017-09-25 16:07:25 -04:00
7d644fb209 Fix benchmarks and remove more unnecessary code.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: a06ad2792ab92d4f246e4b4cc4c3529eb060651e
Component: engine
2017-09-25 16:07:25 -04:00
4701b66889 Remove unused JSONLog marshaling
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 231c5cbd50e1870f31eb6a525b2df2ed7a716565
Component: engine
2017-09-25 16:07:25 -04:00
a001c9d5c7 Remove unused Format
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 638d4cc7e4390ab217be711913017b22ce2cd5c2
Component: engine
2017-09-25 16:07:25 -04:00
0c6f170345 Unexport FastTimeMarshalJSON
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 7de92de636ef307d66b7b20b24f166a47f40f72b
Component: engine
2017-09-25 16:07:25 -04:00
101f740d40 Move RFC3339NanoFixed to a more appropriate package.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 27cfa68af16721c978803c3b695bcc7181ccc721
Component: engine
2017-09-25 16:07:24 -04:00
658351133f Fix error string about containers feature
Signed-off-by: Darren Stahl <darst@microsoft.com>
Upstream-commit: 31405b556f155d8f56902086c7c24efe25dd8de0
Component: engine
2017-09-25 12:39:27 -07:00
3c4574bac3 Ensure Host Network Service exists
If HNS does not exist on the Docker host, the daemon may fail with unexpected
and difficult to diagnose errors. This check prevents the daemon from starting
on a system that does not have the correct prerequisites.

Signed-off-by: Darren Stahl <darst@microsoft.com>
Upstream-commit: 1edcc63560cb1286f452565754092bc2eb428ffa
Component: engine
2017-09-25 11:07:44 -07:00
025e41d2ae Add note about joining through a load balancer
Signed-off-by: Joao Fernandes <joao.fernandes@docker.com>
Upstream-commit: 8595d15d60
Component: cli
2017-09-25 10:53:20 -07:00
702bac1553 mark command as experimental in docs and cli
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: e07f345267
Component: cli
2017-09-25 09:39:46 -07:00
e0bca90fda trust: rename inspect to view, add repo name to signer table header
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: c6db0cd7a1
Component: cli
2017-09-25 09:39:46 -07:00
94f2b59302 tests: use alice/bob/claire conventional names for signers
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 46a879e3b9
Component: cli
2017-09-25 09:39:46 -07:00
188ec7af2a trust: update remove to error on empty references for consistency
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 4e95fcd72c
Component: cli
2017-09-25 09:39:46 -07:00
a59fc63f3b tests: move trust test to proper package
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 67cf09cbe1
Component: cli
2017-09-25 09:39:46 -07:00
7c83ece8ef trust: update reference type and use golden output
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 4e89dc800a
Component: cli
2017-09-25 09:39:44 -07:00
1659928f34 tests: address review feedback
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 6fca400f1e
Component: cli
2017-09-25 09:38:41 -07:00
51f87f33d4 trust: use mock CLI for testing offline
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: f667bd7559
Component: cli
2017-09-25 09:38:40 -07:00
93ba24cc42 cli: introduce NotaryClient getter
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: e5c35ab9d1
Component: cli
2017-09-25 09:38:38 -07:00
b53048a314 trust: add Repository client interface
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 7c5b836ca5
Component: cli
2017-09-25 09:34:54 -07:00
e42a2df102 trust: address review feedback, refactor to align with existing cli/command semantics
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 45c102a03d
Component: cli
2017-09-25 09:34:53 -07:00
e92c4686dd docs: update docker trust docs with correct tense and formatting
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 007aff70bf
Component: cli
2017-09-25 09:34:53 -07:00
97f2ec42fa trust revoke: docs for docker trust revoke
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 43717a866e
Component: cli
2017-09-25 09:34:53 -07:00
e8d4ecb361 trust revoke: add docker trust revoke command
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 609f8b4b81
Component: cli
2017-09-25 09:34:53 -07:00
ad5c7cb4bb trust sign: docs for docker trust sign
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: bc665ed762
Component: cli
2017-09-25 09:34:53 -07:00
644ae3a3f1 trust sign: add docker trust sign command
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: fab6bb6798
Component: cli
2017-09-25 09:34:53 -07:00
1115dc5cef trust inspect: docs for docker trust inspect
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 809ef0fd74
Component: cli
2017-09-25 09:34:53 -07:00
530ee183f1 trust inspect: add docker trust inspect command with formatting print
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: ec6bc9460f
Component: cli
2017-09-25 09:34:52 -07:00
742798f154 trust: update existing code for new vendoring, refactor for docker trust code sharing
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: 5846e6e5d5
Component: cli
2017-09-25 09:34:52 -07:00
86beae9d05 vendor: upgrade notary version for docker trust
Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Upstream-commit: fb1cbaeb66
Component: cli
2017-09-25 09:34:52 -07:00
0975184f91 Docker EE integration test fixes
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 8c5f98c93e06de81b7fb6416372a3f42aa7aeb5d
Component: engine
2017-09-25 18:09:19 +02:00
0c54b3a041 Improve error message for COPY missing destination
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 5d05a8291314b8f727b04b504b8d7fc7ed7f42da
Component: engine
2017-09-25 14:17:18 +02:00
522e6cc8ec Do not use deprecated call for APIClient
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 82440a039f58b6a1487f8042486fe8dba675df54
Component: engine
2017-09-25 14:08:03 +02:00
0b2721b9c1 Protect environment for system integration tests
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: d43dac2202667a407f4c5ab061c04b0ea334aa20
Component: engine
2017-09-25 14:05:18 +02:00
e38ecccceb Match not implemented error check to others
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 7406088853b6cbcb8996c367062cee2e1ee6eaaa
Component: engine
2017-09-25 13:58:51 +02:00
954a7de027 Dockerfile: use seccomp provided by stretch
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Upstream-commit: 1b51a05375b48c5f655fbbedc5a1e7cba044122c
Component: engine
2017-09-25 10:03:37 +00:00
08619d0c7c Fix TestMount under a selinux system
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Upstream-commit: 8bebd42df2d8eaa0ecdc9c78bc1e395a752eb5c9
Component: engine
2017-09-25 11:54:30 +02:00
5c2be22475 Merge pull request #307 from allencloud/sort-secrets-and-configs-in-cli
using nature sort secrets and configs in cli
Upstream-commit: bd6e1757f5
Component: cli
2017-09-25 09:41:50 +02:00
fdeab20153 sort secrets and configs in cli
Signed-off-by: Allen Sun <shlallen1990@gmail.com>
Upstream-commit: 26f06c5bcb
Component: cli
2017-09-25 13:18:13 +08:00
28762b7242 Vendoring libnetwork
Fix for networkDB garbage collection (PR: https://github.com/docker/libnetwork/pull/1944)
Added extra logs to monitor the netowrkDB status and number of entries per network

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Upstream-commit: 04043428ea5ce679618aec2007b77ac51d0b6af0
Component: engine
2017-09-24 16:44:16 -07:00
0f097012c8 Merge pull request #546 from dnephin/fix-version-on-failure
Set APIVersion on the client, even when Ping fails
Upstream-commit: a41caadef0
Component: cli
2017-09-23 09:04:03 -04:00
753a551b2e Merge pull request #552 from allencloud/volume-has-no-id
remove volume id because it only has name
Upstream-commit: 29c4f0df57
Component: cli
2017-09-23 08:58:37 -04:00
a0ff43ff51 remove volume id because it only has name
Signed-off-by: Allen Sun <shlallen1990@gmail.com>
Upstream-commit: fe1c1b6b5c
Component: cli
2017-09-23 11:26:56 +08:00
f3a4b20d25 Use a local constant
This constant is going to be removed from jsonlog package.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 32612058cb
Component: cli
2017-09-22 17:59:46 -04:00
278bf3cb85 Merge pull request #34929 from stevvooe/remove-promise-package
pkg/package: remove promise package
Upstream-commit: c982ee805d895a4fc2bf01f2d1d8afa06b408dd0
Component: engine
2017-09-22 11:52:23 -07:00
afac6be123 builder: updates to session after vendor
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Upstream-commit: d4729749023fde0c57cded0c8159dc85cd7ee448
Component: engine
2017-09-22 09:51:52 -07:00
441f6cef6d Set APIVersion on the client, even when Ping fails
Refactor to support testing
Also add tests

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: e828efa4ab
Component: cli
2017-09-22 10:08:19 -04:00
6771dc87e0 Merge pull request #34878 from chchliang/imagebranch
Add  testcases with ` Image` , covering all methods.
Upstream-commit: ba317637de9b9918cdc2139466dd51c6200bd158
Component: engine
2017-09-22 10:08:54 +02:00
793cd3af24 Merge pull request #30696 from yummypeng/lock-RWLayer-while-committing
Fixes #29654: take reference to RWLayer while committing/exporting
Upstream-commit: a157dc53a850dff19ead074f24f9eff61b9d0622
Component: engine
2017-09-22 09:41:57 +02:00
2d68241660 vendor: update buildkit
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Upstream-commit: ed6fd3d95bde4651ffb66d37cd1e5e76ee3c1f7b
Component: engine
2017-09-21 22:17:43 -07:00
d1d8439f3f Fixes #29654: take reference to RWLayer while committing/exporting
Take an extra reference to rwlayer while the container is being
committed or exported to avoid the removal of that layer.

Also add some checks before commit/export.

Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
Upstream-commit: 8c32659979150630a2c4eae4e7da944806c46297
Component: engine
2017-09-22 09:47:42 +08:00
6700f361c5 pkg/package: remove promise package
The promise package represents a simple enough concurrency pattern that
replicating it in place is sufficient. To end the propagation of this
package, it has been removed and the uses have been inlined.

While this code could likely be refactored to be simpler without the
package, the changes have been minimized to reduce the possibility of
defects. Someone else may want to do further refactoring to remove
closures and reduce the number of goroutines in use.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
Upstream-commit: 0cd4ab3f9a3f242468484fc62b46e632fdba5e13
Component: engine
2017-09-21 17:56:45 -07:00
3a50fe644a Merge pull request #34861 from tklauser/fix-cstring-leaks
Fix CString memory leaks
Upstream-commit: 777d4a1bf45c85db6931205d4adbe38a17c583d7
Component: engine
2017-09-21 09:14:07 -07:00
e22297f2e2 Merge pull request #34907 from chris-crone/set-test-ostype
Set integration test OSType with environment variable
Upstream-commit: 409d4711812c5c23815a783524e543ec653a234b
Component: engine
2017-09-21 04:13:17 -07:00
9f6a445ef2 Merge pull request #34910 from chris-crone/plugin-list-not-implemented
Handle plugin list not implemented
Upstream-commit: 7d8deaa0db40b8b88d8e5039d23d4fcdb627fc00
Component: engine
2017-09-21 04:12:35 -07:00
aebe8e8ce7 add Images testcase
Signed-off-by: chchliang <chen.chuanliang@zte.com.cn>
Upstream-commit: 832f39c2ed53fc4a91265798198273044448bc7f
Component: engine
2017-09-21 17:54:29 +08:00
0dfdf37ab2 Merge pull request #34914 from euank/000003-percent
overlay2: fix faulty errcheck
Upstream-commit: 48cce229330561c104f777dac4f3f39ef2e2de6e
Component: engine
2017-09-20 19:52:10 -07:00
ccdce91e65 overlay2: fix faulty errcheck
The change in 7a7357dae1bcccb17e9b2d4c7c8f5c025fce56ca inadvertently
changed the `defer` error code into a no-op. This restores its behavior
prior to that code change, and also introduces a little more error
logging.

Signed-off-by: Euan Kemp <euan.kemp@coreos.com>
Upstream-commit: 639ab92f011245e17e9a293455a8dae1eb034022
Component: engine
2017-09-20 15:25:57 -07:00
e55d5634bf Add a new entrypoint for CI
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: dbf580be57a4bb854d7ce20d313e3a22ea337be5
Component: engine
2017-09-20 17:26:30 -04:00
028b015443 Merge pull request #250 from seemethere/update_moby_components_hash
Hash needs to be updated for moby-components script
2017-09-20 13:40:13 -07:00
1e4bfaa04a Hash needs to be updated for moby-components script
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-20 13:25:51 -07:00
5cb2c664ef Merge pull request #34886 from cpuguy83/may_detach_mount
Automatically set `may_detach_mounts=1` on startup
Upstream-commit: 7d70d0fac339b2ed9715739748c89d0486456407
Component: engine
2017-09-20 11:31:45 -07:00
da0223d365 Set integration test OSType with environment variable
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: f0e5b3d7d89c0c87d001faa18bc60fd1b4531901
Component: engine
2017-09-20 19:50:17 +02:00
20c1a2b928 Handle plugin list not implemented
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: e7e11bdd44878d28c642d72761aa41eb9ffce3d1
Component: engine
2017-09-20 19:48:33 +02:00
9337e13113 prefer pass backend if it is available
Signed-off-by: Tycho Andersen <tycho@docker.com>
Upstream-commit: 713e87e780
Component: cli
2017-09-20 11:15:49 -06:00
6280c12bb9 version bump for docker-credential-helpers
Signed-off-by: Tycho Andersen <tycho@docker.com>
Upstream-commit: 6bd5c63c78
Component: cli
2017-09-20 11:15:49 -06:00
315e815656 defaultCredentialStore: make this a function
In the next patch, we'll use this to implement some logic about which
password backend to use.

Signed-off-by: Tycho Andersen <tycho@docker.com>
Upstream-commit: 4cf1849418
Component: cli
2017-09-20 11:14:27 -06:00
7e0e805bca Merge pull request #34863 from keloyang/close-pipe
Close pipe in overlay2 graphdriver
Upstream-commit: e40d5e665c6de904ea1e22bb3aa615638ec05e2a
Component: engine
2017-09-20 09:37:15 -07:00
cdbfcd2c1d Merge pull request #545 from thaJeztah/fix-nocopy-description
Fix nocopy description
Upstream-commit: 10e292dbab
Component: cli
2017-09-20 17:54:55 +02:00
36e37bb56e Merge pull request #544 from vdemeester/fix-build-loading
Fix loader error with different build syntax
Upstream-commit: 09c8f47af1
Component: cli
2017-09-20 11:03:54 -04:00
62cdceef74 Fix nocopy description
nocopy does not apply to bind mounts, only volumes

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 0e72a6ff81
Component: cli
2017-09-20 16:43:15 +02:00
de0f898e39 Automatically set may_detach_mounts=1 on startup
This is kernel config available in RHEL7.4 based kernels that enables
mountpoint removal where the mountpoint exists in other namespaces.
In particular this is important for making this pattern work:

```
umount -l /some/path
rm -r /some/path
```

Where `/some/path` exists in another mount namespace.
Setting this value will prevent `device or resource busy` errors when
attempting to the removal of `/some/path` in the example.

This setting is the default, and non-configurable, on upstream kernels
since 3.15.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Upstream-commit: 83c2152de503012195bd26069fd8fbd2dea4b32f
Component: engine
2017-09-20 09:57:25 -04:00
e2fa4c4d55 Bump API version to 1.33
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 15a59e763b6bdb44f28ffafb20e173606308ce2c
Component: engine
2017-09-20 15:19:16 +02:00
7d19908a7b Merge pull request #504 from albers/completion-search--format
Add bash completion for `search --format`
Upstream-commit: da82dcb1db
Component: cli
2017-09-20 14:41:28 +02:00
95b34532ce Fix loader error with different build syntax
`build: .` was not working anymore. Fixing this by adding a new
tranform function for BuildConfig.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Upstream-commit: 0da9f14821
Component: cli
2017-09-20 14:02:33 +02:00
c59fc2b89e Merge pull request #352 from albers/fix-completion--credential-spec
Improve bash completion for `--credential-spec`
Upstream-commit: 16804b7313
Component: cli
2017-09-20 11:52:11 +02:00
48266cefa7 Merge pull request #531 from seemethere/add_cross_targets
Add a way to just build windows and osx
Upstream-commit: bd31cb4bd5
Component: cli
2017-09-20 08:52:56 +02:00
0ee27e86a8 Add a way to just build windows and osx
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
Upstream-commit: 51080d6148
Component: cli
2017-09-19 16:48:31 -07:00
bb1c0c5aa8 Merge pull request #34846 from Microsoft/jjh/debuggcs
LCOW: Add UVM debugability by grabbing logs before tear-down
Upstream-commit: 7cbbbb95097f065757d38bcccdb1bbef81d10ddb
Component: engine
2017-09-19 22:33:46 +02:00
d9942eee10 Merge pull request #34117 from cpuguy83/decouple_plugin_manager_from_executor
Decouple plugin manager from libcontainerd package
Upstream-commit: b6b85da6576b3e923325897aab9b12d85c014e1b
Component: engine
2017-09-19 21:07:57 +02:00
5338e5013a Merge component 'packaging' from git@github.com:docker/docker-ce-packaging master 2017-09-19 11:14:46 -07:00
46ea757ea5 Merge component 'engine' from git@github.com:moby/moby master 2017-09-19 11:14:35 -07:00
95004c9da9 Merge pull request #31993 from dccurtis/issue-31816
Fixing ‘docker cp’ to allow new target file name in a host symlinked directory
Upstream-commit: 149f3aceb277ecccd33ee815e9c54d6aec782ab5
Component: engine
2017-09-19 10:54:53 -07:00
d382cdf023 Merge pull request #33492 from simonferquel/typed-builder-commands-squashed
[Builder] Introduce a typed command system and 2 phase parse/dispatch build
Upstream-commit: 22e15721b1f33f32f07615e034cf3a7b4c865aa3
Component: engine
2017-09-20 02:52:23 +09:00
6a9321461a Merge pull request #34684 from cpuguy83/fix_selinux_with_mount_api
Set selinux label on local volumes from mounts API
Upstream-commit: 3ddced570dbd7c07291df15bf0b5ac02b04453ca
Component: engine
2017-09-19 13:43:40 -04:00
a5ceeb03a8 Merge component 'cli' from git@github.com:docker/cli master 2017-09-19 10:12:43 -07:00
ddb0ee3757 Revendor Microsoft/opengcs @ v0.3.4
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: 2798576b37aa99643a06366f00072b6026c0b77e
Component: engine
2017-09-19 09:56:23 -07:00
cb0c1a12c4 Decouple plugin manager from libcontainerd package
libcontainerd has a bunch of platform dependent code and huge interfaces
that are a pain implement.
To make the plugin manager a bit easier to work with, extract the plugin
executor into an interface and move the containerd implementation to a
separate package.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Upstream-commit: c85e8622a4813d7b72d74517faa03ab5de4c4550
Component: engine
2017-09-19 12:17:55 -04:00
84b2d8c7a7 Merge pull request #34732 from vizv/fix-relabel-config-files
daemon: relabel config files.
Upstream-commit: 1bb55e6495cea72d6bca17d90ab25573766d07b3
Component: engine
2017-09-19 08:46:54 -07:00
1411476434 Merge pull request #542 from vdemeester/tidying-loader-test-a-bit
Tidying up compose/loader test a bit
Upstream-commit: 9e162fb011
Component: cli
2017-09-19 17:44:08 +02:00
00de807109 Merge pull request #541 from thaJeztah/fix-service-create-markdown
Fix service_create markdown
Upstream-commit: 68935944b3
Component: cli
2017-09-19 17:17:45 +02:00
13c06c5996 Tidying up compose/loader test a bit
- Use `require` instead of `assert` when the assumption is "breaking" for the code
following. For example when asserting an error is not nil and then doing
`err.Error` on it ; if `err` is nil, the test will panic instead of fail.
- Use `assert.Len` when possible. The error message is better.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Upstream-commit: f34655ecf8
Component: cli
2017-09-19 16:48:52 +02:00
f7daf26c0f Set selinux label on local volumes from mounts API
When using a volume via the `Binds` API, a shared selinux label is
automatically set.
The `Mounts` API is not setting this, which makes volumes specified via
the mounts API useless when selinux is enabled.

This fix adopts the same selinux label for volumes on the mounts API as on
binds.
Note in the case of both the `Binds` API and the `Mounts` API, the
selinux label is only applied when the volume driver is the `local`
driver.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Upstream-commit: 5bbf5cc671ec8007bf8e0416799fff01d6a79b7e
Component: engine
2017-09-19 10:46:38 -04:00
8828a6255a Merge pull request #537 from vdemeester/add-jenkins-status-to-readme
Add jenkins build status to readme
Upstream-commit: b3aa1195d4
Component: cli
2017-09-19 16:33:33 +02:00
6daf6c2b58 Fix service_create markdown
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 01ef9acd31
Component: cli
2017-09-19 16:29:52 +02:00
da00b40eb4 Merge pull request #34721 from kinvolk/iaguis/add-missing-ecryptfs-string
Add missing eCryptfs translation to FsNames
Upstream-commit: 3fa72d38ec61377b506d31711f5cf1b855219926
Component: engine
2017-09-19 05:45:24 -07:00
07893693ca Merge pull request #34891 from Microsoft/jjh/fixcomment
LCOW: Fix comment in graphdriver code
Upstream-commit: 13e8a7a0067ce5d8d458b3a5985691bed0b0f30e
Component: engine
2017-09-19 14:43:35 +02:00
889843574b volume: evaluate symlinks before relabeling mount source
Simple reproducer:

```sh
$ mkdir /var/foo
$ touch /var/foo/test
$ ln -s /var/foo /var/bar
$ docker run -ti -v /var/bar:/var/bar:Z fedora sh
sh-4.3# ls -lZ /var/bar/
ls: cannot open directory '/var/bar/': Permission denied
```

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
Upstream-commit: e0b22c0b9e013527ef121250b51ae780d2d2912d
Component: engine
2017-09-19 10:54:03 +02:00
822098983e Merge pull request #34520 from fnoeding/fixed-raw-splunk-logger
Fixed `raw` mode splunk logger
Upstream-commit: 5c57ca17d50c392b7ad627fc1215d7a7e91e0c41
Component: engine
2017-09-19 10:53:01 +02:00
1cc4bb63c2 Merge pull request #34856 from dnephin/cleanup-version-tests
Replace old version tests
Upstream-commit: 7cd7cf9167fd4bc57889dfe01447f4bb0d52acc2
Component: engine
2017-09-19 10:34:50 +02:00
1cc36398f9 Merge pull request #34495 from ripcurld0/registry_mirror_json
Exit if service config is loaded unsuccessfully on startup
Upstream-commit: b075cd2d78c1bafcded7d12ddb2e7c215e2e5117
Component: engine
2017-09-18 21:59:14 -07:00
a17ffddbf6 Merge pull request #34550 from kolyshkin/libeudev
Update Dockerfiles to use Debian Stretch
Upstream-commit: cfdac1245a8d97ef21fb739ef3e631bdb852bbc7
Component: engine
2017-09-18 21:03:31 -07:00
f8cc2fb021 LCOW: Fix comment in graphdriver code
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: f9fc269c204b96b34a479f3e55e41886ed2626b0
Component: engine
2017-09-18 19:52:55 -07:00
b07dcb72fb Close pipe if mountFrom failed.
Signed-off-by: Shukui Yang <yangshukui@huawei.com>
Upstream-commit: 9f38923901352459bb621d0b3587a6517e67eeb3
Component: engine
2017-09-19 01:25:39 +00:00
7ac80a2691 Merge pull request #34674 from pradipd/windows_routingmesh
Enabling ILB/ELB on windows using per-node, per-network LB endpoint.
Upstream-commit: a2ee40b98c281139c75b38e0e11aa35726021169
Component: engine
2017-09-18 15:56:17 -07:00
3303de2b82 Merge pull request #34759 from kolyshkin/gometalinter
Gometalinter fixups for non-x86
Upstream-commit: 65e88d996ad13ad5ca9c2d2c625a87f9271d1e82
Component: engine
2017-09-18 13:44:15 -07:00
b8677707a9 vendoring libnetwork and swarmkit
Signed-off-by: Pradip Dhara <pradipd@microsoft.com>
Upstream-commit: 4c1b07924a7449e6e37fac4479624fcaf01ce889
Component: engine
2017-09-18 20:38:18 +00:00
61af2a7b87 Enabling ILB/ELB on windows using per-node, per-network LB endpoint.
Signed-off-by: Pradip Dhara <pradipd@microsoft.com>
Upstream-commit: 9bed0883e762181ad6c4d5607ae2228e164e44b5
Component: engine
2017-09-18 20:27:56 +00:00
fab90b5b50 Merge pull request #524 from thaJeztah/update-deprecated-api-cors
Update deprecated.md for "api-enable-cors"
Upstream-commit: 139fcd3ee9
Component: cli
2017-09-18 21:37:08 +02:00
f01963dfea Merge pull request #34805 from chris-crone/containerize-integration-tests
Containerize integration tests
Upstream-commit: 9be245f438f9fb2eaeb7891673b16aed9262a192
Component: engine
2017-09-18 21:11:06 +02:00
dd976e6170 integration-cli/docker_cli_logs_test.go: Wait()
To avoid a zombie apocalypse, use cmd.Wait() to properly finish
the processes we spawn by Start().

Found while investigating DockerSuite.TestLogsFollowSlowStdoutConsumer
failure on ARM (see
https://github.com/moby/moby/pull/34550#issuecomment-324937936).

[v2: don't expect no error from Wait() when process is killed]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 14f0a1888f92667f82bea548bfa2fe4a890a75e8
Component: engine
2017-09-18 11:18:36 -07:00
0a503dae01 Merge pull request #366 from twistlock/plugable_secrets_backend
Plugable secrets backend
Upstream-commit: 3edf97e5a9
Component: cli
2017-09-18 19:25:15 +02:00
50bc0b5a39 Merge pull request #523 from thaJeztah/more-yaml-information
Add more information to the generated YAML for documentation
Upstream-commit: 37ac97c72e
Component: cli
2017-09-18 13:12:39 -04:00
9f902b9066 Merge pull request #526 from thaJeztah/docs-fix-system-prune
Update system prune docs for --volumes flag
Upstream-commit: d4251b4268
Component: cli
2017-09-18 19:10:46 +02:00
5421741502 Add missing eCryptfs translation to FsNames
It was causing the error message to be

    'overlay' is not supported over <unknown>

instead of

    'overlay' is not supported over ecryptfs

Signed-off-by: Iago López Galeiras <iago@kinvolk.io>
Upstream-commit: ddb31b4fdf7311ad6c7e62aa15b5f6da16518e77
Component: engine
2017-09-18 19:06:13 +02:00
133eff770e TestLogsFollowSlowStdoutConsumer: fix for slow ARM
We run our CI on Scaleway C1 machine, which is pretty slow,
including I/O. This test was failing on it, as it tried to
write 100000 lines of log very fast, and the loggerCloseTimeout
(defined and used in container/monitor.go) prevents the
daemon to finish writing it within this time frame,

Reducing the size to 150000 characters (75000 lines) should
help avoiding hitting it, without compromising the test case
itself.

Alternatively, we could have increased the timeout further. It was
originally set to 1s (commit b6a42673a) and later increased 10x
(commit c0391bf55). Please let me know if you want me to go that way.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 1bc93bff221bd30e80f776cc620a8937314569ef
Component: engine
2017-09-18 08:47:55 -07:00
e01e198f54 Introduce a typed command system and 2 phase parse/dispatch build
This is a work base to introduce more features like build time
dockerfile optimisations, dependency analysis and parallel build, as
well as a first step to go from a dispatch-inline process to a
frontend+backend process.

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Upstream-commit: 669c0677980b04bcbf871bb7c2d9f07caccfd42b
Component: engine
2017-09-18 09:48:56 +02:00
3a4f4fd3c4 overlay gd: fix build for 32-bit ARM
This commit reverts a hunk of commit 2f5f0af3f ("Add unconvert linter")
and adds a hint for unconvert linter to ignore excessive conversion as
it is required on 32-bit platforms (e.g. armhf).

The exact error on armhf is this:

	19:06:45 ---> Making bundle: dynbinary (in bundles/17.06.0-dev/dynbinary)
	19:06:48 Building: bundles/17.06.0-dev/dynbinary-daemon/dockerd-17.06.0-dev
	19:10:58 # github.com/docker/docker/daemon/graphdriver/overlay
	19:10:58 daemon/graphdriver/overlay/copy.go:161: cannot use stat.Atim.Sec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:161: cannot use stat.Atim.Nsec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:162: cannot use stat.Mtim.Sec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:162: cannot use stat.Mtim.Nsec (type int32) as type int64 in argument to time.Unix

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: b569f57890d4cad132be437e5dac55130b6c76e9
Component: engine
2017-09-17 22:04:31 -07:00
dd4630ca9c Fix test-docker-py on some arches
When running 'make all' on armhf, I got this:

> ---> Making bundle: .integration-daemon-start (in bundles/17.06.0-dev/test-docker-py)
> Using test binary docker
> INFO: Waiting for daemon to start...
> Starting dockerd
> .
> Traceback (most recent call last):
>   File "/usr/local/lib/python2.7/dist-packages/_pytest/config.py", line
> 320, in _importconftest
>     mod = conftestpath.pyimport()
>   File "/usr/local/lib/python2.7/dist-packages/py/_path/local.py", line
> 662, in pyimport
>     __import__(modname)
>   File "/docker-py/tests/integration/conftest.py", line 6, in <module>
>     import docker.errors
>   File "/docker-py/docker/__init__.py", line 2, in <module>
>     from .api import APIClient
>   File "/docker-py/docker/api/__init__.py", line 2, in <module>
>     from .client import APIClient
>   File "/docker-py/docker/api/client.py", line 11, in <module>
>     from .build import BuildApiMixin
>   File "/docker-py/docker/api/build.py", line 6, in <module>
>     from .. import auth
>   File "/docker-py/docker/auth.py", line 6, in <module>
>     import dockerpycreds
> ImportError: No module named dockerpycreds
> ERROR: could not load /docker-py/tests/integration/conftest.py

The fix for this was already provided by commit 0ec8f56a3 and
commit c7c923594, but for some reason it did not made its way
to Dockerfiles for all architectures.

While at it, remove excessive comments.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 7439d360fd567e063b8e9c4174a5c21b9fbc06aa
Component: engine
2017-09-17 22:04:31 -07:00
a14ef1d5fc devmapper: tell why xfs is not supported
Instead of providing a generic message listing all possible reasons
why xfs is not available on the system, let's be specific.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: c21245c9200ab39a9219b28f8185573b78a55074
Component: engine
2017-09-17 22:04:31 -07:00
e3dc487328 devmapper: show dmesg if mount fails
If mount fails, the reason might be right there in the kernel log ring buffer.
Let's include it in the error message, it might be of great help.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 46833ee1c353c247e3ef817a08d5a35a2a43bdf3
Component: engine
2017-09-17 22:04:31 -07:00
a4c2f1d0c4 devmapper: don't create too new xfs
Since the update to Debian Stretch, devmapper unit test fails. One
reason is, the combination of somewhat old (less than 3.16) kernel and
relatively new xfsprogs leads to creating a filesystem which is not supported
by the kernel:

> [12206.467518] XFS (dm-1): Superblock has unknown read-only compatible features (0x1) enabled.
> [12206.472046] XFS (dm-1): Attempted to mount read-only compatible filesystem read-write.
> Filesystem can only be safely mounted read only.
> [12206.472079] XFS (dm-1): SB validate failed with error 22.

Ideally, that would be automatically and implicitly handled by xfsprogs.
In real life, we have to take care about it here. Sigh.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 6b01bc5adb1255cb48e22e755ab86fd2c3305211
Component: engine
2017-09-17 22:04:31 -07:00
c25f7e149b Dockerfiles: fix test-docker-py
Presumably after switch to debian-stretch as a base, the following
errors happens in Jenkins:

10:48:03 ---> Making bundle: test-docker-py (in
bundles/17.06.0-dev/test-docker-py)
10:48:03 ---> Making bundle: .integration-daemon-start (in
bundles/17.06.0-dev/test-docker-py)
10:48:03 Using test binary docker
10:48:03 # DOCKER_EXPERIMENTAL is set: starting daemon with experimental
features enabled!
10:48:03 /etc/init.d/apparmor: 130: /etc/init.d/apparmor:
systemd-detect-virt: not found
10:48:03 Starting AppArmor profiles:Warning from stdin (line 1):
/sbin/apparmor_parser: cannot use or update cache, disable, or
force-complain via stdin
10:48:03 Warning failed to create cache: (null)
10:48:03 .
10:48:03 INFO: Waiting for daemon to start...
10:48:03 Starting dockerd
10:48:05 .
10:48:06 Traceback (most recent call last):
10:48:06   File
"/usr/local/lib/python2.7/dist-packages/_pytest/config.py", line 320, in
_importconftest
10:48:06     mod = conftestpath.pyimport()
10:48:06   File
"/usr/local/lib/python2.7/dist-packages/py/_path/local.py", line 662, in
pyimport
10:48:06     __import__(modname)
10:48:06   File "/docker-py/tests/integration/conftest.py", line 6, in
<module>
10:48:06     import docker.errors
10:48:06   File "/docker-py/docker/__init__.py", line 2, in <module>
10:48:06     from .api import APIClient
10:48:06   File "/docker-py/docker/api/__init__.py", line 2, in <module>
10:48:06     from .client import APIClient
10:48:06   File "/docker-py/docker/api/client.py", line 6, in <module>
10:48:06     import requests
10:48:06 ImportError: No module named requests
10:48:06 ERROR: could not load /docker-py/tests/integration/conftest.py
10:48:06

and

00:38:55   File "/docker-py/docker/transport/ssladapter.py", line 21, in
<module>
00:38:55     from backports.ssl_match_hostname import match_hostname
00:38:55 ImportError: No module named backports.ssl_match_hostname
00:38:55 ERROR: could not load /docker-py/tests/integration/conftest.py

To fix, install the missing python modules.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: ce2a0120c1925492a9bb7f6339cdbf716a4c50e0
Component: engine
2017-09-17 22:04:31 -07:00
c53f4217c9 TestRunSeccompProfileAllow32Bit: fix
Since the update to Debian Stretch, this test fails. The reason is dynamic
binary, which requires i386 ld.so for loading (and apparently it is no longer
installed by default):

> root@09d4b173c3dc:/go/src/github.com/docker/docker# file exit32-test
> exit32-test: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=a0d3d6cb59788453b983f65f8dc6ac52920147b6, stripped
> root@09d4b173c3dc:/go/src/github.com/docker/docker# ls -l /lib/ld-linux.so.2
> ls: cannot access '/lib/ld-linux.so.2': No such file or directory

To fix, just add -static.

Interestingly, ldd can'f figure it out.

> root@a324f8edfcaa:/go/src/github.com/docker/docker# ldd exit32-test
>	not a dynamic executable

Other tools (e.g. objdump) also show it's a dynamic binary.

While at it, remove the extra "id" argument (a copy-paste error I
guess).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 771256b305c8c06fca5eb1d041b60fbe093c0e1b
Component: engine
2017-09-17 22:04:31 -07:00
322ee8f812 devmapper gd: disable for static build
Static build with devmapper is impossible now since libudev is required
and no static version of libudev is available (as static libraries are
not supported by systemd which udev is part of).

This should not hurt anyone as "[t]he primary user of static builds
is the Editions, and docker in docker via the containers, and none
of those use device mapper".

Also, since the need for static libdevmapper is gone, there is no need
to self-compile libdevmapper -- let's use the one from Debian Stretch.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 84f1c054e66d3999aaf2751062cda8a77925b7ae
Component: engine
2017-09-17 22:04:31 -07:00
8fb9073dbb Update Dockerfiles to use Debian stretch
The main gain here is that they all use exactly the same distro; previously
arm64 was using Ubuntu Xenial because Debian jessie was too old.

Does not seem that we can change any of the downloaded dependencies still,
as eg libseccomp is still not the version we are using.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
Upstream-commit: e89a5e5e91476102a471797fc2a81aa2f0f2b3fb
Component: engine
2017-09-17 22:02:13 -07:00
5681a2921d Exit if service config is loaded unsuccessfully on startup
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
Upstream-commit: 5258297dac1e32c8dd1caff528d321ac7eb4a87c
Component: engine
2017-09-17 18:50:16 +03:00
af2e8abbf0 Merge pull request #34842 from dnephin/fix-integration-on-timeout
[integration-cli] Only attempt to find pid with local daemon
Upstream-commit: c5c0702a4d523071b3e41a13c233b6ec9e261b06
Component: engine
2017-09-16 06:48:18 -07:00
347269ee44 Merge pull request #52 from thaJeztah/switch-to-arm64v8
Switch aarch64 images to arm64v8
Upstream-commit: a1debdbcf0220c10799fce225f2f189e681de385
Component: packaging
2017-09-15 18:54:10 -07:00
19d23646ea Merge pull request #51 from thaJeztah/switch-to-arm32v7
Switch armhf images to arm32v7
Upstream-commit: dfb5b129949527991b6ef9fa1d82c1a8a3f412eb
Component: packaging
2017-09-15 18:53:37 -07:00
35f91d208e Switch aarch64 images to arm64v8
The "aarch64" images on Docker Hub are deprecated
in favor of the "arm64v8" images.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: cc436770b773767ad59e766be66323282b030d33
Component: packaging
2017-09-16 03:10:07 +02:00
4609e2004f Switch armhf images to arm32v7
The "armhf" images on Docker Hub are deprecated
in favor of the "arm32v7" and "arm32v6" images.

Note that the Alpine image is built for arm32v6,
which is compatible for both arm32v6 and arm32v7.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 2b8d4afddf118b809157f4249a45656cfaa96cd3
Component: packaging
2017-09-16 03:05:34 +02:00
a8090896a0 Merge pull request #34252 from Microsoft/akagup/lcow-remotefs-sandbox
LCOW: Support for docker cp, ADD/COPY on build
Upstream-commit: a5f9783c930834b8e6035fb0ad9c22fd4bbfc355
Component: engine
2017-09-15 16:49:48 -07:00
d8ebaa5838 Replace old version tests
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 813d2e082a094d11bda0d0f5a708ce30805ab28e
Component: engine
2017-09-15 12:56:09 -04:00
a785d9466c Merge pull request #535 from thaJeztah/remove-swp-file
Remove .swp file that was accidentally added
Upstream-commit: 6d614ec54d
Component: cli
2017-09-15 16:13:31 +02:00
892a44a627 Various fixes
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: b7d8d2c4ab709f072cbdc4f89a8c80065648757e
Component: engine
2017-09-15 16:01:15 +02:00
2a72ee1fde Merge pull request #509 from xificurC/fix-secrets-and-configs-idempotence
sort secrets and configs to ensure idempotence
Upstream-commit: a09a2c6d15
Component: cli
2017-09-15 15:43:59 +02:00
adba854430 Merge pull request #34849 from chchliang/testlayer
add testcase in layer/empty_test.go with Platform(),Metadata()
Upstream-commit: 5c10698d5c5223f9cb49704124be592e3d39d0df
Component: engine
2017-09-15 06:39:20 -07:00
2a306cdba9 Add jenkins build status to readme
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Upstream-commit: c56d7ec37f
Component: cli
2017-09-15 15:08:28 +02:00
04f1d90792 Merge pull request #532 from dnephin/fix-e2e-fixture
Fix e2e test by using a pinned version of alpine
Upstream-commit: 9053aa1038
Component: cli
2017-09-15 14:49:37 +02:00
eae91199bd Remove .swp file that was accidentally added
This file was added by accident in dd95731a21
and not noticed during review.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: e612236a3d
Component: cli
2017-09-15 13:20:40 +02:00
b66e771f48 Merge pull request #534 from mion00/document_node_hostname_templating
Document .Node.Hostname templating
Upstream-commit: e2ee30ae42
Component: cli
2017-09-15 13:02:31 +02:00
3223c51c8a Remove erroneous Println
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: eb396e8984ce64ea6ee9c04905780d74ed7d8d8b
Component: engine
2017-09-15 13:02:27 +02:00
b43594fccc Merge pull request #442 from jhowardmsft/jjh/34508docs
Docs for Windows daemon graphdriver options
Upstream-commit: 5a7f25f24c
Component: cli
2017-09-15 12:19:14 +02:00
a5b24016fd Document .Node.Hostname templating
Update placeholders table and add example code
Follow up to moby/moby#34686

Signed-off-by: Carlo Mion <mion00@gmail.com>
Upstream-commit: 21825b6842
Component: cli
2017-09-15 10:23:56 +02:00
5086fdcfde Fix CString memory leaks
Make sure to call C.free on C string allocated using C.CString in every
exit path.

C.CString allocates memory in the C heap using malloc. It is the callers
responsibility to free them. See
https://golang.org/cmd/cgo/#hdr-Go_references_to_C for details.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Upstream-commit: 593dbfd1448e8dac08488786fde6fe7fb057bdac
Component: engine
2017-09-15 09:57:26 +02:00
ae2d031a76 add testcase in layer/empty_test.go with Metadata()
Signed-off-by: chchliang <chen.chuanliang@zte.com.cn>
Upstream-commit: c72112b171ac046d11e8279b799315e962332450
Component: engine
2017-09-15 14:13:48 +08:00
70abc439d8 Merge pull request #34258 from simonferquel/lcow-mounts
LCOW: Prepare work for bind mounts
Upstream-commit: 0300fa7f806f978451c09ebbff402ddd34e928d9
Component: engine
2017-09-14 15:00:08 -07:00
a641c1b7f0 Add LCOW behind experimental,
might not be the cleanest way, but it's definitly the way with the
minimum code change.

Signed-off-by: Victor Vieux <victorvieux@gmail.com>
Upstream-commit: ff686743c50dc34b57f5627ba6fee38502bdd3ec
Component: engine
2017-09-14 13:51:16 -07:00
aeb89eb179 Volume refactoring for LCOW
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Upstream-commit: e89b6e8c2d2c36c43f22aeaf2a885646c2994051
Component: engine
2017-09-14 12:33:31 -07:00
cddfe04f6a LCOW: Implemented support for docker cp + build
This enables docker cp and ADD/COPY docker build support for LCOW.
Originally, the graphdriver.Get() interface returned a local path
to the container root filesystem. This does not work for LCOW, so
the Get() method now returns an interface that LCOW implements to
support copying to and from the container.

Signed-off-by: Akash Gupta <akagup@microsoft.com>
Upstream-commit: 7a7357dae1bcccb17e9b2d4c7c8f5c025fce56ca
Component: engine
2017-09-14 12:07:52 -07:00
14427ba493 Vendor containerd/continuity@22694c680e
Signed-off-by: Akash Gupta <akagup@microsoft.com>
Upstream-commit: ba13c173d1704168b918705b827963dc6e3900ab
Component: engine
2017-09-14 12:00:38 -07:00
29ef2e0479 Merge pull request #34217 from yongtang/34208-http-add-root
Fix build with `ADD` urls without any sub path
Upstream-commit: d60c1866679f9fcd5701eedabe49e9fa11228b08
Component: engine
2017-09-14 11:55:24 -07:00
f34f36be87 Merge pull request #34332 from clnperez/logrus-revendor
revendor logrus and x/crypto
Upstream-commit: 2a54dc080471476037c87cc6961cc126368ffdd9
Component: engine
2017-09-14 11:29:05 -07:00
44733ed80a Fixes after dnephin review
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 7dabed019a7aac9b317b586d582431eef3b65e33
Component: engine
2017-09-14 19:27:09 +02:00
6cc83af533 Fix Windows build
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 81f69a593146f61d3f6568403168ba28b1714f97
Component: engine
2017-09-14 19:27:09 +02:00
82ba6d5d3e Test requires SameHostDaemon
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 61b13ba0d12aeeadc1c08eae62ba83f62208a6d3
Component: engine
2017-09-14 19:27:09 +02:00
414afe084c Correct log message
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 5eab08930c9c2d39bb76fd6320e9979b504750a6
Component: engine
2017-09-14 19:27:09 +02:00
a13cdc241b Set client version instead of negotiating it
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 85431566a81792e3612df3b6b858f7b0c3506883
Component: engine
2017-09-14 19:27:09 +02:00
454535ed22 Bring up DockerNetworkSuite
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 42d812df0a12d92fad1f327f0b0f5d9eb7a9f107
Component: engine
2017-09-14 19:27:09 +02:00
58906ac91c Remove race and split TestAPINetworkInspect test
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 6936ce3b65f149ba6ab1cd5c257358c06eb9cdbb
Component: engine
2017-09-14 19:27:09 +02:00
4d643fb18a Fixes for dnephin review
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 86f9eb4a085a61b3355dc38452c47def806bf7c9
Component: engine
2017-09-14 19:27:09 +02:00
f23d5bec57 Skip some tests for E2E
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: f089a1df393228085c4895b8db0fa95128173398
Component: engine
2017-09-14 19:27:09 +02:00
abba79d025 Check integration test requirements using daemon
When running against a remote daemon, we cannot use the local
filesystem to determine configuration.

Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: b1fb41988dc1b7071a58f76f6ad2730fc1a02eca
Component: engine
2017-09-14 19:27:09 +02:00
2801aaa58e Use TLS for tests if needed
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 0bdba0e91a072ee2cdecb4e632c13f187eb88e9c
Component: engine
2017-09-14 19:27:09 +02:00
e3234a8303 Fix tests that depend on clean environment
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: dc6ddfa8415d90e9a9788d5cfd5a10c17449bbc9
Component: engine
2017-09-14 19:27:09 +02:00
fe0ff1cb68 Add E2E requirement for integration tests
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: d622e81af50f4690d5867a89b430d1b94707fd26
Component: engine
2017-09-14 19:27:09 +02:00
559acd0f8b Containerize integration tests
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 07f10d8e2e2214000635c32d23f9435fa3fb48b8
Component: engine
2017-09-14 19:27:09 +02:00
16788ee2e5 Protect entire environment when testing
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 063c89c71fd1fbeb7ef7c46f43ee805b620e7136
Component: engine
2017-09-14 19:27:09 +02:00
9c49974512 Allow protection of entire environment during tests
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
Upstream-commit: 0520581523caeacdf718a2dd1db2958c24b47cf6
Component: engine
2017-09-14 19:27:09 +02:00
b3c31e9800 Add unit test to cover changes.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Upstream-commit: 027297a60f5f5a70e1e3eb3a68280f64c66bc877
Component: engine
2017-09-14 16:17:38 +00:00
ac38bbaf63 Fix build with ADD urls without any sub path
This fix tries to address the issue raised in #34208 where
in Dockerfile an `ADD` followed by an url without any sub path
will cause an error.

The issue is because the temporary filename relies on the sub path.

An integration test has been added.

This fix fixes #34208.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Upstream-commit: bea0a072d86604071c99e9b6989b19ca4fe22032
Component: engine
2017-09-14 16:17:38 +00:00
97847089f1 revendor logrus and x/crypto
this fixes the issue that was blocking a test from running on ppc64le.
the logrus revendor changes the color code used in that same test, so
that breaks the test for all platforms (updated in this pr)

Signed-off-by: Christy Perez <christy@linux.vnet.ibm.com>
Upstream-commit: 008b217844f8738cc47ef9ff108dc41dc37736cc
Component: engine
2017-09-14 11:05:47 -05:00
1546d32eb0 Only attempt to find pid with local daemon
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 014cecda464fb1171e613676e0a8a85c02ec1674
Component: engine
2017-09-14 12:05:18 -04:00
c95e22b252 Merge pull request #34837 from tophj-ibm/switch-hub-test-to-alpine
[integration-cli] fix p/z HubPullSuite tests
Upstream-commit: 3a081f53c150190201ddb05c97344ed5071446b0
Component: engine
2017-09-14 18:02:13 +02:00
6c749ced41 Fix e2e test by using a pinned version of alpine
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: ab2e219116
Component: cli
2017-09-14 11:38:46 -04:00
023fe0b32f [integration-cli] fix p/z HubPullSuite tests
This test tries to pull all the tags in the busybox repo and looks to see
if there were more than two images pulled. This was failing on
p/z due to the recent change to manifest lists, where one of the busybox
tags didn't have a p/z manifest in it's manifest list.

This error seems fine to me, so I changed the test to see if pull fails,
it fails with the "manifest not found" error.

Also switched from busybox -> alpine, because it has significantly less tags,
and the images are close in size.

Signed-off-by: Christopher Jones <tophj@linux.vnet.ibm.com>
Upstream-commit: 5739ba1b918402b8eda748ac2f5dd7ce00f2e69f
Component: engine
2017-09-14 09:42:09 -04:00
93617a3f74 Merge pull request #34784 from dnephin/fix-client-not-found
Cleanup client not found errors
Upstream-commit: bb0e8ee51c8940c3ce23e4f594068612203c6139
Component: engine
2017-09-14 12:04:56 +02:00
c30f13232a Merge pull request #34686 from mion00/templating-node-hostname-support
Add support for .Node.Hostname templating in swarm services
Upstream-commit: 2ee8ef864f9fb9c31848fe10a61605a39fb81635
Component: engine
2017-09-13 21:06:11 -07:00
803b5f0e94 Merge pull request #34821 from thaJeztah/remove-enable-api-cors
Remove deprecated --enable-api-cors flag
Upstream-commit: dc35a8a5d22b6c828cd105be7c62b72919df25cd
Component: engine
2017-09-13 20:10:27 -07:00
63f4bb52b4 Merge pull request #34828 from allencloud/add-config-tags-in-swagger
add configs tag in swagger.yml
Upstream-commit: 80edccda708c6771824c245b4d634c2a9ce29795
Component: engine
2017-09-14 02:37:28 +02:00
4fe1c1584a Merge pull request #34844 from kolyshkin/lvm2-fix
Fix fetching LVM2 sources
Upstream-commit: a8f6e60bfc95421f0d8539fddaecd32642cd947f
Component: engine
2017-09-14 02:01:14 +02:00
150f7f6a55 Add more information about commands to generated YAML docs
This patch adds aditional information about commands to the YAML files
that are generated for the reference documentation.

The following fields are added for each command:

Property          | Type      | Description
------------------|-----------|---------------------------------------------------------------------------------------
deprecated        | Boolean   | Indicates if the command is marked deprecated
min_api_version   | String    | The API version required to use this command (e.g. "1.23")
experimental      | Boolean   | Indicates if the command requires the daemon to run with experimental features enabled

For example (taken from the experimental `docker checkpoint create` command):

    command: docker checkpoint create
    short: Create a checkpoint from a running container
    long: Create a checkpoint from a running container
    usage: docker checkpoint create [OPTIONS] CONTAINER CHECKPOINT
    pname: docker checkpoint
    plink: docker_checkpoint.yaml
    options:
    - option: checkpoint-dir
      value_type: string
      description: Use a custom checkpoint storage directory
      deprecated: false
      experimental: false
    - option: leave-running
      value_type: bool
      default_value: "false"
      description: Leave the container running after checkpoint
      deprecated: false
      experimental: false
    deprecated: false
    min_api_version: "1.25"
    experimental: true

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 1f48e75c5c
Component: cli
2017-09-14 00:48:22 +02:00
46def61677 Add more information about command flags to generated YAML docs
This patch adds aditional information about command flags to the YAML files
that are generated for the reference documentation.

The following fields are added for each flag:

Property          | Type      | Description
------------------|-----------|---------------------------------------------------------------------------------------
value_type        | String    | The "type" of value to be passed to this flag (e.g., `uint64`, `list`)
deprecated        | Boolean   | Indicates if the flag is marked deprecated
min_api_version   | String    | The API version required to use this flag (e.g. "1.23")
experimental      | Boolean   | Indicates if the flag requires the daemon to run with experimental features enabled

For example (taken from the `docker image build` command):

    - option: security-opt
      value_type: stringSlice
      default_value: '[]'
      description: Security options
      deprecated: false
      experimental: false
    - option: shm-size
      value_type: bytes
      default_value: "0"
      description: Size of /dev/shm
      deprecated: false
      experimental: false
    - option: squash
      value_type: bool
      default_value: "false"
      description: Squash newly built layers into a single new layer
      deprecated: false
      min_api_version: "1.25"
      experimental: true

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: a8ba6f93d9
Component: cli
2017-09-14 00:47:42 +02:00
c752d6bc2e Update system prune docs for --volumes flag
The `--volumes` flag was added in 37fd6128dc,
but the documentation was not updated.

This patch updates the documentation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: b4db84de69
Component: cli
2017-09-14 00:42:12 +02:00
d011c4127f LCOW: Add GCS debugging
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: 5a0e2beac330d49c2b7436bf29e87d52dab4f557
Component: engine
2017-09-13 14:54:34 -07:00
08356f8921 Fix fetching LVM2 sources
Version 2.02.173 has disappeared, let's revert back to latest stable
one.

https://github.com/moby/moby/issues/34843

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: a436d8a634392f9e82b6930a560d56900d887ce7
Component: engine
2017-09-13 14:34:36 -07:00
69753f2d25 Merge pull request #513 from shouze/reset-id-pair-during-build-to-avoid-cache-busting
Reset uid/gid to 0 in build context to fix cache busting issues on ADD/COPY
Upstream-commit: 7b77ab5c60
Component: cli
2017-09-13 15:19:26 -04:00
57a43e8ab0 Merge pull request #34775 from darrenstahlmsft/RevendorHcsshim
Update hcsshim to v0.6.5
Upstream-commit: a15cdd707acc37e7bc5dd618a461618c3a0cda20
Component: engine
2017-09-13 11:14:36 -07:00
07369b8b77 Merge pull request #34809 from dnephin/add-gosimple-linter
Add gosimple linter
Upstream-commit: e51bc3ecd04d950f8854947ec8906937eaf87129
Component: engine
2017-09-13 12:44:59 -04:00
1a8ec36d61 Merge pull request #529 from thaJeztah/bump-version
Bump version to 17.10.0-dev
Upstream-commit: acc29884fa
Component: cli
2017-09-13 18:21:01 +02:00
7742f2c56c Merge pull request #481 from cdrage/add-build-to-service-config
Add 'build' to types.go
Upstream-commit: 2eb31e6b60
Component: cli
2017-09-13 18:20:42 +02:00
8453ea8ddd Merge pull request #525 from thaJeztah/change-detach-default
Use non-detached mode as default for service commands
Upstream-commit: e5aeb4b5e8
Component: cli
2017-09-13 11:35:08 -04:00
f7e5e8fdc8 Add 'build' to types.go
This adds 'build' to types.go in order for projects that use docker/cli
to parse Docker Compose files to correctly retrieve `build` keys

Signed-off-by: Charlie Drage <charlie@charliedrage.com>
Upstream-commit: 9bdb0763b9
Component: cli
2017-09-13 10:47:17 -04:00
002e234c45 Merge pull request #34829 from Microsoft/jjh/spotfix
LCOW: Spot fix for multi-os image pulling
Upstream-commit: 0dbc182b6c4f6a72933680f98a6240a7681d94ee
Component: engine
2017-09-13 14:32:15 +02:00
b402c14275 Bump version to 17.10.0-dev
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: e17475e935
Component: cli
2017-09-13 14:08:56 +02:00
ad105d4aec Use non-detached mode as default for service commands
Commit 330a0035334871d92207b583c1c36d52a244753f added a `--detach=false` option
to various service-related commands, with the intent to make this the default in
a future version (17.09).

This patch changes the default to use "interactive" (non-detached), allowing
users to override this by setting the `--detach` option.

To prevent problems when connecting to older daemon versions (17.05 and below,
see commit db60f25561), the detach option is
ignored for those versions, and detach is always true.

Before this change, a warning was printed to announce the upcoming default:

    $ docker service create nginx:alpine
    saxiyn3pe559d753730zr0xer
    Since --detach=false was not specified, tasks will be created in the background.
    In a future release, --detach=false will become the default.

After this change, no warning is printed, but `--detach` is disabled;

    $ docker service create nginx:alpine
    y9jujwzozi0hwgj5yaadzliq6
    overall progress: 1 out of 1 tasks
    1/1: running   [==================================================>]
    verify: Service converged

Setting the `--detach` flag makes the cli use the pre-17.06 behavior:

    $ docker service create --detach nginx:alpine
    280hjnzy0wzje5o56gr22a46n

Running against a 17.03 daemon, without specifying the `--detach` flag;

    $ docker service create nginx:alpine
    kqheg7ogj0kszoa34g4p73i8q

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 0c27355f7b
Component: cli
2017-09-13 12:27:55 +02:00
806d838e90 LCOW: Spot fix for multi-os image pulling
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: b291f5a31728f7ff6386bb37f15e7c0885d3b2a7
Component: engine
2017-09-12 23:33:34 -07:00
523435549c add configs tag in swagger.yml
Signed-off-by: Allen Sun <allensun.shl@alibaba-inc.com>
Upstream-commit: 16929d337a5dbd9aaa029271db1cdba25dd0d2f2
Component: engine
2017-09-13 09:48:05 +08:00
9d7caf267c Update gometalinter
This is mostly to include the following fix:
https://github.com/alecthomas/gometalinter/commit/78e3fbd90a20b03a

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 6be4b3703c2a2b41ccdf97fcf8d2da6863a402bd
Component: engine
2017-09-12 18:46:37 -07:00
99b37c7406 Update hcsshim to v0.6.5
Signed-off-by: Darren Stahl <darst@microsoft.com>
Upstream-commit: bffc7a423f20730f086c30bc189d6c6ad81d16dd
Component: engine
2017-09-12 18:46:12 -07:00
57c34191f2 gometalinter: add per-platform configurable options
I have run into two separate issues while doing 'make all' on armhf
(a Scaleway C1 machine, same as used in CI). This commit fixes both.

1. There were a lot of "not enough memory" errors, and after that
in a few runs gometalinter just stuck forever on FUTEX_WAIT with
no children left.

Looking into docs, I found the --enable-gc option which solved the issue.

[Update: this has already been added]

2. Timeout of 2 minutes is not enough for the abovementioned platform.
The longest running linter is goimports which takes almost 6 minutes to run.

Set the timeout to the observable run time roughly doubled.

In addition, ARM platforms does not have too much RAM (2GB), so
running too many processes in parallel might be problematic. Limit
it by using -j2

[v2: make the timeout arch-dependent, also tested on aarch64 (2m15s)]
[v3: moved timeout setting to Dockerfiles]
[v4: generalized to GOMETALINTER_OPTS, added -j2 for ARM platforms]
[v5: rebase to master]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: b96093fa56a9c085cb3123010be2430753c40cbc
Component: engine
2017-09-12 18:45:34 -07:00
4219a83be8 overlay gd: fix build for 32-bit ARM
This commit reverts a hunk of commit 2f5f0af3f ("Add unconvert linter")
and adds a hint for unconvert linter to ignore excessive conversion as
it is required on 32-bit platforms (e.g. armhf).

The exact error on armhf is this:

	19:06:45 ---> Making bundle: dynbinary (in bundles/17.06.0-dev/dynbinary)
	19:06:48 Building: bundles/17.06.0-dev/dynbinary-daemon/dockerd-17.06.0-dev
	19:10:58 # github.com/docker/docker/daemon/graphdriver/overlay
	19:10:58 daemon/graphdriver/overlay/copy.go:161: cannot use stat.Atim.Sec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:161: cannot use stat.Atim.Nsec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:162: cannot use stat.Mtim.Sec (type int32) as type int64 in argument to time.Unix
	19:10:58 daemon/graphdriver/overlay/copy.go:162: cannot use stat.Mtim.Nsec (type int32) as type int64 in argument to time.Unix

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: 21b2c278cc86f0fc411018becbcbf2a7e44b6057
Component: engine
2017-09-12 18:44:55 -07:00
a87f17c01b Fix 'make all' for other platforms
Since commit d7e2c4ce7 ("Use gometalinter for linting") command
"make all" fails on all the non-default platforms (i.e. ARMs, PPC, and
s390) in this way:

	# make all
	...
	Congratulations!  All commits are properly signed with the DCO!
	/go/src/github.com/docker/docker/hack/validate/gometalinter: line 6: gometalinter: command not found
	Makefile:105: recipe for target 'all' failed
	make: *** [all] Error 127

Make sure gometalinter is installed for those platforms

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Upstream-commit: fc3040a4c41d3916739639b70fc3efd92888a0f5
Component: engine
2017-09-12 18:44:55 -07:00
053e3db35e Merge pull request #528 from andrewhsu/ven
vndr github.com/docker/docker to 84144a8 to fix stuff
Upstream-commit: f697de32b9
Component: cli
2017-09-12 17:52:55 -07:00
e18e2f39e3 vndr github.com/docker/docker to 84144a8 to fix stuff
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
Upstream-commit: 850b46e67c
Component: cli
2017-09-12 17:27:15 -07:00
6e9f643bb2 Reset idPair during build to avoid cache busting
Signed-off-by: Sébastien HOUZÉ <cto@verylastroom.com>
Upstream-commit: 7e407610d4
Component: cli
2017-09-13 02:04:03 +02:00
eae7cc4c29 Merge pull request #516 from andrewhsu/v
vndr docker/docker to ea220e7 to bring in fix for arm
Upstream-commit: b60413264d
Component: cli
2017-09-12 16:01:04 -07:00
ca1972776d Merge pull request #34826 from cezarsa/usagefix
Fix variable shadowing causing LayersSize to be reported as 0
Upstream-commit: 84144a8c66c1bb2af8fa997288f51ef2719971b4
Component: engine
2017-09-12 15:51:26 -07:00
baffbb54c8 remove unused vndr github.com/docker/libtrust
Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
Upstream-commit: 536da4a07a
Component: cli
2017-09-12 13:48:21 -07:00
fda4a38658 vndr golang.org/x/sys to 07c1829
To satisfy requirements of the vndr of docker/docker

Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
Upstream-commit: 50696bbf72
Component: cli
2017-09-12 12:11:18 -07:00
55cb898a72 Fix variable shadowing causing LayersSize to be reported as 0
Signed-off-by: Cezar Sa Espinola <cezarsa@gmail.com>
Upstream-commit: 313bc1e339fa4292d9ef5bc74acc82436eab7e1e
Component: engine
2017-09-12 14:11:11 -03:00
18c29c5c5f Add gosimple linter
Update gometalinter

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: f7f101d57ef8cbf2d8723a18b7d723c5c5dd04b6
Component: engine
2017-09-12 12:09:59 -04:00
1d65628454 Merge pull request #34754 from Microsoft/jjh/read-only
LCOW: VHDX boot to readonly.
Upstream-commit: 969b76d85f93e214cbc44f25a3f44b67cb0dc078
Component: engine
2017-09-12 08:35:21 -07:00
52611dee7a Merge pull request #34796 from donutloop/fix_typos_in_locker_example
Fix typos in Locker example
Upstream-commit: 099b4de391696b740779bfcb8322b4f4186e297e
Component: engine
2017-09-12 15:48:23 +02:00
a300c8a80f Update deprecated.md for "api-enable-cors"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 7c69bf1d24
Component: cli
2017-09-12 12:47:57 +02:00
3e4a18de4d Remove deprecated --enable-api-cors flag
The `--enable-api-cors` flag was deprecated in f3dd2db4ff7de1399a49af928cd3eae4fccf8764,
and marked for removal in docker 17.09 through 85f92ef3590b386ea17e3948262725a2d3ce4db5.

This patch removes the deprecated flag.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 7d4eab554379524c2421a7ecd3319d1d087d1de2
Component: engine
2017-09-12 12:43:34 +02:00
ee7b60968b Cleanup client not found errors.
And fix remove calls to return a notFound error

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 81bb9978ab5ac99e84a5bf62d0d469f0aec1d506
Component: engine
2017-09-11 19:53:18 -04:00
7f5ba34576 Merge pull request #48 from seemethere/remove_version_dependency_from_package_building
Removes engine VERSION dependency
Upstream-commit: 3c05e034e76cb3025a9f10cf6086fed312dc7670
Component: packaging
2017-09-11 13:19:31 -07:00
528c150b8c Removes engine VERSION dependency
Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
Upstream-commit: 89d8a83e20172e66c16c6ddbc46f43e5f67f7045
Component: packaging
2017-09-11 12:11:59 -07:00
99e268ef3c Merge pull request #508 from docker/revert-493-patch-1
Revert "Change sshfs by cloudstor on Installing and using a plugin"
Upstream-commit: 04390f8a74
Component: cli
2017-09-11 11:25:50 -07:00
599a2ae3b1 Merge pull request #521 from dnephin/add-albers-to-maintainers
Add albers to maintainers
Upstream-commit: d0bda815d2
Component: cli
2017-09-11 19:47:20 +02:00
591014017f Add albers to maintainers.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 92cf825238
Component: cli
2017-09-11 11:22:10 -04:00
2c45bc6a92 Merge pull request #34770 from dnephin/fix-client-with-empty-id
Fix volume inspect with empty ID
Upstream-commit: 63a9ea58eb4c704ed7d7dab950f12f708cf220f7
Component: engine
2017-09-11 07:01:50 -07:00
8e2757c531 Merge pull request #421 from thaJeztah/refactor-docker-info
Refactor/cleanup of docker info
Upstream-commit: e77dc2232e
Component: cli
2017-09-11 15:25:02 +02:00
033298b8f6 Refactor/cleanup of docker info
Some mild refactoring of the docker info command;

- Use `fmt.Fprinln()` instead of `fmt.Fprintf()` where possible
- Rename `fprintfIfNotEmpty()` to `fprintlnNonEmpty()`, and removed
  return variables, because they were not used. `fprintlnNonEmpty()`
  now uses fmt.Fprintln()` instead of `fmt.Fprintf()`, because
  formatting was not used.
- Use `fprintlnNonEmpty()` to get rid of some `if` statements
- Extract printing Swarm-related information to a `printSwarmInfo()` function
- Change `Http Proxy` and `Https Proxy` to `HTTP Proxy` / `HTTPS Proxy`

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 6f1b510843
Component: cli
2017-09-11 15:13:06 +02:00
95956aa7ef Merge pull request #519 from gesellix/typo-configration
[docs] Fix typo in configration.
Upstream-commit: 202205365a
Component: cli
2017-09-11 14:57:08 +02:00
1b8f2ad866 [docs] Fix typo in configration.
Signed-off-by: Tobias Gesellchen <tobias@gesellix.de>
Upstream-commit: f8ed8d22c6
Component: cli
2017-09-10 23:12:29 +02:00
e388be9473 Fix typos in Locker example
Signed-off-by: Marcel Edmund Franke <marcel.edmund.franke@gmail.com>
Upstream-commit: 6d3bc28289c265a65879a7f28264e6bacb95fbe1
Component: engine
2017-09-10 11:34:19 +02:00
af0adf66d4 Merge pull request #34790 from dnephin/add-ineffassign-linter
Add ineffassign linter
Upstream-commit: 13fec0607394f7c6da0148f8d513b6fcbf7cce61
Component: engine
2017-09-09 15:41:55 -07:00
4b9c2f5fd5 vndr docker/docker to ea220e7 to bring in fix for arm
Primarily to bring in fix for "Clear Architecture field in platform
constraint for arm architectures".

Signed-off-by: Andrew Hsu <andrewhsu@docker.com>
Upstream-commit: ef027b6d72
Component: cli
2017-09-08 16:27:56 -07:00
fdd3e06a77 Add ineffassign linter
Also enable GC in linting to reduce memory usage.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 09652bf8789142a5a5a1de2d41590300761b4954
Component: engine
2017-09-08 18:23:21 -04:00
30a4e0ab8e Merge pull request #510 from dnephin/add-parse-log-details
Use a local copy of ParseLogDetails
Upstream-commit: aae519d0f6
Component: cli
2017-09-08 11:38:24 -07:00
fbd21afa80 Merge pull request #511 from dnephin/fix-end-of-line-whitespace-tests
Use golden files for tests that expect end-of-line whitespace
Upstream-commit: d3d9b38d55
Component: cli
2017-09-08 11:37:28 -07:00
94dd311bdc Merge pull request #495 from dnephin/container-run-e2e
Add en e2e test for `container run`
Upstream-commit: cc517f2d8a
Component: cli
2017-09-08 11:36:32 -07:00
9211237d01 Merge pull request #34767 from dnephin/deprecate-some-client
Cleanup client/ interface
Upstream-commit: 96255ba07ae7de2bb2a18567c478b63d5ac74ee4
Component: engine
2017-09-08 13:29:10 -04:00
b363a8f8a7 sort secrets and configs to ensure idempotence
`docker stack deploy` keeps restarting services it doesn't need to (no changes)
because the entries' order gets randomized at some previous (de)serialization.
Maybe it would be worth looking into this at a higher level and ensure
all (de)serialization happens in an ordered collection.

This quick fix sorts secrets and configs (in place, mutably) which ensures the
same order for each run.

Based on
https://github.com/moby/moby/pull/30506

Fixes
https://github.com/moby/moby/issues/34746

Signed-off-by: Peter Nagy <xificurC@gmail.com>
Upstream-commit: 27e8bdf32b
Component: cli
2017-09-08 16:09:48 +02:00
66ae0e70f8 Merge pull request #34771 from Microsoft/jjh/hcsshim
Revendor Microsoft/hcsshim @ v0.6.4
Upstream-commit: 8ec484ff4bef7698cc4b3ba8195dd182c2af8045
Component: engine
2017-09-07 14:51:07 -07:00
d7ed53048b Use golden files for tests that expect end-of-line whitespace
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 51587de1c4
Component: cli
2017-09-07 17:50:44 -04:00
b543555e86 Merge pull request #34761 from dnephin/fix-mount-create-api-test
Some cleanup of mount create API test
Upstream-commit: bf3a8bddeb5e1ae04b6f73bfe811372ee3e78e36
Component: engine
2017-09-07 17:09:19 -04:00
58743c32f5 Merge pull request #34756 from dnephin/better-filters
Improve docs and interface for api/types/filters
Upstream-commit: c8400bf24dcea8e160d6b614d996b0f659c7d8d9
Component: engine
2017-09-07 17:00:59 -04:00
810209d155 Revendor Microsoft/hcsshim @ v0.6.4
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: e47c626e0a5e7285782620c027b3d5195c643a5a
Component: engine
2017-09-07 12:08:40 -07:00
f1b816d854 Merge pull request #34685 from dnephin/remove-bundle-version
Remove version from bundle path
Upstream-commit: f69188aec9f74a946422a256c14bf8efc82f20d4
Component: engine
2017-09-07 11:53:53 -07:00
2e7d5b113f Merge pull request #34757 from dnephin/fix-test-run-environment
Fix TestRunEnvironment
Upstream-commit: d76f0d4e0694f5adcaab327e801ee8553620c5b3
Component: engine
2017-09-07 11:28:57 -07:00
5899c64938 Fix volume inspect with empty ID
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 5ac298fd0e5c065483653970be587626026971c2
Component: engine
2017-09-07 13:46:23 -04:00
56f259f37d Revert "Change sshfs by cloudstor on Installing and using a plugin"
Signed-off-by: Misty Stanley-Jones <misty@docker.com>
Upstream-commit: eb77961399
Component: cli
2017-09-07 10:15:59 -07:00
0d3330814c Use a local copy of ParseLogDetails
It's being removed from client/

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: a747389bf4
Component: cli
2017-09-07 12:50:25 -04:00
d7504f67d1 Merge pull request #34738 from wgliang/optimization1
Optimize some wrong usage and spelling
Upstream-commit: 2dcb77b24c80dd95b52358c92436f68f2a33eb01
Component: engine
2017-09-07 09:45:14 -07:00
980d05f2ea Cleanup client/ interface
- Remove ParseLogDetails, this is not part of the client. Moved to docker/cli
- Deprecate ParseHost and replace with ParseHostURL
- Deprecate redundant IsErr helpers

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 54242cd067c234960d1295a67271475f9d099f22
Component: engine
2017-09-07 12:32:38 -04:00
5f49aab36a Merge pull request #34687 from tych0/bump-runc
bump runc version
Upstream-commit: a68ee8c8950b1923c3a92b9cec0d9a723897111d
Component: engine
2017-09-07 14:52:18 +02:00
6f155f233b Merge pull request #34021 from nishanttotla/dont-set-architecture-constraint
Clear Architecture field in platform constraint for arm architectures
Upstream-commit: ea220e70a13963da544645376cd9331021eec6b4
Component: engine
2017-09-07 11:18:12 +02:00
a8b7a6b071 Merge pull request #34730 from simonferquel/fix-TestEventsOOMDisableTrue-flakkyness
Events CLI tests: fix flakyness of TestEventsOOMDisableTrue
Upstream-commit: 72eb1d0a47488d279df2b80bfd3f6091eaff66a7
Component: engine
2017-09-07 11:16:37 +02:00
3aa4929239 Plugable secret backend
This commit extends SwarmKit secret management with pluggable secret
backends support.
Following previous commits:
1. docker/swarmkit@eebac27434
2. docker/docker@08f7cf0526
Added driver parameter to `docker secret` command.

Specifically:

1. `docker secret create [secret_name] --driver [driver_name]`
2.  Displaying the driver in
```
    $ docker secret ls
    $ docker secret inspect [secret_name]
    $ docker secret inspect [secret_name] -pretty
```

Signed-off-by: Liron Levin <liron@twistlock.com>
Upstream-commit: 0ee9e05d8f
Component: cli
2017-09-07 11:10:44 +03:00
eec1d4ef54 Optimize some wrong usage and spelling
Signed-off-by: wgliang <liangcszzu@163.com>
Upstream-commit: 94cefa21459a0c620e5a9c2da04df6d3a43dae17
Component: engine
2017-09-07 09:44:08 +08:00
567b25fb28 Some cleanup of mount create API test
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 58b96aced87b33c4175fa5d3422289f763ab599d
Component: engine
2017-09-06 19:32:35 -04:00
5063459b89 Merge pull request #34748 from dnephin/cleanup-client-deps
Cleanup client/ package dependencies
Upstream-commit: be97c66708c24727836a22247319ff2943d91a03
Component: engine
2017-09-06 16:14:29 -07:00
74473d87d6 Merge pull request #493 from jmaitrehenry/patch-1
Change sshfs by cloudstor on Installing and using a plugin
Upstream-commit: af94015b8c
Component: cli
2017-09-06 14:42:34 -07:00
11b376603e Fix a bad assumption
If the empty variable happens to be sorted to the end of the list then TrimSpace()
would remove it. Instead only strip the single trailing newline.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: fff605c3b3557acf6bf793813d695fba59d7fa21
Component: engine
2017-09-06 17:32:56 -04:00
4a595ff1d9 Add an end-to-end test for container run
for testing attach, remove, and pull image when missing.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: c34360cc8e
Component: cli
2017-09-06 17:07:38 -04:00
6fc4c48771 Move common e2e things into an internal package.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 677d17150a
Component: cli
2017-09-06 17:07:38 -04:00
e65a64c87e Add gotestyourself/poll
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 683b6226ed
Component: cli
2017-09-06 17:07:35 -04:00
cb4257d5fb Cleanup filter package.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 065118390a3ecaf0dbd2fa752d54d43f8f1e8ec6
Component: engine
2017-09-06 16:41:47 -04:00
9f20b18453 Move tlsconfig to client package.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 6916c215b00ab4d7edf4be14848ab2e695697381
Component: engine
2017-09-06 16:39:55 -04:00
c87a482794 Revendor Microsoft/opengcs @v0.3.3
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: bf898b7a0cedfec5b7e8104a1ac684f9dd232638
Component: engine
2017-09-06 12:55:25 -07:00
8db4d9c803 LCOW: VHDX boot to read-only
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: 17a24034bb4281e2b63949beaa5d3846c0891726
Component: engine
2017-09-06 10:55:19 -07:00
cc7b3620f0 Remove libtrust dep from api
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 2f007e46d0100d865a061c1a8e544bddc0b7a368
Component: engine
2017-09-06 12:05:19 -04:00
33519380e5 Move names to a more appropriate package.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 22b246417f52aa6bd0e358e41e2bfb9c0a59c867
Component: engine
2017-09-06 12:05:16 -04:00
67de569278 Merge pull request #34745 from simonferquel/fix-pkg-archive-conversion
Re-enable some conversion for darwin-amd64 platform
Upstream-commit: 945d80cd6ad5fc9d30a947ab8872721272ac7bff
Component: engine
2017-09-06 09:00:29 -07:00
6ee8cdfa2e Merge pull request #34697 from fcrisciani/ln-vendoring
Vendoring libnetwork
Upstream-commit: 3b449dbfbad4374f618a901ff585d2ea62b1029e
Component: engine
2017-09-06 17:52:56 +02:00
0bd644faaf re-enable some conversion for darwin-amd64 platform
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Upstream-commit: 7c9e64a2e1891bf1020d9312a18741c734fa1cd6
Component: engine
2017-09-06 12:22:41 +02:00
fd94302cba Relabel config files.
Without relabel these files, SELinux-enabled containers will show
"permission denied" errors for configuration files mounted with
`docker server create ... --config ... ...`.

Signed-off-by: Wenxuan Zhao <viz@linux.com>
Upstream-commit: 472c03a8c364090afb88258b3dd9748183c29d05
Component: engine
2017-09-05 18:39:48 -03:00
54efaca689 Merge pull request #34707 from vieux/force_format
force inspect test format
Upstream-commit: d7b4c7e0eac223eda54940adbb4c44bf71ec039c
Component: engine
2017-09-05 13:35:07 -07:00
50ebf89669 Merge pull request #219 from seemethere/update_makefile
Add update-components target, Fix PHONY Targets
2017-09-05 13:10:56 -07:00
57918230aa Add update-components target, Fix PHONY Targets
This allows easier updating of Docker CE components

Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
2017-09-05 12:57:43 -07:00
f109c25168 Merge pull request #34682 from dnephin/fail-build-on-integration-suite
Fix integration suite and propagate failures
Upstream-commit: 975675e9245e1d9a18cae978a0231ff83772048b
Component: engine
2017-09-05 12:40:00 -07:00
33d6fdcfda Merge pull request #353 from albers/completion-nodelist
Use native formatting in bash completion of nodes
Upstream-commit: 0426ea1443
Component: cli
2017-09-05 15:09:00 -04:00
28cf6767d3 Merge pull request #424 from simonferquel/update-vendoring
updated vendoring
Upstream-commit: 5c5cdd0e36
Component: cli
2017-09-05 15:06:09 -04:00
56b8d8a2a0 Remove version from bundle path
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: bac2447964c8cdfcf35f928841d60310db997c76
Component: engine
2017-09-05 13:38:32 -04:00
33179f56a2 force inspect test format
Signed-off-by: Victor Vieux <victorvieux@gmail.com>
Upstream-commit: 8e6567cb837e1c885de5146517557c7a5d8a5f17
Component: engine
2017-09-05 08:31:44 -07:00
e76adc6a0e Merge pull request #406 from ksouf/issue_37_network_list_test
adding network list test
Upstream-commit: ec99774a85
Component: cli
2017-09-05 11:24:32 -04:00
30986cbc05 Avoid failing the test if container is already stopped
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Upstream-commit: adf75503dba2e782139173c011999eacd0c3d7e2
Component: engine
2017-09-05 17:19:57 +02:00
db0c7d8918 Merge pull request #34704 from seemethere/add_overwriteable_version
Allows VERSION to be overwritten by env variable
Upstream-commit: 9e0a1845f23327c4623a49329b2480d98e02173f
Component: engine
2017-09-04 16:47:52 -07:00
2f974e7293 Add bash completion for search --format
Signed-off-by: Harald Albers <github@albersweb.de>
Upstream-commit: f6219ac3c6
Component: cli
2017-09-04 18:21:47 +02:00
09edca8b4e Merge pull request #491 from FrenchBen/fix-stack
Move output of stack rm to stdout
Upstream-commit: 38c1895021
Component: cli
2017-09-04 15:56:30 +02:00
55c903723c Add support for .Node.Hostname templating in swarm services
Signed-off-by: Carlo Mion <mion00@gmail.com>
Upstream-commit: e2f09fa6dd1705eb69ab97fbf759253a4162228a
Component: engine
2017-09-02 10:06:16 +02:00
444c2e65a4 Remove unused depdendencies from vendor
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 724f03bb23
Component: cli
2017-09-01 19:41:06 -04:00
4bafd44516 updated vendoring
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
Upstream-commit: a0113c3a44
Component: cli
2017-09-01 19:41:06 -04:00
0699e6b42a Allows VERSION to be overwritten by env variable
VERSION was hardcoded to be used as the `VERSION` file from the root
directory, this makes it so that you have the option to overwrite this.

Signed-off-by: Eli Uriegas <eli.uriegas@docker.com>
Upstream-commit: 76643025793ca742b1c19bd35cab35c8ff7d3e77
Component: engine
2017-09-01 15:47:15 -07:00
ee07288be3 Move output of stack rm to stdout
Signed-off-by: French Ben <frenchben@docker.com>

Update for the test to capture the proper removal

Signed-off-by: French Ben <frenchben@docker.com>

Satisfy lint length limit

Signed-off-by: French Ben <frenchben@docker.com>

Updated e2e test

Signed-off-by: French Ben <frenchben@docker.com>
Upstream-commit: bb8f49773c
Component: cli
2017-09-01 14:25:20 -07:00
2578773887 Clear Architecture field in platform constraint for arm architectures
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
Upstream-commit: 772af6040ed4f2f26c22901597333a900be17aae
Component: engine
2017-09-01 13:08:20 -07:00
d99a5ff6bf Change sshfs by cloudstor on Installing and using a plugin
Signed-off-by: Julien Maitrehenry <julien.maitrehenry@me.com>
Upstream-commit: e97d72334f
Component: cli
2017-09-01 14:42:01 -04:00
58ef7a0132 Fix integration suite and propagate failures
Failures from the integration suite were not propagating to the outter shell
for some reason. Handle the failure with an if exit 1.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Upstream-commit: 96707bc600747257e82917ca079fa5006d636b2c
Component: engine
2017-09-01 13:07:47 -04:00
35c8905315 Vendoring libnetwork
Diff:
5b28c0ec98...d5c8223190

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Upstream-commit: 1ddeb11835600127a3319fc0dd3764e57ffbf521
Component: engine
2017-08-31 19:10:23 -07:00
3c0eab373a bump runc version
This picks up 66eb2a3e8fc930e1bb6703561152edf5ab550bff, which fixes
readonly containers in user namespaces.

Signed-off-by: Tycho Andersen <tycho@docker.com>
Upstream-commit: 47e9d856c43b6b251d86afc099ec092aa83b1534
Component: engine
2017-08-30 14:26:59 -07:00
6eb6b7d9d2 adding network list test
Signed-off-by: khaled souf <khaled.souf@gmail.com>
Upstream-commit: 15d92a9e03
Component: cli
2017-08-29 16:30:37 +02:00
b812e1036b Use native formatting in bash completion of nodes
Completion of nodes now uses native Docker commands that were not available
when this function was created.

Signed-off-by: Harald Albers <github@albersweb.de>
Upstream-commit: e391e34801
Component: cli
2017-08-28 09:59:19 +02:00
b132c15093 Improve bash completion for --credential-spec
This option is Windows specific and should be only available if the
daemon runs on Windows.

Signed-off-by: Harald Albers <github@albersweb.de>
Upstream-commit: 056ccf88be
Component: cli
2017-08-28 09:53:58 +02:00
ce23144495 Fixed raw mode splunk logger
Splunk HEC does not accept log events with an empty string or a
whitespace-only string.

Signed-off-by: Florian Noeding <florian@noeding.com>
Upstream-commit: 5f6d6a5093a4db799f9c1a6bb82eed1eea13ec0c
Component: engine
2017-08-18 12:03:43 +02:00
934616e542 Replacing os.Lstat with os.Stat to determine directory status in CopyInfoDestinationPath
Signed-off-by: Douglas Curtis <dougcurtis1@gmail.com>

Commenting out tests for now

Signed-off-by: Doug Curtis <dougcurtis1@gmail.com>

Added unit test for CopyInfoDestionationPath.

Signed-off-by: Doug Curtis <dougcurtis1@gmail.com>

Removing integration-cli test case additions

Signed-off-by: Doug Curtis <dougcurtis1@gmail.com>

Removing extra spaces between archive_unix_test.go test cases

Signed-off-by: Doug Curtis <dougcurtis1@gmail.com>

Fixed gofmt issues in archive_unix_test.go

Signed-off-by: Doug Curtis <dougcurtis1@gmail.com>
Upstream-commit: cd7489f2b745578e0d8855aa44213b07b495f86f
Component: engine
2017-08-15 23:19:42 +00:00
615f3700ae Docs for Windows daemon graphdriver options
Signed-off-by: John Howard <jhoward@microsoft.com>
Upstream-commit: c848f9acb6
Component: cli
2017-08-15 10:20:15 -07:00
993 changed files with 33960 additions and 16335 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.helpers/

View File

@ -5,110 +5,50 @@ information on the list of deprecated flags and APIs please have a look at
https://docs.docker.com/engine/deprecated/ where target removal dates can also
be found.
## 17.09.1-ce (2017-12-07)
## 17.10.0-ce (2017-10-17)
IMPORTANT: Starting with this release, `docker service create`, `docker service update`,
`docker service scale` and `docker service rollback` use non-detached mode as default,
use `--detach` to keep the old behaviour.
### Builder
- Fix config leakage on shared parent stage [moby/moby#33753](https://github.com/moby/moby/issues/33753)
- Warn on empty continuation lines only, not on comment-only lines [moby/moby#35004](https://github.com/moby/moby/pull/35004)
* Reset uid/gid to 0 in uploaded build context to share build cache with other clients [docker/cli#513](https://github.com/docker/cli/pull/513)
+ Add support for `ADD` urls without any sub path [moby/moby#34217](https://github.com/moby/moby/pull/34217)
### Client
- Set API version on Client even when Ping fails [docker/cli#546](https://github.com/docker/cli/pull/546)
### Networking
- Overlay fix for transient IP reuse [docker/libnetwork#2016](https://github.com/docker/libnetwork/pull/2016)
- Fix reapTime logic in NetworkDB and handle DNS cleanup for attachable container [docker/libnetwork#2017](https://github.com/docker/libnetwork/pull/2017)
- Disable hostname lookup on chain exists check [docker/libnetwork#2019](https://github.com/docker/libnetwork/pull/2019)
- Fix lint issues [docker/libnetwork#2020](https://github.com/docker/libnetwork/pull/2020)
- Restore error type in FindNetwork [moby/moby#35634](https://github.com/moby/moby/pull/35634)
### Runtime
- Protect `health monitor` Go channel [moby/moby#35482](https://github.com/moby/moby/pull/35482)
- Fix test failure on stopped container [moby/moby#34730](https://github.com/moby/moby/pull/34730)
- Fix leaking container/exec state [moby/moby#35484](https://github.com/moby/moby/pull/35484)
- Add /proc/scsi to masked paths (patch to work around [CVE-2017-16539](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16539)) [moby/moby/#35399](https://github.com/moby/moby/pull/35399)
- Vendor tar-split: fix to prevent memory exhaustion issue that could crash Docker daemon [moby/moby/#35424](https://github.com/moby/moby/pull/35424) Fixes [CVE-2017-14992](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14992)
- Fix P/Z HubPullSuite tests [moby/moby#34837](https://github.com/moby/moby/pull/34837)
+ Windows: Add support for version filtering on pull [moby/moby#35090](https://github.com/moby/moby/pull/35090)
- Windows: Stop filtering Windows manifest lists by version [moby/moby#35117](https://github.com/moby/moby/pull/35117)
- Use rslave instead of rprivate in chroot archive [moby/moby/#35217](https://github.com/moby/moby/pull/35217)
- Remove container rootfs mountPath after unmount [moby/moby#34573](https://github.com/moby/moby/pull/34573)
- Fix honoring tmpfs size of user /dev/shm mount [moby/moby#35316](https://github.com/moby/moby/pull/35316)
- Don't abort when setting may_detach_mounts (log the error instead) [moby/moby#35172](https://github.com/moby/moby/pull/35172)
- Fix version comparison when negotiating the API version [moby/moby#35008](https://github.com/moby/moby/pull/35008)
### Swarm mode
* Increase gRPC request timeout when sending snapshots [docker/swarmkit#2404](https://github.com/docker/swarmkit/pull/2404)
- Fix node filtering when there is no log driver [docker/swarmkit#2442](https://github.com/docker/swarmkit/pull/2442)
- Add an error on attempt to change cluster name [docker/swarmkit/#2454](https://github.com/docker/swarmkit/pull/2454)
- Delete node attachments when node is removed [docker/swarmkit/#2456](https://github.com/docker/swarmkit/pull/2456)
- Provide custom gRPC dialer to override default proxy dialer [docker/swarmkit/#2457](https://github.com/docker/swarmkit/pull/2457)
- Avoids recursive readlock on swarm info [moby/moby#35388](https://github.com/moby/moby/pull/35388)
## 17.09.0-ce (2017-09-26)
### Builder
+ Add `--chown` flag to `ADD/COPY` commands in Dockerfile [moby/moby#34263](https://github.com/moby/moby/pull/34263)
* Fix cloning unneeded files while building from git repositories [moby/moby#33704](https://github.com/moby/moby/pull/33704)
### Client
* Allow extension fields in the v3.4 version of the compose format [docker/cli#452](https://github.com/docker/cli/pull/452)
* Make compose file allow to specify names for non-external volume [docker/cli#306](https://github.com/docker/cli/pull/306)
* Support `--compose-file -` as stdin [docker/cli#347](https://github.com/docker/cli/pull/347)
* Support `start_period` for healthcheck in Docker Compose [docker/cli#475](https://github.com/docker/cli/pull/475)
+ Add support for `stop-signal` in docker stack commands [docker/cli#388](https://github.com/docker/cli/pull/388)
+ Add support for update order in compose deployments [docker/cli#360](https://github.com/docker/cli/pull/360)
+ Add ulimits to unsupported compose fields [docker/cli#482](https://github.com/docker/cli/pull/482)
+ Add `--format` to `docker-search` [docker/cli#440](https://github.com/docker/cli/pull/440)
* Show images digests when `{{.Digest}}` is in format [docker/cli#439](https://github.com/docker/cli/pull/439)
* Print output of `docker stack rm` on `stdout` instead of `stderr` [docker/cli#491](https://github.com/docker/cli/pull/491)
- Fix `docker history --format '{{json .}}'` printing human-readable timestamps instead of ISO8601 when `--human=true` [docker/cli#438](https://github.com/docker/cli/pull/438)
- Fix idempotence of `docker stack deploy` when secrets or configs are used [docker/cli#509](https://github.com/docker/cli/pull/509)
- Fix presentation of random host ports [docker/cli#404](https://github.com/docker/cli/pull/404)
- Fix redundant service restarts when service created with multiple secrets [moby/moby#34746](https://github.com/moby/moby/issues/34746)
### Logging
- Fix Splunk logger not transmitting log data when tag is empty and raw-mode is used [moby/moby#34520](https://github.com/moby/moby/pull/34520)
* Move output of `docker stack rm` to stdout [docker/cli#491](https://github.com/docker/cli/pull/491)
* Use natural sort secrets and configs in cli [docker/cli#307](https://github.com/docker/cli/pull/307)
* Use non-detached mode as default for `docker service` commands [docker/cli#525](https://github.com/docker/cli/pull/525)
* Set APIVersion on the client, even when Ping fails [docker/cli#546](https://github.com/docker/cli/pull/546)
- Fix loader error with different build syntax in `docker stack deploy` [docker/cli#544](https://github.com/docker/cli/pull/544)
* Change the default output format for `docker container stats` to show `CONTAINER ID` and `NAME` [docker/cli#565](https://github.com/docker/cli/pull/565)
+ Add `--no-trunc` flag to `docker container stats` [docker/cli#565](https://github.com/docker/cli/pull/565)
+ Add experimental `docker trust`: `view`, `revoke`, `sign` subcommands [docker/cli#472](https://github.com/docker/cli/pull/472)
- Various doc and shell completion fixes [docker/cli#610](https://github.com/docker/cli/pull/610) [docker/cli#611](https://github.com/docker/cli/pull/611) [docker/cli#618](https://github.com/docker/cli/pull/618) [docker/cli#580](https://github.com/docker/cli/pull/580) [docker/cli#598](https://github.com/docker/cli/pull/698) [docker/cli#603](https://github.com/docker/cli/pull/603)
### Networking
+ Add the control plane MTU option in the daemon config [moby/moby#34103](https://github.com/moby/moby/pull/34103)
+ Add service virtual IP to sandbox's loopback address [docker/libnetwork#1877](https://github.com/docker/libnetwork/pull/1877)
* Enabling ILB/ELB on windows using per-node, per-network LB endpoint [moby/moby#34674](https://github.com/moby/moby/pull/34674)
* Overlay fix for transient IP reuse [docker/libnetwork#1935](https://github.com/docker/libnetwork/pull/1935)
* Serializing bitseq alloc [docker/libnetwork#1788](https://github.com/docker/libnetwork/pull/1788)
- Disable hostname lookup on chain exists check [docker/libnetwork#1974](https://github.com/docker/libnetwork/pull/1974)
### Runtime
* Graphdriver: promote overlay2 over aufs [moby/moby#34430](https://github.com/moby/moby/pull/34430)
* LCOW: Additional flags for VHD boot [moby/moby#34451](https://github.com/moby/moby/pull/34451)
* LCOW: Don't block export [moby/moby#34448](https://github.com/moby/moby/pull/34448)
* LCOW: Dynamic sandbox management [moby/moby#34170](https://github.com/moby/moby/pull/34170)
* LCOW: Force Hyper-V Isolation [moby/moby#34468](https://github.com/moby/moby/pull/34468)
* LCOW: Move toolsScratchPath to /tmp [moby/moby#34396](https://github.com/moby/moby/pull/34396)
* LCOW: Remove hard-coding [moby/moby#34398](https://github.com/moby/moby/pull/34398)
* LCOW: WORKDIR correct handling [moby/moby#34405](https://github.com/moby/moby/pull/34405)
* Windows: named pipe mounts [moby/moby#33852](https://github.com/moby/moby/pull/33852)
- Fix "permission denied" errors when accessing volume with SELinux enforcing mode [moby/moby#34684](https://github.com/moby/moby/pull/34684)
- Fix layers size reported as `0` in `docker system df` [moby/moby#34826](https://github.com/moby/moby/pull/34826)
- Fix some "device or resource busy" errors when removing containers on RHEL 7.4 based kernels [moby/moby#34886](https://github.com/moby/moby/pull/34886)
* LCOW: Add UVM debugability by grabbing logs before tear-down [moby/moby#34846](https://github.com/moby/moby/pull/34846)
* LCOW: Prepare work for bind mounts [moby/moby#34258](https://github.com/moby/moby/pull/34258)
* LCOW: Support for docker cp, ADD/COPY on build [moby/moby#34252](https://github.com/moby/moby/pull/34252)
* LCOW: VHDX boot to readonly [moby/moby#34754](https://github.com/moby/moby/pull/34754)
* Volume: evaluate symlinks before relabeling mount source [moby/moby#34792](https://github.com/moby/moby/pull/34792)
- Fixing docker cp to allow new target file name in a host symlinked directory [moby/moby#31993](https://github.com/moby/moby/pull/31993)
+ Add support for Windows version filtering on pull [moby/moby#35090](https://github.com/moby/moby/pull/35090)
### Swarm mode
* Include whether the managers in the swarm are autolocked as part of `docker info` [docker/cli#471](https://github.com/docker/cli/pull/471)
+ Add 'docker service rollback' subcommand [docker/cli#205](https://github.com/docker/cli/pull/205)
- Fix managers failing to join if the gRPC snapshot is larger than 4MB [docker/swarmkit#2375](https://github.com/docker/swarmkit/pull/2375)
- Fix "permission denied" errors for configuration file in SELinux-enabled containers [moby/moby#34732](https://github.com/moby/moby/pull/34732)
- Fix services failing to deploy on ARM nodes [moby/moby#34021](https://github.com/moby/moby/pull/34021)
### Packaging
+ Build scripts for ppc64el on Ubuntu [docker/docker-ce-packaging#43](https://github.com/docker/docker-ce-packaging/pull/43)
### Deprecation
+ Remove deprecated `--enable-api-cors` daemon flag [moby/moby#34821](https://github.com/moby/moby/pull/34821)
* Produce an error if `docker swarm init --force-new-cluster` is executed on worker nodes [moby/moby#34881](https://github.com/moby/moby/pull/34881)
+ Add support for `.Node.Hostname` templating in swarm services [moby/moby#34686](https://github.com/moby/moby/pull/34686)
* Increase gRPC request timeout to 20 seconds for sending snapshots [docker/swarmkit#2391](https://github.com/docker/swarmkit/pull/2391)
- Do not filter nodes if logdriver is set to `none` [docker/swarmkit#2396](https://github.com/docker/swarmkit/pull/2396)
+ Adding ipam options to ipam driver requests [docker/swarmkit#2324](https://github.com/docker/swarmkit/pull/2324)

View File

@ -1,27 +1,56 @@
CLI_DIR:=$(CURDIR)/components/cli
ENGINE_DIR:=$(CURDIR)/components/engine
PACKAGING_DIR:=$(CURDIR)/components/packaging
MOBY_COMPONENTS_SHA=f79265f1412af0a68aadd11e1d2f374446f3681b
MOBY_COMPONENTS_URL=https://raw.githubusercontent.com/shykes/moby-extras/$(MOBY_COMPONENTS_SHA)/cmd/moby-components
MOBY_COMPONENTS=.helpers/moby-components-$(MOBY_COMPONENTS_SHA)
VERSION=$(shell cat VERSION)
.PHONY: help
help: ## show make targets
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.PHONY: test-integration-cli
test-integration-cli: $(CLI_DIR)/build/docker ## test integration of cli and engine
$(MAKE) -C $(ENGINE_DIR) DOCKER_CLI_PATH=$< test-integration-cli
$(CLI_DIR)/build/docker:
$(MAKE) -C $(CLI_DIR) -f docker.Makefile build
.PHONY: deb
deb: ## build deb packages
$(MAKE) VERSION=$(VERSION) CLI_DIR=$(CLI_DIR) ENGINE_DIR=$(ENGINE_DIR) -C $(PACKAGING_DIR) deb
.PHONY: rpm
rpm: ## build rpm packages
$(MAKE) VERSION=$(VERSION) CLI_DIR=$(CLI_DIR) ENGINE_DIR=$(ENGINE_DIR) -C $(PACKAGING_DIR) rpm
.PHONY: static
static: ## build static packages
$(MAKE) VERSION=$(VERSION) CLI_DIR=$(CLI_DIR) ENGINE_DIR=$(ENGINE_DIR) -C $(PACKAGING_DIR) static
.PHONY: clean
clean: ## clean the build artifacts
-$(MAKE) -C $(CLI_DIR) clean
-$(MAKE) -C $(ENGINE_DIR) clean
-$(MAKE) -C $(PACKAGING_DIR) clean
$(MOBY_COMPONENTS):
mkdir -p .helpers
curl -fsSL $(MOBY_COMPONENTS_URL) > $(MOBY_COMPONENTS)
chmod +x $(MOBY_COMPONENTS)
.PHONY: update-components
update-components: update-components-cli update-components-engine update-components-packaging ## udpate components using moby extra tool
.PHONY: update-components-cli
update-components-cli: $(MOBY_COMPONENTS)
$(MOBY_COMPONENTS) update cli
.PHONY: update-components-engine
update-components-engine: $(MOBY_COMPONENTS)
$(MOBY_COMPONENTS) update engine
.PHONY: update-components-packaging
update-components-packaging: $(MOBY_COMPONENTS)
$(MOBY_COMPONENTS) update packaging

View File

@ -1 +1 @@
17.09.1-ce
17.10.0-ce

View File

@ -27,6 +27,7 @@
people = [
"aaronlehmann",
"albers",
"aluzzardi",
"anusha",
"cpuguy83",
@ -84,6 +85,11 @@
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.albers]
Name = "Harald Albers"
Email = "github@albersweb.de"
GitHub = "albers"
[people.aluzzardi]
Name = "Andrea Luzzardi"
Email = "al@docker.com"

View File

@ -34,6 +34,14 @@ binary: ## build executable for Linux
cross: ## build executable for macOS and Windows
./scripts/build/cross
.PHONY: binary-windows
binary-windows: ## build executable for Windows
./scripts/build/windows
.PHONY: binary-osx
binary-osx: ## build executable for macOS
./scripts/build/osx
.PHONY: dynbinary
dynbinary: ## build dynamically linked binary
./scripts/build/dynbinary

View File

@ -1,4 +1,4 @@
[![build status](https://circleci.com/gh/docker/cli.svg?style=shield)](https://circleci.com/gh/docker/cli/tree/master)
[![build status](https://circleci.com/gh/docker/cli.svg?style=shield)](https://circleci.com/gh/docker/cli/tree/master) [![Build Status](https://jenkins.dockerproject.org/job/docker/job/cli/job/master/badge/icon)](https://jenkins.dockerproject.org/job/docker/job/cli/job/master/)
docker/cli
==========

View File

@ -1 +1 @@
17.09.1-ce
17.10.0-ce

View File

@ -12,12 +12,14 @@ import (
cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/trust"
dopts "github.com/docker/cli/opts"
"github.com/docker/docker/api"
"github.com/docker/docker/client"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/docker/notary"
notaryclient "github.com/docker/notary/client"
"github.com/docker/notary/passphrase"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@ -40,6 +42,7 @@ type Cli interface {
SetIn(in *InStream)
ConfigFile() *configfile.ConfigFile
ServerInfo() ServerInfo
NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
}
// DockerCli is an instance the docker command line client.
@ -161,6 +164,11 @@ func getClientWithPassword(passRetriever notary.PassRetriever, newClient func(pa
}
}
// NotaryClient provides a Notary Repository to interact with signed metadata for an image
func (cli *DockerCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
return trust.GetNotaryRepository(cli.In(), cli.Out(), UserAgent(), imgRefAndAuth.RepoInfo(), imgRefAndAuth.AuthConfig(), actions...)
}
// ServerInfo stores details about the supported features and platform of the
// server
type ServerInfo struct {

View File

@ -17,6 +17,7 @@ import (
"github.com/docker/cli/cli/command/stack"
"github.com/docker/cli/cli/command/swarm"
"github.com/docker/cli/cli/command/system"
"github.com/docker/cli/cli/command/trust"
"github.com/docker/cli/cli/command/volume"
"github.com/spf13/cobra"
)
@ -69,6 +70,9 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) {
// swarm
swarm.NewSwarmCommand(dockerCli),
// trust
trust.NewTrustCommand(dockerCli),
// volume
volume.NewVolumeCommand(dockerCli),

View File

@ -1,15 +1,27 @@
package config
import (
"sort"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"vbom.ml/util/sortorder"
)
type byConfigName []swarm.Config
func (r byConfigName) Len() int { return len(r) }
func (r byConfigName) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r byConfigName) Less(i, j int) bool {
return sortorder.NaturalLess(r[i].Spec.Name, r[j].Spec.Name)
}
type listOptions struct {
quiet bool
format string
@ -55,6 +67,8 @@ func runConfigList(dockerCli command.Cli, options listOptions) error {
}
}
sort.Sort(byConfigName(configs))
configCtx := formatter.Context{
Output: dockerCli.Out(),
Format: formatter.NewConfigFormat(format, options.quiet),

View File

@ -50,14 +50,20 @@ func TestConfigList(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) {
return []swarm.Config{
*Config(ConfigID("ID-foo"),
ConfigName("foo"),
*Config(ConfigID("ID-1-foo"),
ConfigName("1-foo"),
ConfigVersion(swarm.Version{Index: 10}),
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
),
*Config(ConfigID("ID-bar"),
ConfigName("bar"),
*Config(ConfigID("ID-10-foo"),
ConfigName("10-foo"),
ConfigVersion(swarm.Version{Index: 11}),
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
),
*Config(ConfigID("ID-2-foo"),
ConfigName("2-foo"),
ConfigVersion(swarm.Version{Index: 11}),
ConfigCreatedAt(time.Now().Add(-2*time.Hour)),
ConfigUpdatedAt(time.Now().Add(-1*time.Hour)),
@ -66,9 +72,8 @@ func TestConfigList(t *testing.T) {
},
})
cmd := newConfigListCommand(cli)
cmd.SetOutput(cli.OutBuffer())
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "config-list.golden")
golden.Assert(t, cli.OutBuffer().String(), "config-list-sort.golden")
}
func TestConfigListWithQuietOption(t *testing.T) {

View File

@ -0,0 +1,4 @@
ID NAME CREATED UPDATED
ID-1-foo 1-foo 2 hours ago About an hour ago
ID-2-foo 2-foo 2 hours ago About an hour ago
ID-10-foo 10-foo 2 hours ago About an hour ago

View File

@ -1,2 +1,2 @@
foo
bar label=label-bar
foo

View File

@ -1,3 +1,3 @@
ID NAME CREATED UPDATED
ID-foo foo 2 hours ago About an hour ago
ID-bar bar 2 hours ago About an hour ago
ID-foo foo 2 hours ago About an hour ago

View File

@ -1,2 +1,2 @@
foo
bar label=label-bar
foo

View File

@ -1,2 +1,2 @@
ID-foo
ID-bar
ID-foo

View File

@ -1,3 +0,0 @@
ID NAME CREATED UPDATED
ID-foo foo 2 hours ago About an hour ago
ID-bar bar 2 hours ago About an hour ago

View File

@ -113,7 +113,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
return
}
return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
return archive.PreserveTrailingDotOrSeparator(absPath, localPath, filepath.Separator), nil
}
func copyFromContainer(ctx context.Context, dockerCli *command.DockerCli, srcContainer, srcPath, dstPath string, cpParam *cpConfig) (err error) {

View File

@ -10,7 +10,6 @@ import (
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
apiclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/promise"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@ -106,7 +105,6 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *typ
var (
out, stderr io.Writer
in io.ReadCloser
errCh chan error
)
if execConfig.AttachStdin {
@ -129,19 +127,25 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *typ
return err
}
defer resp.Close()
errCh = promise.Go(func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: out,
errorStream: stderr,
resp: resp,
tty: execConfig.Tty,
detachKeys: execConfig.DetachKeys,
}
return streamer.stream(ctx)
})
errCh := make(chan error, 1)
go func() {
defer close(errCh)
errCh <- func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: out,
errorStream: stderr,
resp: resp,
tty: execConfig.Tty,
detachKeys: execConfig.DetachKeys,
}
return streamer.stream(ctx)
}()
}()
if execConfig.Tty && dockerCli.In().IsTerminal() {
if err := MonitorTtySize(ctx, dockerCli, execID, true); err != nil {

View File

@ -185,6 +185,7 @@ func setRawTerminal(streams command.Streams) error {
return streams.Out().SetRawTerminal()
}
// nolint: unparam
func restoreTerminal(streams command.Streams, in io.Closer) error {
streams.In().RestoreTerminal()
streams.Out().RestoreTerminal()

View File

@ -43,6 +43,7 @@ func TestValidateAttach(t *testing.T) {
}
}
// nolint: unparam
func parseRun(args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) {
flags := pflag.NewFlagSet("run", pflag.ContinueOnError)
flags.SetOutput(ioutil.Discard)

View File

@ -15,7 +15,6 @@ import (
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/term"
"github.com/pkg/errors"
@ -291,22 +290,27 @@ func attachContainer(
return nil, errAttach
}
*errCh = promise.Go(func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: out,
errorStream: cerr,
resp: resp,
tty: config.Tty,
detachKeys: options.DetachKeys,
}
ch := make(chan error, 1)
*errCh = ch
if errHijack := streamer.stream(ctx); errHijack != nil {
return errHijack
}
return errAttach
})
go func() {
ch <- func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: out,
errorStream: cerr,
resp: resp,
tty: config.Tty,
detachKeys: options.DetachKeys,
}
if errHijack := streamer.stream(ctx); errHijack != nil {
return errHijack
}
return errAttach
}()
}()
return resp.Close, nil
}

View File

@ -9,7 +9,6 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/term"
"github.com/pkg/errors"
@ -103,23 +102,28 @@ func runStart(dockerCli *command.DockerCli, opts *startOptions) error {
return errAttach
}
defer resp.Close()
cErr := promise.Go(func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: dockerCli.Out(),
errorStream: dockerCli.Err(),
resp: resp,
tty: c.Config.Tty,
detachKeys: options.DetachKeys,
}
errHijack := streamer.stream(ctx)
if errHijack == nil {
return errAttach
}
return errHijack
})
cErr := make(chan error, 1)
go func() {
cErr <- func() error {
streamer := hijackedIOStreamer{
streams: dockerCli,
inputStream: in,
outputStream: dockerCli.Out(),
errorStream: dockerCli.Err(),
resp: resp,
tty: c.Config.Tty,
detachKeys: options.DetachKeys,
}
errHijack := streamer.stream(ctx)
if errHijack == nil {
return errAttach
}
return errHijack
}()
}()
// 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.

View File

@ -21,6 +21,7 @@ import (
type statsOptions struct {
all bool
noStream bool
noTrunc bool
format string
containers []string
}
@ -42,6 +43,7 @@ func NewStatsCommand(dockerCli *command.DockerCli) *cobra.Command {
flags := cmd.Flags()
flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)")
flags.BoolVar(&opts.noStream, "no-stream", false, "Disable streaming stats and only pull the first result")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output")
flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template")
return cmd
}
@ -214,7 +216,7 @@ func runStats(dockerCli *command.DockerCli, opts *statsOptions) error {
ccstats = append(ccstats, c.GetStatistics())
}
cStats.mu.Unlock()
if err = formatter.ContainerStatsWrite(statsCtx, ccstats, daemonOSType); err != nil {
if err = formatter.ContainerStatsWrite(statsCtx, ccstats, daemonOSType, !opts.noTrunc); err != nil {
break
}
if len(cStats.cs) == 0 && !showAll {

View File

@ -10,6 +10,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -230,10 +231,7 @@ size: 0B
// Special headers for customized table format
{
Context{Format: NewContainerFormat(`table {{truncate .ID 5}}\t{{json .Image}} {{.RunningFor}}/{{title .Status}}/{{pad .Ports 2 2}}.{{upper .Names}} {{lower .Status}}`, false, true)},
`CONTAINER ID IMAGE CREATED/STATUS/ PORTS .NAMES STATUS
conta "ubuntu" 24 hours ago//.FOOBAR_BAZ
conta "ubuntu" 24 hours ago//.FOOBAR_BAR
`,
string(golden.Get(t, "container-context-write-special-headers.golden")),
},
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"testing"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
@ -83,12 +84,7 @@ Build Cache 0B
Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}"),
},
},
`TYPE ACTIVE
Images 0
Containers 0
Local Volumes 0
Build Cache
`,
string(golden.Get(t, "disk-usage-context-write-custom.golden")),
},
// Raw Format
{
@ -97,31 +93,7 @@ Build Cache
Format: NewDiskUsageFormat("raw"),
},
},
`type: Images
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Containers
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Local Volumes
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Build Cache
total:
active:
size: 0B
reclaimable: 0B
`,
string(golden.Get(t, "disk-usage-raw-format.golden")),
},
}

View File

@ -8,6 +8,7 @@ import (
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/stringutils"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
@ -120,10 +121,7 @@ func TestSearchContextWrite(t *testing.T) {
// Table format
{
Context{Format: NewSearchFormat("table")},
`NAME DESCRIPTION STARS OFFICIAL AUTOMATED
result1 Official build 5000 [OK]
result2 Not official 5 [OK]
`,
string(golden.Get(t, "search-context-write-table.golden")),
},
{
Context{Format: NewSearchFormat("table {{.Name}}")},
@ -210,9 +208,7 @@ func TestSearchContextWriteStars(t *testing.T) {
// Table format
{
Context{Format: NewSearchFormat("table")},
`NAME DESCRIPTION STARS OFFICIAL AUTOMATED
result1 Official build 5000 [OK]
`,
string(golden.Get(t, "search-context-write-stars-table.golden")),
},
{
Context{Format: NewSearchFormat("table {{.Name}}")},

View File

@ -12,19 +12,20 @@ import (
)
const (
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.CreatedAt}}\t{{.UpdatedAt}}"
defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}"
secretIDHeader = "ID"
secretCreatedHeader = "CREATED"
secretUpdatedHeader = "UPDATED"
secretInspectPrettyTemplate Format = `ID: {{.ID}}
Name: {{.Name}}
secretInspectPrettyTemplate Format = `ID: {{.ID}}
Name: {{.Name}}
{{- if .Labels }}
Labels:
{{- range $k, $v := .Labels }}
- {{ $k }}{{if $v }}={{ $v }}{{ end }}
{{- end }}{{ end }}
Created at: {{.CreatedAt}}
Updated at: {{.UpdatedAt}}`
Driver: {{.Driver}}
Created at: {{.CreatedAt}}
Updated at: {{.UpdatedAt}}`
)
// NewSecretFormat returns a Format for rendering using a secret Context
@ -61,6 +62,7 @@ func newSecretContext() *secretContext {
sCtx.header = map[string]string{
"ID": secretIDHeader,
"Name": nameHeader,
"Driver": driverHeader,
"CreatedAt": secretCreatedHeader,
"UpdatedAt": secretUpdatedHeader,
"Labels": labelsHeader,
@ -89,6 +91,13 @@ func (c *secretContext) CreatedAt() string {
return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.CreatedAt)) + " ago"
}
func (c *secretContext) Driver() string {
if c.s.Spec.Driver == nil {
return ""
}
return c.s.Spec.Driver.Name
}
func (c *secretContext) UpdatedAt() string {
return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.UpdatedAt)) + " ago"
}
@ -153,6 +162,13 @@ func (ctx *secretInspectContext) Labels() map[string]string {
return ctx.Secret.Spec.Labels
}
func (ctx *secretInspectContext) Driver() string {
if ctx.Secret.Spec.Driver == nil {
return ""
}
return ctx.Secret.Spec.Driver.Name
}
func (ctx *secretInspectContext) CreatedAt() string {
return command.PrettyPrint(ctx.Secret.CreatedAt)
}

View File

@ -28,9 +28,9 @@ func TestSecretContextFormatWrite(t *testing.T) {
},
// Table format
{Context{Format: NewSecretFormat("table", false)},
`ID NAME CREATED UPDATED
1 passwords Less than a second ago Less than a second ago
2 id_rsa Less than a second ago Less than a second ago
`ID NAME DRIVER CREATED UPDATED
1 passwords Less than a second ago Less than a second ago
2 id_rsa Less than a second ago Less than a second ago
`},
{Context{Format: NewSecretFormat("table {{.Name}}", true)},
`NAME

View File

@ -8,6 +8,7 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -59,21 +60,7 @@ bar
// Raw Format
{
Context{Format: NewServiceListFormat("raw", false)},
`id: id_baz
name: baz
mode: global
replicas: 2/4
image:
ports: *:80->8080/tcp
id: id_bar
name: bar
mode: replicated
replicas: 2/4
image:
ports: *:80->8080/tcp
`,
string(golden.Get(t, "service-context-write-raw.golden")),
},
{
Context{Format: NewServiceListFormat("raw", true)},

View File

@ -4,13 +4,14 @@ import (
"fmt"
"sync"
"github.com/docker/docker/pkg/stringid"
units "github.com/docker/go-units"
)
const (
winOSType = "windows"
defaultStatsTableFormat = "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
winDefaultStatsTableFormat = "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
defaultStatsTableFormat = "table {{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
winDefaultStatsTableFormat = "table {{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
containerHeader = "CONTAINER"
cpuPercHeader = "CPU %"
@ -114,12 +115,13 @@ func NewContainerStats(container string) *ContainerStats {
}
// ContainerStatsWrite renders the context for a list of containers statistics
func ContainerStatsWrite(ctx Context, containerStats []StatsEntry, osType string) error {
func ContainerStatsWrite(ctx Context, containerStats []StatsEntry, osType string, trunc bool) error {
render := func(format func(subContext subContext) error) error {
for _, cstats := range containerStats {
containerStatsCtx := &containerStatsContext{
s: cstats,
os: osType,
s: cstats,
os: osType,
trunc: trunc,
}
if err := format(containerStatsCtx); err != nil {
return err
@ -149,8 +151,9 @@ func ContainerStatsWrite(ctx Context, containerStats []StatsEntry, osType string
type containerStatsContext struct {
HeaderContext
s StatsEntry
os string
s StatsEntry
os string
trunc bool
}
func (c *containerStatsContext) MarshalJSON() ([]byte, error) {
@ -169,6 +172,9 @@ func (c *containerStatsContext) Name() string {
}
func (c *containerStatsContext) ID() string {
if c.trunc {
return stringid.TruncateID(c.s.ID)
}
return c.s.ID
}

View File

@ -114,7 +114,7 @@ container2 --
}
var out bytes.Buffer
te.context.Output = &out
err := ContainerStatsWrite(te.context, stats, "linux")
err := ContainerStatsWrite(te.context, stats, "linux", false)
if err != nil {
assert.EqualError(t, err, te.expected)
} else {
@ -180,7 +180,7 @@ container2 -- --
}
var out bytes.Buffer
te.context.Output = &out
err := ContainerStatsWrite(te.context, stats, "windows")
err := ContainerStatsWrite(te.context, stats, "windows", false)
if err != nil {
assert.EqualError(t, err, te.expected)
} else {
@ -220,7 +220,7 @@ func TestContainerStatsContextWriteWithNoStats(t *testing.T) {
}
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{}, "linux")
ContainerStatsWrite(context.context, []StatsEntry{}, "linux", false)
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
@ -258,7 +258,41 @@ func TestContainerStatsContextWriteWithNoStatsWindows(t *testing.T) {
}
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{}, "windows")
ContainerStatsWrite(context.context, []StatsEntry{}, "windows", false)
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()
}
}
func TestContainerStatsContextWriteTrunc(t *testing.T) {
var out bytes.Buffer
contexts := []struct {
context Context
trunc bool
expected string
}{
{
Context{
Format: "{{.ID}}",
Output: &out,
},
false,
"b95a83497c9161c9b444e3d70e1a9dfba0c1840d41720e146a95a08ebf938afc\n",
},
{
Context{
Format: "{{.ID}}",
Output: &out,
},
true,
"b95a83497c91\n",
},
}
for _, context := range contexts {
ContainerStatsWrite(context.context, []StatsEntry{{ID: "b95a83497c9161c9b444e3d70e1a9dfba0c1840d41720e146a95a08ebf938afc"}}, "linux", context.trunc)
assert.Equal(t, context.expected, out.String())
// Clean buffer
out.Reset()

View File

@ -7,6 +7,7 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
@ -33,10 +34,7 @@ taskID2
},
{
Context{Format: NewTaskFormat("table {{.Name}}\t{{.Node}}\t{{.Ports}}", false)},
`NAME NODE PORTS
foobar_baz foo1
foobar_bar foo2
`,
string(golden.Get(t, "task-context-write-table-custom.golden")),
},
{
Context{Format: NewTaskFormat("table {{.Name}}", true)},

View File

@ -0,0 +1,3 @@
CONTAINER ID IMAGE CREATED/STATUS/ PORTS .NAMES STATUS
conta "ubuntu" 24 hours ago//.FOOBAR_BAZ
conta "ubuntu" 24 hours ago//.FOOBAR_BAR

View File

@ -0,0 +1,5 @@
TYPE ACTIVE
Images 0
Containers 0
Local Volumes 0
Build Cache

View File

@ -0,0 +1,24 @@
type: Images
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Containers
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Local Volumes
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Build Cache
total:
active:
size: 0B
reclaimable: 0B

View File

@ -0,0 +1,2 @@
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
result1 Official build 5000 [OK]

View File

@ -0,0 +1,3 @@
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
result1 Official build 5000 [OK]
result2 Not official 5 [OK]

View File

@ -0,0 +1,14 @@
id: id_baz
name: baz
mode: global
replicas: 2/4
image:
ports: *:80->8080/tcp
id: id_bar
name: bar
mode: replicated
replicas: 2/4
image:
ports: *:80->8080/tcp

View File

@ -0,0 +1,3 @@
NAME NODE PORTS
foobar_baz foo1
foobar_bar foo2

View File

@ -0,0 +1,150 @@
package formatter
import (
"sort"
"strings"
"github.com/docker/docker/pkg/stringid"
)
const (
defaultTrustTagTableFormat = "table {{.SignedTag}}\t{{.Digest}}\t{{.Signers}}"
signedTagNameHeader = "SIGNED TAG"
trustedDigestHeader = "DIGEST"
signersHeader = "SIGNERS"
defaultSignerInfoTableFormat = "table {{.Signer}}\t{{.Keys}}"
signerNameHeader = "SIGNER"
keysHeader = "KEYS"
)
// SignedTagInfo represents all formatted information needed to describe a signed tag:
// Name: name of the signed tag
// Digest: hex encoded digest of the contents
// Signers: list of entities who signed the tag
type SignedTagInfo struct {
Name string
Digest string
Signers []string
}
// SignerInfo represents all formatted information needed to describe a signer:
// Name: name of the signer role
// Keys: the keys associated with the signer
type SignerInfo struct {
Name string
Keys []string
}
// NewTrustTagFormat returns a Format for rendering using a trusted tag Context
func NewTrustTagFormat() Format {
return defaultTrustTagTableFormat
}
// NewSignerInfoFormat returns a Format for rendering a signer role info Context
func NewSignerInfoFormat() Format {
return defaultSignerInfoTableFormat
}
// TrustTagWrite writes the context
func TrustTagWrite(ctx Context, signedTagInfoList []SignedTagInfo) error {
render := func(format func(subContext subContext) error) error {
for _, signedTag := range signedTagInfoList {
if err := format(&trustTagContext{s: signedTag}); err != nil {
return err
}
}
return nil
}
trustTagCtx := trustTagContext{}
trustTagCtx.header = trustTagHeaderContext{
"SignedTag": signedTagNameHeader,
"Digest": trustedDigestHeader,
"Signers": signersHeader,
}
return ctx.Write(&trustTagCtx, render)
}
type trustTagHeaderContext map[string]string
type trustTagContext struct {
HeaderContext
s SignedTagInfo
}
// SignedTag returns the name of the signed tag
func (c *trustTagContext) SignedTag() string {
return c.s.Name
}
// Digest returns the hex encoded digest associated with this signed tag
func (c *trustTagContext) Digest() string {
return c.s.Digest
}
// Signers returns the sorted list of entities who signed this tag
func (c *trustTagContext) Signers() string {
sort.Strings(c.s.Signers)
return strings.Join(c.s.Signers, ", ")
}
// SignerInfoWrite writes the context
func SignerInfoWrite(ctx Context, signerInfoList []SignerInfo) error {
render := func(format func(subContext subContext) error) error {
for _, signerInfo := range signerInfoList {
if err := format(&signerInfoContext{
trunc: ctx.Trunc,
s: signerInfo,
}); err != nil {
return err
}
}
return nil
}
signerInfoCtx := signerInfoContext{}
signerInfoCtx.header = signerInfoHeaderContext{
"Signer": signerNameHeader,
"Keys": keysHeader,
}
return ctx.Write(&signerInfoCtx, render)
}
type signerInfoHeaderContext map[string]string
type signerInfoContext struct {
HeaderContext
trunc bool
s SignerInfo
}
// Keys returns the sorted list of keys associated with the signer
func (c *signerInfoContext) Keys() string {
sort.Strings(c.s.Keys)
truncatedKeys := []string{}
if c.trunc {
for _, keyID := range c.s.Keys {
truncatedKeys = append(truncatedKeys, stringid.TruncateID(keyID))
}
return strings.Join(truncatedKeys, ", ")
}
return strings.Join(c.s.Keys, ", ")
}
// Signer returns the name of the signer
func (c *signerInfoContext) Signer() string {
return c.s.Name
}
// SignerInfoList helps sort []SignerInfo by signer names
type SignerInfoList []SignerInfo
func (signerInfoComp SignerInfoList) Len() int {
return len(signerInfoComp)
}
func (signerInfoComp SignerInfoList) Less(i, j int) bool {
return signerInfoComp[i].Name < signerInfoComp[j].Name
}
func (signerInfoComp SignerInfoList) Swap(i, j int) {
signerInfoComp[i], signerInfoComp[j] = signerInfoComp[j], signerInfoComp[i]
}

View File

@ -0,0 +1,238 @@
package formatter
import (
"bytes"
"testing"
"github.com/docker/docker/pkg/stringid"
"github.com/stretchr/testify/assert"
)
func TestTrustTag(t *testing.T) {
digest := stringid.GenerateRandomID()
trustedTag := "tag"
var ctx trustTagContext
cases := []struct {
trustTagCtx trustTagContext
expValue string
call func() string
}{
{
trustTagContext{
s: SignedTagInfo{Name: trustedTag,
Digest: digest,
Signers: nil,
},
},
digest,
ctx.Digest,
},
{
trustTagContext{
s: SignedTagInfo{Name: trustedTag,
Digest: digest,
Signers: nil,
},
},
trustedTag,
ctx.SignedTag,
},
// Empty signers makes a row with empty string
{
trustTagContext{
s: SignedTagInfo{Name: trustedTag,
Digest: digest,
Signers: nil,
},
},
"",
ctx.Signers,
},
{
trustTagContext{
s: SignedTagInfo{Name: trustedTag,
Digest: digest,
Signers: []string{"alice", "bob", "claire"},
},
},
"alice, bob, claire",
ctx.Signers,
},
// alphabetic signing on Signers
{
trustTagContext{
s: SignedTagInfo{Name: trustedTag,
Digest: digest,
Signers: []string{"claire", "bob", "alice"},
},
},
"alice, bob, claire",
ctx.Signers,
},
}
for _, c := range cases {
ctx = c.trustTagCtx
v := c.call()
if v != c.expValue {
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
}
}
}
func TestTrustTagContextWrite(t *testing.T) {
cases := []struct {
context Context
expected string
}{
// Errors
{
Context{
Format: "{{InvalidFunction}}",
},
`Template parsing error: template: :1: function "InvalidFunction" not defined
`,
},
{
Context{
Format: "{{nil}}",
},
`Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
`,
},
// Table Format
{
Context{
Format: NewTrustTagFormat(),
},
`SIGNED TAG DIGEST SIGNERS
tag1 deadbeef alice
tag2 aaaaaaaa alice, bob
tag3 bbbbbbbb
`,
},
}
for _, testcase := range cases {
signedTags := []SignedTagInfo{
{Name: "tag1", Digest: "deadbeef", Signers: []string{"alice"}},
{Name: "tag2", Digest: "aaaaaaaa", Signers: []string{"alice", "bob"}},
{Name: "tag3", Digest: "bbbbbbbb", Signers: []string{}},
}
out := bytes.NewBufferString("")
testcase.context.Output = out
err := TrustTagWrite(testcase.context, signedTags)
if err != nil {
assert.EqualError(t, err, testcase.expected)
} else {
assert.Equal(t, testcase.expected, out.String())
}
}
}
// With no trust data, the TrustTagWrite will print an empty table:
// it's up to the caller to decide whether or not to print this versus an error
func TestTrustTagContextEmptyWrite(t *testing.T) {
emptyCase := struct {
context Context
expected string
}{
Context{
Format: NewTrustTagFormat(),
},
`SIGNED TAG DIGEST SIGNERS
`,
}
emptySignedTags := []SignedTagInfo{}
out := bytes.NewBufferString("")
emptyCase.context.Output = out
err := TrustTagWrite(emptyCase.context, emptySignedTags)
assert.NoError(t, err)
assert.Equal(t, emptyCase.expected, out.String())
}
func TestSignerInfoContextEmptyWrite(t *testing.T) {
emptyCase := struct {
context Context
expected string
}{
Context{
Format: NewSignerInfoFormat(),
},
`SIGNER KEYS
`,
}
emptySignerInfo := []SignerInfo{}
out := bytes.NewBufferString("")
emptyCase.context.Output = out
err := SignerInfoWrite(emptyCase.context, emptySignerInfo)
assert.NoError(t, err)
assert.Equal(t, emptyCase.expected, out.String())
}
func TestSignerInfoContextWrite(t *testing.T) {
cases := []struct {
context Context
expected string
}{
// Errors
{
Context{
Format: "{{InvalidFunction}}",
},
`Template parsing error: template: :1: function "InvalidFunction" not defined
`,
},
{
Context{
Format: "{{nil}}",
},
`Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
`,
},
// Table Format
{
Context{
Format: NewSignerInfoFormat(),
Trunc: true,
},
`SIGNER KEYS
alice key11, key12
bob key21
eve foobarbazqux, key31, key32
`,
},
// No truncation
{
Context{
Format: NewSignerInfoFormat(),
},
`SIGNER KEYS
alice key11, key12
bob key21
eve foobarbazquxquux, key31, key32
`,
},
}
for _, testcase := range cases {
signerInfo := SignerInfoList{
{Name: "alice", Keys: []string{"key11", "key12"}},
{Name: "bob", Keys: []string{"key21"}},
{Name: "eve", Keys: []string{"key31", "key32", "foobarbazquxquux"}},
}
out := bytes.NewBufferString("")
testcase.context.Output = out
err := SignerInfoWrite(testcase.context, signerInfo)
if err != nil {
assert.EqualError(t, err, testcase.expected)
} else {
assert.Equal(t, testcase.expected, out.String())
}
}
}

View File

@ -21,6 +21,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
@ -243,6 +244,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, options.dockerfileFromStdin())
buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
ExcludePatterns: excludes,
ChownOpts: &idtools.IDPair{UID: 0, GID: 0},
})
if err != nil {
return err
@ -376,13 +378,13 @@ func runBuild(dockerCli command.Cli, options buildOptions) error {
if s != nil {
go func() {
logrus.Debugf("running session: %v", s.UUID())
logrus.Debugf("running session: %v", s.ID())
if err := s.Run(ctx, dockerCli.Client().DialSession); err != nil {
logrus.Error(err)
cancel() // cancel progress context
}
}()
buildOptions.SessionID = s.UUID()
buildOptions.SessionID = s.ID()
}
response, err := dockerCli.Client().ImageBuild(ctx, body, buildOptions)

View File

@ -53,7 +53,9 @@ func addDirToSession(session *session.Session, contextDir string, progressOutput
p := &sizeProgress{out: progressOutput, action: "Streaming build context to Docker daemon"}
workdirProvider := filesync.NewFSSyncProvider(contextDir, excludes)
workdirProvider := filesync.NewFSSyncProvider([]filesync.SyncedDir{
{Dir: contextDir, Excludes: excludes},
})
session.Allow(workdirProvider)
// this will be replaced on parallel build jobs. keep the current

View File

@ -6,18 +6,57 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sort"
"syscall"
"testing"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
"github.com/gotestyourself/gotestyourself/fs"
"github.com/gotestyourself/gotestyourself/skip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/context"
)
func TestRunBuildResetsUidAndGidInContext(t *testing.T) {
skip.IfCondition(t, runtime.GOOS == "windows", "uid and gid not relevant on windows")
dest := fs.NewDir(t, "test-build-context-dest")
defer dest.Remove()
fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
assert.NoError(t, archive.Untar(context, dest.Path(), nil))
body := new(bytes.Buffer)
return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil
}
cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild})
dir := fs.NewDir(t, "test-build-context",
fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)),
fs.WithFile("Dockerfile", `
FROM alpine:3.6
COPY foo bar /
`),
)
defer dir.Remove()
options := newBuildOptions()
options.context = dir.Path()
err := runBuild(cli, options)
require.NoError(t, err)
files, err := ioutil.ReadDir(dest.Path())
require.NoError(t, err)
for _, fileInfo := range files {
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid)
assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid)
}
}
func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
dest, err := ioutil.TempDir("", "test-build-compress-dest")
require.NoError(t, err)

View File

@ -6,8 +6,8 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/trust"
"github.com/docker/distribution/reference"
"github.com/docker/docker/registry"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/net/context"
@ -40,39 +40,32 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
return cmd
}
func runPull(dockerCli command.Cli, opts pullOptions) error {
func runPull(cli command.Cli, opts pullOptions) error {
distributionRef, err := reference.ParseNormalizedNamed(opts.remote)
if err != nil {
switch {
case err != nil:
return err
}
if opts.all && !reference.IsNameOnly(distributionRef) {
case opts.all && !reference.IsNameOnly(distributionRef):
return errors.New("tag can't be used with --all-tags/-a")
}
if !opts.all && reference.IsNameOnly(distributionRef) {
case !opts.all && reference.IsNameOnly(distributionRef):
distributionRef = reference.TagNameOnly(distributionRef)
if tagged, ok := distributionRef.(reference.Tagged); ok {
fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag())
fmt.Fprintf(cli.Out(), "Using default tag: %s\n", tagged.Tag())
}
}
// Resolve the Repository name from fqn to RepositoryInfo
repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), distributionRef.String())
if err != nil {
return err
}
ctx := context.Background()
authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "pull")
// Check if reference has a digest
_, isCanonical := distributionRef.(reference.Canonical)
if command.IsTrusted() && !isCanonical {
err = trustedPull(ctx, dockerCli, repoInfo, distributionRef, authConfig, requestPrivilege)
err = trustedPull(ctx, cli, imgRefAndAuth)
} else {
err = imagePullPrivileged(ctx, dockerCli, authConfig, reference.FamiliarString(distributionRef), requestPrivilege, opts.all)
err = imagePullPrivileged(ctx, cli, imgRefAndAuth, opts.all)
}
if err != nil {
if strings.Contains(err.Error(), "when fetching 'plugin'") {
@ -80,6 +73,5 @@ func runPull(dockerCli command.Cli, opts pullOptions) error {
}
return err
}
return nil
}

View File

@ -2,11 +2,14 @@ package image
import (
"fmt"
"io"
"io/ioutil"
"strings"
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
@ -32,11 +35,6 @@ func TestNewPullCommandErrors(t *testing.T) {
expectedError: "tag can't be used with --all-tags/-a",
args: []string{"--all-tags", "image:tag"},
},
{
name: "pull-error",
args: []string{"--disable-content-trust=false", "image:tag"},
expectedError: "you are not authorized to perform this operation: server returned 401.",
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{})
@ -49,20 +47,28 @@ func TestNewPullCommandErrors(t *testing.T) {
func TestNewPullCommandSuccess(t *testing.T) {
testCases := []struct {
name string
args []string
name string
args []string
expectedTag string
}{
{
name: "simple",
args: []string{"image:tag"},
name: "simple",
args: []string{"image:tag"},
expectedTag: "image:tag",
},
{
name: "simple-no-tag",
args: []string{"image"},
name: "simple-no-tag",
args: []string{"image"},
expectedTag: "image:latest",
},
}
for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{})
cli := test.NewFakeCli(&fakeClient{
imagePullFunc: func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
assert.Equal(t, tc.expectedTag, ref, tc.name)
return ioutil.NopCloser(strings.NewReader("")), nil
},
})
cmd := NewPullCommand(cli)
cmd.SetOutput(ioutil.Discard)
cmd.SetArgs(tc.args)

View File

@ -48,7 +48,7 @@ func runPush(dockerCli command.Cli, remote string) error {
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
if command.IsTrusted() {
return trustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)
return TrustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege)
}
responseBody, err := imagePushPrivileged(ctx, dockerCli, authConfig, ref, requestPrivilege)

View File

@ -5,18 +5,18 @@ import (
"encoding/json"
"fmt"
"io"
"path"
"sort"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/trust"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
"github.com/opencontainers/go-digest"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
@ -28,8 +28,8 @@ type target struct {
size int64
}
// trustedPush handles content trust pushing of an image
func trustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
// TrustedPush handles content trust pushing of an image
func TrustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
responseBody, err := imagePushPrivileged(ctx, cli, authConfig, ref, requestPrivilege)
if err != nil {
return err
@ -103,25 +103,25 @@ func PushTrustedReference(streams command.Streams, repoInfo *registry.Repository
fmt.Fprintln(streams.Out(), "Signing and pushing trust metadata")
repo, err := trust.GetNotaryRepository(streams, repoInfo, authConfig, "push", "pull")
repo, err := trust.GetNotaryRepository(streams.In(), streams.Out(), command.UserAgent(), repoInfo, &authConfig, "push", "pull")
if err != nil {
fmt.Fprintf(streams.Out(), "Error establishing connection to notary repository: %s\n", err)
return err
}
// get the latest repository metadata so we can figure out which roles to sign
err = repo.Update(false)
_, err = repo.ListTargets()
switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
keys := repo.GetCryptoService().ListKeys(data.CanonicalRootRole)
var rootKeyID string
// always select the first root key
if len(keys) > 0 {
sort.Strings(keys)
rootKeyID = keys[0]
} else {
rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey)
rootPublicKey, err := repo.GetCryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey)
if err != nil {
return err
}
@ -136,7 +136,7 @@ func PushTrustedReference(streams command.Streams, repoInfo *registry.Repository
err = repo.AddTarget(target, data.CanonicalTargetsRole)
case nil:
// already initialized and we have successfully downloaded the latest metadata
err = addTargetToAllSignableRoles(repo, target)
err = AddTargetToAllSignableRoles(repo, target)
default:
return trust.NotaryError(repoInfo.Name.Name(), err)
}
@ -154,51 +154,16 @@ func PushTrustedReference(streams command.Streams, repoInfo *registry.Repository
return nil
}
// Attempt to add the image target to all the top level delegation roles we can
// AddTargetToAllSignableRoles attempts to add the image target to all the top level delegation roles we can
// (based on whether we have the signing key and whether the role's path allows
// us to).
// If there are no delegation roles, we add to the targets role.
func addTargetToAllSignableRoles(repo *client.NotaryRepository, target *client.Target) error {
var signableRoles []string
// translate the full key names, which includes the GUN, into just the key IDs
allCanonicalKeyIDs := make(map[string]struct{})
for fullKeyID := range repo.CryptoService.ListAllKeys() {
allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{}
}
allDelegationRoles, err := repo.GetDelegationRoles()
func AddTargetToAllSignableRoles(repo client.Repository, target *client.Target) error {
signableRoles, err := trust.GetSignableRoles(repo, target)
if err != nil {
return err
}
// if there are no delegation roles, then just try to sign it into the targets role
if len(allDelegationRoles) == 0 {
return repo.AddTarget(target, data.CanonicalTargetsRole)
}
// there are delegation roles, find every delegation role we have a key for, and
// attempt to sign into into all those roles.
for _, delegationRole := range allDelegationRoles {
// We do not support signing any delegation role that isn't a direct child of the targets role.
// Also don't bother checking the keys if we can't add the target
// to this role due to path restrictions
if path.Dir(delegationRole.Name) != data.CanonicalTargetsRole || !delegationRole.CheckPaths(target.Name) {
continue
}
for _, canonicalKeyID := range delegationRole.KeyIDs {
if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok {
signableRoles = append(signableRoles, delegationRole.Name)
break
}
}
}
if len(signableRoles) == 0 {
return errors.Errorf("no valid signing keys for delegation roles")
}
return repo.AddTarget(target, signableRoles...)
}
@ -217,57 +182,13 @@ func imagePushPrivileged(ctx context.Context, cli command.Cli, authConfig types.
}
// trustedPull handles content trust pulling of an image
func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
var refs []target
notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull")
func trustedPull(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth) error {
refs, err := getTrustedPullTargets(cli, imgRefAndAuth)
if err != nil {
fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err)
return err
}
if tagged, isTagged := ref.(reference.NamedTagged); !isTagged {
// List all targets
targets, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return trust.NotaryError(ref.Name(), err)
}
for _, tgt := range targets {
t, err := convertTarget(tgt.Target)
if err != nil {
fmt.Fprintf(cli.Out(), "Skipping target for %q\n", reference.FamiliarName(ref))
continue
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if tgt.Role != trust.ReleasesRole && tgt.Role != data.CanonicalTargetsRole {
continue
}
refs = append(refs, t)
}
if len(refs) == 0 {
return trust.NotaryError(ref.Name(), errors.Errorf("No trusted tags for %s", ref.Name()))
}
} else {
t, err := notaryRepo.GetTargetByName(tagged.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return trust.NotaryError(ref.Name(), err)
}
// Only get the tag if it's in the top level targets role or the releases delegation role
// ignore it if it's in any other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return trust.NotaryError(ref.Name(), errors.Errorf("No trust data for %s", tagged.Tag()))
}
logrus.Debugf("retrieving target for %s role\n", t.Role)
r, err := convertTarget(t.Target)
if err != nil {
return err
}
refs = append(refs, r)
}
ref := imgRefAndAuth.Reference()
for i, r := range refs {
displayTag := r.name
if displayTag != "" {
@ -279,7 +200,11 @@ func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
if err != nil {
return err
}
if err := imagePullPrivileged(ctx, cli, authConfig, reference.FamiliarString(trustedRef), requestPrivilege, false); err != nil {
updatedImgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, AuthResolver(cli), trustedRef.String())
if err != nil {
return err
}
if err := imagePullPrivileged(ctx, cli, updatedImgRefAndAuth, false); err != nil {
return err
}
@ -295,13 +220,65 @@ func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.Reposi
return nil
}
// imagePullPrivileged pulls the image and displays it to the output
func imagePullPrivileged(ctx context.Context, cli command.Cli, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
func getTrustedPullTargets(cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth) ([]target, error) {
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPullOnly)
if err != nil {
fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err)
return nil, err
}
encodedAuth, err := command.EncodeAuthToBase64(authConfig)
ref := imgRefAndAuth.Reference()
tagged, isTagged := ref.(reference.NamedTagged)
if !isTagged {
// List all targets
targets, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return nil, trust.NotaryError(ref.Name(), err)
}
var refs []target
for _, tgt := range targets {
t, err := convertTarget(tgt.Target)
if err != nil {
fmt.Fprintf(cli.Out(), "Skipping target for %q\n", reference.FamiliarName(ref))
continue
}
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if tgt.Role != trust.ReleasesRole && tgt.Role != data.CanonicalTargetsRole {
continue
}
refs = append(refs, t)
}
if len(refs) == 0 {
return nil, trust.NotaryError(ref.Name(), errors.Errorf("No trusted tags for %s", ref.Name()))
}
return refs, nil
}
t, err := notaryRepo.GetTargetByName(tagged.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return nil, trust.NotaryError(ref.Name(), err)
}
// Only get the tag if it's in the top level targets role or the releases delegation role
// ignore it if it's in any other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return nil, trust.NotaryError(ref.Name(), errors.Errorf("No trust data for %s", tagged.Tag()))
}
logrus.Debugf("retrieving target for %s role\n", t.Role)
r, err := convertTarget(t.Target)
return []target{r}, err
}
// imagePullPrivileged pulls the image and displays it to the output
func imagePullPrivileged(ctx context.Context, cli command.Cli, imgRefAndAuth trust.ImageRefAndAuth, all bool) error {
ref := reference.FamiliarString(imgRefAndAuth.Reference())
encodedAuth, err := command.EncodeAuthToBase64(*imgRefAndAuth.AuthConfig())
if err != nil {
return err
}
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "pull")
options := types.ImagePullOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: requestPrivilege,
@ -335,7 +312,7 @@ func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedT
// Resolve the Auth config relevant for this server
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull")
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil {
fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err)
return nil, err
@ -348,7 +325,7 @@ func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedT
// Only list tags in the top level targets role or the releases delegation role - ignore
// all other delegation roles
if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole {
return nil, trust.NotaryError(repoInfo.Name.Name(), errors.Errorf("No trust data for %s", ref.Tag()))
return nil, trust.NotaryError(repoInfo.Name.Name(), client.ErrNoSuchTarget(ref.Tag()))
}
r, err := convertTarget(t.Target)
if err != nil {
@ -382,3 +359,10 @@ func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canon
return cli.Client().ImageTag(ctx, trustedFamiliarRef, familiarRef)
}
// AuthResolver returns an auth resolver function from a command.Cli
func AuthResolver(cli command.Cli) func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
return func(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
return command.ResolveAuthConfig(ctx, cli, index)
}
}

View File

@ -1,12 +1,18 @@
package image
import (
"io/ioutil"
"os"
"testing"
"github.com/docker/cli/cli/trust"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/registry"
"github.com/docker/notary/client"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/trustpinning"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func unsetENV() {
@ -55,3 +61,15 @@ func TestNonOfficialTrustServer(t *testing.T) {
t.Fatalf("Expected server to be %s, got %s", expectedStr, output)
}
}
func TestAddTargetToAllSignableRolesError(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
require.NoError(t, err)
target := client.Target{}
err = AddTargetToAllSignableRoles(notaryRepo, &target)
assert.EqualError(t, err, "client is offline")
}

View File

@ -12,6 +12,7 @@ type fakeClient struct {
networkCreateFunc func(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error
networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
}
func (c *fakeClient) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
@ -34,3 +35,10 @@ func (c *fakeClient) NetworkDisconnect(ctx context.Context, networkID, container
}
return nil
}
func (c *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
if c.networkListFunc != nil {
return c.networkListFunc(ctx, options)
}
return []types.NetworkResource{}, nil
}

View File

@ -0,0 +1,69 @@
package network
import (
"testing"
"io/ioutil"
"strings"
"github.com/docker/cli/internal/test"
. "github.com/docker/cli/internal/test/builders"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
func TestNetworkListErrors(t *testing.T) {
testCases := []struct {
networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
expectedError string
}{
{
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
return []types.NetworkResource{}, errors.Errorf("error creating network")
},
expectedError: "error creating network",
},
}
for _, tc := range testCases {
cmd := newListCommand(
test.NewFakeCli(&fakeClient{
networkListFunc: tc.networkListFunc,
}),
)
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestNetworkListWithFlags(t *testing.T) {
filterArgs := filters.NewArgs()
filterArgs.Add("image.name", "ubuntu")
expectedOpts := types.NetworkListOptions{
Filters: filterArgs,
}
cli := test.NewFakeCli(&fakeClient{
networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
assert.Equal(t, expectedOpts, options, "not expected options error")
return []types.NetworkResource{*NetworkResource(NetworkResourceID("123454321"),
NetworkResourceName("network_1"),
NetworkResourceDriver("09.7.01"),
NetworkResourceScope("global"))}, nil
},
})
cmd := newListCommand(cli)
cmd.Flags().Set("filter", "image.name=ubuntu")
assert.NoError(t, cmd.Execute())
golden.Assert(t, strings.TrimSpace(cli.OutBuffer().String()), "network-list.golden")
}

View File

@ -0,0 +1,2 @@
NETWORK ID NAME DRIVER SCOPE
123454321 network_1 09.7.01 global

View File

@ -65,10 +65,12 @@ func (s pluginRegistryService) ResolveRepository(name reference.Named) (repoInfo
return
}
func newRegistryService() registry.Service {
return pluginRegistryService{
Service: registry.NewService(registry.ServiceOptions{V2Only: true}),
func newRegistryService() (registry.Service, error) {
svc, err := registry.NewService(registry.ServiceOptions{V2Only: true})
if err != nil {
return nil, err
}
return pluginRegistryService{Service: svc}, nil
}
func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) {
@ -96,7 +98,11 @@ func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts plu
}
ctx := context.Background()
trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService())
svc, err := newRegistryService()
if err != nil {
return types.PluginInstallOptions{}, err
}
trusted, err := image.TrustedReference(ctx, dockerCli, nt, svc)
if err != nil {
return types.PluginInstallOptions{}, err
}

View File

@ -17,6 +17,7 @@ import (
type createOptions struct {
name string
driver string
file string
labels opts.ListOpts
}
@ -27,17 +28,21 @@ func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command {
}
cmd := &cobra.Command{
Use: "create [OPTIONS] SECRET file|-",
Use: "create [OPTIONS] SECRET [file|-]",
Short: "Create a secret from a file or STDIN as content",
Args: cli.ExactArgs(2),
Args: cli.RequiresRangeArgs(1, 2),
RunE: func(cmd *cobra.Command, args []string) error {
options.name = args[0]
options.file = args[1]
if len(args) == 2 {
options.file = args[1]
}
return runSecretCreate(dockerCli, options)
},
}
flags := cmd.Flags()
flags.VarP(&options.labels, "label", "l", "Secret labels")
flags.StringVarP(&options.driver, "driver", "d", "", "Secret driver")
flags.SetAnnotation("driver", "version", []string{"1.31"})
return cmd
}
@ -46,21 +51,14 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
client := dockerCli.Client()
ctx := context.Background()
var in io.Reader = dockerCli.In()
if options.file != "-" {
file, err := system.OpenSequential(options.file)
if err != nil {
return err
}
in = file
defer file.Close()
if options.driver != "" && options.file != "" {
return errors.Errorf("When using secret driver secret data must be empty")
}
secretData, err := ioutil.ReadAll(in)
secretData, err := readSecretData(dockerCli.In(), options.file)
if err != nil {
return errors.Errorf("Error reading content from %q: %v", options.file, err)
}
spec := swarm.SecretSpec{
Annotations: swarm.Annotations{
Name: options.name,
@ -68,6 +66,11 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
},
Data: secretData,
}
if options.driver != "" {
spec.Driver = &swarm.Driver{
Name: options.driver,
}
}
r, err := client.SecretCreate(ctx, spec)
if err != nil {
@ -77,3 +80,23 @@ func runSecretCreate(dockerCli command.Cli, options createOptions) error {
fmt.Fprintln(dockerCli.Out(), r.ID)
return nil
}
func readSecretData(in io.ReadCloser, file string) ([]byte, error) {
// Read secret value from external driver
if file == "" {
return nil, nil
}
if file != "-" {
var err error
in, err = system.OpenSequential(file)
if err != nil {
return nil, err
}
defer in.Close()
}
data, err := ioutil.ReadAll(in)
if err != nil {
return nil, err
}
return data, nil
}

View File

@ -24,12 +24,11 @@ func TestSecretCreateErrors(t *testing.T) {
secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error)
expectedError string
}{
{
args: []string{"too_few"},
expectedError: "requires exactly 2 arguments",
},
{args: []string{"too", "many", "arguments"},
expectedError: "requires exactly 2 arguments",
expectedError: "requires at least 1 and at most 2 arguments",
},
{args: []string{"create", "--driver", "driver", "-"},
expectedError: "secret data must be empty",
},
{
args: []string{"name", filepath.Join("testdata", secretDataFile)},
@ -75,6 +74,35 @@ func TestSecretCreateWithName(t *testing.T) {
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
}
func TestSecretCreateWithDriver(t *testing.T) {
expectedDriver := &swarm.Driver{
Name: "secret-driver",
}
name := "foo"
cli := test.NewFakeCli(&fakeClient{
secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) {
if spec.Name != name {
return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name)
}
if !reflect.DeepEqual(spec.Driver.Name, expectedDriver.Name) {
return types.SecretCreateResponse{}, errors.Errorf("expected driver %v, got %v", expectedDriver, spec.Labels)
}
return types.SecretCreateResponse{
ID: "ID-" + spec.Name,
}, nil
},
})
cmd := newSecretCreateCommand(cli)
cmd.SetArgs([]string{name})
cmd.Flags().Set("driver", expectedDriver.Name)
assert.NoError(t, cmd.Execute())
assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String()))
}
func TestSecretCreateWithLabels(t *testing.T) {
expectedLabels := map[string]string{
"lbl1": "Label-foo",

View File

@ -154,6 +154,7 @@ func TestSecretInspectPretty(t *testing.T) {
}),
SecretID("secretID"),
SecretName("secretName"),
SecretDriver("driver"),
SecretCreatedAt(time.Time{}),
SecretUpdatedAt(time.Time{}),
), []byte{}, nil

View File

@ -1,15 +1,27 @@
package secret
import (
"sort"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"vbom.ml/util/sortorder"
)
type bySecretName []swarm.Secret
func (r bySecretName) Len() int { return len(r) }
func (r bySecretName) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r bySecretName) Less(i, j int) bool {
return sortorder.NaturalLess(r[i].Spec.Name, r[j].Spec.Name)
}
type listOptions struct {
quiet bool
format string
@ -53,6 +65,9 @@ func runSecretList(dockerCli command.Cli, options listOptions) error {
format = formatter.TableFormatKey
}
}
sort.Sort(bySecretName(secrets))
secretCtx := formatter.Context{
Output: dockerCli.Out(),
Format: formatter.NewSecretFormat(format, options.quiet),

View File

@ -1,7 +1,6 @@
package secret
import (
"bytes"
"io/ioutil"
"testing"
"time"
@ -48,29 +47,35 @@ func TestSecretListErrors(t *testing.T) {
}
func TestSecretList(t *testing.T) {
buf := new(bytes.Buffer)
cli := test.NewFakeCli(&fakeClient{
secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) {
return []swarm.Secret{
*Secret(SecretID("ID-foo"),
SecretName("foo"),
*Secret(SecretID("ID-1-foo"),
SecretName("1-foo"),
SecretVersion(swarm.Version{Index: 10}),
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
),
*Secret(SecretID("ID-bar"),
SecretName("bar"),
*Secret(SecretID("ID-10-foo"),
SecretName("10-foo"),
SecretVersion(swarm.Version{Index: 11}),
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
SecretDriver("driver"),
),
*Secret(SecretID("ID-2-foo"),
SecretName("2-foo"),
SecretVersion(swarm.Version{Index: 11}),
SecretCreatedAt(time.Now().Add(-2*time.Hour)),
SecretUpdatedAt(time.Now().Add(-1*time.Hour)),
SecretDriver("driver"),
),
}, nil
},
})
cmd := newSecretListCommand(cli)
cmd.SetOutput(buf)
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "secret-list.golden")
golden.Assert(t, cli.OutBuffer().String(), "secret-list-sort.golden")
}
func TestSecretListWithQuietOption(t *testing.T) {

View File

@ -1,6 +1,7 @@
ID: secretID
Name: secretName
ID: secretID
Name: secretName
Labels:
- lbl1=value1
Created at: 0001-01-01 00:00:00 +0000 utc
Updated at: 0001-01-01 00:00:00 +0000 utc
Driver: driver
Created at: 0001-01-01 00:00:00 +0000 utc
Updated at: 0001-01-01 00:00:00 +0000 utc

View File

@ -0,0 +1,4 @@
ID NAME DRIVER CREATED UPDATED
ID-1-foo 1-foo 2 hours ago About an hour ago
ID-2-foo 2-foo driver 2 hours ago About an hour ago
ID-10-foo 10-foo driver 2 hours ago About an hour ago

View File

@ -1,2 +1,2 @@
foo
bar label=label-bar
foo

View File

@ -1,3 +1,3 @@
ID NAME CREATED UPDATED
ID-foo foo 2 hours ago About an hour ago
ID-bar bar 2 hours ago About an hour ago
ID NAME DRIVER CREATED UPDATED
ID-bar bar 2 hours ago About an hour ago
ID-foo foo 2 hours ago About an hour ago

View File

@ -1,2 +1,2 @@
foo
bar label=label-bar
foo

View File

@ -1,2 +1,2 @@
ID-foo
ID-bar
ID-foo

View File

@ -1,3 +0,0 @@
ID NAME CREATED UPDATED
ID-foo foo 2 hours ago About an hour ago
ID-bar bar 2 hours ago About an hour ago

View File

@ -123,8 +123,7 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID)
if opts.detach {
warnDetachDefault(dockerCli.Err(), apiClient.ClientVersion(), flags, "created")
if opts.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
return nil
}

View File

@ -1,15 +1,12 @@
package service
import (
"fmt"
"io"
"io/ioutil"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/service/progress"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/spf13/pflag"
"golang.org/x/net/context"
)
@ -34,11 +31,3 @@ func waitOnService(ctx context.Context, dockerCli command.Cli, serviceID string,
}
return err
}
// warnDetachDefault warns about the --detach flag future change if it's supported.
func warnDetachDefault(err io.Writer, clientVersion string, flags *pflag.FlagSet, msg string) {
if !flags.Changed("detach") && versions.GreaterThanOrEqualTo(clientVersion, "1.29") {
fmt.Fprintf(err, "Since --detach=false was not specified, tasks will be %s in the background.\n"+
"In a future release, --detach=false will become the default.\n", msg)
}
}

View File

@ -1,40 +0,0 @@
package service
import (
"bytes"
"testing"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
func TestWarnDetachDefault(t *testing.T) {
var detach bool
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
addDetachFlag(flags, &detach)
var tests = []struct {
detach bool
version string
expectWarning bool
}{
{true, "1.28", false},
{true, "1.29", false},
{false, "1.28", false},
{false, "1.29", true},
}
for _, test := range tests {
out := new(bytes.Buffer)
flags.Lookup(flagDetach).Changed = test.detach
warnDetachDefault(out, test.version, flags, "")
if test.expectWarning {
assert.NotEmpty(t, out.String(), "expected warning")
} else {
assert.Empty(t, out.String(), "expected no warning")
}
}
}

View File

@ -691,7 +691,7 @@ func buildServiceDefaultFlagMapping() flagDefaults {
}
func addDetachFlag(flags *pflag.FlagSet, detach *bool) {
flags.BoolVarP(detach, flagDetach, "d", true, "Exit immediately instead of waiting for the service to converge")
flags.BoolVarP(detach, flagDetach, "d", false, "Exit immediately instead of waiting for the service to converge")
flags.SetAnnotation(flagDetach, "version", []string{"1.29"})
}

View File

@ -7,8 +7,8 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
@ -19,7 +19,7 @@ func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
Short: "Revert changes to a service's configuration",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runRollback(dockerCli, cmd.Flags(), options, args[0])
return runRollback(dockerCli, options, args[0])
},
Tags: map[string]string{"version": "1.31"},
}
@ -31,7 +31,7 @@ func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
return cmd
}
func runRollback(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
func runRollback(dockerCli command.Cli, options *serviceOptions, serviceID string) error {
apiClient := dockerCli.Client()
ctx := context.Background()
@ -56,8 +56,7 @@ func runRollback(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOp
fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)
if options.detach {
warnDetachDefault(dockerCli.Err(), apiClient.ClientVersion(), flags, "rolled back")
if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
return nil
}

View File

@ -10,9 +10,9 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
type scaleOptions struct {
@ -27,7 +27,7 @@ func newScaleCommand(dockerCli command.Cli) *cobra.Command {
Short: "Scale one or multiple replicated services",
Args: scaleArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runScale(dockerCli, cmd.Flags(), options, args)
return runScale(dockerCli, options, args)
},
}
@ -54,7 +54,7 @@ func scaleArgs(cmd *cobra.Command, args []string) error {
return nil
}
func runScale(dockerCli command.Cli, flags *pflag.FlagSet, options *scaleOptions, args []string) error {
func runScale(dockerCli command.Cli, options *scaleOptions, args []string) error {
var errs []string
var serviceIDs []string
ctx := context.Background()
@ -79,9 +79,7 @@ func runScale(dockerCli command.Cli, flags *pflag.FlagSet, options *scaleOptions
}
if len(serviceIDs) > 0 {
if options.detach {
warnDetachDefault(dockerCli.Err(), dockerCli.Client().ClientVersion(), flags, "scaled")
} else {
if !options.detach && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.29") {
for _, serviceID := range serviceIDs {
if err := waitOnService(ctx, dockerCli, serviceID, false); err != nil {
errs = append(errs, fmt.Sprintf("%s: %v", serviceID, err))

View File

@ -59,7 +59,7 @@ func trustedResolveDigest(ctx context.Context, cli command.Cli, ref reference.Na
authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index)
notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull")
notaryRepo, err := trust.GetNotaryRepository(cli.In(), cli.Out(), command.UserAgent(), repoInfo, &authConfig, "pull")
if err != nil {
return nil, errors.Wrap(err, "error establishing connection to trust repository")
}

View File

@ -216,8 +216,7 @@ func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOpti
fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)
if options.detach {
warnDetachDefault(dockerCli.Err(), dockerCli.Client().ClientVersion(), flags, "updated")
if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") {
return nil
}

View File

@ -104,13 +104,12 @@ func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error
}
// pruneServices removes services that are no longer referenced in the source
func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) bool {
func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) {
client := dockerCli.Client()
oldServices, err := getServices(ctx, client, namespace.Name())
if err != nil {
fmt.Fprintf(dockerCli.Err(), "Failed to list services: %s", err)
return true
}
pruneServices := []swarm.Service{}
@ -119,5 +118,5 @@ func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert
pruneServices = append(pruneServices, service)
}
}
return removeServices(ctx, dockerCli, pruneServices)
removeServices(ctx, dockerCli, pruneServices)
}

View File

@ -59,6 +59,7 @@ func TestStackPsEmptyStack(t *testing.T) {
})
cmd := newPsCommand(fakeCli)
cmd.SetArgs([]string{"foo"})
cmd.SetOutput(ioutil.Discard)
assert.Error(t, cmd.Execute())
assert.EqualError(t, cmd.Execute(), "nothing found in stack: foo")

View File

@ -103,7 +103,7 @@ func removeServices(
var hasError bool
sort.Slice(services, sortServiceByName(services))
for _, service := range services {
fmt.Fprintf(dockerCli.Err(), "Removing service %s\n", service.Spec.Name)
fmt.Fprintf(dockerCli.Out(), "Removing service %s\n", service.Spec.Name)
if err := dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil {
hasError = true
fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err)
@ -119,7 +119,7 @@ func removeNetworks(
) bool {
var hasError bool
for _, network := range networks {
fmt.Fprintf(dockerCli.Err(), "Removing network %s\n", network.Name)
fmt.Fprintf(dockerCli.Out(), "Removing network %s\n", network.Name)
if err := dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil {
hasError = true
fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err)
@ -135,7 +135,7 @@ func removeSecrets(
) bool {
var hasError bool
for _, secret := range secrets {
fmt.Fprintf(dockerCli.Err(), "Removing secret %s\n", secret.Spec.Name)
fmt.Fprintf(dockerCli.Out(), "Removing secret %s\n", secret.Spec.Name)
if err := dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil {
hasError = true
fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err)
@ -151,7 +151,7 @@ func removeConfigs(
) bool {
var hasError bool
for _, config := range configs {
fmt.Fprintf(dockerCli.Err(), "Removing config %s\n", config.Spec.Name)
fmt.Fprintf(dockerCli.Out(), "Removing config %s\n", config.Spec.Name)
if err := dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil {
hasError = true
fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err)

View File

@ -101,7 +101,13 @@ func TestRemoveStackSkipEmpty(t *testing.T) {
cmd.SetArgs([]string{"foo", "bar"})
assert.NoError(t, cmd.Execute())
assert.Equal(t, "", fakeCli.OutBuffer().String())
expectedList := []string{"Removing service bar_service1",
"Removing service bar_service2",
"Removing secret bar_secret1",
"Removing config bar_config1",
"Removing network bar_network1\n",
}
assert.Equal(t, strings.Join(expectedList, "\n"), fakeCli.OutBuffer().String())
assert.Contains(t, fakeCli.ErrBuffer().String(), "Nothing found in stack: foo\n")
assert.Equal(t, allServiceIDs, fakeClient.removedServices)
assert.Equal(t, allNetworkIDs, fakeClient.removedNetworks)

View File

@ -15,24 +15,20 @@ import (
"golang.org/x/net/context"
)
type unlockOptions struct{}
func newUnlockCommand(dockerCli command.Cli) *cobra.Command {
opts := unlockOptions{}
cmd := &cobra.Command{
Use: "unlock",
Short: "Unlock swarm",
Args: cli.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runUnlock(dockerCli, opts)
return runUnlock(dockerCli)
},
}
return cmd
}
func runUnlock(dockerCli command.Cli, opts unlockOptions) error {
func runUnlock(dockerCli command.Cli) error {
client := dockerCli.Client()
ctx := context.Background()

View File

@ -15,7 +15,6 @@ import (
"github.com/docker/cli/templates"
"github.com/docker/docker/api/types"
eventtypes "github.com/docker/docker/api/types/events"
"github.com/docker/docker/pkg/jsonlog"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
@ -104,14 +103,18 @@ func makeTemplate(format string) (*template.Template, error) {
return tmpl, tmpl.Execute(ioutil.Discard, &eventtypes.Message{})
}
// rfc3339NanoFixed is similar to time.RFC3339Nano, except it pads nanoseconds
// zeros to maintain a fixed number of characters
const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
// prettyPrintEvent prints all types of event information.
// Each output includes the event type, actor id, name and action.
// Actor attributes are printed at the end if the actor has any.
func prettyPrintEvent(out io.Writer, event eventtypes.Message) error {
if event.TimeNano != 0 {
fmt.Fprintf(out, "%s ", time.Unix(0, event.TimeNano).Format(jsonlog.RFC3339NanoFixed))
fmt.Fprintf(out, "%s ", time.Unix(0, event.TimeNano).Format(rfc3339NanoFixed))
} else if event.Time != 0 {
fmt.Fprintf(out, "%s ", time.Unix(event.Time, 0).Format(jsonlog.RFC3339NanoFixed))
fmt.Fprintf(out, "%s ", time.Unix(event.Time, 0).Format(rfc3339NanoFixed))
}
fmt.Fprintf(out, "%s %s %s", event.Type, event.Action, event.Actor.ID)

View File

@ -55,109 +55,50 @@ func runInfo(dockerCli *command.DockerCli, opts *infoOptions) error {
// nolint: gocyclo
func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
fmt.Fprintf(dockerCli.Out(), "Containers: %d\n", info.Containers)
fmt.Fprintf(dockerCli.Out(), " Running: %d\n", info.ContainersRunning)
fmt.Fprintf(dockerCli.Out(), " Paused: %d\n", info.ContainersPaused)
fmt.Fprintf(dockerCli.Out(), " Stopped: %d\n", info.ContainersStopped)
fmt.Fprintf(dockerCli.Out(), "Images: %d\n", info.Images)
fprintfIfNotEmpty(dockerCli.Out(), "Server Version: %s\n", info.ServerVersion)
fprintfIfNotEmpty(dockerCli.Out(), "Storage Driver: %s\n", info.Driver)
fmt.Fprintln(dockerCli.Out(), "Containers:", info.Containers)
fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning)
fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused)
fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped)
fmt.Fprintln(dockerCli.Out(), "Images:", info.Images)
fprintlnNonEmpty(dockerCli.Out(), "Server Version:", info.ServerVersion)
fprintlnNonEmpty(dockerCli.Out(), "Storage Driver:", info.Driver)
if info.DriverStatus != nil {
for _, pair := range info.DriverStatus {
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1])
}
}
if info.SystemStatus != nil {
for _, pair := range info.SystemStatus {
fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1])
}
}
fprintfIfNotEmpty(dockerCli.Out(), "Logging Driver: %s\n", info.LoggingDriver)
fprintfIfNotEmpty(dockerCli.Out(), "Cgroup Driver: %s\n", info.CgroupDriver)
fprintlnNonEmpty(dockerCli.Out(), "Logging Driver:", info.LoggingDriver)
fprintlnNonEmpty(dockerCli.Out(), "Cgroup Driver:", info.CgroupDriver)
fmt.Fprintf(dockerCli.Out(), "Plugins:\n")
fmt.Fprintf(dockerCli.Out(), " Volume:")
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Volume, " "))
fmt.Fprintf(dockerCli.Out(), "\n")
fmt.Fprintf(dockerCli.Out(), " Network:")
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Network, " "))
fmt.Fprintf(dockerCli.Out(), "\n")
fmt.Fprintln(dockerCli.Out(), "Plugins:")
fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " "))
fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " "))
if len(info.Plugins.Authorization) != 0 {
fmt.Fprintf(dockerCli.Out(), " Authorization:")
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Authorization, " "))
fmt.Fprintf(dockerCli.Out(), "\n")
fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " "))
}
fmt.Fprintf(dockerCli.Out(), " Log:")
fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Log, " "))
fmt.Fprintf(dockerCli.Out(), "\n")
fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " "))
fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState)
if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked {
fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID)
if info.Swarm.Error != "" {
fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error)
}
fmt.Fprintf(dockerCli.Out(), " Is Manager: %v\n", info.Swarm.ControlAvailable)
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
fmt.Fprintf(dockerCli.Out(), " ClusterID: %s\n", info.Swarm.Cluster.ID)
fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers)
fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes)
fmt.Fprintf(dockerCli.Out(), " Orchestration:\n")
taskHistoryRetentionLimit := int64(0)
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
}
fmt.Fprintf(dockerCli.Out(), " Task History Retention Limit: %d\n", taskHistoryRetentionLimit)
fmt.Fprintf(dockerCli.Out(), " Raft:\n")
fmt.Fprintf(dockerCli.Out(), " Snapshot Interval: %d\n", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
}
fmt.Fprintf(dockerCli.Out(), " Heartbeat Tick: %d\n", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
fmt.Fprintf(dockerCli.Out(), " Election Tick: %d\n", info.Swarm.Cluster.Spec.Raft.ElectionTick)
fmt.Fprintf(dockerCli.Out(), " Dispatcher:\n")
fmt.Fprintf(dockerCli.Out(), " Heartbeat Period: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
fmt.Fprintf(dockerCli.Out(), " CA Configuration:\n")
fmt.Fprintf(dockerCli.Out(), " Expiry Duration: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
fmt.Fprintf(dockerCli.Out(), " Force Rotate: %d\n", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
fprintfIfNotEmpty(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert))
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
fmt.Fprintf(dockerCli.Out(), " External CAs:\n")
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
}
}
fmt.Fprintf(dockerCli.Out(), " Autolock Managers: %v\n", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
fmt.Fprintf(dockerCli.Out(), " Root Rotation In Progress: %v\n", info.Swarm.Cluster.RootRotationInProgress)
}
fmt.Fprintf(dockerCli.Out(), " Node Address: %s\n", info.Swarm.NodeAddr)
managers := []string{}
for _, entry := range info.Swarm.RemoteManagers {
managers = append(managers, entry.Addr)
}
if len(managers) > 0 {
sort.Strings(managers)
fmt.Fprintf(dockerCli.Out(), " Manager Addresses:\n")
for _, entry := range managers {
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
}
}
}
fmt.Fprintln(dockerCli.Out(), "Swarm:", info.Swarm.LocalNodeState)
printSwarmInfo(dockerCli, info)
if len(info.Runtimes) > 0 {
fmt.Fprintf(dockerCli.Out(), "Runtimes:")
fmt.Fprint(dockerCli.Out(), "Runtimes:")
for name := range info.Runtimes {
fmt.Fprintf(dockerCli.Out(), " %s", name)
}
fmt.Fprint(dockerCli.Out(), "\n")
fmt.Fprintf(dockerCli.Out(), "Default Runtime: %s\n", info.DefaultRuntime)
fmt.Fprintln(dockerCli.Out(), "Default Runtime:", info.DefaultRuntime)
}
if info.OSType == "linux" {
fmt.Fprintf(dockerCli.Out(), "Init Binary: %v\n", info.InitBinary)
fmt.Fprintln(dockerCli.Out(), "Init Binary:", info.InitBinary)
for _, ci := range []struct {
Name string
@ -171,23 +112,23 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
if ci.Commit.ID != ci.Commit.Expected {
fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected)
}
fmt.Fprintf(dockerCli.Out(), "\n")
fmt.Fprint(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")
fmt.Fprintln(dockerCli.Out(), "Security Options:")
for _, so := range kvs {
fmt.Fprintf(dockerCli.Out(), " %s\n", so.Name)
fmt.Fprintln(dockerCli.Out(), " "+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.Fprintln(dockerCli.Err(), " WARNING: You're not using the default seccomp profile")
}
fmt.Fprintf(dockerCli.Out(), " Profile: %s\n", o.Value)
fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value)
}
}
}
@ -196,44 +137,44 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
// Isolation only has meaning on a Windows daemon.
if info.OSType == "windows" {
fmt.Fprintf(dockerCli.Out(), "Default Isolation: %v\n", info.Isolation)
fmt.Fprintln(dockerCli.Out(), "Default Isolation:", info.Isolation)
}
fprintfIfNotEmpty(dockerCli.Out(), "Kernel Version: %s\n", info.KernelVersion)
fprintfIfNotEmpty(dockerCli.Out(), "Operating System: %s\n", info.OperatingSystem)
fprintfIfNotEmpty(dockerCli.Out(), "OSType: %s\n", info.OSType)
fprintfIfNotEmpty(dockerCli.Out(), "Architecture: %s\n", info.Architecture)
fmt.Fprintf(dockerCli.Out(), "CPUs: %d\n", info.NCPU)
fmt.Fprintf(dockerCli.Out(), "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal)))
fprintfIfNotEmpty(dockerCli.Out(), "Name: %s\n", info.Name)
fprintfIfNotEmpty(dockerCli.Out(), "ID: %s\n", info.ID)
fmt.Fprintf(dockerCli.Out(), "Docker Root Dir: %s\n", info.DockerRootDir)
fmt.Fprintf(dockerCli.Out(), "Debug Mode (client): %v\n", debug.IsEnabled())
fmt.Fprintf(dockerCli.Out(), "Debug Mode (server): %v\n", info.Debug)
fprintlnNonEmpty(dockerCli.Out(), "Kernel Version:", info.KernelVersion)
fprintlnNonEmpty(dockerCli.Out(), "Operating System:", info.OperatingSystem)
fprintlnNonEmpty(dockerCli.Out(), "OSType:", info.OSType)
fprintlnNonEmpty(dockerCli.Out(), "Architecture:", info.Architecture)
fmt.Fprintln(dockerCli.Out(), "CPUs:", info.NCPU)
fmt.Fprintln(dockerCli.Out(), "Total Memory:", units.BytesSize(float64(info.MemTotal)))
fprintlnNonEmpty(dockerCli.Out(), "Name:", info.Name)
fprintlnNonEmpty(dockerCli.Out(), "ID:", info.ID)
fmt.Fprintln(dockerCli.Out(), "Docker Root Dir:", info.DockerRootDir)
fmt.Fprintln(dockerCli.Out(), "Debug Mode (client):", debug.IsEnabled())
fmt.Fprintln(dockerCli.Out(), "Debug Mode (server):", info.Debug)
if info.Debug {
fmt.Fprintf(dockerCli.Out(), " File Descriptors: %d\n", info.NFd)
fmt.Fprintf(dockerCli.Out(), " Goroutines: %d\n", info.NGoroutines)
fmt.Fprintf(dockerCli.Out(), " System Time: %s\n", info.SystemTime)
fmt.Fprintf(dockerCli.Out(), " EventsListeners: %d\n", info.NEventsListener)
fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd)
fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines)
fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime)
fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener)
}
fprintfIfNotEmpty(dockerCli.Out(), "Http Proxy: %s\n", info.HTTPProxy)
fprintfIfNotEmpty(dockerCli.Out(), "Https Proxy: %s\n", info.HTTPSProxy)
fprintfIfNotEmpty(dockerCli.Out(), "No Proxy: %s\n", info.NoProxy)
fprintlnNonEmpty(dockerCli.Out(), "HTTP Proxy:", info.HTTPProxy)
fprintlnNonEmpty(dockerCli.Out(), "HTTPS Proxy:", info.HTTPSProxy)
fprintlnNonEmpty(dockerCli.Out(), "No Proxy:", info.NoProxy)
if info.IndexServerAddress != "" {
u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username
if len(u) > 0 {
fmt.Fprintf(dockerCli.Out(), "Username: %v\n", u)
fmt.Fprintln(dockerCli.Out(), "Username:", u)
}
fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress)
fmt.Fprintln(dockerCli.Out(), "Registry:", info.IndexServerAddress)
}
if info.Labels != nil {
fmt.Fprintln(dockerCli.Out(), "Labels:")
for _, attribute := range info.Labels {
fmt.Fprintf(dockerCli.Out(), " %s\n", attribute)
for _, lbl := range info.Labels {
fmt.Fprintln(dockerCli.Out(), " "+lbl)
}
// TODO: Engine labels with duplicate keys has been deprecated in 1.13 and will be error out
// after 3 release cycles (17.12). For now, a WARNING will be generated. The following will
@ -252,20 +193,15 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
}
}
fmt.Fprintf(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild)
if info.ClusterStore != "" {
fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore)
}
if info.ClusterAdvertise != "" {
fmt.Fprintf(dockerCli.Out(), "Cluster Advertise: %s\n", info.ClusterAdvertise)
}
fmt.Fprintln(dockerCli.Out(), "Experimental:", info.ExperimentalBuild)
fprintlnNonEmpty(dockerCli.Out(), "Cluster Store:", info.ClusterStore)
fprintlnNonEmpty(dockerCli.Out(), "Cluster Advertise:", info.ClusterAdvertise)
if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) {
fmt.Fprintln(dockerCli.Out(), "Insecure Registries:")
for _, registry := range info.RegistryConfig.IndexConfigs {
if !registry.Secure {
fmt.Fprintf(dockerCli.Out(), " %s\n", registry.Name)
fmt.Fprintln(dockerCli.Out(), " "+registry.Name)
}
}
@ -278,11 +214,12 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 {
fmt.Fprintln(dockerCli.Out(), "Registry Mirrors:")
for _, mirror := range info.RegistryConfig.Mirrors {
fmt.Fprintf(dockerCli.Out(), " %s\n", mirror)
fmt.Fprintln(dockerCli.Out(), " "+mirror)
}
}
fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n\n", info.LiveRestoreEnabled)
fmt.Fprintln(dockerCli.Out(), "Live Restore Enabled:", info.LiveRestoreEnabled)
fmt.Fprint(dockerCli.Out(), "\n")
// Only output these warnings if the server does not support these features
if info.OSType != "windows" {
@ -326,6 +263,63 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
return nil
}
func printSwarmInfo(dockerCli command.Cli, info types.Info) {
if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked {
return
}
fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID)
if info.Swarm.Error != "" {
fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error)
}
fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable)
if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError {
fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID)
fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers)
fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes)
fmt.Fprintln(dockerCli.Out(), " Orchestration:")
taskHistoryRetentionLimit := int64(0)
if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil {
taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit
}
fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit)
fmt.Fprintln(dockerCli.Out(), " Raft:")
fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval)
if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil {
fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots)
}
fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick)
fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick)
fmt.Fprintln(dockerCli.Out(), " Dispatcher:")
fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))
fmt.Fprintln(dockerCli.Out(), " CA Configuration:")
fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry))
fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate)
if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" {
fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert)
}
if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 {
fmt.Fprintln(dockerCli.Out(), " External CAs:")
for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs {
fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL)
}
}
fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers)
fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress)
}
fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr)
if len(info.Swarm.RemoteManagers) > 0 {
managers := []string{}
for _, entry := range info.Swarm.RemoteManagers {
managers = append(managers, entry.Addr)
}
sort.Strings(managers)
fmt.Fprintln(dockerCli.Out(), " Manager Addresses:")
for _, entry := range managers {
fmt.Fprintf(dockerCli.Out(), " %s\n", entry)
}
}
}
func printStorageDriverWarnings(dockerCli command.Cli, info types.Info) {
if info.DriverStatus == nil {
return
@ -374,9 +368,8 @@ func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) er
return err
}
func fprintfIfNotEmpty(w io.Writer, format, value string) (int, error) {
func fprintlnNonEmpty(w io.Writer, label, value string) {
if value != "" {
return fmt.Fprintf(w, format, value)
fmt.Fprintln(w, label, value)
}
return 0, nil
}

View File

@ -0,0 +1,413 @@
package trust
import (
"github.com/docker/cli/cli/trust"
"github.com/docker/notary/client"
"github.com/docker/notary/client/changelist"
"github.com/docker/notary/cryptoservice"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/storage"
"github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/signed"
)
// Sample mock CLI interfaces
func getOfflineNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
return OfflineNotaryRepository{}, nil
}
// OfflineNotaryRepository is a mock Notary repository that is offline
type OfflineNotaryRepository struct{}
func (o OfflineNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
return storage.ErrOffline{}
}
func (o OfflineNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
return storage.ErrOffline{}
}
func (o OfflineNotaryRepository) Publish() error {
return storage.ErrOffline{}
}
func (o OfflineNotaryRepository) AddTarget(target *client.Target, roles ...data.RoleName) error {
return nil
}
func (o OfflineNotaryRepository) RemoveTarget(targetName string, roles ...data.RoleName) error {
return nil
}
func (o OfflineNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
return nil, storage.ErrOffline{}
}
func (o OfflineNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
return nil, storage.ErrOffline{}
}
func (o OfflineNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
return nil, storage.ErrOffline{}
}
func (o OfflineNotaryRepository) GetChangelist() (changelist.Changelist, error) {
return changelist.NewMemChangelist(), nil
}
func (o OfflineNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
return nil, storage.ErrOffline{}
}
func (o OfflineNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
return nil, storage.ErrOffline{}
}
func (o OfflineNotaryRepository) AddDelegation(name data.RoleName, delegationKeys []data.PublicKey, paths []string) error {
return nil
}
func (o OfflineNotaryRepository) AddDelegationRoleAndKeys(name data.RoleName, delegationKeys []data.PublicKey) error {
return nil
}
func (o OfflineNotaryRepository) AddDelegationPaths(name data.RoleName, paths []string) error {
return nil
}
func (o OfflineNotaryRepository) RemoveDelegationKeysAndPaths(name data.RoleName, keyIDs, paths []string) error {
return nil
}
func (o OfflineNotaryRepository) RemoveDelegationRole(name data.RoleName) error {
return nil
}
func (o OfflineNotaryRepository) RemoveDelegationPaths(name data.RoleName, paths []string) error {
return nil
}
func (o OfflineNotaryRepository) RemoveDelegationKeys(name data.RoleName, keyIDs []string) error {
return nil
}
func (o OfflineNotaryRepository) ClearDelegationPaths(name data.RoleName) error {
return nil
}
func (o OfflineNotaryRepository) Witness(roles ...data.RoleName) ([]data.RoleName, error) {
return nil, nil
}
func (o OfflineNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
return storage.ErrOffline{}
}
func (o OfflineNotaryRepository) GetCryptoService() signed.CryptoService {
return nil
}
func (o OfflineNotaryRepository) SetLegacyVersions(version int) {}
func (o OfflineNotaryRepository) GetGUN() data.GUN {
return data.GUN("gun")
}
func getUninitializedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
return UninitializedNotaryRepository{}, nil
}
// UninitializedNotaryRepository is a mock Notary repository that is uninintialized
// it builds on top of the OfflineNotaryRepository, instead returning ErrRepositoryNotExist
// for any online operation
type UninitializedNotaryRepository struct {
OfflineNotaryRepository
}
func (u UninitializedNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
return client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
return client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) Publish() error {
return client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
return nil, client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
return nil, client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
return nil, client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
return nil, client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
return nil, client.ErrRepositoryNotExist{}
}
func (u UninitializedNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
return client.ErrRepositoryNotExist{}
}
func getEmptyTargetsNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
return EmptyTargetsNotaryRepository{}, nil
}
// EmptyTargetsNotaryRepository is a mock Notary repository that is initialized
// but does not have any signed targets
type EmptyTargetsNotaryRepository struct {
OfflineNotaryRepository
}
func (e EmptyTargetsNotaryRepository) Initialize(rootKeyIDs []string, serverManagedRoles ...data.RoleName) error {
return nil
}
func (e EmptyTargetsNotaryRepository) InitializeWithCertificate(rootKeyIDs []string, rootCerts []data.PublicKey, serverManagedRoles ...data.RoleName) error {
return nil
}
func (e EmptyTargetsNotaryRepository) Publish() error {
return nil
}
func (e EmptyTargetsNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
return []*client.TargetWithRole{}, nil
}
func (e EmptyTargetsNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
return nil, client.ErrNoSuchTarget(name)
}
func (e EmptyTargetsNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
return nil, client.ErrNoSuchTarget(name)
}
func (e EmptyTargetsNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
return []client.RoleWithSignatures{}, nil
}
func (e EmptyTargetsNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
return []data.Role{}, nil
}
func (e EmptyTargetsNotaryRepository) RotateKey(role data.RoleName, serverManagesKey bool, keyList []string) error {
return nil
}
func getLoadedNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
return LoadedNotaryRepository{}, nil
}
// LoadedNotaryRepository is a mock Notary repository that is loaded with targets, delegations, and keys
type LoadedNotaryRepository struct {
EmptyTargetsNotaryRepository
statefulCryptoService signed.CryptoService
}
// LoadedNotaryRepository has three delegations:
// - targets/releases: includes keys A and B
// - targets/alice: includes key A
// - targets/bob: includes key B
var loadedReleasesRole = data.DelegationRole{
BaseRole: data.BaseRole{
Name: "targets/releases",
Keys: map[string]data.PublicKey{"A": nil, "B": nil},
Threshold: 1,
},
}
var loadedAliceRole = data.DelegationRole{
BaseRole: data.BaseRole{
Name: "targets/alice",
Keys: map[string]data.PublicKey{"A": nil},
Threshold: 1,
},
}
var loadedBobRole = data.DelegationRole{
BaseRole: data.BaseRole{
Name: "targets/bob",
Keys: map[string]data.PublicKey{"B": nil},
Threshold: 1,
},
}
var loadedDelegationRoles = []data.Role{
{
Name: loadedReleasesRole.Name,
RootRole: data.RootRole{
KeyIDs: []string{"A", "B"},
Threshold: 1,
},
},
{
Name: loadedAliceRole.Name,
RootRole: data.RootRole{
KeyIDs: []string{"A"},
Threshold: 1,
},
},
{
Name: loadedBobRole.Name,
RootRole: data.RootRole{
KeyIDs: []string{"B"},
Threshold: 1,
},
},
}
var loadedTargetsRole = data.DelegationRole{
BaseRole: data.BaseRole{
Name: data.CanonicalTargetsRole,
Keys: map[string]data.PublicKey{"C": nil},
Threshold: 1,
},
}
// LoadedNotaryRepository has three targets:
// - red: signed by targets/releases, targets/alice, targets/bob
// - blue: signed by targets/releases, targets/alice
// - green: signed by targets/releases
var loadedRedTarget = client.Target{
Name: "red",
Hashes: data.Hashes{"sha256": []byte("red-digest")},
}
var loadedBlueTarget = client.Target{
Name: "blue",
Hashes: data.Hashes{"sha256": []byte("blue-digest")},
}
var loadedGreenTarget = client.Target{
Name: "green",
Hashes: data.Hashes{"sha256": []byte("green-digest")},
}
var loadedTargets = []client.TargetSignedStruct{
// red is signed by all three delegations
{Target: loadedRedTarget, Role: loadedReleasesRole},
{Target: loadedRedTarget, Role: loadedAliceRole},
{Target: loadedRedTarget, Role: loadedBobRole},
// blue is signed by targets/releases, targets/alice
{Target: loadedBlueTarget, Role: loadedReleasesRole},
{Target: loadedBlueTarget, Role: loadedAliceRole},
// green is signed by targets/releases
{Target: loadedGreenTarget, Role: loadedReleasesRole},
}
func (l LoadedNotaryRepository) ListRoles() ([]client.RoleWithSignatures, error) {
rootRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"rootID"},
Threshold: 1,
},
Name: data.CanonicalRootRole,
}
targetsRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"targetsID"},
Threshold: 1,
},
Name: data.CanonicalTargetsRole,
}
return []client.RoleWithSignatures{{Role: rootRole}, {Role: targetsRole}}, nil
}
func (l LoadedNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
filteredTargets := []*client.TargetWithRole{}
for _, tgt := range loadedTargets {
if len(roles) == 0 || (len(roles) > 0 && roles[0] == tgt.Role.Name) {
filteredTargets = append(filteredTargets, &client.TargetWithRole{Target: tgt.Target, Role: tgt.Role.Name})
}
}
return filteredTargets, nil
}
func (l LoadedNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
for _, tgt := range loadedTargets {
if name == tgt.Target.Name {
if len(roles) == 0 || (len(roles) > 0 && roles[0] == tgt.Role.Name) {
return &client.TargetWithRole{Target: tgt.Target, Role: tgt.Role.Name}, nil
}
}
}
return nil, client.ErrNoSuchTarget(name)
}
func (l LoadedNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
if name == "" {
return loadedTargets, nil
}
filteredTargets := []client.TargetSignedStruct{}
for _, tgt := range loadedTargets {
if name == tgt.Target.Name {
filteredTargets = append(filteredTargets, tgt)
}
}
if len(filteredTargets) == 0 {
return nil, client.ErrNoSuchTarget(name)
}
return filteredTargets, nil
}
func (l LoadedNotaryRepository) GetGUN() data.GUN {
return data.GUN("signed-repo")
}
func (l LoadedNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
return loadedDelegationRoles, nil
}
func (l LoadedNotaryRepository) GetCryptoService() signed.CryptoService {
if l.statefulCryptoService == nil {
// give it an in-memory cryptoservice with a root key and targets key
l.statefulCryptoService = cryptoservice.NewCryptoService(trustmanager.NewKeyMemoryStore(passphrase.ConstantRetriever("password")))
l.statefulCryptoService.AddKey(data.CanonicalRootRole, l.GetGUN(), nil)
l.statefulCryptoService.AddKey(data.CanonicalTargetsRole, l.GetGUN(), nil)
}
return l.statefulCryptoService
}
func getLoadedWithNoSignersNotaryRepository(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (client.Repository, error) {
return LoadedWithNoSignersNotaryRepository{}, nil
}
// LoadedWithNoSignersNotaryRepository is a mock Notary repository that is loaded with targets but no delegations
// it only contains the green target
type LoadedWithNoSignersNotaryRepository struct {
LoadedNotaryRepository
}
func (l LoadedWithNoSignersNotaryRepository) ListTargets(roles ...data.RoleName) ([]*client.TargetWithRole, error) {
filteredTargets := []*client.TargetWithRole{}
for _, tgt := range loadedTargets {
if len(roles) == 0 || (len(roles) > 0 && roles[0] == tgt.Role.Name) {
filteredTargets = append(filteredTargets, &client.TargetWithRole{Target: tgt.Target, Role: tgt.Role.Name})
}
}
return filteredTargets, nil
}
func (l LoadedWithNoSignersNotaryRepository) GetTargetByName(name string, roles ...data.RoleName) (*client.TargetWithRole, error) {
if name == "" || name == loadedGreenTarget.Name {
return &client.TargetWithRole{Target: loadedGreenTarget, Role: data.CanonicalTargetsRole}, nil
}
return nil, client.ErrNoSuchTarget(name)
}
func (l LoadedWithNoSignersNotaryRepository) GetAllTargetMetadataByName(name string) ([]client.TargetSignedStruct, error) {
if name == "" || name == loadedGreenTarget.Name {
return []client.TargetSignedStruct{{Target: loadedGreenTarget, Role: loadedTargetsRole}}, nil
}
return nil, client.ErrNoSuchTarget(name)
}
func (l LoadedWithNoSignersNotaryRepository) GetDelegationRoles() ([]data.Role, error) {
return []data.Role{}, nil
}

View File

@ -0,0 +1,23 @@
package trust
import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
)
// NewTrustCommand returns a cobra command for `trust` subcommands
func NewTrustCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "trust",
Short: "Manage trust on Docker images (experimental)",
Args: cli.NoArgs,
RunE: command.ShowHelp(dockerCli.Err()),
}
cmd.AddCommand(
newViewCommand(dockerCli),
newRevokeCommand(dockerCli),
newSignCommand(dockerCli),
)
return cmd
}

View File

@ -0,0 +1,33 @@
package trust
import (
"strings"
"github.com/docker/cli/cli/trust"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
)
const releasedRoleName = "Repo Admin"
// check if a role name is "released": either targets/releases or targets TUF roles
func isReleasedTarget(role data.RoleName) bool {
return role == data.CanonicalTargetsRole || role == trust.ReleasesRole
}
// convert TUF role name to a human-understandable signer name
func notaryRoleToSigner(tufRole data.RoleName) string {
// don't show a signer for "targets" or "targets/releases"
if isReleasedTarget(data.RoleName(tufRole.String())) {
return releasedRoleName
}
return strings.TrimPrefix(tufRole.String(), "targets/")
}
func clearChangeList(notaryRepo client.Repository) error {
cl, err := notaryRepo.GetChangelist()
if err != nil {
return err
}
return cl.Clear("")
}

View File

@ -0,0 +1,125 @@
package trust
import (
"context"
"fmt"
"os"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image"
"github.com/docker/cli/cli/trust"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
type revokeOptions struct {
forceYes bool
}
func newRevokeCommand(dockerCli command.Cli) *cobra.Command {
options := revokeOptions{}
cmd := &cobra.Command{
Use: "revoke [OPTIONS] IMAGE[:TAG]",
Short: "Remove trust for an image",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return revokeTrust(dockerCli, args[0], options)
},
}
flags := cmd.Flags()
flags.BoolVarP(&options.forceYes, "yes", "y", false, "Do not prompt for confirmation")
return cmd
}
func revokeTrust(cli command.Cli, remote string, options revokeOptions) error {
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
if err != nil {
return err
}
tag := imgRefAndAuth.Tag()
if imgRefAndAuth.Tag() == "" && imgRefAndAuth.Digest() != "" {
return fmt.Errorf("cannot use a digest reference for IMAGE:TAG")
}
if imgRefAndAuth.Tag() == "" && !options.forceYes {
deleteRemote := command.PromptForConfirmation(os.Stdin, cli.Out(), fmt.Sprintf("Please confirm you would like to delete all signature data for %s?", remote))
if !deleteRemote {
fmt.Fprintf(cli.Out(), "\nAborting action.\n")
return nil
}
}
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull)
if err != nil {
return err
}
if err = clearChangeList(notaryRepo); err != nil {
return err
}
defer clearChangeList(notaryRepo)
if err := revokeSignature(notaryRepo, tag); err != nil {
return errors.Wrapf(err, "could not remove signature for %s", remote)
}
fmt.Fprintf(cli.Out(), "Successfully deleted signature for %s\n", remote)
return nil
}
func revokeSignature(notaryRepo client.Repository, tag string) error {
if tag != "" {
// Revoke signature for the specified tag
if err := revokeSingleSig(notaryRepo, tag); err != nil {
return err
}
} else {
// revoke all signatures for the image, as no tag was given
if err := revokeAllSigs(notaryRepo); err != nil {
return err
}
}
// Publish change
return notaryRepo.Publish()
}
func revokeSingleSig(notaryRepo client.Repository, tag string) error {
releasedTargetWithRole, err := notaryRepo.GetTargetByName(tag, trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return err
}
releasedTarget := releasedTargetWithRole.Target
return getSignableRolesForTargetAndRemove(releasedTarget, notaryRepo)
}
func revokeAllSigs(notaryRepo client.Repository) error {
releasedTargetWithRoleList, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole)
if err != nil {
return err
}
if len(releasedTargetWithRoleList) == 0 {
return fmt.Errorf("no signed tags to remove")
}
// we need all the roles that signed each released target so we can remove from all roles.
for _, releasedTargetWithRole := range releasedTargetWithRoleList {
// remove from all roles
if err := getSignableRolesForTargetAndRemove(releasedTargetWithRole.Target, notaryRepo); err != nil {
return err
}
}
return nil
}
// get all the roles that signed the target and removes it from all roles.
func getSignableRolesForTargetAndRemove(releasedTarget client.Target, notaryRepo client.Repository) error {
signableRoles, err := trust.GetSignableRoles(notaryRepo, &releasedTarget)
if err != nil {
return err
}
// remove from all roles
return notaryRepo.RemoveTarget(releasedTarget.Name, signableRoles...)
}

View File

@ -0,0 +1,148 @@
package trust
import (
"io/ioutil"
"os"
"testing"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/notary/client"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/trustpinning"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestTrustRevokeCommandErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
}{
{
name: "not-enough-args",
expectedError: "requires exactly 1 argument",
},
{
name: "too-many-args",
args: []string{"remote1", "remote2"},
expectedError: "requires exactly 1 argument",
},
{
name: "sha-reference",
args: []string{"870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"},
expectedError: "invalid repository name",
},
{
name: "invalid-img-reference",
args: []string{"ALPINE"},
expectedError: "invalid reference format",
},
{
name: "digest-reference",
args: []string{"ubuntu@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2"},
expectedError: "cannot use a digest reference for IMAGE:TAG",
},
}
for _, tc := range testCases {
cmd := newRevokeCommand(
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestTrustRevokeCommandOfflineErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd := newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image"})
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action.")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
cmd.SetOutput(ioutil.Discard)
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image:tag"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image:tag: client is offline")
}
func TestTrustRevokeCommandUninitializedErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getUninitializedNotaryRepository)
cmd := newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image"})
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action.")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getUninitializedNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image: does not have trust data for")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getUninitializedNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image:tag"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image:tag: does not have trust data for")
}
func TestTrustRevokeCommandEmptyNotaryRepo(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd := newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image"})
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] \nAborting action.")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image", "-y"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image: no signed tags to remove")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd = newRevokeCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image:tag"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "could not remove signature for reg-name.io/image:tag: No valid trust data for tag")
}
func TestNewRevokeTrustAllSigConfirmation(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd := newRevokeCommand(cli)
cmd.SetArgs([]string{"alpine"})
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "Please confirm you would like to delete all signature data for alpine? [y/N] \nAborting action.")
}
func TestGetSignableRolesForTargetAndRemoveError(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
require.NoError(t, err)
target := client.Target{}
err = getSignableRolesForTargetAndRemove(target, notaryRepo)
assert.EqualError(t, err, "client is offline")
}

View File

@ -0,0 +1,227 @@
package trust
import (
"context"
"fmt"
"io"
"path"
"sort"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/image"
"github.com/docker/cli/cli/trust"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
func newSignCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "sign IMAGE:TAG",
Short: "Sign an image",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runSignImage(dockerCli, args[0])
},
}
return cmd
}
func runSignImage(cli command.Cli, imageName string) error {
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), imageName)
if err != nil {
return err
}
if err := validateTag(imgRefAndAuth); err != nil {
return err
}
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPushAndPull)
if err != nil {
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
}
if err = clearChangeList(notaryRepo); err != nil {
return err
}
defer clearChangeList(notaryRepo)
// get the latest repository metadata so we can figure out which roles to sign
if _, err = notaryRepo.ListTargets(); err != nil {
switch err.(type) {
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
// before initializing a new repo, check that the image exists locally:
if err := checkLocalImageExistence(ctx, cli, imageName); err != nil {
return err
}
userRole := data.RoleName(path.Join(data.CanonicalTargetsRole.String(), imgRefAndAuth.AuthConfig().Username))
if err := initNotaryRepoWithSigners(notaryRepo, userRole); err != nil {
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
}
fmt.Fprintf(cli.Out(), "Created signer: %s\n", imgRefAndAuth.AuthConfig().Username)
fmt.Fprintf(cli.Out(), "Finished initializing signed repository for %s\n", imageName)
default:
return trust.NotaryError(imgRefAndAuth.RepoInfo().Name.Name(), err)
}
}
requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(cli, imgRefAndAuth.RepoInfo().Index, "push")
target, err := createTarget(notaryRepo, imgRefAndAuth.Tag())
if err != nil {
switch err := err.(type) {
case client.ErrNoSuchTarget, client.ErrRepositoryNotExist:
// Fail fast if the image doesn't exist locally
if err := checkLocalImageExistence(ctx, cli, imageName); err != nil {
return err
}
return image.TrustedPush(ctx, cli, imgRefAndAuth.RepoInfo(), imgRefAndAuth.Reference(), *imgRefAndAuth.AuthConfig(), requestPrivilege)
default:
return err
}
}
return signAndPublishToTarget(cli.Out(), imgRefAndAuth, notaryRepo, target)
}
func signAndPublishToTarget(out io.Writer, imgRefAndAuth trust.ImageRefAndAuth, notaryRepo client.Repository, target client.Target) error {
tag := imgRefAndAuth.Tag()
fmt.Fprintf(out, "Signing and pushing trust metadata for %s\n", imgRefAndAuth.Name())
existingSigInfo, err := getExistingSignatureInfoForReleasedTag(notaryRepo, tag)
if err != nil {
return err
}
err = image.AddTargetToAllSignableRoles(notaryRepo, &target)
if err == nil {
prettyPrintExistingSignatureInfo(out, existingSigInfo)
err = notaryRepo.Publish()
}
if err != nil {
return errors.Wrapf(err, "failed to sign %q:%s", imgRefAndAuth.RepoInfo().Name.Name(), tag)
}
fmt.Fprintf(out, "Successfully signed %q:%s\n", imgRefAndAuth.RepoInfo().Name.Name(), tag)
return nil
}
func validateTag(imgRefAndAuth trust.ImageRefAndAuth) error {
tag := imgRefAndAuth.Tag()
if tag == "" {
if imgRefAndAuth.Digest() != "" {
return fmt.Errorf("cannot use a digest reference for IMAGE:TAG")
}
return fmt.Errorf("No tag specified for %s", imgRefAndAuth.Name())
}
return nil
}
func checkLocalImageExistence(ctx context.Context, cli command.Cli, imageName string) error {
_, _, err := cli.Client().ImageInspectWithRaw(ctx, imageName)
return err
}
func createTarget(notaryRepo client.Repository, tag string) (client.Target, error) {
target := &client.Target{}
var err error
if tag == "" {
return *target, fmt.Errorf("No tag specified")
}
target.Name = tag
target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, tag)
return *target, err
}
func getSignedManifestHashAndSize(notaryRepo client.Repository, tag string) (data.Hashes, int64, error) {
targets, err := notaryRepo.GetAllTargetMetadataByName(tag)
if err != nil {
return nil, 0, err
}
return getReleasedTargetHashAndSize(targets, tag)
}
func getReleasedTargetHashAndSize(targets []client.TargetSignedStruct, tag string) (data.Hashes, int64, error) {
for _, tgt := range targets {
if isReleasedTarget(tgt.Role.Name) {
return tgt.Target.Hashes, tgt.Target.Length, nil
}
}
return nil, 0, client.ErrNoSuchTarget(tag)
}
func getExistingSignatureInfoForReleasedTag(notaryRepo client.Repository, tag string) (trustTagRow, error) {
targets, err := notaryRepo.GetAllTargetMetadataByName(tag)
if err != nil {
return trustTagRow{}, err
}
releasedTargetInfoList := matchReleasedSignatures(targets)
if len(releasedTargetInfoList) == 0 {
return trustTagRow{}, nil
}
return releasedTargetInfoList[0], nil
}
func prettyPrintExistingSignatureInfo(out io.Writer, existingSigInfo trustTagRow) {
sort.Strings(existingSigInfo.Signers)
joinedSigners := strings.Join(existingSigInfo.Signers, ", ")
fmt.Fprintf(out, "Existing signatures for tag %s digest %s from:\n%s\n", existingSigInfo.TagName, existingSigInfo.HashHex, joinedSigners)
}
func initNotaryRepoWithSigners(notaryRepo client.Repository, newSigner data.RoleName) error {
rootKey, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
if err != nil {
return err
}
rootKeyID := rootKey.ID()
// Initialize the notary repository with a remotely managed snapshot key
if err := notaryRepo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil {
return err
}
signerKey, err := getOrGenerateNotaryKey(notaryRepo, newSigner)
if err != nil {
return err
}
addStagedSigner(notaryRepo, newSigner, []data.PublicKey{signerKey})
return notaryRepo.Publish()
}
// generates an ECDSA key without a GUN for the specified role
func getOrGenerateNotaryKey(notaryRepo client.Repository, role data.RoleName) (data.PublicKey, error) {
// use the signer name in the PEM headers if this is a delegation key
if data.IsDelegation(role) {
role = data.RoleName(notaryRoleToSigner(role))
}
keys := notaryRepo.GetCryptoService().ListKeys(role)
var err error
var key data.PublicKey
// always select the first key by ID
if len(keys) > 0 {
sort.Strings(keys)
keyID := keys[0]
privKey, _, err := notaryRepo.GetCryptoService().GetPrivateKey(keyID)
if err != nil {
return nil, err
}
key = data.PublicKeyFromPrivate(privKey)
} else {
key, err = notaryRepo.GetCryptoService().Create(role, "", data.ECDSAKey)
if err != nil {
return nil, err
}
}
return key, nil
}
// stages changes to add a signer with the specified name and key(s). Adds to targets/<name> and targets/releases
func addStagedSigner(notaryRepo client.Repository, newSigner data.RoleName, signerKeys []data.PublicKey) {
// create targets/<username>
notaryRepo.AddDelegationRoleAndKeys(newSigner, signerKeys)
notaryRepo.AddDelegationPaths(newSigner, []string{""})
// create targets/releases
notaryRepo.AddDelegationRoleAndKeys(trust.ReleasesRole, signerKeys)
notaryRepo.AddDelegationPaths(trust.ReleasesRole, []string{""})
}

View File

@ -0,0 +1,297 @@
package trust
import (
"encoding/json"
"io/ioutil"
"os"
"testing"
"bytes"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
"github.com/docker/notary"
"github.com/docker/notary/client"
"github.com/docker/notary/client/changelist"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/trustpinning"
"github.com/docker/notary/tuf/data"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const passwd = "password"
func TestTrustSignCommandErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
}{
{
name: "not-enough-args",
expectedError: "requires exactly 1 argument",
},
{
name: "too-many-args",
args: []string{"image", "tag"},
expectedError: "requires exactly 1 argument",
},
{
name: "sha-reference",
args: []string{"870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"},
expectedError: "invalid repository name",
},
{
name: "invalid-img-reference",
args: []string{"ALPINE:latest"},
expectedError: "invalid reference format",
},
{
name: "no-tag",
args: []string{"reg/img"},
expectedError: "No tag specified for reg/img",
},
{
name: "digest-reference",
args: []string{"ubuntu@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2"},
expectedError: "cannot use a digest reference for IMAGE:TAG",
},
}
// change to a tmpdir
tmpDir, err := ioutil.TempDir("", "docker-sign-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
config.SetDir(tmpDir)
for _, tc := range testCases {
cmd := newSignCommand(
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestTrustSignCommandOfflineErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd := newSignCommand(cli)
cmd.SetArgs([]string{"reg-name.io/image:tag"})
cmd.SetOutput(ioutil.Discard)
assert.Error(t, cmd.Execute())
testutil.ErrorContains(t, cmd.Execute(), "client is offline")
}
func TestGetOrGenerateNotaryKey(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
// repo is empty, try making a root key
rootKeyA, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
assert.NoError(t, err)
assert.NotNil(t, rootKeyA)
// we should only have one newly generated key
allKeys := notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 1)
assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(rootKeyA.ID()))
// this time we should get back the same key if we ask for another root key
rootKeyB, err := getOrGenerateNotaryKey(notaryRepo, data.CanonicalRootRole)
assert.NoError(t, err)
assert.NotNil(t, rootKeyB)
// we should only have one newly generated key
allKeys = notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 1)
assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(rootKeyB.ID()))
// The key we retrieved should be identical to the one we generated
assert.Equal(t, rootKeyA, rootKeyB)
// Now also try with a delegation key
releasesKey, err := getOrGenerateNotaryKey(notaryRepo, data.RoleName(trust.ReleasesRole))
assert.NoError(t, err)
assert.NotNil(t, releasesKey)
// we should now have two keys
allKeys = notaryRepo.GetCryptoService().ListAllKeys()
assert.Len(t, allKeys, 2)
assert.NotNil(t, notaryRepo.GetCryptoService().GetKey(releasesKey.ID()))
// The key we retrieved should be identical to the one we generated
assert.NotEqual(t, releasesKey, rootKeyA)
assert.NotEqual(t, releasesKey, rootKeyB)
}
func TestAddStageSigners(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
// stage targets/user
userRole := data.RoleName("targets/user")
userKey := data.NewPublicKey("algoA", []byte("a"))
addStagedSigner(notaryRepo, userRole, []data.PublicKey{userKey})
// check the changelist for four total changes: two on targets/releases and two on targets/user
cl, err := notaryRepo.GetChangelist()
assert.NoError(t, err)
changeList := cl.List()
assert.Len(t, changeList, 4)
// ordering is determinstic:
// first change is for targets/user key creation
newSignerKeyChange := changeList[0]
expectedJSON, err := json.Marshal(&changelist.TUFDelegation{
NewThreshold: notary.MinThreshold,
AddKeys: data.KeyList([]data.PublicKey{userKey}),
})
require.NoError(t, err)
expectedChange := changelist.NewTUFChange(
changelist.ActionCreate,
userRole,
changelist.TypeTargetsDelegation,
"", // no path for delegations
expectedJSON,
)
assert.Equal(t, expectedChange, newSignerKeyChange)
// second change is for targets/user getting all paths
newSignerPathsChange := changeList[1]
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
AddPaths: []string{""},
})
require.NoError(t, err)
expectedChange = changelist.NewTUFChange(
changelist.ActionCreate,
userRole,
changelist.TypeTargetsDelegation,
"", // no path for delegations
expectedJSON,
)
assert.Equal(t, expectedChange, newSignerPathsChange)
releasesRole := data.RoleName("targets/releases")
// third change is for targets/releases key creation
releasesKeyChange := changeList[2]
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
NewThreshold: notary.MinThreshold,
AddKeys: data.KeyList([]data.PublicKey{userKey}),
})
require.NoError(t, err)
expectedChange = changelist.NewTUFChange(
changelist.ActionCreate,
releasesRole,
changelist.TypeTargetsDelegation,
"", // no path for delegations
expectedJSON,
)
assert.Equal(t, expectedChange, releasesKeyChange)
// fourth change is for targets/releases getting all paths
releasesPathsChange := changeList[3]
expectedJSON, err = json.Marshal(&changelist.TUFDelegation{
AddPaths: []string{""},
})
require.NoError(t, err)
expectedChange = changelist.NewTUFChange(
changelist.ActionCreate,
releasesRole,
changelist.TypeTargetsDelegation,
"", // no path for delegations
expectedJSON,
)
assert.Equal(t, expectedChange, releasesPathsChange)
}
func TestGetSignedManifestHashAndSize(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
target := &client.Target{}
target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, "test")
assert.EqualError(t, err, "client is offline")
}
func TestGetReleasedTargetHashAndSize(t *testing.T) {
oneReleasedTgt := []client.TargetSignedStruct{}
// make and append 3 non-released signatures on the "unreleased" target
unreleasedTgt := client.Target{Name: "unreleased", Hashes: data.Hashes{notary.SHA256: []byte("hash")}}
for _, unreleasedRole := range []string{"targets/a", "targets/b", "targets/c"} {
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName(unreleasedRole), Target: unreleasedTgt})
}
_, _, err := getReleasedTargetHashAndSize(oneReleasedTgt, "unreleased")
assert.EqualError(t, err, "No valid trust data for unreleased")
releasedTgt := client.Target{Name: "released", Hashes: data.Hashes{notary.SHA256: []byte("released-hash")}}
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: releasedTgt})
hash, _, _ := getReleasedTargetHashAndSize(oneReleasedTgt, "unreleased")
assert.Equal(t, data.Hashes{notary.SHA256: []byte("released-hash")}, hash)
}
func TestCreateTarget(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
_, err = createTarget(notaryRepo, "")
assert.EqualError(t, err, "No tag specified")
_, err = createTarget(notaryRepo, "1")
assert.EqualError(t, err, "client is offline")
}
func TestGetExistingSignatureInfoForReleasedTag(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "notary-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "gun", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
_, err = getExistingSignatureInfoForReleasedTag(notaryRepo, "test")
assert.EqualError(t, err, "client is offline")
}
func TestPrettyPrintExistingSignatureInfo(t *testing.T) {
buf := bytes.NewBuffer(nil)
signers := []string{"Bob", "Alice", "Carol"}
existingSig := trustTagRow{trustTagKey{"tagName", "abc123"}, signers}
prettyPrintExistingSignatureInfo(buf, existingSig)
assert.Contains(t, buf.String(), "Existing signatures for tag tagName digest abc123 from:\nAlice, Bob, Carol")
}
func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "docker-sign-test-")
assert.NoError(t, err)
defer os.RemoveAll(tmpDir)
config.SetDir(tmpDir)
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedNotaryRepository)
cmd := newSignCommand(cli)
cmd.SetArgs([]string{"ubuntu:latest"})
cmd.SetOutput(ioutil.Discard)
err = cmd.Execute()
require.Error(t, err)
notaryRepo, err := client.NewFileCachedRepository(tmpDir, "docker.io/library/ubuntu", "https://localhost", nil, passphrase.ConstantRetriever(passwd), trustpinning.TrustPinConfig{})
assert.NoError(t, err)
cl, err := notaryRepo.GetChangelist()
require.NoError(t, err)
assert.Equal(t, len(cl.List()), 0)
}

View File

@ -0,0 +1,6 @@
SIGNED TAG DIGEST SIGNERS
green 677265656e2d646967657374 (Repo Admin)
Administrative keys for signed-repo:
Repository Key: targetsID
Root Key: rootID

View File

@ -0,0 +1,14 @@
SIGNED TAG DIGEST SIGNERS
blue 626c75652d646967657374 alice
green 677265656e2d646967657374 (Repo Admin)
red 7265642d646967657374 alice, bob
List of signers and their keys for signed-repo:
SIGNER KEYS
alice A
bob B
Administrative keys for signed-repo:
Repository Key: targetsID
Root Key: rootID

View File

@ -0,0 +1,6 @@
SIGNED TAG DIGEST SIGNERS
green 677265656e2d646967657374 (Repo Admin)
Administrative keys for signed-repo:
Repository Key: targetsID
Root Key: rootID

View File

@ -0,0 +1,13 @@
No signatures for signed-repo:unsigned
List of signers and their keys for signed-repo:
SIGNER KEYS
alice A
bob B
Administrative keys for signed-repo:
Repository Key: targetsID
Root Key: rootID

View File

@ -0,0 +1,227 @@
package trust
import (
"context"
"encoding/hex"
"fmt"
"io"
"sort"
"strings"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter"
"github.com/docker/cli/cli/command/image"
"github.com/docker/cli/cli/trust"
"github.com/docker/notary"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// trustTagKey represents a unique signed tag and hex-encoded hash pair
type trustTagKey struct {
TagName string
HashHex string
}
// trustTagRow encodes all human-consumable information for a signed tag, including signers
type trustTagRow struct {
trustTagKey
Signers []string
}
type trustTagRowList []trustTagRow
func (tagComparator trustTagRowList) Len() int {
return len(tagComparator)
}
func (tagComparator trustTagRowList) Less(i, j int) bool {
return tagComparator[i].TagName < tagComparator[j].TagName
}
func (tagComparator trustTagRowList) Swap(i, j int) {
tagComparator[i], tagComparator[j] = tagComparator[j], tagComparator[i]
}
func newViewCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "view IMAGE[:TAG]",
Short: "Display detailed information about keys and signatures",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return lookupTrustInfo(dockerCli, args[0])
},
}
return cmd
}
func lookupTrustInfo(cli command.Cli, remote string) error {
ctx := context.Background()
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, image.AuthResolver(cli), remote)
if err != nil {
return err
}
tag := imgRefAndAuth.Tag()
notaryRepo, err := cli.NotaryClient(imgRefAndAuth, trust.ActionsPullOnly)
if err != nil {
return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
}
if err = clearChangeList(notaryRepo); err != nil {
return err
}
defer clearChangeList(notaryRepo)
// Retrieve all released signatures, match them, and pretty print them
allSignedTargets, err := notaryRepo.GetAllTargetMetadataByName(tag)
if err != nil {
logrus.Debug(trust.NotaryError(imgRefAndAuth.Reference().Name(), err))
// print an empty table if we don't have signed targets, but have an initialized notary repo
if _, ok := err.(client.ErrNoSuchTarget); !ok {
return fmt.Errorf("No signatures or cannot access %s", remote)
}
}
signatureRows := matchReleasedSignatures(allSignedTargets)
if len(signatureRows) > 0 {
if err := printSignatures(cli.Out(), signatureRows); err != nil {
return err
}
} else {
fmt.Fprintf(cli.Out(), "\nNo signatures for %s\n\n", remote)
}
// get the administrative roles
adminRolesWithSigs, err := notaryRepo.ListRoles()
if err != nil {
return fmt.Errorf("No signers for %s", remote)
}
// get delegation roles with the canonical key IDs
delegationRoles, err := notaryRepo.GetDelegationRoles()
if err != nil {
logrus.Debugf("no delegation roles found, or error fetching them for %s: %v", remote, err)
}
signerRoleToKeyIDs := getDelegationRoleToKeyMap(delegationRoles)
// If we do not have additional signers, do not display
if len(signerRoleToKeyIDs) > 0 {
fmt.Fprintf(cli.Out(), "\nList of signers and their keys for %s:\n\n", strings.Split(remote, ":")[0])
if err := printSignerInfo(cli.Out(), signerRoleToKeyIDs); err != nil {
return err
}
}
// This will always have the root and targets information
fmt.Fprintf(cli.Out(), "\nAdministrative keys for %s:\n", strings.Split(remote, ":")[0])
printSortedAdminKeys(cli.Out(), adminRolesWithSigs)
return nil
}
func printSortedAdminKeys(out io.Writer, adminRoles []client.RoleWithSignatures) {
sort.Slice(adminRoles, func(i, j int) bool { return adminRoles[i].Name > adminRoles[j].Name })
for _, adminRole := range adminRoles {
fmt.Fprintf(out, "%s", formatAdminRole(adminRole))
}
}
func formatAdminRole(roleWithSigs client.RoleWithSignatures) string {
adminKeyList := roleWithSigs.KeyIDs
sort.Strings(adminKeyList)
var role string
switch roleWithSigs.Name {
case data.CanonicalTargetsRole:
role = "Repository Key"
case data.CanonicalRootRole:
role = "Root Key"
default:
return ""
}
return fmt.Sprintf("%s:\t%s\n", role, strings.Join(adminKeyList, ", "))
}
func getDelegationRoleToKeyMap(rawDelegationRoles []data.Role) map[string][]string {
signerRoleToKeyIDs := make(map[string][]string)
for _, delRole := range rawDelegationRoles {
switch delRole.Name {
case trust.ReleasesRole, data.CanonicalRootRole, data.CanonicalSnapshotRole, data.CanonicalTargetsRole, data.CanonicalTimestampRole:
continue
default:
signerRoleToKeyIDs[notaryRoleToSigner(delRole.Name)] = delRole.KeyIDs
}
}
return signerRoleToKeyIDs
}
// aggregate all signers for a "released" hash+tagname pair. To be "released," the tag must have been
// signed into the "targets" or "targets/releases" role. Output is sorted by tag name
func matchReleasedSignatures(allTargets []client.TargetSignedStruct) trustTagRowList {
signatureRows := trustTagRowList{}
// do a first pass to get filter on tags signed into "targets" or "targets/releases"
releasedTargetRows := map[trustTagKey][]string{}
for _, tgt := range allTargets {
if isReleasedTarget(tgt.Role.Name) {
releasedKey := trustTagKey{tgt.Target.Name, hex.EncodeToString(tgt.Target.Hashes[notary.SHA256])}
releasedTargetRows[releasedKey] = []string{}
}
}
// now fill out all signers on released keys
for _, tgt := range allTargets {
targetKey := trustTagKey{tgt.Target.Name, hex.EncodeToString(tgt.Target.Hashes[notary.SHA256])}
// only considered released targets
if _, ok := releasedTargetRows[targetKey]; ok && !isReleasedTarget(tgt.Role.Name) {
releasedTargetRows[targetKey] = append(releasedTargetRows[targetKey], notaryRoleToSigner(tgt.Role.Name))
}
}
// compile the final output as a sorted slice
for targetKey, signers := range releasedTargetRows {
signatureRows = append(signatureRows, trustTagRow{targetKey, signers})
}
sort.Sort(signatureRows)
return signatureRows
}
// pretty print with ordered rows
func printSignatures(out io.Writer, signatureRows trustTagRowList) error {
trustTagCtx := formatter.Context{
Output: out,
Format: formatter.NewTrustTagFormat(),
}
// convert the formatted type before printing
formattedTags := []formatter.SignedTagInfo{}
for _, sigRow := range signatureRows {
formattedSigners := sigRow.Signers
if len(formattedSigners) == 0 {
formattedSigners = append(formattedSigners, fmt.Sprintf("(%s)", releasedRoleName))
}
formattedTags = append(formattedTags, formatter.SignedTagInfo{
Name: sigRow.TagName,
Digest: sigRow.HashHex,
Signers: formattedSigners,
})
}
return formatter.TrustTagWrite(trustTagCtx, formattedTags)
}
func printSignerInfo(out io.Writer, roleToKeyIDs map[string][]string) error {
signerInfoCtx := formatter.Context{
Output: out,
Format: formatter.NewSignerInfoFormat(),
Trunc: true,
}
formattedSignerInfo := formatter.SignerInfoList{}
for name, keyIDs := range roleToKeyIDs {
formattedSignerInfo = append(formattedSignerInfo, formatter.SignerInfo{
Name: name,
Keys: keyIDs,
})
}
sort.Sort(formattedSignerInfo)
return formatter.SignerInfoWrite(signerInfoCtx, formattedSignerInfo)
}

View File

@ -0,0 +1,433 @@
package trust
import (
"encoding/hex"
"io/ioutil"
"testing"
"github.com/docker/cli/cli/trust"
"github.com/docker/cli/internal/test"
"github.com/docker/cli/internal/test/testutil"
dockerClient "github.com/docker/docker/client"
"github.com/docker/notary"
"github.com/docker/notary/client"
"github.com/docker/notary/tuf/data"
"github.com/gotestyourself/gotestyourself/golden"
"github.com/stretchr/testify/assert"
)
type fakeClient struct {
dockerClient.Client
}
func TestTrustInspectCommandErrors(t *testing.T) {
testCases := []struct {
name string
args []string
expectedError string
}{
{
name: "not-enough-args",
expectedError: "requires exactly 1 argument",
},
{
name: "too-many-args",
args: []string{"remote1", "remote2"},
expectedError: "requires exactly 1 argument",
},
{
name: "sha-reference",
args: []string{"870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"},
expectedError: "invalid repository name",
},
{
name: "invalid-img-reference",
args: []string{"ALPINE"},
expectedError: "invalid reference format",
},
}
for _, tc := range testCases {
cmd := newViewCommand(
test.NewFakeCli(&fakeClient{}))
cmd.SetArgs(tc.args)
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
func TestTrustInspectCommandOfflineErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"nonexistent-reg-name.io/image"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "No signatures or cannot access nonexistent-reg-name.io/image")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getOfflineNotaryRepository)
cmd = newViewCommand(cli)
cmd.SetArgs([]string{"nonexistent-reg-name.io/image:tag"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "No signatures or cannot access nonexistent-reg-name.io/image")
}
func TestTrustInspectCommandUninitializedErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getUninitializedNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"reg/unsigned-img"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "No signatures or cannot access reg/unsigned-img")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getUninitializedNotaryRepository)
cmd = newViewCommand(cli)
cmd.SetArgs([]string{"reg/unsigned-img:tag"})
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), "No signatures or cannot access reg/unsigned-img:tag")
}
func TestTrustInspectCommandEmptyNotaryRepoErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"reg/img:unsigned-tag"})
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "No signatures for reg/img:unsigned-tag")
assert.Contains(t, cli.OutBuffer().String(), "Administrative keys for reg/img:")
cli = test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getEmptyTargetsNotaryRepository)
cmd = newViewCommand(cli)
cmd.SetArgs([]string{"reg/img"})
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Contains(t, cli.OutBuffer().String(), "No signatures for reg/img")
assert.Contains(t, cli.OutBuffer().String(), "Administrative keys for reg/img:")
}
func TestTrustInspectCommandFullRepoWithoutSigners(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"signed-repo"})
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-full-repo-no-signers.golden")
}
func TestTrustInspectCommandOneTagWithoutSigners(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedWithNoSignersNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"signed-repo:green"})
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-one-tag-no-signers.golden")
}
func TestTrustInspectCommandFullRepoWithSigners(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"signed-repo"})
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-full-repo-with-signers.golden")
}
func TestTrustInspectCommandUnsignedTagInSignedRepo(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(getLoadedNotaryRepository)
cmd := newViewCommand(cli)
cmd.SetArgs([]string{"signed-repo:unsigned"})
assert.NoError(t, cmd.Execute())
golden.Assert(t, cli.OutBuffer().String(), "trust-inspect-unsigned-tag-with-signers.golden")
}
func TestNotaryRoleToSigner(t *testing.T) {
assert.Equal(t, releasedRoleName, notaryRoleToSigner(data.CanonicalTargetsRole))
assert.Equal(t, releasedRoleName, notaryRoleToSigner(trust.ReleasesRole))
assert.Equal(t, "signer", notaryRoleToSigner("targets/signer"))
assert.Equal(t, "docker/signer", notaryRoleToSigner("targets/docker/signer"))
// It's nonsense for other base roles to have signed off on a target, but this function leaves role names intact
for _, role := range data.BaseRoles {
if role == data.CanonicalTargetsRole {
continue
}
assert.Equal(t, role.String(), notaryRoleToSigner(role))
}
assert.Equal(t, "notarole", notaryRoleToSigner(data.RoleName("notarole")))
}
// check if a role name is "released": either targets/releases or targets TUF roles
func TestIsReleasedTarget(t *testing.T) {
assert.True(t, isReleasedTarget(trust.ReleasesRole))
for _, role := range data.BaseRoles {
assert.Equal(t, role == data.CanonicalTargetsRole, isReleasedTarget(role))
}
assert.False(t, isReleasedTarget(data.RoleName("targets/not-releases")))
assert.False(t, isReleasedTarget(data.RoleName("random")))
assert.False(t, isReleasedTarget(data.RoleName("targets/releases/subrole")))
}
// creates a mock delegation with a given name and no keys
func mockDelegationRoleWithName(name string) data.DelegationRole {
baseRole := data.NewBaseRole(
data.RoleName(name),
notary.MinThreshold,
)
return data.DelegationRole{baseRole, []string{}}
}
func TestMatchEmptySignatures(t *testing.T) {
// first try empty targets
emptyTgts := []client.TargetSignedStruct{}
matchedSigRows := matchReleasedSignatures(emptyTgts)
assert.Empty(t, matchedSigRows)
}
func TestMatchUnreleasedSignatures(t *testing.T) {
// try an "unreleased" target with 3 signatures, 0 rows will appear
unreleasedTgts := []client.TargetSignedStruct{}
tgt := client.Target{Name: "unreleased", Hashes: data.Hashes{notary.SHA256: []byte("hash")}}
for _, unreleasedRole := range []string{"targets/a", "targets/b", "targets/c"} {
unreleasedTgts = append(unreleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName(unreleasedRole), Target: tgt})
}
matchedSigRows := matchReleasedSignatures(unreleasedTgts)
assert.Empty(t, matchedSigRows)
}
func TestMatchOneReleasedSingleSignature(t *testing.T) {
// now try only 1 "released" target with no additional sigs, 1 row will appear with 0 signers
oneReleasedTgt := []client.TargetSignedStruct{}
// make and append the "released" target to our mock input
releasedTgt := client.Target{Name: "released", Hashes: data.Hashes{notary.SHA256: []byte("released-hash")}}
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: releasedTgt})
// make and append 3 non-released signatures on the "unreleased" target
unreleasedTgt := client.Target{Name: "unreleased", Hashes: data.Hashes{notary.SHA256: []byte("hash")}}
for _, unreleasedRole := range []string{"targets/a", "targets/b", "targets/c"} {
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName(unreleasedRole), Target: unreleasedTgt})
}
matchedSigRows := matchReleasedSignatures(oneReleasedTgt)
assert.Len(t, matchedSigRows, 1)
outputRow := matchedSigRows[0]
// Empty signers because "targets/releases" doesn't show up
assert.Empty(t, outputRow.Signers)
assert.Equal(t, releasedTgt.Name, outputRow.TagName)
assert.Equal(t, hex.EncodeToString(releasedTgt.Hashes[notary.SHA256]), outputRow.HashHex)
}
func TestMatchOneReleasedMultiSignature(t *testing.T) {
// now try only 1 "released" target with 3 additional sigs, 1 row will appear with 3 signers
oneReleasedTgt := []client.TargetSignedStruct{}
// make and append the "released" target to our mock input
releasedTgt := client.Target{Name: "released", Hashes: data.Hashes{notary.SHA256: []byte("released-hash")}}
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: releasedTgt})
// make and append 3 non-released signatures on both the "released" and "unreleased" targets
unreleasedTgt := client.Target{Name: "unreleased", Hashes: data.Hashes{notary.SHA256: []byte("hash")}}
for _, unreleasedRole := range []string{"targets/a", "targets/b", "targets/c"} {
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName(unreleasedRole), Target: unreleasedTgt})
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName(unreleasedRole), Target: releasedTgt})
}
matchedSigRows := matchReleasedSignatures(oneReleasedTgt)
assert.Len(t, matchedSigRows, 1)
outputRow := matchedSigRows[0]
// We should have three signers
assert.Equal(t, outputRow.Signers, []string{"a", "b", "c"})
assert.Equal(t, releasedTgt.Name, outputRow.TagName)
assert.Equal(t, hex.EncodeToString(releasedTgt.Hashes[notary.SHA256]), outputRow.HashHex)
}
func TestMatchMultiReleasedMultiSignature(t *testing.T) {
// now try 3 "released" targets with additional sigs to show 3 rows as follows:
// target-a is signed by targets/releases and targets/a - a will be the signer
// target-b is signed by targets/releases, targets/a, targets/b - a and b will be the signers
// target-c is signed by targets/releases, targets/a, targets/b, targets/c - a, b, and c will be the signers
multiReleasedTgts := []client.TargetSignedStruct{}
// make target-a, target-b, and target-c
targetA := client.Target{Name: "target-a", Hashes: data.Hashes{notary.SHA256: []byte("target-a-hash")}}
targetB := client.Target{Name: "target-b", Hashes: data.Hashes{notary.SHA256: []byte("target-b-hash")}}
targetC := client.Target{Name: "target-c", Hashes: data.Hashes{notary.SHA256: []byte("target-c-hash")}}
// have targets/releases "sign" on all of these targets so they are released
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: targetA})
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: targetB})
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/releases"), Target: targetC})
// targets/a signs off on all three targets (target-a, target-b, target-c):
for _, tgt := range []client.Target{targetA, targetB, targetC} {
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/a"), Target: tgt})
}
// targets/b signs off on the final two targets (target-b, target-c):
for _, tgt := range []client.Target{targetB, targetC} {
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/b"), Target: tgt})
}
// targets/c only signs off on the last target (target-c):
multiReleasedTgts = append(multiReleasedTgts, client.TargetSignedStruct{Role: mockDelegationRoleWithName("targets/c"), Target: targetC})
matchedSigRows := matchReleasedSignatures(multiReleasedTgts)
assert.Len(t, matchedSigRows, 3)
// note that the output is sorted by tag name, so we can reliably index to validate data:
outputTargetA := matchedSigRows[0]
assert.Equal(t, outputTargetA.Signers, []string{"a"})
assert.Equal(t, targetA.Name, outputTargetA.TagName)
assert.Equal(t, hex.EncodeToString(targetA.Hashes[notary.SHA256]), outputTargetA.HashHex)
outputTargetB := matchedSigRows[1]
assert.Equal(t, outputTargetB.Signers, []string{"a", "b"})
assert.Equal(t, targetB.Name, outputTargetB.TagName)
assert.Equal(t, hex.EncodeToString(targetB.Hashes[notary.SHA256]), outputTargetB.HashHex)
outputTargetC := matchedSigRows[2]
assert.Equal(t, outputTargetC.Signers, []string{"a", "b", "c"})
assert.Equal(t, targetC.Name, outputTargetC.TagName)
assert.Equal(t, hex.EncodeToString(targetC.Hashes[notary.SHA256]), outputTargetC.HashHex)
}
func TestMatchReleasedSignatureFromTargets(t *testing.T) {
// now try only 1 "released" target with no additional sigs, one rows will appear
oneReleasedTgt := []client.TargetSignedStruct{}
// make and append the "released" target to our mock input
releasedTgt := client.Target{Name: "released", Hashes: data.Hashes{notary.SHA256: []byte("released-hash")}}
oneReleasedTgt = append(oneReleasedTgt, client.TargetSignedStruct{Role: mockDelegationRoleWithName(data.CanonicalTargetsRole.String()), Target: releasedTgt})
matchedSigRows := matchReleasedSignatures(oneReleasedTgt)
assert.Len(t, matchedSigRows, 1)
outputRow := matchedSigRows[0]
// Empty signers because "targets" doesn't show up
assert.Empty(t, outputRow.Signers)
assert.Equal(t, releasedTgt.Name, outputRow.TagName)
assert.Equal(t, hex.EncodeToString(releasedTgt.Hashes[notary.SHA256]), outputRow.HashHex)
}
func TestGetSignerRolesWithKeyIDs(t *testing.T) {
roles := []data.Role{
{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: "targets/alice",
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key21", "key22"},
},
Name: "targets/releases",
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key31"},
},
Name: data.CanonicalTargetsRole,
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key41", "key01"},
},
Name: data.CanonicalRootRole,
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key51"},
},
Name: data.CanonicalSnapshotRole,
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key61"},
},
Name: data.CanonicalTimestampRole,
},
{
RootRole: data.RootRole{
KeyIDs: []string{"key71", "key72"},
},
Name: "targets/bob",
},
}
expectedSignerRoleToKeyIDs := map[string][]string{
"alice": {"key11"},
"bob": {"key71", "key72"},
}
var roleWithSigs []client.RoleWithSignatures
for _, role := range roles {
roleWithSig := client.RoleWithSignatures{Role: role, Signatures: nil}
roleWithSigs = append(roleWithSigs, roleWithSig)
}
signerRoleToKeyIDs := getDelegationRoleToKeyMap(roles)
assert.Equal(t, expectedSignerRoleToKeyIDs, signerRoleToKeyIDs)
}
func TestFormatAdminRole(t *testing.T) {
aliceRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: "targets/alice",
}
aliceRoleWithSigs := client.RoleWithSignatures{Role: aliceRole, Signatures: nil}
assert.Equal(t, "", formatAdminRole(aliceRoleWithSigs))
releasesRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: "targets/releases",
}
releasesRoleWithSigs := client.RoleWithSignatures{Role: releasesRole, Signatures: nil}
assert.Equal(t, "", formatAdminRole(releasesRoleWithSigs))
timestampRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: data.CanonicalTimestampRole,
}
timestampRoleWithSigs := client.RoleWithSignatures{Role: timestampRole, Signatures: nil}
assert.Equal(t, "", formatAdminRole(timestampRoleWithSigs))
snapshotRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: data.CanonicalSnapshotRole,
}
snapshotRoleWithSigs := client.RoleWithSignatures{Role: snapshotRole, Signatures: nil}
assert.Equal(t, "", formatAdminRole(snapshotRoleWithSigs))
rootRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key11"},
},
Name: data.CanonicalRootRole,
}
rootRoleWithSigs := client.RoleWithSignatures{Role: rootRole, Signatures: nil}
assert.Equal(t, "Root Key:\tkey11\n", formatAdminRole(rootRoleWithSigs))
targetsRole := data.Role{
RootRole: data.RootRole{
KeyIDs: []string{"key99", "abc", "key11"},
},
Name: data.CanonicalTargetsRole,
}
targetsRoleWithSigs := client.RoleWithSignatures{Role: targetsRole, Signatures: nil}
assert.Equal(t, "Repository Key:\tabc, key11, key99\n", formatAdminRole(targetsRoleWithSigs))
}

View File

@ -2,6 +2,21 @@ version: "3.4"
services:
foo:
build:
context: ./dir
dockerfile: Dockerfile
args:
foo: bar
target: foo
network: foo
cache_from:
- foo
- bar
labels: [FOO=BAR]
cap_add:
- ALL

View File

@ -221,6 +221,7 @@ func createTransformHook() mapstructure.DecodeHookFuncType {
reflect.TypeOf(types.Labels{}): transformMappingOrListFunc("=", false),
reflect.TypeOf(types.MappingWithColon{}): transformMappingOrListFunc(":", false),
reflect.TypeOf(types.ServiceVolumeConfig{}): transformServiceVolumeConfig,
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig,
}
return func(_ reflect.Type, target reflect.Type, data interface{}) (interface{}, error) {
@ -563,6 +564,17 @@ func transformStringSourceMap(data interface{}) (interface{}, error) {
}
}
func transformBuildConfig(data interface{}) (interface{}, error) {
switch value := data.(type) {
case string:
return map[string]interface{}{"context": value}, nil
case map[string]interface{}:
return data, nil
default:
return data, errors.Errorf("invalid type %T for service build", value)
}
}
func transformServiceVolumeConfig(data interface{}) (interface{}, error) {
switch value := data.(type) {
case string:

View File

@ -10,6 +10,7 @@ import (
"github.com/docker/cli/cli/compose/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func buildConfigDetails(source map[string]interface{}, env map[string]string) types.ConfigDetails {
@ -164,17 +165,13 @@ var sampleConfig = types.Config{
func TestParseYAML(t *testing.T) {
dict, err := ParseYAML([]byte(sampleYAML))
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
assert.Equal(t, sampleDict, dict)
}
func TestLoad(t *testing.T) {
actual, err := Load(buildConfigDetails(sampleDict, nil))
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
assert.Equal(t, serviceSort(sampleConfig.Services), serviceSort(actual.Services))
assert.Equal(t, sampleConfig.Networks, actual.Networks)
assert.Equal(t, sampleConfig.Volumes, actual.Volumes)
@ -191,11 +188,9 @@ secrets:
super:
external: true
`)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, len(actual.Services), 1)
assert.Equal(t, len(actual.Secrets), 1)
require.NoError(t, err)
assert.Len(t, actual.Services, 1)
assert.Len(t, actual.Secrets, 1)
}
func TestLoadV33(t *testing.T) {
@ -211,19 +206,15 @@ configs:
super:
external: true
`)
if !assert.NoError(t, err) {
return
}
assert.Equal(t, len(actual.Services), 1)
require.NoError(t, err)
require.Len(t, actual.Services, 1)
assert.Equal(t, actual.Services[0].CredentialSpec.File, "/foo")
assert.Equal(t, len(actual.Configs), 1)
require.Len(t, actual.Configs, 1)
}
func TestParseAndLoad(t *testing.T) {
actual, err := loadYAML(sampleYAML)
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
assert.Equal(t, serviceSort(sampleConfig.Services), serviceSort(actual.Services))
assert.Equal(t, sampleConfig.Networks, actual.Networks)
assert.Equal(t, sampleConfig.Volumes, actual.Volumes)
@ -231,15 +222,15 @@ func TestParseAndLoad(t *testing.T) {
func TestInvalidTopLevelObjectType(t *testing.T) {
_, err := loadYAML("1")
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
_, err = loadYAML("\"hello\"")
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
_, err = loadYAML("[\"hello\"]")
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
}
@ -250,7 +241,7 @@ version: "3"
foo:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key at top level: 123")
_, err = loadYAML(`
@ -261,7 +252,7 @@ services:
123:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in services: 123")
_, err = loadYAML(`
@ -275,7 +266,7 @@ networks:
config:
- 123: oh dear
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in networks.default.ipam.config[0]: 123")
_, err = loadYAML(`
@ -286,7 +277,7 @@ services:
environment:
1: FOO
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in services.dict-env.environment: 1")
}
@ -297,7 +288,7 @@ services:
foo:
image: busybox
`)
assert.NoError(t, err)
require.NoError(t, err)
_, err = loadYAML(`
version: "3.0"
@ -305,7 +296,7 @@ services:
foo:
image: busybox
`)
assert.NoError(t, err)
require.NoError(t, err)
}
func TestUnsupportedVersion(t *testing.T) {
@ -315,7 +306,7 @@ services:
foo:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "version")
_, err = loadYAML(`
@ -324,7 +315,7 @@ services:
foo:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "version")
}
@ -335,7 +326,7 @@ services:
foo:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "version must be a string")
}
@ -354,7 +345,7 @@ services:
- foo:
image: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "services must be a mapping")
_, err = loadYAML(`
@ -362,7 +353,7 @@ version: "3"
services:
foo: busybox
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "services.foo must be a mapping")
_, err = loadYAML(`
@ -371,7 +362,7 @@ networks:
- default:
driver: bridge
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "networks must be a mapping")
_, err = loadYAML(`
@ -379,7 +370,7 @@ version: "3"
networks:
default: bridge
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "networks.default must be a mapping")
_, err = loadYAML(`
@ -388,7 +379,7 @@ volumes:
- data:
driver: local
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "volumes must be a mapping")
_, err = loadYAML(`
@ -396,7 +387,7 @@ version: "3"
volumes:
data: local
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "volumes.data must be a mapping")
}
@ -407,7 +398,7 @@ services:
foo:
image: ["busybox", "latest"]
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "services.foo.image must be a string")
}
@ -458,7 +449,7 @@ services:
environment:
FOO: ["1"]
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "services.dict-env.environment.FOO must be a string, number or null")
}
@ -470,7 +461,7 @@ services:
image: busybox
environment: "FOO=1"
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "services.dict-env.environment must be a mapping")
}
@ -497,7 +488,7 @@ volumes:
"FOO": "foo",
})
assert.NoError(t, err)
require.NoError(t, err)
expectedLabels := types.Labels{
"home1": home,
@ -517,24 +508,46 @@ version: "3"
services:
web:
image: web
build: ./web
build:
context: ./web
links:
- bar
db:
image: db
build: ./db
build:
context: ./db
`))
assert.NoError(t, err)
require.NoError(t, err)
configDetails := buildConfigDetails(dict, nil)
_, err = Load(configDetails)
assert.NoError(t, err)
require.NoError(t, err)
unsupported := GetUnsupportedProperties(configDetails)
assert.Equal(t, []string{"build", "links"}, unsupported)
}
func TestBuildProperties(t *testing.T) {
dict, err := ParseYAML([]byte(`
version: "3"
services:
web:
image: web
build: .
links:
- bar
db:
image: db
build:
context: ./db
`))
require.NoError(t, err)
configDetails := buildConfigDetails(dict, nil)
_, err = Load(configDetails)
require.NoError(t, err)
}
func TestDeprecatedProperties(t *testing.T) {
dict, err := ParseYAML([]byte(`
version: "3"
@ -547,15 +560,15 @@ services:
container_name: db
expose: ["5434"]
`))
assert.NoError(t, err)
require.NoError(t, err)
configDetails := buildConfigDetails(dict, nil)
_, err = Load(configDetails)
assert.NoError(t, err)
require.NoError(t, err)
deprecated := GetDeprecatedProperties(configDetails)
assert.Equal(t, 2, len(deprecated))
assert.Len(t, deprecated, 2)
assert.Contains(t, deprecated, "container_name")
assert.Contains(t, deprecated, "expose")
}
@ -574,12 +587,12 @@ services:
service: foo
`)
assert.Error(t, err)
require.Error(t, err)
assert.IsType(t, &ForbiddenPropertiesError{}, err)
fmt.Println(err)
forbidden := err.(*ForbiddenPropertiesError).Properties
assert.Equal(t, 2, len(forbidden))
assert.Len(t, forbidden, 2)
assert.Contains(t, forbidden, "volume_driver")
assert.Contains(t, forbidden, "extends")
}
@ -595,7 +608,7 @@ func TestInvalidResource(t *testing.T) {
impossible:
x: 1
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "Additional property impossible is not allowed")
}
@ -608,7 +621,7 @@ volumes:
driver: foobar
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "conflicting parameters \"external\" and \"driver\" specified for volume")
assert.Contains(t, err.Error(), "external_volume")
}
@ -623,7 +636,7 @@ volumes:
beep: boop
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "conflicting parameters \"external\" and \"driver_opts\" specified for volume")
assert.Contains(t, err.Error(), "external_volume")
}
@ -638,7 +651,7 @@ volumes:
- beep=boop
`)
assert.Error(t, err)
require.Error(t, err)
assert.Contains(t, err.Error(), "conflicting parameters \"external\" and \"labels\" specified for volume")
assert.Contains(t, err.Error(), "external_volume")
}
@ -653,8 +666,7 @@ volumes:
name: external_name
`)
assert.Error(t, err)
fmt.Println(err)
require.Error(t, err)
assert.Contains(t, err.Error(), "volume.external.name and volume.name conflict; only use volume.name")
assert.Contains(t, err.Error(), "external_volume")
}
@ -669,23 +681,30 @@ func uint64Ptr(value uint64) *uint64 {
func TestFullExample(t *testing.T) {
bytes, err := ioutil.ReadFile("full-example.yml")
assert.NoError(t, err)
require.NoError(t, err)
homeDir := "/home/foo"
env := map[string]string{"HOME": homeDir, "QUX": "qux_from_environment"}
config, err := loadYAMLWithEnv(string(bytes), env)
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
workingDir, err := os.Getwd()
assert.NoError(t, err)
require.NoError(t, err)
stopGracePeriod := time.Duration(20 * time.Second)
expectedServiceConfig := types.ServiceConfig{
Name: "foo",
Build: types.BuildConfig{
Context: "./dir",
Dockerfile: "Dockerfile",
Args: map[string]*string{"foo": strPtr("bar")},
Target: "foo",
Network: "foo",
CacheFrom: []string{"foo", "bar"},
Labels: map[string]string{"FOO": "BAR"},
},
CapAdd: []string{"ALL"},
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
CgroupParent: "m-executor-abcd",
@ -1069,9 +1088,7 @@ networks:
mynet2:
driver: bridge
`)
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
expected := map[string]types.NetworkConfig{
"mynet1": {
@ -1105,9 +1122,7 @@ services:
target: 22
published: 10022
`)
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
expected := []types.ServicePortConfig{
{
@ -1170,7 +1185,7 @@ services:
},
}
assert.Equal(t, 1, len(config.Services))
assert.Len(t, config.Services, 1)
assert.Equal(t, expected, config.Services[0].Ports)
}
@ -1188,9 +1203,7 @@ services:
volumes:
foo: {}
`)
if !assert.NoError(t, err) {
return
}
require.NoError(t, err)
expected := types.ServiceVolumeConfig{
Type: "volume",
@ -1199,7 +1212,7 @@ volumes:
ReadOnly: true,
}
assert.Equal(t, 1, len(config.Services))
assert.Equal(t, 1, len(config.Services[0].Volumes))
require.Len(t, config.Services, 1)
assert.Len(t, config.Services[0].Volumes, 1)
assert.Equal(t, expected, config.Services[0].Volumes[0])
}

View File

@ -79,6 +79,7 @@ type Config struct {
type ServiceConfig struct {
Name string
Build BuildConfig
CapAdd []string `mapstructure:"cap_add"`
CapDrop []string `mapstructure:"cap_drop"`
CgroupParent string `mapstructure:"cgroup_parent"`
@ -126,6 +127,18 @@ type ServiceConfig struct {
WorkingDir string `mapstructure:"working_dir"`
}
// BuildConfig is a type for build
// using the same format at libcompose: https://github.com/docker/libcompose/blob/master/yaml/build.go#L12
type BuildConfig struct {
Context string
Dockerfile string
Args MappingWithEquals
Labels Labels
CacheFrom StringList `mapstructure:"cache_from"`
Network string
Target string
}
// ShellCommand is a string or list of string args
type ShellCommand []string

View File

@ -7,13 +7,15 @@ import (
// DetectDefaultStore return the default credentials store for the platform if
// the store executable is available.
func DetectDefaultStore(store string) string {
platformDefault := defaultCredentialsStore()
// user defined or no default for platform
if store != "" || defaultCredentialsStore == "" {
if store != "" || platformDefault == "" {
return store
}
if _, err := exec.LookPath(remoteCredentialsPrefix + defaultCredentialsStore); err == nil {
return defaultCredentialsStore
if _, err := exec.LookPath(remoteCredentialsPrefix + platformDefault); err == nil {
return platformDefault
}
return ""
}

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