Compare commits

...

131 Commits

Author SHA1 Message Date
James Hunt b58a22a7e1 Allow "docker info" to recognise Clear Linux.
As per os-release spec, /usr/lib/os-release file should be tried if
/etc/os-release is missing.

http://www.freedesktop.org/software/systemd/man/os-release.html

Signed-off-by: James Hunt <james.o.hunt@intel.com>
Signed-off-by: Dimitri John Ledkov <dimitri.j.ledkov@intel.com>
2015-10-20 12:00:31 +01:00
Phil Estes 8eba018b61 Merge pull request #17155 from janten/meitner
Correct Lise Meitner's name, add Euler and Noether
2015-10-19 08:26:55 -04:00
Phil Estes 1f9557ac66 Merge pull request #17166 from echo33/docker_cli_diff_test
use of checkers on docker_cli_diff_test.go
2015-10-19 08:25:32 -04:00
Phil Estes 1c783567c0 Merge pull request #17167 from liaoqingwei/16756-docker_cli_inspect_experimental_test.go
Use of checkers on docker_cli_inspect_experimental_test.go
2015-10-19 08:21:17 -04:00
liaoqingwei f3b2b8700f Use of checkers on docker_cli_inspect_experimental_test.go.
Signed-off-by: liaoqingwei <liaoqingwei@huawei.com>
2015-10-19 19:44:04 +08:00
weiyan 7be79767c1 use of checkers on docker_cli_diff_test.go
Signed-off-by: weiyan <weiyan3@huawei.com>
2015-10-19 19:07:59 +08:00
Antonio Murdaca eaa1fc41c6 Merge pull request #16897 from sunyuan3/docker_cli_rm_test
use of checkers on docker_cli_rm_test.go
2015-10-19 09:14:23 +02:00
Vincent Demeester cfdb954303 Merge pull request #17162 from echo33/docker_cli_exec_unix_test
use of checkers on docker_cli_exec_unix_test.go
2015-10-19 08:54:42 +02:00
weiyan d65ac42ca8 use of checkers on docker_cli_exec_unix_test.go
Signed-off-by: weiyan <weiyan3@huawei.com>
2015-10-19 15:14:59 +08:00
Yuan Sun 0780ddc498 use of checkers on docker_cli_rm_test.go
Signed-off-by: Yuan Sun <sunyuan3@huawei.com>
2015-10-19 10:42:56 +08:00
Jan-Gerd Tenberge ab31d9500e Fix spelling error, add Noether and Euler
Signed-off-by: Jan-Gerd Tenberge <janten@gmail.com>
2015-10-19 01:14:39 +02:00
moxiegirl bab701c143 Merge pull request #17157 from ripcurld00d/fedora_doc
Update fedora doc
2015-10-18 14:41:07 -07:00
ripcurld00d 6a64865991 Update fedora doc
`service` is deprecated from Fedora v21.
It's important to enable and start the `docker` daemon using `systemctl`.

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
2015-10-18 23:00:23 +03:00
Vincent Demeester bece5b82a8 Merge pull request #17008 from liaoqingwei/dev1
Update testcases: use of checkers on docker_cli_nat_test.go
2015-10-18 18:11:02 +02:00
liaoqingwei 26ae6d6b36 Use of checkers on docker_cli_nat_test.go.
Signed-off-by: liaoqingwei <liaoqingwei@huawei.com>
2015-10-18 20:02:55 +08:00
moxiegirl ef49d127e3 Merge pull request #17141 from thaJeztah/fix-17140-storage-driver-formatting
docs: fix storage driver options list
2015-10-17 19:33:40 -07:00
Sebastiaan van Stijn 8f36ded5b1 docs: fix storage driver options list
This fixes the indentation of the storage driver
options list.

Also wraps/reformats some examples to prevent
horizontal scrollbars on the rendered HTML

Fixes #17140

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2015-10-17 19:17:07 -07:00
Vincent Batts 2726434f72 Merge pull request #16960 from pydima/9283_consider_hard_links_in_image_size
Consider hardlinks in image size.
2015-10-17 14:22:33 -04:00
Sebastiaan van Stijn cffd50752c Merge pull request #17056 from vdemeester/16756-integration-cli-checkers-api-build
Vendoring new go-check checkers and use checker for docker_api_build_test.go
2015-10-17 08:50:51 -07:00
Vincent Demeester 253f975fdb Use checker assert for docker_api_build_test.go
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-10-17 14:28:13 +02:00
Vincent Demeester 9685b4767f Vendoring shakers library and update go-check
The shakers library defines a bunch of go-check checkers to ease
writing tests.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-10-17 14:28:08 +02:00
Brian Goff 9b1fb0d45b Merge pull request #16871 from ZJU-SEL/fix_version_test
update docker_cli_version_test.go
2015-10-17 08:02:18 -04:00
Dmitry Vorobev 4102537cfd Fixes #9283. Consider hardlinks in image size.
Based on #8984. This patch fixes behavior when image size calculation
didn't consider hardlinks.

Signed-off-by: Dmitry Vorobev <dimahabr@gmail.com>
2015-10-17 12:24:05 +02:00
Antonio Murdaca ab1f03397e Merge pull request #17119 from vdemeester/17117-deprecate-c-cli-opts
Deprecate -c cli short variant flag in docker cli build & create
2015-10-17 10:22:46 +02:00
Sebastiaan van Stijn e3fabf3ea1 Merge pull request #16831 from jfrazelle/release-updates
Release updates
2015-10-16 16:57:10 -07:00
David Calavera c3f42b29a8 Merge pull request #17113 from mountkin/validate-filter
make sure the value of the dangling filter is correct
2015-10-16 16:32:11 -07:00
Tibor Vass 365a0db0f0 Merge pull request #17046 from mavenugo/dopts
driver-opts for network create
2015-10-16 15:23:59 -07:00
David Calavera ec7c368ff0 Merge pull request #16901 from WeiZhang555/rmi-inte
Update integration test `integration-cli/docker_cli_rmi_test.go` with Assert
2015-10-16 15:23:00 -07:00
Vincent Demeester d8b4471a59 Merge pull request #16977 from mountkin/refactor-test
refactor integration test to use checkers
2015-10-17 00:22:03 +02:00
Antonio Murdaca 4fc97e40c9 Merge pull request #16950 from cpuguy83/support_ipv6_in_host_parser
Allow API to bind to ipv6 addresses
2015-10-17 00:20:49 +02:00
David Calavera 8c1fa7f320 Merge pull request #16994 from Microsoft/10662-copied
Windows: Fix annoying bad log
2015-10-16 15:14:08 -07:00
David Calavera 475be776b8 Merge pull request #17051 from thaJeztah/fix-volume-readonly-doc
remove incorrect "readonly" example
2015-10-16 15:11:48 -07:00
Vincent Demeester d1064bd441 Deprecate -c cli short variant flag in docker cli
- build
- create

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
2015-10-17 00:05:34 +02:00
David Calavera 258357857b Merge pull request #17065 from ZJaffee/api-exec-resize-test
cleaned up integration-cli/docker_api_exec_resize_test.go
2015-10-16 14:59:06 -07:00
David Calavera 3668be932e Merge pull request #16574 from Djelibeybi/rpm-changelog
Generate a full RPM changelog from the existing CHANGELOG.md file
2015-10-16 14:55:39 -07:00
Madhu Venugopal 6f3eb994b5 Pass network driver option in docker network command
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-10-16 14:33:54 -07:00
Madhu Venugopal cf1b5fe601 Vendoring libnetwork to Replace the label variable to DriverOpts
Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-10-16 14:30:57 -07:00
Tibor Vass e23d834a01 Merge pull request #17106 from albers/completion-import
Add missing options to bash completion for `docker import`
2015-10-16 14:28:14 -07:00
Tibor Vass b1bab9e1e7 Merge pull request #17107 from albers/completion-build
Add missing options to bash completion for `docker build`
2015-10-16 14:27:51 -07:00
Vincent Demeester c56b02b284 Merge pull request #17081 from ZJaffee/api_network_test
Cleaned up integration-cli/docker_api_network_test.go
2015-10-16 23:14:17 +02:00
Vincent Demeester 8b90aefd14 Merge pull request #17121 from sdurrheimer/zsh-completion-fix-double-dash-option-arguments
Zsh : all --<option>= flag values may be given in the next argument
2015-10-16 23:13:25 +02:00
Brian Goff 84be89a273 Merge pull request #16969 from zhangjianfnst/16756-improve-integration-cli
Use c.Assert in integration-cli/docker_cli_logs_test.go
2015-10-16 16:55:44 -04:00
Steve Durrheimer b34aa69e8f Zsh completion : all --<option>= flag values may be given in the next argument
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-16 21:18:27 +02:00
Sebastiaan van Stijn ccf5b60c6f Merge pull request #17098 from sdurrheimer/zsh-completion-import-message
Add zsh completion for 'docker import -m --message'
2015-10-16 11:36:46 -07:00
Tibor Vass b054a88af1 Merge pull request #17093 from endophage/update_notary_gotuf
updating notary and gotuf with latest bugfixes
2015-10-16 11:19:21 -07:00
Zachary Jaffee 7b6bca5af1 cleaned up integration-cli/docker_api_exec_resize_test.go
Signed-off-by: Zachary Jaffee <zij@case.edu>
2015-10-16 13:22:40 -04:00
Sebastiaan van Stijn e2870bda43 Merge pull request #17085 from dnephin/add_digest_to_api_docs
Correct API docs for /images/create
2015-10-16 10:10:41 -07:00
Vincent Demeester 2afdab4454 Merge pull request #17100 from WeiZhang555/port-inte
update docker_cli_port_test.go with Assert
2015-10-16 19:06:14 +02:00
David Lawrence 7ce9f02751 updating notary and gotuf with latest bugfixes
Signed-off-by: David Lawrence <david.lawrence@docker.com>
2015-10-16 09:33:26 -07:00
David Calavera 841205ec01 Merge pull request #17062 from coolljt0725/fix_cancel
Fix cancel build doesn't remove the intermediate container
2015-10-16 09:06:09 -07:00
Brian Goff 08a43b8b3b Merge pull request #17101 from sdurrheimer/zsh-completion-deprecate-run-dash-c-option
Deprecate 'docker run -c' option in zsh completion
2015-10-16 11:40:02 -04:00
Brian Goff 30b945fac9 Merge pull request #17099 from sdurrheimer/zsh-completion-restart-unless-stopped
Add zsh completion for 'unless-stopped' restart policy
2015-10-16 11:37:27 -04:00
Vincent Demeester 71982d8e57 Merge pull request #17105 from liaoqingwei/dev3
Use of checkers on docker_cli_pause_test.go.
2015-10-16 17:36:56 +02:00
David Calavera 579cf43f0f Merge pull request #17102 from sdurrheimer/zsh-completion-build-build-arg
Add zsh completion for 'docker build --build-arg'
2015-10-16 08:34:12 -07:00
David Calavera f9026e2b7b Merge pull request #17078 from kevinkucharczyk/api_version_test
Clean up integration-cli/docker_api_version_test.go
2015-10-16 08:26:53 -07:00
Zhang Wei 1ae4eeb813 update docker_cli_port_test.go with Assert
Part of #16756

Use c.Assert instead of condition judgement

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2015-10-16 22:58:51 +08:00
Shijiang Wei 98c1a412b4 make sure the value of the dangling filter is correct
Signed-off-by: Shijiang Wei <mountkin@gmail.com>
2015-10-16 22:09:32 +08:00
Brian Goff 835fbee9a2 Merge pull request #17053 from liaoqingwei/dev2
use of checkers on docker_cli_network_unix_test.go
2015-10-16 09:36:59 -04:00
Brian Goff 60b5b0d380 Merge pull request #17112 from moxiegirl/fix-16961-tic
Removing extra tic
2015-10-16 09:10:12 -04:00
Mary Anthony ee30af5ffb bad d
Signed-off-by: Mary Anthony <mary@docker.com>
2015-10-16 06:09:03 -07:00
Mary Anthony e44876bf1f Removing extra tic
Signed-off-by: Mary Anthony <mary@docker.com>
2015-10-16 06:07:52 -07:00
liaoqingwei 851a533a82 Use of checkers on docker_cli_pause_test.go.
Signed-off-by: liaoqingwei <liaoqingwei@huawei.com>
2015-10-16 21:07:02 +08:00
Harald Albers b0315375f8 Add missing options to bash completion for docker import
Signed-off-by: Harald Albers <github@albersweb.de>
2015-10-16 12:42:12 +02:00
Harald Albers 3a713d91ce bash completion: minor refactoring for consistency
Signed-off-by: Harald Albers <github@albersweb.de>
2015-10-16 12:41:09 +02:00
Harald Albers 28c66b0491 Add missing options to bash completion for docker build
Signed-off-by: Harald Albers <github@albersweb.de>
2015-10-16 12:40:55 +02:00
Antonio Murdaca dee57e4c3e Merge pull request #17087 from LK4D4/speedup_ps
Speedup container list
2015-10-16 12:35:28 +02:00
Lei Jitang 9392de9dfe Fix cancel build doesn't remove the intermediate container
Signed-off-by: Lei Jitang <leijitang@huawei.com>
2015-10-16 05:18:10 -04:00
liaoqingwei 9e3db08363 Use of checkers on docker_cli_network_unix_test.go.
Signed-off-by: liaoqingwei <liaoqingwei@huawei.com>
2015-10-16 16:56:40 +08:00
Steve Durrheimer 96a09ea77c Add zsh completion for 'docker import -m --message'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-16 10:14:42 +02:00
Steve Durrheimer 89e0990224 Add zsh completion for 'docker build --build-arg'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-16 08:48:12 +02:00
Steve Durrheimer c37c9df18a Deprecate 'docker run -c' option in zsh completion
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-16 08:37:16 +02:00
Steve Durrheimer cb2bd8bcec Add zsh completion for 'unless-stopped' restart policy
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-16 08:30:56 +02:00
Kevin P. Kucharczyk 6f1b5946b1 Clean up integration-cli/docker_api_version_test.go
Signed-off-by: Kevin P. Kucharczyk <kevinkucharczyk@gmail.com>
2015-10-16 07:03:39 +02:00
Alexander Morozov f256d8ad2d Speedup container list
Remove all unneeded disk operations (reload TagStore, umarshal image)
for checking if image still points to same ID. Now slowest part is
queries to sqlite which hopefuly will be removed soon.

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
2015-10-15 20:41:35 -07:00
Vincent Batts d35a1f2868 Merge pull request #16932 from c0b/fix-race-16924
Fix race #16924 [panic: runtime error: slice bounds out of range] docker daemon crash of racing
2015-10-15 18:05:05 -05:00
Vincent Demeester 1052ff674c Merge pull request #17073 from ZJaffee/api_events_test
Cleaned up integration-cli/docker_api_events_test.go
2015-10-16 00:22:29 +02:00
Vincent Demeester 58b36ba242 Merge pull request #17080 from ZJaffee/api_logs_test
Cleaned up integration-cli/docker_api_logs_test.go
2015-10-16 00:21:30 +02:00
David Calavera e1804098b9 Merge pull request #16997 from Microsoft/10662-kill-parttwo
Windows: [TP4] docker kill handling part two
2015-10-15 14:42:19 -07:00
Jess Frazelle ebfed4d474 Merge pull request #17082 from sdurrheimer/zsh-completion-remove-network-ls-old-options
Remove 'docker network ls -n -l --latest' options from in zsh completion
2015-10-15 13:48:39 -07:00
Jess Frazelle ff4026fa5b Merge pull request #17084 from sdurrheimer/zsh-completion-network-ipam
Add zsh completion for '--ipam-driver --subnet --ip-range --gateway -…
2015-10-15 13:48:19 -07:00
Daniel Nephin 2ec4404ba0 Correct API docs for /images/create
Signed-off-by: Daniel Nephin <dnephin@docker.com>
2015-10-15 16:00:05 -04:00
Steve Durrheimer a00c0d795d Add zsh completion for '--ipam-driver --subnet --ip-range --gateway --aux-address' for 'docker network create'
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-15 21:40:50 +02:00
Steve Durrheimer 080a906aac Remove '-n -l --latest' options from 'docker network ls' in zsh completion
Signed-off-by: Steve Durrheimer <s.durrheimer@gmail.com>
2015-10-15 21:12:31 +02:00
David Calavera f255155f6b Merge pull request #17057 from mavenugo/nls
Added `network` to docker --help and help cleanup
2015-10-15 11:00:43 -07:00
Zachary Jaffee 7345050e4d Cleaned up integration-cli/docker_api_network_test.go
Signed-off-by: Zachary Jaffee <zij@case.edu>
2015-10-15 13:37:54 -04:00
Zachary Jaffee 7aab43e8d4 Cleaned up integration-cli/docker_api_logs_test.go
Signed-off-by: Zachary Jaffee <zij@case.edu>
2015-10-15 13:33:31 -04:00
Tianon Gravi add0d25029 Merge pull request #17054 from hqhq/hq_use_go1.4.3
Bump Go to 1.4.3 for builder
2015-10-15 10:13:23 -07:00
Zachary Jaffee 176d8c5a14 Cleaned up integration-cli/docker_api_events_test.go
Signed-off-by: Zachary Jaffee <zij@case.edu>
2015-10-15 12:40:36 -04:00
Arnaud Porterie 9216b08536 Merge pull request #16998 from vieux/engine_version
only display 'Engine Version' when it's not empty
2015-10-15 08:43:32 -07:00
Vincent Demeester 0f00c36d65 Merge pull request #17004 from echo33/docker_cli_restart_test
use of checkers on docker_cli_restart_test.go
2015-10-15 13:31:05 +02:00
Doug Davis 32ead68e9f Merge pull request #16966 from MHBauer/image-refactor
refactor use of container struct from daemon
2015-10-15 07:30:08 -04:00
Madhu Venugopal 46f7ab3585 Added network to docker --help and help cleanup
Fixes https://github.com/docker/docker/issues/16909

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-10-15 03:10:39 -07:00
weiyan 196af472a6 use of checkers on docker_cli_restart_test.go
Signed-off-by: weiyan <weiyan3@huawei.com>
2015-10-15 16:35:03 +08:00
Vincent Demeester e4dadeed88 Merge pull request #17011 from sunyuan3/TestRunWithBlkioInvalidWeight
update TestRunWithBlkioInvalidWeight
2015-10-15 08:34:52 +02:00
Qiang Huang 42d643af55 Bump Go to 1.4.3 for builder
We already bumped this for Dockerfile, should keep build environment
consistent with that.

Signed-off-by: Qiang Huang <h.huangqiang@huawei.com>
2015-10-15 14:02:18 +08:00
Jian Zhang 946e8cde53 Use c.Assert in integration-cli/docker_cli_logs_test.go
Signed-off-by: Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
2015-10-15 10:53:19 +08:00
Sebastiaan van Stijn 244d9c3370 remove incorrect "readonly" example
The :ro option can only be used for named and bind-mounted
volumes, not on "regular" (unnamed) volumes as explained in
https://github.com/docker/docker/pull/16013#issuecomment-146647216

The example in the documentation actually resulted in a
bind-mounted volume, mounted at "ro" inside the container.

This removes the incorrect example from the documentation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2015-10-14 17:56:38 -07:00
Victor Vieux 17b0017cd0 use Server Version
Signed-off-by: Victor Vieux <vieux@docker.com>
2015-10-14 17:46:59 -07:00
moxiegirl 919c3c1ec8 Merge pull request #17024 from sallyom/man-run-clarify
add clarity to -p option
2015-10-14 14:12:25 -07:00
Brian Goff 84488e228a Merge pull request #17030 from calavera/remove_var_check
Remove defensive check of mux vars handling.
2015-10-14 16:36:50 -04:00
Jess Frazelle b22f89cb77 Merge pull request #16221 from flavio/get-docker-update-suse-installation
Update SUSE/openSUSE installation script
2015-10-14 13:02:45 -07:00
Sally O'Malley 37c6c53b56 add clarity to -p option
Signed-off-by: Sally O'Malley <somalley@redhat.com>
2015-10-14 15:18:04 -04:00
Flavio Castelli 400ac8a66c Update SUSE/openSUSE installation script
Fix installation on SUSE Linux Enterprise machine, the updated Docker RPMs have
been moved to a different location.

Update both openSUSE and SUSE Linux Enterprise scripts to allow the
installation of experimental builds.

Signed-off-by: Flavio Castelli <fcastelli@suse.com>
2015-10-14 20:55:28 +02:00
Sebastiaan van Stijn 2b4128e904 Merge pull request #16617 from zhangjianfnst/15869-improve-commandline-doc
Improve the way we deliver Examples in command line.
2015-10-14 11:05:27 -07:00
Brian Goff adb37a1b39 Merge pull request #17025 from albers/completion-inspect-size
[Fix #15796] Add bash completion for `docker inspect --size`
2015-10-14 13:48:43 -04:00
David Calavera 389ce0aae6 Remove defensive check of mux vars handling.
We should not check if the mux framework internals work as expected in every handler.
The missing parameter error doesn't make sense from the user point of view.

This change initializes a proper vars context if the mux fails to do so and delegates
specific parameter error checks to the handlers.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2015-10-14 10:31:09 -07:00
Vincent Demeester aaa8cae345 Merge pull request #16968 from MHBauer/network-refactor
refactor use of container struct from daemon
2015-10-14 17:48:08 +02:00
Harald Albers 29714ee836 Add bash completion for docker inspect --size
Signed-off-by: Harald Albers <github@albersweb.de>
2015-10-14 17:34:56 +02:00
Brian Goff d60883eb10 Merge pull request #17006 from echo33/docker_cli_v2_only
use of checkers on docker_cli_v2_only.go
2015-10-14 10:27:37 -04:00
Victor Vieux ddf04ad113 only display 'Engine Version' when it's not empty
Signed-off-by: Victor Vieux <vieux@docker.com>
2015-10-14 06:45:11 -07:00
weiyan 899ca94ce8 use of checkers on docker_cli_v2_only.go
Signed-off-by: weiyan <weiyan3@huawei.com>
2015-10-14 20:10:34 +08:00
Yuan Sun d550fbb80e update TestRunWithBlkioInvalidWeight
Signed-off-by: Yuan Sun <sunyuan3@huawei.com>
2015-10-14 16:20:52 +08:00
Jian Zhang cc653b5d61 Improve the way we deliver Examples in command line. (Add descriptive titles)
Signed-off-by: Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
2015-10-14 11:04:51 +08:00
Tibor Vass 7a19164c17 Merge pull request #16995 from jfrazelle/lxc-i-loathe-you
Fix lxc
2015-10-13 19:00:24 -07:00
Jess Frazelle 22a0b0a4f9 Merge pull request #16999 from tiborvass/bump_apiversion_to_v1.22
Bump API Version to v1.22
2015-10-13 18:59:09 -07:00
Tibor Vass 22a0ea5550 Bump API Version to v1.22
Signed-off-by: Tibor Vass <tibor@docker.com>
2015-10-13 17:27:33 -07:00
Morgan Bauer a0398fbd19 refactor use of container struct from daemon
- do existence check instead of get container
 - new connect method on daemon.
 - cli network disconnect integration test

Signed-off-by: Morgan Bauer <mbauer@us.ibm.com>
2015-10-13 16:34:28 -07:00
John Howard bc503ca8ab Windows: [TP4] docker kill handling
Signed-off-by: John Howard <jhoward@microsoft.com>
2015-10-13 16:04:49 -07:00
Derek Ch b48f4bf523 fix a race crash when building with "ADD some-broken.tar.xz ..."
The race is between pools.Put which calls buf.Reset and exec.Cmd
doing io.Copy from the buffer; it caused a runtime crash, as
described in #16924:

``` docker-daemon cat the-tarball.xz | xz -d -c -q | docker-untar /path/to/... (aufs ) ```

When docker-untar side fails (like try to set xattr on aufs, or a broken
tar), invokeUnpack will be responsible to exhaust all input, otherwise
`xz` will be write pending for ever.

this change add a receive only channel to cmdStream, and will close it
to notify it's now safe to close the input stream;

in CmdStream the change to use Stdin / Stdout / Stderr keeps the
code simple, os/exec.Cmd will spawn goroutines and call io.Copy automatically.

the CmdStream is actually called in the same file only, change it
lowercase to mark as private.

[...]
INFO[0000] Docker daemon                                 commit=0a8c2e3 execdriver=native-0.2 graphdriver=aufs version=1.8.2

DEBU[0006] Calling POST /build
INFO[0006] POST /v1.20/build?cgroupparent=&cpuperiod=0&cpuquota=0&cpusetcpus=&cpusetmems=&cpushares=0&dockerfile=Dockerfile&memory=0&memswap=0&rm=1&t=gentoo-x32&ulimits=null
DEBU[0008] [BUILDER] Cache miss
DEBU[0009] Couldn't untar /home/lib-docker-v1.8.2-tmp/tmp/docker-build316710953/stage3-x32-20151004.tar.xz to /home/lib-docker-v1.8.2-tmp/aufs/mnt/d909abb87150463939c13e8a349b889a72d9b14f0cfcab42a8711979be285537: Untar re-exec error: exit status 1: output: operation not supported
DEBU[0009] CopyFileWithTar(/home/lib-docker-v1.8.2-tmp/tmp/docker-build316710953/stage3-x32-20151004.tar.xz, /home/lib-docker-v1.8.2-tmp/aufs/mnt/d909abb87150463939c13e8a349b889a72d9b14f0cfcab42a8711979be285537/)
panic: runtime error: slice bounds out of range

goroutine 42 [running]:
bufio.(*Reader).fill(0xc208187800)
    /usr/local/go/src/bufio/bufio.go:86 +0x2db
bufio.(*Reader).WriteTo(0xc208187800, 0x7ff39602d150, 0xc2083f11a0, 0x508000, 0x0, 0x0)
    /usr/local/go/src/bufio/bufio.go:449 +0x27e
io.Copy(0x7ff39602d150, 0xc2083f11a0, 0x7ff3960261f8, 0xc208187800, 0x0, 0x0, 0x0)
    /usr/local/go/src/io/io.go:354 +0xb2
github.com/docker/docker/pkg/archive.func·006()
    /go/src/github.com/docker/docker/pkg/archive/archive.go:817 +0x71
created by github.com/docker/docker/pkg/archive.CmdStream
    /go/src/github.com/docker/docker/pkg/archive/archive.go:819 +0x1ec

goroutine 1 [chan receive]:
main.(*DaemonCli).CmdDaemon(0xc20809da30, 0xc20800a020, 0xd, 0xd, 0x0, 0x0)
    /go/src/github.com/docker/docker/docker/daemon.go:289 +0x1781
reflect.callMethod(0xc208140090, 0xc20828fce0)
    /usr/local/go/src/reflect/value.go:605 +0x179
reflect.methodValueCall(0xc20800a020, 0xd, 0xd, 0x1, 0xc208140090, 0x0, 0x0, 0xc208140090, 0x0, 0x45343f, ...)
    /usr/local/go/src/reflect/asm_amd64.s:29 +0x36
github.com/docker/docker/cli.(*Cli).Run(0xc208129fb0, 0xc20800a010, 0xe, 0xe, 0x0, 0x0)
    /go/src/github.com/docker/docker/cli/cli.go:89 +0x38e
main.main()
    /go/src/github.com/docker/docker/docker/docker.go:69 +0x428

goroutine 5 [syscall]:
os/signal.loop()
    /usr/local/go/src/os/signal/signal_unix.go:21 +0x1f
created by os/signal.init·1
    /usr/local/go/src/os/signal/signal_unix.go:27 +0x35

Signed-off-by: Derek Ch <denc716@gmail.com>
2015-10-13 15:58:06 -07:00
Jessica Frazelle 28ad7c588f update tests
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2015-10-13 15:52:14 -07:00
John Howard 69949df242 Windows: Fix annoying bad log
Signed-off-by: John Howard <jhoward@microsoft.com>
2015-10-13 15:03:20 -07:00
Antonio Murdaca cfcddefacd daemon: execdriver: lxc: fix cgroup paths
When running LXC dind (outer docker is started with native driver)
cgroup paths point to `/docker/CID` inside `/proc/self/mountinfo` but
these paths aren't mounted (root is wrong). This fix just discard the
cgroup dir from mountinfo and set it to root `/`.
This patch fixes/skip OOM LXC tests that were failing.
Fix #16520

Signed-off-by: Antonio Murdaca <runcom@linux.com>
Signed-off-by: Antonio Murdaca <amurdaca@redhat.com>
2015-10-13 14:46:59 -07:00
Antonio Murdaca 06f0d03ced daemon: execdriver: lxc: fix set memory swap
On LXC memory swap was only set to memory_limit*2 even if a value for
memory swap was provided. This patch fix this behavior to be the same
as the native driver and set correct memory swap in the template.
Also add a test specifically for LXC but w/o adding a new test
requirement.

Signed-off-by: Antonio Murdaca <runcom@linux.com>
2015-10-13 14:46:59 -07:00
Shijiang Wei a1d4b7dd0d refactor integration test to use checkers
Signed-off-by: Shijiang Wei <mountkin@gmail.com>
2015-10-13 20:21:38 +08:00
Morgan Bauer 844fb29619 refactor use of container struct from daemon
- use Exists instead of Get
 - push Get inside of daemonbuilder

Signed-off-by: Morgan Bauer <mbauer@us.ibm.com>
2015-10-12 16:20:55 -07:00
Brian Goff a82e3bc704 Allow API to bind to ipv6 addresses
Use `net.SplitHostPort` which supports ipv6 rather than relying on
splitting on `:`

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2015-10-12 13:55:27 -04:00
Mageee d4d0718ebf update docker_cli_version_test.go
fix spelling mistake again

Signed-off-by: Mageee <fangpuyi@foxmail.com>
2015-10-12 15:13:31 +08:00
Zhang Wei c6b02ad73b Update integration test with Assert
Part of #16756

Update integration-cli/docker_cli_rmi_test.go:
Use Assert instead of condition judgement in test.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2015-10-11 10:56:02 +08:00
Jessica Frazelle 96559aaef2 add clean apt db to release script
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2015-10-08 09:21:20 -07:00
Jessica Frazelle 0aee0b1f9e add script to generate index listing for the repo if say hosted on s3
Signed-off-by: Jessica Frazelle <acidburn@docker.com>
2015-10-08 09:21:16 -07:00
Avi Miller 1374ebcde0 Generate a full RPM changelog from the existing CHANGELOG.md file
Signed-off-by: Avi Miller <avi.miller@oracle.com>
2015-09-25 17:25:00 +10:00
156 changed files with 5663 additions and 1812 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
dockerfileName := cmd.String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")
flMemoryString := cmd.String([]string{"m", "-memory"}, "", "Memory limit")
flMemorySwap := cmd.String([]string{"-memory-swap"}, "", "Total memory (memory + swap), '-1' to disable swap")
flCPUShares := cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
flCPUShares := cmd.Int64([]string{"#c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
flCPUPeriod := cmd.Int64([]string{"-cpu-period"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) period")
flCPUQuota := cmd.Int64([]string{"-cpu-quota"}, 0, "Limit the CPU CFS (Completely Fair Scheduler) quota")
flCPUSetCpus := cmd.String([]string{"-cpuset-cpus"}, "", "CPUs in which to allow execution (0-3, 0,1)")
+1 -1
View File
@@ -35,7 +35,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers)
fmt.Fprintf(cli.out, "Images: %d\n", info.Images)
fmt.Fprintf(cli.out, "Engine Version: %s\n", info.ServerVersion)
ioutils.FprintfIfNotEmpty(cli.out, "Server Version: %s\n", info.ServerVersion)
ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver)
if info.DriverStatus != nil {
for _, pair := range info.DriverStatus {
+5 -2
View File
@@ -34,6 +34,7 @@ func (cli *DockerCli) CmdNetwork(args ...string) error {
func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false)
flDriver := cmd.String([]string{"d", "-driver"}, "bridge", "Driver to manage the Network")
flOpts := opts.NewMapOpts(nil, nil)
flIpamDriver := cmd.String([]string{"-ipam-driver"}, "default", "IP Address Management Driver")
flIpamSubnet := opts.NewListOpts(nil)
@@ -41,10 +42,11 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
flIpamGateway := opts.NewListOpts(nil)
flIpamAux := opts.NewMapOpts(nil, nil)
cmd.Var(&flIpamSubnet, []string{"-subnet"}, "Subnet in CIDR format that represents a network segment")
cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment")
cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range")
cmd.Var(&flIpamGateway, []string{"-gateway"}, "ipv4 or ipv6 Gateway for the master subnet")
cmd.Var(flIpamAux, []string{"-aux-address"}, "Auxiliary ipv4 or ipv6 addresses used by network driver")
cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver")
cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options")
cmd.Require(flag.Exact, 1)
err := cmd.ParseFlags(args, true)
@@ -62,6 +64,7 @@ func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
Name: cmd.Arg(0),
Driver: *flDriver,
IPAM: network.IPAM{Driver: *flIpamDriver, Config: ipamCfg},
Options: flOpts.GetAll(),
CheckDuplicate: true,
}
obj, _, err := readBody(cli.call("POST", "/networks/create", nc, nil))
+1 -1
View File
@@ -18,7 +18,7 @@ import (
// Common constants for daemon and client.
const (
// Version of Current REST API
Version version.Version = "1.21"
Version version.Version = "1.22"
// MinVersion represents Minimun REST API version supported
MinVersion version.Version = "1.12"
-3
View File
@@ -55,9 +55,6 @@ type ArchiveOptions struct {
// ArchiveFormValues parses form values and turns them into ArchiveOptions.
// It fails if the archive name and path are not in the request.
func ArchiveFormValues(r *http.Request, vars map[string]string) (ArchiveOptions, error) {
if vars == nil {
return ArchiveOptions{}, fmt.Errorf("Missing parameter")
}
if err := ParseForm(r); err != nil {
return ArchiveOptions{}, err
}
-56
View File
@@ -56,9 +56,6 @@ func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter,
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
stream := httputils.BoolValueOrDefault(r, "stream", true)
var out io.Writer
@@ -88,9 +85,6 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
// Args are validated before the stream starts because when it starts we're
// sending HTTP 200 by writing an empty chunk of data to tell the client that
@@ -150,18 +144,10 @@ func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r
}
func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
return s.daemon.ContainerExport(vars["name"], w)
}
func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
// If contentLength is -1, we can assumed chunked encoding
// or more technically that the length is unknown
// https://golang.org/src/pkg/net/http/request.go#L139
@@ -193,9 +179,6 @@ func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter,
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
seconds, _ := strconv.Atoi(r.Form.Get("t"))
@@ -208,9 +191,6 @@ func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter,
}
func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -247,9 +227,6 @@ func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWrite
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
timeout, _ := strconv.Atoi(r.Form.Get("t"))
@@ -263,9 +240,6 @@ func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWrite
}
func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -280,9 +254,6 @@ func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter,
}
func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -297,10 +268,6 @@ func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWrite
}
func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second)
if err != nil {
return err
@@ -312,10 +279,6 @@ func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter,
}
func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
changes, err := s.daemon.ContainerChanges(vars["name"])
if err != nil {
return err
@@ -325,10 +288,6 @@ func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter
}
func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -345,9 +304,6 @@ func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter,
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
newName := r.Form.Get("name")
@@ -387,9 +343,6 @@ func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
config := &daemon.ContainerRmConfig{
@@ -415,9 +368,6 @@ func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
height, err := strconv.Atoi(r.Form.Get("h"))
if err != nil {
@@ -435,9 +385,6 @@ func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
containerName := vars["name"]
if !s.daemon.Exists(containerName) {
@@ -477,9 +424,6 @@ func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter,
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
containerName := vars["name"]
if !s.daemon.Exists(containerName) {
-4
View File
@@ -16,10 +16,6 @@ import (
// postContainersCopy is deprecated in favor of getContainersArchive.
func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.CheckForJSON(r); err != nil {
return err
}
-8
View File
@@ -16,10 +16,6 @@ import (
)
func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter 'id'")
}
eConfig, err := s.daemon.ContainerExecInspect(vars["id"])
if err != nil {
return err
@@ -118,10 +114,6 @@ func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWri
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
height, err := strconv.Atoi(r.Form.Get("h"))
if err != nil {
return err
+4 -26
View File
@@ -16,6 +16,7 @@ import (
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/cliconfig"
"github.com/docker/docker/daemon/daemonbuilder"
derr "github.com/docker/docker/errors"
"github.com/docker/docker/graph"
"github.com/docker/docker/graph/tags"
"github.com/docker/docker/pkg/archive"
@@ -63,12 +64,11 @@ func (s *router) postCommit(ctx context.Context, w http.ResponseWriter, r *http.
Config: c,
}
container, err := s.daemon.Get(cname)
if err != nil {
return err
if !s.daemon.Exists(cname) {
return derr.ErrorCodeNoSuchContainer.WithArgs(cname)
}
imgID, err := dockerfile.Commit(container, s.daemon, commitCfg)
imgID, err := dockerfile.Commit(cname, s.daemon, commitCfg)
if err != nil {
return err
}
@@ -156,10 +156,6 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r
}
func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
metaHeaders := map[string][]string{}
for k, v := range r.Header {
if strings.HasPrefix(k, "X-Meta-") {
@@ -208,9 +204,6 @@ func (s *router) postImagesPush(ctx context.Context, w http.ResponseWriter, r *h
}
func (s *router) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
if err := httputils.ParseForm(r); err != nil {
return err
}
@@ -243,9 +236,6 @@ func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *htt
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
@@ -265,10 +255,6 @@ func (s *router) deleteImages(ctx context.Context, w http.ResponseWriter, r *htt
}
func (s *router) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
imageInspect, err := s.daemon.LookupImage(vars["name"])
if err != nil {
return err
@@ -456,10 +442,6 @@ func (s *router) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *ht
}
func (s *router) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil {
return fmt.Errorf("Missing parameter")
}
name := vars["name"]
history, err := s.daemon.ImageHistory(name)
if err != nil {
@@ -473,10 +455,6 @@ func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *ht
if err := httputils.ParseForm(r); err != nil {
return err
}
if vars == nil {
return fmt.Errorf("Missing parameter")
}
repo := r.Form.Get("repo")
tag := r.Form.Get("tag")
name := vars["name"]
-4
View File
@@ -1,7 +1,6 @@
package local
import (
"fmt"
"net/http"
"github.com/docker/docker/api/server/httputils"
@@ -11,9 +10,6 @@ import (
// getContainersByName inspects containers configuration and serializes it as json.
func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
displaySize := httputils.BoolValue(r, "size")
if vars == nil {
return fmt.Errorf("Missing parameter")
}
var json interface{}
var err error
+4 -11
View File
@@ -96,7 +96,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
}
nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM)
nw, err = n.daemon.CreateNetwork(create.Name, create.Driver, create.IPAM, create.Options)
if err != nil {
return err
}
@@ -126,11 +126,7 @@ func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseW
return err
}
container, err := n.daemon.Get(connect.Container)
if err != nil {
return fmt.Errorf("invalid container %s : %v", container, err)
}
return container.ConnectToNetwork(nw.Name())
return n.daemon.ConnectContainerToNetwork(connect.Container, nw.Name())
}
func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -152,11 +148,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
return err
}
container, err := n.daemon.Get(disconnect.Container)
if err != nil {
return fmt.Errorf("invalid container %s : %v", container, err)
}
return container.DisconnectFromNetwork(nw)
return n.daemon.DisconnectContainerFromNetwork(disconnect.Container, nw)
}
func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
@@ -182,6 +174,7 @@ func buildNetworkResource(nw libnetwork.Network) *types.NetworkResource {
r.ID = nw.ID()
r.Scope = nw.Info().Scope()
r.Driver = nw.Type()
r.Options = nw.Info().DriverOptions()
r.Containers = make(map[string]types.EndpointResource)
buildIpamResources(r, nw)
+6 -1
View File
@@ -153,7 +153,12 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
ctx := context.Background()
handlerFunc := s.handleWithGlobalMiddlewares(handler)
if err := handlerFunc(ctx, w, r, mux.Vars(r)); err != nil {
vars := mux.Vars(r)
if vars == nil {
vars = make(map[string]string)
}
if err := handlerFunc(ctx, w, r, vars); err != nil {
logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.URL.Path, utils.GetErrorMessage(err))
httputils.WriteError(w, err)
}
+6 -4
View File
@@ -319,6 +319,7 @@ type NetworkResource struct {
Driver string `json:"driver"`
IPAM network.IPAM `json:"ipam"`
Containers map[string]EndpointResource `json:"containers"`
Options map[string]string `json:"options"`
}
//EndpointResource contains network resources allocated and usd for a container in a network
@@ -331,10 +332,11 @@ type EndpointResource struct {
// NetworkCreate is the expected body of the "create network" http request message
type NetworkCreate struct {
Name string `json:"name"`
CheckDuplicate bool `json:"check_duplicate"`
Driver string `json:"driver"`
IPAM network.IPAM `json:"ipam"`
Name string `json:"name"`
CheckDuplicate bool `json:"check_duplicate"`
Driver string `json:"driver"`
IPAM network.IPAM `json:"ipam"`
Options map[string]string `json:"options"`
}
// NetworkCreateResponse is the response message sent by the server for network create call
+6 -1
View File
@@ -256,7 +256,12 @@ func BuildFromConfig(config *runconfig.Config, changes []string) (*runconfig.Con
// Commit will create a new image from a container's changes
// TODO: remove daemon, make Commit a method on *Builder ?
func Commit(container *daemon.Container, d *daemon.Daemon, c *CommitConfig) (string, error) {
func Commit(containerName string, d *daemon.Daemon, c *CommitConfig) (string, error) {
container, err := d.Get(containerName)
if err != nil {
return "", err
}
// It is not possible to commit a running container on Windows
if runtime.GOOS == "windows" && container.IsRunning() {
return "", fmt.Errorf("Windows does not support commit of a running container")
+15 -7
View File
@@ -557,8 +557,9 @@ func (b *Builder) run(c *daemon.Container) error {
go func() {
select {
case <-b.cancelled:
logrus.Debugln("Build cancelled, killing container:", c.ID)
logrus.Debugln("Build cancelled, killing and removing container:", c.ID)
c.Kill()
b.removeContainer(c.ID)
case <-finished:
}
}()
@@ -582,14 +583,21 @@ func (b *Builder) run(c *daemon.Container) error {
return nil
}
func (b *Builder) removeContainer(c string) error {
rmConfig := &daemon.ContainerRmConfig{
ForceRemove: true,
RemoveVolume: true,
}
if err := b.docker.Remove(c, rmConfig); err != nil {
fmt.Fprintf(b.Stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
return err
}
return nil
}
func (b *Builder) clearTmp() {
for c := range b.tmpContainers {
rmConfig := &daemon.ContainerRmConfig{
ForceRemove: true,
RemoveVolume: true,
}
if err := b.docker.Remove(c, rmConfig); err != nil {
fmt.Fprintf(b.Stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
if err := b.removeContainer(c); err != nil {
return
}
delete(b.tmpContainers, c)
+1
View File
@@ -45,6 +45,7 @@ var dockerCommands = []Command{
{"login", "Register or log in to a Docker registry"},
{"logout", "Log out from a Docker registry"},
{"logs", "Fetch the logs of a container"},
{"network", "Manage Docker networks"},
{"pause", "Pause all processes within a container"},
{"port", "List port mappings or a specific mapping for the CONTAINER"},
{"ps", "List containers"},
+1 -1
View File
@@ -6,7 +6,7 @@ FROM debian:jessie
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
@@ -6,7 +6,7 @@ FROM debian:stretch
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -6,7 +6,7 @@ FROM debian:wheezy-backports
RUN apt-get update && apt-get install -y bash-completion btrfs-tools/wheezy-backports build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
@@ -6,7 +6,7 @@ FROM ubuntu:precise
RUN apt-get update && apt-get install -y bash-completion build-essential curl ca-certificates debhelper git libapparmor-dev libsqlite3-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -6,7 +6,7 @@ FROM ubuntu:trusty
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -6,7 +6,7 @@ FROM ubuntu:vivid
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -6,7 +6,7 @@ FROM ubuntu:wily
RUN apt-get update && apt-get install -y bash-completion btrfs-tools build-essential curl ca-certificates debhelper dh-systemd git libapparmor-dev libdevmapper-dev libsqlite3-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -8,7 +8,7 @@ RUN yum groupinstall -y "Development Tools"
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -7,7 +7,7 @@ FROM fedora:21
RUN yum install -y @development-tools fedora-packager
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -7,7 +7,7 @@ FROM fedora:22
RUN yum install -y @development-tools fedora-packager
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -7,7 +7,7 @@ FROM opensuse:13.2
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -7,7 +7,7 @@ FROM oraclelinux:6
RUN yum groupinstall -y "Development Tools"
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+1 -1
View File
@@ -7,7 +7,7 @@ FROM oraclelinux:7
RUN yum groupinstall -y "Development Tools"
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel selinux-policy selinux-policy-devel sqlite-devel tar
ENV GO_VERSION 1.4.2
ENV GO_VERSION 1.4.3
RUN curl -fSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
+50 -12
View File
@@ -461,8 +461,37 @@ _docker_attach() {
}
_docker_build() {
local options_with_args="
--build-arg
--cgroup-parent
--cpuset-cpus
--cpuset-mems
--cpu-shares
--cpu-period
--cpu-quota
--file -f
--memory -m
--memory-swap
--tag -t
--ulimit
"
local boolean_options="
--disable-content-trust=false
--force-rm
--help
--no-cache
--pull
--quiet -q
--rm
"
local all_options="$options_with_args $boolean_options"
case "$prev" in
--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--memory|-m|--memory-swap)
--build-arg)
COMPREPLY=( $( compgen -e -- "$cur" ) )
__docker_nospace
return
;;
--file|-f)
@@ -473,14 +502,17 @@ _docker_build() {
__docker_image_repos_and_tags
return
;;
$(__docker_to_extglob "$options_with_args") )
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--cgroup-parent --cpuset-cpus --cpuset-mems --cpu-shares -c --cpu-period --cpu-quota --file -f --force-rm --help --memory -m --memory-swap --no-cache --pull --quiet -q --rm --tag -t --ulimit" -- "$cur" ) )
COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) )
;;
*)
local counter="$(__docker_pos_first_nonflag '--cgroup-parent|--cpuset-cpus|--cpuset-mems|--cpu-shares|-c|--cpu-period|--cpu-quota|--file|-f|--memory|-m|--memory-swap|--tag|-t')"
local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) )
if [ $cword -eq $counter ]; then
_filedir -d
fi
@@ -865,12 +897,18 @@ _docker_images() {
}
_docker_import() {
case "$prev" in
--change|-c|--message|-m)
return
;;
esac
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--change -c --help --message -m" -- "$cur" ) )
;;
*)
local counter=$(__docker_pos_first_nonflag)
local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m')
if [ $cword -eq $counter ]; then
return
fi
@@ -906,7 +944,7 @@ _docker_inspect() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--format -f --type --help" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--format -f --help --size -s --type" -- "$cur" ) )
;;
*)
case $(__docker_value_of_option --type) in
@@ -1060,7 +1098,7 @@ _docker_network_ls() {
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--help --latest -l -n --no-trunc --quiet -q" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--help --no-trunc --quiet -q" -- "$cur" ) )
;;
esac
}
@@ -1272,7 +1310,7 @@ _docker_run() {
--cpu-quota
--cpuset-cpus
--cpuset-mems
--cpu-shares -c
--cpu-shares
--device
--dns
--dns-opt
@@ -1311,7 +1349,7 @@ _docker_run() {
--workdir -w
"
local all_options="$options_with_args
local boolean_options="
--disable-content-trust=false
--help
--interactive -i
@@ -1322,14 +1360,14 @@ _docker_run() {
--tty -t
"
local all_options="$options_with_args $boolean_options"
[ "$command" = "run" ] && all_options="$all_options
--detach -d
--rm
--sig-proxy=false
"
local options_with_args_glob=$(__docker_to_extglob "$options_with_args")
case "$prev" in
--add-host)
case "$cur" in
@@ -1454,7 +1492,7 @@ _docker_run() {
__docker_containers_all
return
;;
$options_with_args_glob )
$(__docker_to_extglob "$options_with_args") )
return
;;
esac
+1 -1
View File
@@ -116,7 +116,7 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from cp' -l help -d 'Print u
complete -c docker -f -n '__fish_docker_no_subcommand' -a create -d 'Create a new container'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s a -l attach -d 'Attach to STDIN, STDOUT or STDERR.'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l add-host -d 'Add a custom host-to-IP mapping (host:ip)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s c -l cpu-shares -d 'CPU shares (relative weight)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cpu-shares -d 'CPU shares (relative weight)'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-add -d 'Add Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cap-drop -d 'Drop Linux capabilities'
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l cidfile -d 'Write the container ID to the file'
+117 -112
View File
@@ -253,6 +253,11 @@ __docker_network_subcommand() {
_arguments -A '-*' \
$opts_help \
"($help -d --driver)"{-d,--driver=}"[Driver to manage the Network]:driver:(null host bridge overlay)" \
"($help)--ipam-driver=[IP Address Management Driver]:driver:(default)" \
"($help)*--subnet=[Subnet in CIDR format that represents a network segment]:IP/mask: " \
"($help)*--ip-range=[Allocate container ip from a sub-range]:IP/mask: " \
"($help)*--gateway=[ipv4 or ipv6 Gateway for the master subnet]:IP: " \
"($help)*--aux-address[Auxiliary ipv4 or ipv6 addresses used by network driver]:key=IP: " \
"($help -)1:Network Name: " && ret=0
;;
(inspect|rm)
@@ -263,8 +268,6 @@ __docker_network_subcommand() {
(ls)
_arguments \
$opts_help \
"($help -l --latest)"{-l,--latest}"[Show the latest network created]" \
"($help)-n=-[Show n last created networks]:Number of networks: " \
"($help)--no-trunc[Do not truncate the output]" \
"($help -q --quiet)"{-q,--quiet}"[Only display numeric IDs]" && ret=0
;;
@@ -330,20 +333,20 @@ __docker_volume_subcommand() {
(create)
_arguments \
$opts_help \
"($help -d --driver)"{-d,--driver=-}"[Specify volume driver name]:Driver name: " \
"($help)--name=-[Specify volume name]" \
"($help -o --opt)*"{-o,--opt=-}"[Set driver specific options]:Driver option: " && ret=0
"($help -d --driver)"{-d,--driver=}"[Specify volume driver name]:Driver name: " \
"($help)--name=[Specify volume name]" \
"($help -o --opt)*"{-o,--opt=}"[Set driver specific options]:Driver option: " && ret=0
;;
(inspect)
_arguments \
$opts_help \
"($help -f --format)"{-f,--format=-}"[Format the output using the given go template]:template: " \
"($help -f --format)"{-f,--format=}"[Format the output using the given go template]:template: " \
"($help -)1:volume:__docker_volumes" && ret=0
;;
(ls)
_arguments \
$opts_help \
"($help -f --filter)*"{-f,--filter=-}"[Provide filter values (i.e. 'dangling=true')]:filter: " \
"($help -f --filter)*"{-f,--filter=}"[Provide filter values (i.e. 'dangling=true')]:filter: " \
"($help -q --quiet)"{-q,--quiet}"[Only display volume names]" && ret=0
;;
(rm)
@@ -391,57 +394,57 @@ __docker_subcommand() {
opts_help=("(: -)--help[Print usage]")
opts_cpumemlimit=(
"($help -c --cpu-shares)"{-c,--cpu-shares=-}"[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)"
"($help)--cgroup-parent=-[Parent cgroup for the container]:cgroup: "
"($help)--cpu-period=-[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: "
"($help)--cpu-quota=-[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: "
"($help)--cpuset-cpus=-[CPUs in which to allow execution]:CPUs: "
"($help)--cpuset-mems=-[MEMs in which to allow execution]:MEMs: "
"($help -m --memory)"{-m,--memory=-}"[Memory limit]:Memory limit: "
"($help)--memory-swap=-[Total memory limit with swap]:Memory limit: "
"($help)*--ulimit=-[ulimit options]:ulimit: "
"($help)--cpu-shares=[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)"
"($help)--cgroup-parent=[Parent cgroup for the container]:cgroup: "
"($help)--cpu-period=[Limit the CPU CFS (Completely Fair Scheduler) period]:CPU period: "
"($help)--cpu-quota=[Limit the CPU CFS (Completely Fair Scheduler) quota]:CPU quota: "
"($help)--cpuset-cpus=[CPUs in which to allow execution]:CPUs: "
"($help)--cpuset-mems=[MEMs in which to allow execution]:MEMs: "
"($help -m --memory)"{-m,--memory=}"[Memory limit]:Memory limit: "
"($help)--memory-swap=[Total memory limit with swap]:Memory limit: "
"($help)*--ulimit=[ulimit options]:ulimit: "
)
opts_create=(
"($help -a --attach)"{-a,--attach=-}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
"($help)*--add-host=-[Add a custom host-to-IP mapping]:host\:ip mapping: "
"($help)--blkio-weight=-[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
"($help)*--cap-add=-[Add Linux capabilities]:capability: "
"($help)*--cap-drop=-[Drop Linux capabilities]:capability: "
"($help)--cidfile=-[Write the container ID to the file]:CID file:_files"
"($help)*--device=-[Add a host device to the container]:device:_files"
"($help)*--dns=-[Set custom DNS servers]:DNS server: "
"($help)*--dns-opt=-[Set custom DNS options]:DNS option: "
"($help)*--dns-search=-[Set custom DNS search domains]:DNS domains: "
"($help)*"{-e,--env=-}"[Set environment variables]:environment variable: "
"($help)--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: "
"($help)*--env-file=-[Read environment variables from a file]:environment file:_files"
"($help)*--expose=-[Expose a port from the container without publishing it]: "
"($help)*--group-add=-[Add additional groups to run as]:group:_groups"
"($help -h --hostname)"{-h,--hostname=-}"[Container host name]:hostname:_hosts"
"($help -a --attach)"{-a,--attach=}"[Attach to stdin, stdout or stderr]:device:(STDIN STDOUT STDERR)"
"($help)*--add-host=[Add a custom host-to-IP mapping]:host\:ip mapping: "
"($help)--blkio-weight=[Block IO (relative weight), between 10 and 1000]:Block IO weight:(10 100 500 1000)"
"($help)*--cap-add=[Add Linux capabilities]:capability: "
"($help)*--cap-drop=[Drop Linux capabilities]:capability: "
"($help)--cidfile=[Write the container ID to the file]:CID file:_files"
"($help)*--device=[Add a host device to the container]:device:_files"
"($help)*--dns=[Set custom DNS servers]:DNS server: "
"($help)*--dns-opt=[Set custom DNS options]:DNS option: "
"($help)*--dns-search=[Set custom DNS search domains]:DNS domains: "
"($help)*"{-e,--env=}"[Set environment variables]:environment variable: "
"($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: "
"($help)*--env-file=[Read environment variables from a file]:environment file:_files"
"($help)*--expose=[Expose a port from the container without publishing it]: "
"($help)*--group-add=[Add additional groups to run as]:group:_groups"
"($help -h --hostname)"{-h,--hostname=}"[Container host name]:hostname:_hosts"
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]"
"($help)--ipc=-[IPC namespace to use]:IPC namespace: "
"($help)--ipc=[IPC namespace to use]:IPC namespace: "
"($help)--kernel-memory[Kernel memory limit in bytes.]:Memory limit: "
"($help)*--link=-[Add link to another container]:link:->link"
"($help)*"{-l,--label=-}"[Set meta data on a container]:label: "
"($help)--log-driver=-[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)"
"($help)*--log-opt=-[Log driver specific options]:log driver options: "
"($help)*--lxc-conf=-[Add custom lxc options]:lxc options: "
"($help)--mac-address=-[Container MAC address]:MAC address: "
"($help)--name=-[Container name]:name: "
"($help)--net=-[Connect a container to a network]:network mode:(bridge none container host)"
"($help)*--link=[Add link to another container]:link:->link"
"($help)*"{-l,--label=}"[Set meta data on a container]:label: "
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)"
"($help)*--log-opt=[Log driver specific options]:log driver options: "
"($help)*--lxc-conf=[Add custom lxc options]:lxc options: "
"($help)--mac-address=[Container MAC address]:MAC address: "
"($help)--name=[Container name]:name: "
"($help)--net=[Connect a container to a network]:network mode:(bridge none container host)"
"($help)--oom-kill-disable[Disable OOM Killer]"
"($help -P --publish-all)"{-P,--publish-all}"[Publish all exposed ports]"
"($help)*"{-p,--publish=-}"[Expose a container's port to the host]:port:_ports"
"($help)--pid=-[PID namespace to use]:PID: "
"($help)*"{-p,--publish=}"[Expose a container's port to the host]:port:_ports"
"($help)--pid=[PID namespace to use]:PID: "
"($help)--privileged[Give extended privileges to this container]"
"($help)--read-only[Mount the container's root filesystem as read only]"
"($help)--restart=-[Restart policy]:restart policy:(no on-failure always)"
"($help)*--security-opt=-[Security options]:security option: "
"($help)--restart=[Restart policy]:restart policy:(no on-failure always unless-stopped)"
"($help)*--security-opt=[Security options]:security option: "
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]"
"($help -u --user)"{-u,--user=-}"[Username or UID]:user:_users"
"($help -u --user)"{-u,--user=}"[Username or UID]:user:_users"
"($help)*-v[Bind mount a volume]:volume: "
"($help)*--volumes-from=-[Mount volumes from the specified container]:volume: "
"($help -w --workdir)"{-w,--workdir=-}"[Working directory inside the container]:directory:_directories"
"($help)*--volumes-from=[Mount volumes from the specified container]:volume: "
"($help -w --workdir)"{-w,--workdir=}"[Working directory inside the container]:directory:_directories"
)
case "$words[1]" in
@@ -456,21 +459,22 @@ __docker_subcommand() {
_arguments \
$opts_help \
$opts_cpumemlimit \
"($help -f --file)"{-f,--file=-}"[Name of the Dockerfile]:Dockerfile:_files" \
"($help)*--build-arg[Set build-time variables]:<varname>=<value>: " \
"($help -f --file)"{-f,--file=}"[Name of the Dockerfile]:Dockerfile:_files" \
"($help)--force-rm[Always remove intermediate containers]" \
"($help)--no-cache[Do not use cache when building the image]" \
"($help)--pull[Attempt to pull a newer version of the image]" \
"($help -q --quiet)"{-q,--quiet}"[Suppress verbose build output]" \
"($help)--rm[Remove intermediate containers after a successful build]" \
"($help -t --tag)"{-t,--tag=-}"[Repository, name and tag for the image]: :__docker_repositories_with_tags" \
"($help -t --tag)"{-t,--tag=}"[Repository, name and tag for the image]: :__docker_repositories_with_tags" \
"($help -):path or URL:_directories" && ret=0
;;
(commit)
_arguments \
$opts_help \
"($help -a --author)"{-a,--author=-}"[Author]:author: " \
"($help -c --change)*"{-c,--change=-}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
"($help -m --message)"{-m,--message=-}"[Commit message]:message: " \
"($help -a --author)"{-a,--author=}"[Author]:author: " \
"($help -c --change)*"{-c,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
"($help -m --message)"{-m,--message=}"[Commit message]:message: " \
"($help -p --pause)"{-p,--pause}"[Pause container during commit]" \
"($help -):container:__docker_containers" \
"($help -): :__docker_repositories_with_tags" && ret=0
@@ -513,49 +517,49 @@ __docker_subcommand() {
(daemon)
_arguments \
$opts_help \
"($help)--api-cors-header=-[Set CORS headers in the remote API]:CORS headers: " \
"($help -b --bridge)"{-b,--bridge=-}"[Attach containers to a network bridge]:bridge:_net_interfaces" \
"($help)--bip=-[Specify network bridge IP]" \
"($help)--api-cors-header=[Set CORS headers in the remote API]:CORS headers: " \
"($help -b --bridge)"{-b,--bridge=}"[Attach containers to a network bridge]:bridge:_net_interfaces" \
"($help)--bip=[Specify network bridge IP]" \
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
"($help)--default-gateway[Container default gateway IPv4 address]:IPv4 address: " \
"($help)--default-gateway-v6[Container default gateway IPv6 address]:IPv6 address: " \
"($help)--cluster-store=-[URL of the distributed storage backend]:Cluster Store:->cluster-store" \
"($help)--cluster-advertise=-[Address of the daemon instance to advertise]:Instance to advertise (host\:port): " \
"($help)--cluster-store=[URL of the distributed storage backend]:Cluster Store:->cluster-store" \
"($help)--cluster-advertise=[Address of the daemon instance to advertise]:Instance to advertise (host\:port): " \
"($help)*--cluster-store-opt[Set cluster options]:Cluster options:->cluster-store-options" \
"($help)*--dns=-[DNS server to use]:DNS: " \
"($help)*--dns-search=-[DNS search domains to use]:DNS search: " \
"($help)*--dns-opt=-[DNS options to use]:DNS option: " \
"($help)*--default-ulimit=-[Set default ulimit settings for containers]:ulimit: " \
"($help)*--dns=[DNS server to use]:DNS: " \
"($help)*--dns-search=[DNS search domains to use]:DNS search: " \
"($help)*--dns-opt=[DNS options to use]:DNS option: " \
"($help)*--default-ulimit=[Set default ulimit settings for containers]:ulimit: " \
"($help)--disable-legacy-registry[Do not contact legacy registries]" \
"($help -e --exec-driver)"{-e,--exec-driver=-}"[Exec driver to use]:driver:(native lxc windows)" \
"($help)*--exec-opt=-[Set exec driver options]:exec driver options: " \
"($help)--exec-root=-[Root of the Docker execdriver]:path:_directories" \
"($help)--fixed-cidr=-[IPv4 subnet for fixed IPs]:IPv4 subnet: " \
"($help)--fixed-cidr-v6=-[IPv6 subnet for fixed IPs]:IPv6 subnet: " \
"($help -G --group)"{-G,--group=-}"[Group for the unix socket]:group:_groups" \
"($help -g --graph)"{-g,--graph=-}"[Root of the Docker runtime]:path:_directories" \
"($help -H --host)"{-H,--host=-}"[tcp://host:port to bind/connect to]:host: " \
"($help -e --exec-driver)"{-e,--exec-driver=}"[Exec driver to use]:driver:(native lxc windows)" \
"($help)*--exec-opt=[Set exec driver options]:exec driver options: " \
"($help)--exec-root=[Root of the Docker execdriver]:path:_directories" \
"($help)--fixed-cidr=[IPv4 subnet for fixed IPs]:IPv4 subnet: " \
"($help)--fixed-cidr-v6=[IPv6 subnet for fixed IPs]:IPv6 subnet: " \
"($help -G --group)"{-G,--group=}"[Group for the unix socket]:group:_groups" \
"($help -g --graph)"{-g,--graph=}"[Root of the Docker runtime]:path:_directories" \
"($help -H --host)"{-H,--host=}"[tcp://host:port to bind/connect to]:host: " \
"($help)--icc[Enable inter-container communication]" \
"($help)*--insecure-registry=-[Enable insecure registry communication]:registry: " \
"($help)--ip=-[Default IP when binding container ports]" \
"($help)*--insecure-registry=[Enable insecure registry communication]:registry: " \
"($help)--ip=[Default IP when binding container ports]" \
"($help)--ip-forward[Enable net.ipv4.ip_forward]" \
"($help)--ip-masq[Enable IP masquerading]" \
"($help)--iptables[Enable addition of iptables rules]" \
"($help)--ipv6[Enable IPv6 networking]" \
"($help -l --log-level)"{-l,--log-level=-}"[Set the logging level]:level:(debug info warn error fatal)" \
"($help)*--label=-[Set key=value labels to the daemon]:label: " \
"($help)--log-driver=-[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)" \
"($help)*--log-opt=-[Log driver specific options]:log driver options: " \
"($help)--mtu=-[Set the containers network MTU]:mtu:(0 576 1420 1500 9000)" \
"($help -p --pidfile)"{-p,--pidfile=-}"[Path to use for daemon PID file]:PID file:_files" \
"($help)*--registry-mirror=-[Preferred Docker registry mirror]:registry mirror: " \
"($help -s --storage-driver)"{-s,--storage-driver=-}"[Storage driver to use]:driver:(aufs devicemapper btrfs zfs overlay)" \
"($help -l --log-level)"{-l,--log-level=}"[Set the logging level]:level:(debug info warn error fatal)" \
"($help)*--label=[Set key=value labels to the daemon]:label: " \
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs none)" \
"($help)*--log-opt=[Log driver specific options]:log driver options: " \
"($help)--mtu=[Set the containers network MTU]:mtu:(0 576 1420 1500 9000)" \
"($help -p --pidfile)"{-p,--pidfile=}"[Path to use for daemon PID file]:PID file:_files" \
"($help)*--registry-mirror=[Preferred Docker registry mirror]:registry mirror: " \
"($help -s --storage-driver)"{-s,--storage-driver=}"[Storage driver to use]:driver:(aufs devicemapper btrfs zfs overlay)" \
"($help)--selinux-enabled[Enable selinux support]" \
"($help)*--storage-opt=-[Set storage driver options]:storage driver options: " \
"($help)*--storage-opt=[Set storage driver options]:storage driver options: " \
"($help)--tls[Use TLS]" \
"($help)--tlscacert=-[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlscert=-[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlskey=-[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
"($help)--tlsverify[Use TLS and verify the remote]" \
"($help)--userland-proxy[Use userland proxy for loopback traffic]" && ret=0
@@ -586,9 +590,9 @@ __docker_subcommand() {
(events)
_arguments \
$opts_help \
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
"($help)--since=-[Events created since this timestamp]:timestamp: " \
"($help)--until=-[Events created until this timestamp]:timestamp: " && ret=0
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
"($help)--since=[Events created since this timestamp]:timestamp: " \
"($help)--until=[Events created until this timestamp]:timestamp: " && ret=0
;;
(exec)
local state
@@ -598,7 +602,7 @@ __docker_subcommand() {
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]" \
"($help)--privileged[Give extended Linux capabilities to the command]" \
"($help -t --tty)"{-t,--tty}"[Allocate a pseudo-tty]" \
"($help -u --user)"{-u,--user=-}"[Username or UID]:user:_users" \
"($help -u --user)"{-u,--user=}"[Username or UID]:user:_users" \
"($help -):containers:__docker_runningcontainers" \
"($help -)*::command:->anycommand" && ret=0
@@ -613,7 +617,7 @@ __docker_subcommand() {
(export)
_arguments \
$opts_help \
"($help -o --output)"{-o,--output=-}"[Write to a file, instead of stdout]:output file:_files" \
"($help -o --output)"{-o,--output=}"[Write to a file, instead of stdout]:output file:_files" \
"($help -)*:containers:__docker_containers" && ret=0
;;
(history)
@@ -629,7 +633,7 @@ __docker_subcommand() {
$opts_help \
"($help -a --all)"{-a,--all}"[Show all images]" \
"($help)--digest[Show digests]" \
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
"($help)--no-trunc[Do not truncate output]" \
"($help -q --quiet)"{-q,--quiet}"[Only show numeric IDs]" \
"($help -): :__docker_repositories" && ret=0
@@ -637,7 +641,8 @@ __docker_subcommand() {
(import)
_arguments \
$opts_help \
"($help -c --change)*"{-c,--change=-}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
"($help -c --change)*"{-c,--change=}"[Apply Dockerfile instruction to the created image]:Dockerfile:_files" \
"($help -m --message)"{-m,--message=}"[Set commit message for imported image]:message: " \
"($help -):URL:(- http:// file://)" \
"($help -): :__docker_repositories_with_tags" && ret=0
;;
@@ -649,9 +654,9 @@ __docker_subcommand() {
local state
_arguments \
$opts_help \
"($help -f --format=-)"{-f,--format=-}"[Format the output using the given go template]:template: " \
"($help -f --format)"{-f,--format=}"[Format the output using the given go template]:template: " \
"($help -s --size)"{-s,--size}"[Display total file sizes if the type is container]" \
"($help)--type=-[Return JSON for specified type]:type:(image container)" \
"($help)--type=[Return JSON for specified type]:type:(image container)" \
"($help -)*: :->values" && ret=0
case $state in
@@ -669,20 +674,20 @@ __docker_subcommand() {
(kill)
_arguments \
$opts_help \
"($help -s --signal)"{-s,--signal=-}"[Signal to send]:signal:_signals" \
"($help -s --signal)"{-s,--signal=}"[Signal to send]:signal:_signals" \
"($help -)*:containers:__docker_runningcontainers" && ret=0
;;
(load)
_arguments \
$opts_help \
"($help -i --input)"{-i,--input=-}"[Read from tar archive file]:archive file:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"" && ret=0
"($help -i --input)"{-i,--input=}"[Read from tar archive file]:archive file:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"" && ret=0
;;
(login)
_arguments \
$opts_help \
"($help -e --email)"{-e,--email=-}"[Email]:email: " \
"($help -p --password)"{-p,--password=-}"[Password]:password: " \
"($help -u --user)"{-u,--user=-}"[Username]:username: " \
"($help -e --email)"{-e,--email=}"[Email]:email: " \
"($help -p --password)"{-p,--password=}"[Password]:password: " \
"($help -u --user)"{-u,--user=}"[Username]:username: " \
"($help -)1:server: " && ret=0
;;
(logout)
@@ -694,9 +699,9 @@ __docker_subcommand() {
_arguments \
$opts_help \
"($help -f --follow)"{-f,--follow}"[Follow log output]" \
"($help -s --since)"{-s,--since=-}"[Show logs since this timestamp]:timestamp: " \
"($help -s --since)"{-s,--since=}"[Show logs since this timestamp]:timestamp: " \
"($help -t --timestamps)"{-t,--timestamps}"[Show timestamps]" \
"($help)--tail=-[Output the last K lines]:lines:(1 10 20 50 all)" \
"($help)--tail=[Output the last K lines]:lines:(1 10 20 50 all)" \
"($help -)*:containers:__docker_containers" && ret=0
;;
(network)
@@ -731,15 +736,15 @@ __docker_subcommand() {
_arguments \
$opts_help \
"($help -a --all)"{-a,--all}"[Show all containers]" \
"($help)--before=-[Show only container created before...]:containers:__docker_containers" \
"($help)*"{-f,--filter=-}"[Filter values]:filter: " \
"($help)--before=[Show only container created before...]:containers:__docker_containers" \
"($help)*"{-f,--filter=}"[Filter values]:filter: " \
"($help)--format[Pretty-print containers using a Go template]:format: " \
"($help -l --latest)"{-l,--latest}"[Show only the latest created container]" \
"($help)-n[Show n last created containers, include non-running one]:n:(1 5 10 25 50)" \
"($help)--no-trunc[Do not truncate output]" \
"($help -q --quiet)"{-q,--quiet}"[Only show numeric IDs]" \
"($help -s --size)"{-s,--size}"[Display total file sizes]" \
"($help)--since=-[Show only containers created since...]:containers:__docker_containers" && ret=0
"($help)--since=[Show only containers created since...]:containers:__docker_containers" && ret=0
;;
(pull)
_arguments \
@@ -761,7 +766,7 @@ __docker_subcommand() {
(restart|stop)
_arguments \
$opts_help \
"($help -t --time=-)"{-t,--time=-}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \
"($help -t --time)"{-t,--time=}"[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)" \
"($help -)*:containers:__docker_runningcontainers" && ret=0
;;
(rm)
@@ -787,7 +792,7 @@ __docker_subcommand() {
"($help -d --detach)"{-d,--detach}"[Detached mode: leave the container running in the background]" \
"($help)--rm[Remove intermediate containers when it exits]" \
"($help)--sig-proxy[Proxy all received signals to the process (non-TTY mode only)]" \
"($help)--stop-signal=-[Signal to kill a container]:signal:_signals" \
"($help)--stop-signal=[Signal to kill a container]:signal:_signals" \
"($help -): :__docker_images" \
"($help -):command: _command_names -e" \
"($help -)*::arguments: _normal" && ret=0
@@ -806,7 +811,7 @@ __docker_subcommand() {
(save)
_arguments \
$opts_help \
"($help -o --output)"{-o,--output=-}"[Write to file]:file:_files" \
"($help -o --output)"{-o,--output=}"[Write to file]:file:_files" \
"($help -)*: :__docker_images" && ret=0
;;
(search)
@@ -814,7 +819,7 @@ __docker_subcommand() {
$opts_help \
"($help)--automated[Only show automated builds]" \
"($help)--no-trunc[Do not truncate output]" \
"($help -s --stars)"{-s,--stars=-}"[Only display with at least X stars]:stars:(0 10 100 1000)" \
"($help -s --stars)"{-s,--stars=}"[Only display with at least X stars]:stars:(0 10 100 1000)" \
"($help -):term: " && ret=0
;;
(start)
@@ -895,12 +900,12 @@ _docker() {
"(: -)"{-h,--help}"[Print usage]" \
"($help)--config[Location of client config files]:path:_directories" \
"($help -D --debug)"{-D,--debug}"[Enable debug mode]" \
"($help -H --host)"{-H,--host=-}"[tcp://host:port to bind/connect to]:host: " \
"($help -l --log-level)"{-l,--log-level=-}"[Set the logging level]:level:(debug info warn error fatal)" \
"($help -H --host)"{-H,--host=}"[tcp://host:port to bind/connect to]:host: " \
"($help -l --log-level)"{-l,--log-level=}"[Set the logging level]:level:(debug info warn error fatal)" \
"($help)--tls[Use TLS]" \
"($help)--tlscacert=-[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlscert=-[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlskey=-[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
"($help)--tlscacert=[Trust certs signed only by this CA]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlscert=[Path to TLS certificate file]:PEM file:_files -g "*.(pem|crt)"" \
"($help)--tlskey=[Path to TLS key file]:Key file:_files -g "*.(pem|key)"" \
"($help)--tlsverify[Use TLS and verify the remote]" \
"($help)--userland-proxy[Use userland proxy for loopback traffic]" \
"($help -v --version)"{-v,--version}"[Print version information and quit]" \
+25 -11
View File
@@ -324,24 +324,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
c.ContainerPid = pid
oomKill := false
oomKillNotification, err := notifyOnOOM(cgroupPaths)
if hooks.Start != nil {
logrus.Debugf("Invoking startCallback")
hooks.Start(&c.ProcessConfig, pid, oomKillNotification)
chOOM := make(chan struct{})
close(chOOM)
hooks.Start(&c.ProcessConfig, pid, chOOM)
}
oomKillNotification := notifyChannelOOM(cgroupPaths)
<-waitLock
exitCode := getExitCode(c)
if err == nil {
_, oomKill = <-oomKillNotification
logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
} else {
logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
}
_, oomKill := <-oomKillNotification
logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
// check oom error
if oomKill {
@@ -351,6 +347,17 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr
}
func notifyChannelOOM(paths map[string]string) <-chan struct{} {
oom, err := notifyOnOOM(paths)
if err != nil {
logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
c := make(chan struct{})
close(c)
return c
}
return oom
}
// copy from libcontainer
func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
dir := paths["memory"]
@@ -386,11 +393,13 @@ func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
buf := make([]byte, 8)
for {
if _, err := eventfd.Read(buf); err != nil {
logrus.Warn(err)
return
}
// When a cgroup is destroyed, an event is sent to eventfd.
// So if the control path is gone, return instead of notifying.
if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
logrus.Warn(err)
return
}
ch <- struct{}{}
@@ -424,6 +433,11 @@ func cgroupPaths(containerID string) (map[string]string, error) {
//unsupported subystem
continue
}
// if we are running dind
dockerPathIdx := strings.LastIndex(cgroupDir, "docker")
if dockerPathIdx != -1 {
cgroupDir = cgroupDir[:dockerPathIdx-1]
}
path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID)
paths[subsystem] = path
}
+2 -12
View File
@@ -91,9 +91,9 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
{{if .Resources}}
{{if .Resources.Memory}}
lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
{{with $memSwap := getMemorySwap .Resources}}
lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
{{end}}
{{if gt .Resources.MemorySwap 0}}
lxc.cgroup.memory.memsw.limit_in_bytes = {{.Resources.MemorySwap}}
{{end}}
{{if gt .Resources.MemoryReservation 0}}
lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}}
@@ -209,15 +209,6 @@ func isDirectory(source string) string {
return "file"
}
func getMemorySwap(v *execdriver.Resources) int64 {
// By default, MemorySwap is set to twice the size of RAM.
// If you want to omit MemorySwap, set it to `-1'.
if v.MemorySwap < 0 {
return 0
}
return v.Memory * 2
}
func getLabel(c map[string][]string, name string) string {
label := c["label"]
for _, l := range label {
@@ -242,7 +233,6 @@ func getHostname(env []string) string {
func init() {
var err error
funcMap := template.FuncMap{
"getMemorySwap": getMemorySwap,
"escapeFstabSpaces": escapeFstabSpaces,
"formatMountLabel": label.FormatMountLabel,
"isDirectory": isDirectory,
@@ -34,6 +34,7 @@ func TestLXCConfig(t *testing.T) {
memMin = 33554432
memMax = 536870912
mem = memMin + r.Intn(memMax-memMin)
swap = memMax
cpuMin = 100
cpuMax = 10000
cpu = cpuMin + r.Intn(cpuMax-cpuMin)
@@ -46,8 +47,9 @@ func TestLXCConfig(t *testing.T) {
command := &execdriver.Command{
ID: "1",
Resources: &execdriver.Resources{
Memory: int64(mem),
CPUShares: int64(cpu),
Memory: int64(mem),
MemorySwap: int64(swap),
CPUShares: int64(cpu),
},
Network: &execdriver.Network{
Mtu: 1500,
@@ -63,7 +65,7 @@ func TestLXCConfig(t *testing.T) {
fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
grepFile(t, p,
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", swap))
}
func TestCustomLxcConfig(t *testing.T) {
-1
View File
@@ -167,7 +167,6 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
oom := notifyOnOOM(cont)
if hooks.Start != nil {
pid, err := p.Pid()
if err != nil {
p.Signal(os.Kill)
+8 -4
View File
@@ -18,6 +18,7 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
term execdriver.Terminal
err error
exitCode int32
errno uint32
)
active := d.activeContainers[c.ID]
@@ -77,12 +78,15 @@ func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
}
if exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid); err != nil {
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
if exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite); err != nil {
if errno == hcsshim.Win32PipeHasBeenEnded {
logrus.Debugf("Exiting Run() after WaitForProcessInComputeSystem failed with recognised error 0x%X", errno)
return hcsshim.WaitErrExecFailed, nil
}
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): 0x%X %s", errno, err)
return -1, err
}
// TODO Windows - Do something with this exit code
logrus.Debugln("Exiting Run() with ExitCode 0", c.ID)
logrus.Debugln("Exiting Run()", c.ID)
return int(exitCode), nil
}
+11 -2
View File
@@ -3,6 +3,7 @@
package windows
import (
"fmt"
"io"
"github.com/Sirupsen/logrus"
@@ -22,7 +23,11 @@ func startStdinCopy(dst io.WriteCloser, src io.Reader) {
go func() {
defer dst.Close()
bytes, err := io.Copy(dst, src)
logrus.Debugf("Copied %d bytes from stdin err=%s", bytes, err)
log := fmt.Sprintf("Copied %d bytes from stdin.", bytes)
if err != nil {
log = log + " err=" + err.Error()
}
logrus.Debugf(log)
}()
}
@@ -35,7 +40,11 @@ func startStdouterrCopy(dst io.Writer, src io.ReadCloser, name string) {
go func() {
defer src.Close()
bytes, err := io.Copy(dst, src)
logrus.Debugf("Copied %d bytes from %s err=%s", bytes, name, err)
log := fmt.Sprintf("Copied %d bytes from %s.", bytes, name)
if err != nil {
log = log + " err=" + err.Error()
}
logrus.Debugf(log)
}()
}
+23 -17
View File
@@ -220,22 +220,19 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
}
defer func() {
// Stop the container
if terminateMode {
logrus.Debugf("Terminating container %s", c.ID)
if err := hcsshim.TerminateComputeSystem(c.ID); err != nil {
// IMPORTANT: Don't fail if fails to change state. It could already
// have been stopped through kill().
// Otherwise, the docker daemon will hang in job wait()
logrus.Warnf("Ignoring error from TerminateComputeSystem %s", err)
if forceKill {
logrus.Debugf("Forcibly terminating container %s", c.ID)
if errno, err := hcsshim.TerminateComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
logrus.Warnf("Ignoring error from TerminateComputeSystem 0x%X %s", errno, err)
}
} else {
logrus.Debugf("Shutting down container %s", c.ID)
if err := hcsshim.ShutdownComputeSystem(c.ID); err != nil {
// IMPORTANT: Don't fail if fails to change state. It could already
// have been stopped through kill().
// Otherwise, the docker daemon will hang in job wait()
logrus.Warnf("Ignoring error from ShutdownComputeSystem %s", err)
if errno, err := hcsshim.ShutdownComputeSystem(c.ID, hcsshim.TimeoutInfinite, "exec-run-defer"); err != nil {
if errno != hcsshim.Win32SystemShutdownIsInProgress &&
errno != hcsshim.Win32SpecifiedPathInvalid &&
errno != hcsshim.Win32SystemCannotFindThePathSpecified {
logrus.Warnf("Ignoring error from ShutdownComputeSystem 0x%X %s", errno, err)
}
}
}
}()
@@ -303,11 +300,20 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
hooks.Start(&c.ProcessConfig, int(pid), chOOM)
}
var exitCode int32
exitCode, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid)
var (
exitCode int32
errno uint32
)
exitCode, errno, err = hcsshim.WaitForProcessInComputeSystem(c.ID, pid, hcsshim.TimeoutInfinite)
if err != nil {
logrus.Errorf("Failed to WaitForProcessInComputeSystem %s", err)
return execdriver.ExitStatus{ExitCode: -1}, err
if errno != hcsshim.Win32PipeHasBeenEnded {
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
}
// Do NOT return err here as the container would have
// started, otherwise docker will deadlock. It's perfectly legitimate
// for WaitForProcessInComputeSystem to fail in situations such
// as the container being killed on another thread.
return execdriver.ExitStatus{ExitCode: hcsshim.WaitErrExecFailed}, nil
}
logrus.Debugf("Exiting Run() exitCode %d id=%s", exitCode, c.ID)
+20 -18
View File
@@ -3,6 +3,9 @@
package windows
import (
"fmt"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/daemon/execdriver"
"github.com/microsoft/hcsshim"
@@ -10,37 +13,36 @@ import (
// Terminate implements the exec driver Driver interface.
func (d *Driver) Terminate(p *execdriver.Command) error {
logrus.Debugf("WindowsExec: Terminate() id=%s", p.ID)
return kill(p.ID, p.ContainerPid)
return kill(p.ID, p.ContainerPid, syscall.SIGTERM)
}
// Kill implements the exec driver Driver interface.
func (d *Driver) Kill(p *execdriver.Command, sig int) error {
logrus.Debugf("WindowsExec: Kill() id=%s sig=%d", p.ID, sig)
return kill(p.ID, p.ContainerPid)
return kill(p.ID, p.ContainerPid, syscall.Signal(sig))
}
func kill(id string, pid int) error {
logrus.Debugln("kill() ", id, pid)
func kill(id string, pid int, sig syscall.Signal) error {
logrus.Debugf("WindowsExec: kill() id=%s pid=%d sig=%d", id, pid, sig)
var err error
context := fmt.Sprintf("kill: sig=%d pid=%d", sig, pid)
// Terminate Process
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
// Ignore errors
err = nil
}
if terminateMode {
if sig == syscall.SIGKILL || forceKill {
// Terminate the compute system
if err = hcsshim.TerminateComputeSystem(id); err != nil {
logrus.Errorf("Failed to terminate %s - %q", id, err)
if errno, err := hcsshim.TerminateComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
logrus.Errorf("Failed to terminate %s - 0x%X %q", id, errno, err)
}
} else {
// Terminate Process
if err = hcsshim.TerminateProcessInComputeSystem(id, uint32(pid)); err != nil {
logrus.Warnf("Failed to terminate pid %d in %s: %q", pid, id, err)
// Ignore errors
err = nil
}
// Shutdown the compute system
if err = hcsshim.ShutdownComputeSystem(id); err != nil {
logrus.Errorf("Failed to shutdown %s - %q", id, err)
if errno, err := hcsshim.ShutdownComputeSystem(id, hcsshim.TimeoutInfinite, context); err != nil {
logrus.Errorf("Failed to shutdown %s - 0x%X %q", id, errno, err)
}
}
return err
+5 -4
View File
@@ -18,7 +18,8 @@ import (
var dummyMode bool
// This allows the daemon to terminate containers rather than shutdown
var terminateMode bool
// This allows the daemon to force kill (HCS terminate) rather than shutdown
var forceKill bool
// Define name and version for windows
var (
@@ -62,11 +63,11 @@ func NewDriver(root, initPath string, options []string) (*Driver, error) {
logrus.Warn("Using dummy mode in Windows exec driver. This is for development use only!")
}
case "terminate":
case "forcekill":
switch val {
case "1":
terminateMode = true
logrus.Warn("Using terminate mode in Windows exec driver. This is for testing purposes only.")
forceKill = true
logrus.Warn("Using force kill mode in Windows exec driver. This is for testing purposes only.")
}
default:
+11 -1
View File
@@ -1,6 +1,12 @@
package daemon
import "syscall"
import (
"fmt"
"runtime"
"syscall"
"github.com/docker/docker/pkg/signal"
)
// ContainerKill send signal to the container
// If no signal is given (sig 0), then Kill with SIGKILL and wait
@@ -12,6 +18,10 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
return err
}
if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) {
return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig)
}
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
if err := container.Kill(); err != nil {
+22 -8
View File
@@ -9,6 +9,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
derr "github.com/docker/docker/errors"
"github.com/docker/docker/graph"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/graphdb"
"github.com/docker/docker/pkg/nat"
@@ -285,6 +286,24 @@ func includeContainerInList(container *Container, ctx *listContext) iterationAct
return includeContainer
}
func getImage(s *graph.TagStore, img, imgID string) (string, error) {
// both Image and ImageID is actually ids, nothing to guess
if strings.HasPrefix(imgID, img) {
return img, nil
}
id, err := s.GetID(img)
if err != nil {
if err == graph.ErrNameIsNotExist {
return imgID, nil
}
return "", err
}
if id != imgID {
return imgID, nil
}
return img, nil
}
// transformContainer generates the container type expected by the docker ps command.
func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) (*types.Container, error) {
newC := &types.Container{
@@ -297,16 +316,11 @@ func (daemon *Daemon) transformContainer(container *Container, ctx *listContext)
newC.Names = []string{}
}
img, err := daemon.repositories.LookupImage(container.Config.Image)
showImg, err := getImage(daemon.repositories, container.Config.Image, container.ImageID)
if err != nil {
// If the image can no longer be found by its original reference,
// it makes sense to show the ID instead of a stale reference.
newC.Image = container.ImageID
} else if container.ImageID == img.ID {
newC.Image = container.Config.Image
} else {
newC.Image = container.ImageID
return nil, err
}
newC.Image = showImg
if len(container.Args) > 0 {
args := []string{}
+23 -1
View File
@@ -80,7 +80,7 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
}
// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (libnetwork.Network, error) {
func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, options map[string]string) (libnetwork.Network, error) {
c := daemon.netController
if driver == "" {
driver = c.Config().Daemon.DefaultDriver
@@ -96,6 +96,7 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM) (lib
if len(ipam.Config) > 0 {
nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
}
nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
return c.NewNetwork(driver, name, nwOptions...)
}
@@ -120,3 +121,24 @@ func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnet
}
return ipamV4Cfg, ipamV6Cfg, nil
}
// ConnectContainerToNetwork connects the given container to the given
// network. If either cannot be found, an err is returned. If the
// network cannot be set up, an err is returned.
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string) error {
container, err := daemon.Get(containerName)
if err != nil {
return err
}
return container.ConnectToNetwork(networkName)
}
// DisconnectContainerFromNetwork disconnects the given container from
// the given network. If either cannot be found, an err is returned.
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network) error {
container, err := daemon.Get(containerName)
if err != nil {
return err
}
return container.DisconnectFromNetwork(network)
}
+6 -6
View File
@@ -59,7 +59,7 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
For Fedora 22 run:
$ cat >/etc/yum.repos.d/docker.repo <<-EOF
$ cat >/etc/yum.repos.d/docker.repo <<-EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/fedora/22
@@ -74,7 +74,7 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
5. Start the Docker daemon.
$ sudo service docker start
$ sudo systemctl start docker
6. Verify `docker` is installed correctly by running a test image in a container.
@@ -123,13 +123,13 @@ There are two ways to install Docker Engine. You can install with the `yum` pac
4. Start the Docker daemon.
$ sudo service docker start
$ sudo systemctl start docker
5. Verify `docker` is installed correctly by running a test image in a container.
$ sudo docker run hello-world
## Create a docker group
## Create a docker group
The `docker` daemon binds to a Unix socket instead of a TCP port. By default
that Unix socket is owned by the user `root` and other users can access it with
@@ -163,7 +163,7 @@ To create the `docker` group and add your user:
To ensure Docker starts when you boot your system, do the following:
$ sudo chkconfig docker on
$ sudo systemctl enable docker
If you need to add an HTTP Proxy, set a different directory or partition for the
Docker runtime files, or make other customizations, read our Systemd article to
@@ -190,7 +190,7 @@ This configuration allows IP forwarding from the container as expected.
## Uninstall
You can uninstall the Docker software with `yum`.
You can uninstall the Docker software with `yum`.
1. List the package you have installed.
+2
View File
@@ -21,6 +21,8 @@ The following short variant options are deprecated in favor of their long
variants:
docker run -c (--cpu-shares)
docker build -c (--cpu-shares)
docker create -c (--cpu-shares)
### Driver Specific Log Tags
**Deprecated In Release: v1.9**
+9 -3
View File
@@ -23,14 +23,15 @@ client must have `root` access to interact with the daemon. If a group named
`docker` exists on your system, `docker` applies ownership of the socket to the
group.
The current version of the API is v1.21 which means calling `/info` is the same
as calling `/v1.21/info`. To call an older version of the API use
`/v1.20/info`.
The current version of the API is v1.22 which means calling `/info` is the same
as calling `/v1.22/info`. To call an older version of the API use
`/v1.21/info`.
Use the table below to find the API version for a Docker version:
Docker version | API version | Changes
----------------|-------------------------------------------------|-----------------------------
1.10.x | [1.22](/reference/api/docker_remote_api_v1.22/) | [API changes](/reference/api/docker_remote_api/#v1-22-api-changes)
1.9.x | [1.21](/reference/api/docker_remote_api_v1.21/) | [API changes](/reference/api/docker_remote_api/#v1-21-api-changes)
1.8.x | [1.20](/reference/api/docker_remote_api_v1.20/) | [API changes](/reference/api/docker_remote_api/#v1-20-api-changes)
1.7.x | [1.19](/reference/api/docker_remote_api_v1.19/) | [API changes](/reference/api/docker_remote_api/#v1-19-api-changes)
@@ -89,6 +90,11 @@ Running `docker rmi` emits an **untag** event when removing an image name. The
This section lists each version from latest to oldest. Each listing includes a link to the full documentation set and the changes relevant in that release.
### v1.22 API changes
[Docker Remote API v1.22](docker_remote_api_v1.22.md) documentation
### v1.21 API changes
[Docker Remote API v1.21](docker_remote_api_v1.21.md) documentation
@@ -1465,12 +1465,15 @@ a base64-encoded AuthConfig object.
Query Parameters:
- **fromImage** Name of the image to pull.
- **fromImage** Name of the image to pull. The name may include a tag or
digest. This parameter may only be used when pulling an image.
- **fromSrc** Source to import. The value may be a URL from which the image
can be retrieved or `-` to read the image from the request body.
- **repo** Repository name.
- **tag** Tag.
- **registry** The registry to pull from.
This parameter may only be used when importing an image.
- **repo** Repository name given to an image when it is imported.
The repo may include a tag. This parameter may only be used when importing
an image.
- **tag** Tag or digest.
Request Headers:
File diff suppressed because it is too large Load Diff
+38 -20
View File
@@ -15,7 +15,7 @@ parent = "smn_cli"
Build a new image from the source code at PATH
--build-arg=[] Set build-time variables
-c, --cpu-shares CPU Shares (relative weight)
--cpu-shares CPU Shares (relative weight)
--cgroup-parent="" Optional parent cgroup for the container
--cpu-period=0 Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota=0 Limit the CPU CFS (Completely Fair Scheduler) quota
@@ -128,6 +128,8 @@ See also:
## Examples
### Build with PATH
$ docker build .
Uploading context 10240 bytes
Step 1 : FROM busybox
@@ -168,6 +170,31 @@ The transfer of context from the local machine to the Docker daemon is what the
If you wish to keep the intermediate containers after the build is complete,
you must use `--rm=false`. This does not affect the build cache.
### Build with URL
$ docker build github.com/creack/docker-firefox
This will clone the GitHub repository and use the cloned repository as context.
The Dockerfile at the root of the repository is used as Dockerfile. Note that
you can specify an arbitrary Git repository by using the `git://` or `git@`
schema.
### Build with -
$ docker build - < Dockerfile
This will read a Dockerfile from `STDIN` without context. Due to the lack of a
context, no contents of any local directory will be sent to the Docker daemon.
Since there is no context, a Dockerfile `ADD` only works if it refers to a
remote URL.
$ docker build - < context.tar.gz
This will build an image for a compressed context read from `STDIN`. Supported
formats are: bzip2, gzip and xz.
### Usage of .dockerignore
$ docker build .
Uploading context 18.829 MB
Uploading context
@@ -193,29 +220,14 @@ directory from the context. Its effect can be seen in the changed size of the
uploaded context. The builder reference contains detailed information on
[creating a .dockerignore file](../builder.md#dockerignore-file)
### Tag image (-t)
$ docker build -t vieux/apache:2.0 .
This will build like the previous example, but it will then tag the resulting
image. The repository name will be `vieux/apache` and the tag will be `2.0`
$ docker build - < Dockerfile
This will read a Dockerfile from `STDIN` without context. Due to the lack of a
context, no contents of any local directory will be sent to the Docker daemon.
Since there is no context, a Dockerfile `ADD` only works if it refers to a
remote URL.
$ docker build - < context.tar.gz
This will build an image for a compressed context read from `STDIN`. Supported
formats are: bzip2, gzip and xz.
$ docker build github.com/creack/docker-firefox
This will clone the GitHub repository and use the cloned repository as context.
The Dockerfile at the root of the repository is used as Dockerfile. Note that
you can specify an arbitrary Git repository by using the `git://` or `git@`
schema.
### Specify Dockerfile (-f)
$ docker build -f Dockerfile.debug .
@@ -248,14 +260,20 @@ the command line.
> repeatable builds on remote Docker hosts. This is also the reason why
> `ADD ../file` will not work.
### Optional parent cgroup (--cgroup-parent)
When `docker build` is run with the `--cgroup-parent` option the containers
used in the build will be run with the [corresponding `docker run`
flag](../run.md#specifying-custom-cgroups).
### Set ulimits in container (--ulimit)
Using the `--ulimit` option with `docker build` will cause each build step's
container to be started using those [`--ulimit`
flag values](../run.md#setting-ulimits-in-a-container).
### Set build-time variables (--build-arg)
You can use `ENV` instructions in a Dockerfile to define variable
values. These values persist in the built image. However, often
persistence is not what you want. Users want to specify variables differently
@@ -263,7 +281,7 @@ depending on which host they build an image on.
A good example is `http_proxy` or source versions for pulling intermediate
files. The `ARG` instruction lets Dockerfile authors define values that users
can set at build-time using the `---build-arg` flag:
can set at build-time using the `--build-arg` flag:
$ docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .
+1 -1
View File
@@ -121,7 +121,7 @@ To list the help on any command just execute the command, followed by the
Run a command in a new container
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
-c, --cpu-shares=0 CPU shares (relative weight)
--cpu-shares=0 CPU shares (relative weight)
...
## Option types
+1 -1
View File
@@ -19,7 +19,7 @@ Creates a new container.
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
--add-host=[] Add a custom host-to-IP mapping (host:ip)
--blkio-weight=0 Block IO weight (relative weight)
-c, --cpu-shares=0 CPU shares (relative weight)
--cpu-shares=0 CPU shares (relative weight)
--cap-add=[] Add Linux capabilities
--cap-drop=[] Drop Linux capabilities
--cgroup-parent="" Optional parent cgroup for the container
+36 -23
View File
@@ -205,9 +205,10 @@ options for `zfs` start with `zfs`.
Example use:
docker daemon --storage-opt dm.thinpooldev=/dev/mapper/thin-pool
$ docker daemon \
--storage-opt dm.thinpooldev=/dev/mapper/thin-pool
* `dm.basesize`
* `dm.basesize`
Specifies the size to use when creating the base device, which limits the
size of images and containers. The default value is 100G. Note, thin devices
@@ -227,9 +228,11 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.basesize=20G
* `dm.loopdatasize`
* `dm.loopdatasize`
>**Note**: This option configures devicemapper loopback, which should not be used in production.
> **Note**:
> This option configures devicemapper loopback, which should not
> be used in production.
Specifies the size to use when creating the loopback file for the
"data" device which is used for the thin pool. The default size is
@@ -240,9 +243,11 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.loopdatasize=200G
* `dm.loopmetadatasize`
* `dm.loopmetadatasize`
>**Note**: This option configures devicemapper loopback, which should not be used in production.
> **Note**:
> This option configures devicemapper loopback, which should not
> be used in production.
Specifies the size to use when creating the loopback file for the
"metadata" device which is used for the thin pool. The default size
@@ -253,7 +258,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.loopmetadatasize=4G
* `dm.fs`
* `dm.fs`
Specifies the filesystem type to use for the base device. The supported
options are "ext4" and "xfs". The default is "ext4"
@@ -262,7 +267,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.fs=xfs
* `dm.mkfsarg`
* `dm.mkfsarg`
Specifies extra mkfs arguments to be used when creating the base device.
@@ -270,7 +275,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt "dm.mkfsarg=-O ^has_journal"
* `dm.mountopt`
* `dm.mountopt`
Specifies extra mount options used when mounting the thin devices.
@@ -278,7 +283,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.mountopt=nodiscard
* `dm.datadev`
* `dm.datadev`
(Deprecated, use `dm.thinpooldev`)
@@ -290,9 +295,11 @@ options for `zfs` start with `zfs`.
Example use:
$ docker daemon --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1
$ docker daemon \
--storage-opt dm.datadev=/dev/sdb1 \
--storage-opt dm.metadatadev=/dev/sdc1
* `dm.metadatadev`
* `dm.metadatadev`
(Deprecated, use `dm.thinpooldev`)
@@ -304,13 +311,15 @@ options for `zfs` start with `zfs`.
If setting up a new metadata pool it is required to be valid. This can be
achieved by zeroing the first 4k to indicate empty metadata, like this:
$ dd if=/dev/zero of=$metadata_dev bs=4096 count=1
$ dd if=/dev/zero of=$metadata_dev bs=4096 count=1
Example use:
$ docker daemon --storage-opt dm.datadev=/dev/sdb1 --storage-opt dm.metadatadev=/dev/sdc1
$ docker daemon \
--storage-opt dm.datadev=/dev/sdb1 \
--storage-opt dm.metadatadev=/dev/sdc1
* `dm.blocksize`
* `dm.blocksize`
Specifies a custom blocksize to use for the thin pool. The default
blocksize is 64K.
@@ -319,7 +328,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.blocksize=512K
* `dm.blkdiscard`
* `dm.blkdiscard`
Enables or disables the use of blkdiscard when removing devicemapper
devices. This is enabled by default (only) if using loopback devices and is
@@ -333,7 +342,7 @@ options for `zfs` start with `zfs`.
$ docker daemon --storage-opt dm.blkdiscard=false
* `dm.override_udev_sync_check`
* `dm.override_udev_sync_check`
Overrides the `udev` synchronization checks between `devicemapper` and `udev`.
`udev` is the device manager for the Linux kernel.
@@ -369,7 +378,7 @@ options for `zfs` start with `zfs`.
> Otherwise, set this flag for migrating existing Docker daemons to
> a daemon with a supported environment.
* `dm.use_deferred_removal`
* `dm.use_deferred_removal`
Enables use of deferred device removal if `libdm` and the kernel driver
support the mechanism.
@@ -385,21 +394,25 @@ options for `zfs` start with `zfs`.
system to schedule the device for deferred removal. It does not wait in a
loop trying to remove a busy device.
Example use: `docker daemon --storage-opt dm.use_deferred_removal=true`
Example use:
* `dm.use_deferred_deletion`
$ docker daemon --storage-opt dm.use_deferred_removal=true
* `dm.use_deferred_deletion`
Enables use of deferred device deletion for thin pool devices. By default,
thin pool device deletion is synchronous. Before a container is deleted,
the Docker daemon removes any associated devices. If the storage driver
can not remove a device, the container deletion fails and daemon returns.
`Error deleting container: Error response from daemon: Cannot destroy container`
Error deleting container: Error response from daemon: Cannot destroy container
To avoid this failure, enable both deferred device deletion and deferred
device removal on the daemon.
`docker daemon --storage-opt dm.use_deferred_deletion=true --storage-opt dm.use_deferred_removal=true`
$ docker daemon \
--storage-opt dm.use_deferred_deletion=true \
--storage-opt dm.use_deferred_removal=true
With these two options enabled, if a device is busy when the driver is
deleting a container, the driver marks the device as deleted. Later, when
@@ -411,7 +424,7 @@ options for `zfs` start with `zfs`.
Currently supported options of `zfs`:
* `zfs.fsname`
* `zfs.fsname`
Set zfs filesystem under which docker will create its own datasets.
By default docker will pick up the zfs filesystem where docker graph
+1 -1
View File
@@ -22,7 +22,7 @@ For example:
$ docker -D info
Containers: 14
Images: 52
Engine Version: 1.9.0
Server Version: 1.9.0
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
-2
View File
@@ -14,8 +14,6 @@ parent = "smn_cli"
Lists all the networks created by the user
--help=false Print usage
-l, --latest=false Show the latest network created
-n=-1 Show n last created networks
--no-trunc=false Do not truncate the output
-q, --quiet=false Only display numeric IDs
+62 -39
View File
@@ -17,7 +17,7 @@ parent = "smn_cli"
-a, --attach=[] Attach to STDIN, STDOUT or STDERR
--add-host=[] Add a custom host-to-IP mapping (host:ip)
--blkio-weight=0 Block IO weight (relative weight)
-c, --cpu-shares=0 CPU shares (relative weight)
--cpu-shares=0 CPU shares (relative weight)
--cap-add=[] Add Linux capabilities
--cap-drop=[] Drop Linux capabilities
--cgroup-parent="" Optional parent cgroup for the container
@@ -92,6 +92,8 @@ and linking containers.
## Examples
### Assign name and allocate psuedo-TTY (--name, -it)
$ docker run --name test -it debian
root@d6c0fe130dba:/# exit 13
$ echo $?
@@ -106,6 +108,8 @@ In the example, the `bash` shell is quit by entering
`exit 13`. This exit code is passed on to the caller of
`docker run`, and is recorded in the `test` container's metadata.
### Capture container ID (--cidfile)
$ docker run --cidfile /tmp/docker_test.cid ubuntu echo "test"
This will create a container and print `test` to the console. The `cidfile`
@@ -113,6 +117,8 @@ flag makes Docker attempt to create a new file and write the container ID to it.
If the file exists already, Docker will return an error. Docker will close this
file when `docker run` exits.
### Full container capabilities (--privileged)
$ docker run -t -i --rm ubuntu bash
root@bc338942ef20:/# mount -t tmpfs none /mnt
mount: permission denied
@@ -132,11 +138,15 @@ lifts all the limitations enforced by the `device` cgroup controller. In other
words, the container can then do almost everything that the host can do. This
flag exists to allow special use-cases, like running Docker within Docker.
### Set working directory (-w)
$ docker run -w /path/to/dir/ -i -t ubuntu pwd
The `-w` lets the command being executed inside directory given, here
`/path/to/dir/`. If the path does not exists it is created inside the container.
### Mount volume (-v, --read-only)
$ docker run -v `pwd`:`pwd` -w `pwd` -i -t ubuntu pwd
The `-v` flag mounts the current working directory into the container. The `-w`
@@ -166,6 +176,8 @@ binary (such as that provided by [https://get.docker.com](
https://get.docker.com)), you give the container the full access to create and
manipulate the host's Docker daemon.
### Publish or expose port (-p, --expose)
$ docker run -p 127.0.0.1:80:8080 ubuntu bash
This binds port `8080` of the container to port `80` on `127.0.0.1` of
@@ -179,6 +191,8 @@ publishing the port to the host system's interfaces. The [Docker User
Guide](../../userguide/dockerlinks.md) explains in detail how to manipulate
ports in Docker.
### Set environment variables (-e, --env, --env-file)
$ docker run -e MYVAR1 --env MYVAR2=foo --env-file ./env.list ubuntu bash
This sets environmental variables in the container. For illustration all three
@@ -247,7 +261,9 @@ An example of a file passed with `--env-file`
123qwe=bar
org.spring.config=something
A label is a a `key=value` pair that applies metadata to a container. To label a container with two labels:
### Set metadata on container (-l, --label, --label-file)
A label is a `key=value` pair that applies metadata to a container. To label a container with two labels:
$ docker run -l my-label --label com.example.foo=bar ubuntu bash
@@ -281,6 +297,8 @@ For additional information on working with labels, see [*Labels - custom
metadata in Docker*](../../userguide/labels-custom-metadata.md) in the Docker User
Guide.
### Add link to another container (--link)
$ docker run --link /redis:redis --name console ubuntu bash
The `--link` flag will link the container named `/redis` into the newly
@@ -295,6 +313,8 @@ example as:
The `--name` flag will assign the name `console` to the newly created
container.
### Mount volumes from container (--volumes-from)
$ docker run --volumes-from 777f7dc92da7 --volumes-from ba8c0c54f0f2:ro -i -t ubuntu pwd
The `--volumes-from` flag mounts all the defined volumes from the referenced
@@ -317,6 +337,8 @@ content label. Shared volume labels allow all containers to read/write content.
The `Z` option tells Docker to label the content with a private unshared label.
Only the current container can use a private volume.
### Attach to STDIN/STDOUT/STDERR (-a)
The `-a` flag tells `docker run` to bind to the container's `STDIN`, `STDOUT`
or `STDERR`. This makes it possible to manipulate the output and input as
needed.
@@ -340,6 +362,8 @@ logs could be retrieved using `docker logs`. This is
useful if you need to pipe a file or something else into a container and
retrieve the container's ID once the container has finished running.
### Add host device to container (--device)
$ docker run --device=/dev/sdc:/dev/xvdc --device=/dev/sdd --device=/dev/zero:/dev/nulo -i -t ubuntu ls -l /dev/{xvdc,sdd,nulo}
brw-rw---- 1 root disk 8, 2 Feb 9 16:05 /dev/xvdc
brw-rw---- 1 root disk 8, 3 Feb 9 16:05 /dev/sdd
@@ -375,38 +399,7 @@ flag:
> that may be removed should not be added to untrusted containers with
> `--device`.
**A complete example:**
$ docker run -d --name static static-web-files sh
$ docker run -d --expose=8098 --name riak riakserver
$ docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver
$ docker run -d -p 1443:443 --dns=10.0.0.1 --dns-search=dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
$ docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log
This example shows five containers that might be set up to test a web
application change:
1. Start a pre-prepared volume image `static-web-files` (in the background)
that has CSS, image and static HTML in it, (with a `VOLUME` instruction in
the Dockerfile to allow the web server to use those files);
2. Start a pre-prepared `riakserver` image, give the container name `riak` and
expose port `8098` to any containers that link to it;
3. Start the `appserver` image, restricting its memory usage to 100MB, setting
two environment variables `DEVELOPMENT` and `BRANCH` and bind-mounting the
current directory (`$(pwd)`) in the container in read-only mode as `/app/bin`;
4. Start the `webserver`, mapping port `443` in the container to port `1443` on
the Docker server, setting the DNS server to `10.0.0.1` and DNS search
domain to `dev.org`, creating a volume to put the log files into (so we can
access it from another container), then importing the files from the volume
exposed by the `static` container, and linking to all exposed ports from
`riak` and `app`. Lastly, we set the hostname to `web.sven.dev.org` so its
consistent with the pre-generated SSL certificate;
5. Finally, we create a container that runs `tail -f access.log` using the logs
volume from the `web` container, setting the workdir to `/var/log/httpd`. The
`--rm` option means that when the container exits, the container's layer is
removed.
## Restart policies
### Restart policies (--restart)
Use Docker's `--restart` to specify a container's *restart policy*. A restart
policy controls whether the Docker daemon restarts a container after exit.
@@ -468,7 +461,7 @@ More detailed information on restart policies can be found in the
[Restart Policies (--restart)](../run.md#restart-policies-restart)
section of the Docker run reference page.
## Adding entries to a container hosts file
### Add entries to container hosts file (--add-host)
You can add other hosts into a container's `/etc/hosts` file by using one or
more `--add-host` flags. This example adds a static address for a host named
@@ -499,7 +492,7 @@ For IPv6 use the `-6` flag instead of the `-4` flag. For other network
devices, replace `eth0` with the correct device name (for example `docker0`
for the bridge device).
### Setting ulimits in a container
### Set ulimits in container (--ulimit)
Since setting `ulimit` settings in a container requires extra privileges not
available in the default container, you can set these using the `--ulimit` flag.
@@ -519,13 +512,12 @@ available in the default container, you can set these using the `--ulimit` flag.
The values are sent to the appropriate `syscall` as they are set.
Docker doesn't perform any byte conversion. Take this into account when setting the values.
#### For `nproc` usage:
#### For `nproc` usage
Be careful setting `nproc` with the `ulimit` flag as `nproc` is designed by Linux to set the
maximum number of processes available to a user, not to a container. For example, start four
containers with `daemon` user:
docker run -d -u daemon --ulimit nproc=3 busybox top
docker run -d -u daemon --ulimit nproc=3 busybox top
docker run -d -u daemon --ulimit nproc=3 busybox top
@@ -535,8 +527,39 @@ The 4th container fails and reports "[8] System error: resource temporarily unav
This fails because the caller set `nproc=3` resulting in the first three containers using up
the three processes quota set for the `daemon` user.
### Stopping a container with a specific signal
### Stop container with signal (--stop-signal)
The `--stop-signal` flag sets the system call signal that will be sent to the container to exit.
This signal can be a valid unsigned number that matches a position in the kernel's syscall table, for instance 9,
or a signal name in the format SIGNAME, for instance SIGKILL.
### A complete example
$ docker run -d --name static static-web-files sh
$ docker run -d --expose=8098 --name riak riakserver
$ docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver
$ docker run -d -p 1443:443 --dns=10.0.0.1 --dns-search=dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
$ docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log
This example shows five containers that might be set up to test a web
application change:
1. Start a pre-prepared volume image `static-web-files` (in the background)
that has CSS, image and static HTML in it, (with a `VOLUME` instruction in
the Dockerfile to allow the web server to use those files);
2. Start a pre-prepared `riakserver` image, give the container name `riak` and
expose port `8098` to any containers that link to it;
3. Start the `appserver` image, restricting its memory usage to 100MB, setting
two environment variables `DEVELOPMENT` and `BRANCH` and bind-mounting the
current directory (`$(pwd)`) in the container in read-only mode as `/app/bin`;
4. Start the `webserver`, mapping port `443` in the container to port `1443` on
the Docker server, setting the DNS server to `10.0.0.1` and DNS search
domain to `dev.org`, creating a volume to put the log files into (so we can
access it from another container), then importing the files from the volume
exposed by the `static` container, and linking to all exposed ports from
`riak` and `app`. Lastly, we set the hostname to `web.sven.dev.org` so its
consistent with the pre-generated SSL certificate;
5. Finally, we create a container that runs `tail -f access.log` using the logs
volume from the `web` container, setting the workdir to `/var/log/httpd`. The
`--rm` option means that when the container exits, the container's layer is
removed.
+1 -1
View File
@@ -39,7 +39,7 @@ Then, run a container and specify values for the `labels` or `env`. For example
```
docker run --label foo=bar -e fizz=buzz -d -P training/webapp python app.py
````
```
This adds additional fields to the log depending on the driver, e.g. for
`json-file` that looks like:
-5
View File
@@ -59,11 +59,6 @@ This will create a new volume inside a container at `/webapp`.
> You can also use the `VOLUME` instruction in a `Dockerfile` to add one or
> more new volumes to any container created from that image.
Docker volumes default to mount in read-write mode, but you can also set it to be mounted read-only.
$ docker run -d -P --name web -v /opt/webapp:ro training/webapp python app.py
### Locating a volume
You can locate the volume on the host by utilizing the 'docker inspect' command.
+1 -1
View File
@@ -188,7 +188,7 @@ These labels appear as part of the `docker info` output for the daemon:
$ docker -D info
Containers: 12
Images: 672
Engine Version: 1.9.0
Server Version: 1.9.0
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
+3 -1
View File
@@ -51,8 +51,10 @@ func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image,
if i, ok := imageFilters["dangling"]; ok {
for _, value := range i {
if strings.ToLower(value) == "true" {
if v := strings.ToLower(value); v == "true" {
filtTagged = false
} else if v != "false" {
return nil, fmt.Errorf("Invalid filter 'dangling=%s'", v)
}
}
}
+23
View File
@@ -24,6 +24,9 @@ import (
"github.com/docker/libtrust"
)
// ErrNameIsNotExist returned when there is no image with requested name.
var ErrNameIsNotExist = errors.New("image with specified name does not exist")
// TagStore manages repositories. It encompasses the Graph used for versioned
// storage, as well as various services involved in pushing and pulling
// repositories.
@@ -164,6 +167,26 @@ func (store *TagStore) LookupImage(name string) (*image.Image, error) {
return img, nil
}
// GetID returns ID for image name.
func (store *TagStore) GetID(name string) (string, error) {
repoName, ref := parsers.ParseRepositoryTag(name)
if ref == "" {
ref = tags.DefaultTag
}
store.Lock()
defer store.Unlock()
repoName = registry.NormalizeLocalName(repoName)
repo, ok := store.Repositories[repoName]
if !ok {
return "", ErrNameIsNotExist
}
id, ok := repo[ref]
if !ok {
return "", ErrNameIsNotExist
}
return id, nil
}
// ByID returns a reverse-lookup table of all the names which refer to each
// image - e.g. {"43b5f19b10584": {"base:latest", "base:v1"}}
func (store *TagStore) ByID() map[string][]string {
+62 -2
View File
@@ -80,6 +80,16 @@ check_forked() {
fi
}
rpm_import_repository_key() {
local key=$1; shift
local tmpdir=$(mktemp -d)
chmod 600 "$tmpdir"
gpg --homedir "$tmpdir" --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"
gpg --homedir "$tmpdir" --export --armor "$key" > "$tmpdir"/repo.key
rpm --import "$tmpdir"/repo.key
rm -rf "$tmpdir"
}
do_install() {
case "$(uname -m)" in
*64)
@@ -231,10 +241,60 @@ do_install() {
exit 0
;;
'opensuse project'|opensuse|'suse linux'|sle[sd])
'opensuse project'|opensuse)
echo 'Going to perform the following operations:'
if [ "$repo" != 'main' ]; then
echo ' * add repository obs://Virtualization:containers'
fi
echo ' * install Docker'
$sh_c 'echo "Press CTRL-C to abort"; sleep 3'
if [ "$repo" != 'main' ]; then
# install experimental packages from OBS://Virtualization:containers
(
set -x
zypper -n ar -f obs://Virtualization:containers Virtualization:containers
rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
)
fi
(
set -x
$sh_c 'sleep 3; zypper -n install docker'
zypper -n install docker
)
echo_docker_as_nonroot
exit 0
;;
'suse linux'|sle[sd])
echo 'Going to perform the following operations:'
if [ "$repo" != 'main' ]; then
echo ' * add repository obs://Virtualization:containers'
echo ' * install experimental Docker using packages NOT supported by SUSE'
else
echo ' * add the "Containers" module'
echo ' * install Docker using packages supported by SUSE'
fi
$sh_c 'echo "Press CTRL-C to abort"; sleep 3'
if [ "$repo" != 'main' ]; then
# install experimental packages from OBS://Virtualization:containers
echo >&2 'Warning: installing experimental packages from OBS, these packages are NOT supported by SUSE'
(
set -x
zypper -n ar -f obs://Virtualization:containers/SLE_12 Virtualization:containers
rpm_import_repository_key 55A0B34D49501BB7CA474F5AA193FBB572174FC2
)
else
# Add the containers module
# Note well-1: the SLE machine must already be registered against SUSE Customer Center
# Note well-2: the `-r ""` is required to workaround a known issue of SUSEConnect
(
set -x
SUSEConnect -p sle-module-containers/12/x86_64 -r ""
)
fi
(
set -x
zypper -n install docker
)
echo_docker_as_nonroot
exit 0
+15 -1
View File
@@ -46,6 +46,20 @@ set -e
./man/md2man-all.sh -q || true
# TODO decide if it's worth getting go-md2man in _each_ builder environment to avoid this
# Convert the CHANGELOG.md file into RPM changelog format
VERSION_REGEX="^\W\W (.*) \((.*)\)$"
ENTRY_REGEX="^[-+*] (.*)$"
while read -r line || [[ -n "$line" ]]; do
if [ -z "$line" ]; then continue; fi
if [[ "$line" =~ $VERSION_REGEX ]]; then
echo >> contrib/builder/rpm/changelog
echo "* `date -d ${BASH_REMATCH[2]} '+%a %b %d %Y'` ${rpmPackager} - ${BASH_REMATCH[1]}" >> contrib/builder/rpm/changelog
fi
if [[ "$line" =~ $ENTRY_REGEX ]]; then
echo "- ${BASH_REMATCH[1]//\`}" >> contrib/builder/rpm/changelog
fi
done < CHANGELOG.md
# TODO add a configurable knob for _which_ rpms to build so we don't have to modify the file or build all of them every time we need to test
for dir in contrib/builder/rpm/*/; do
version="$(basename "$dir")"
@@ -71,7 +85,7 @@ set -e
RUN ln -sfv /usr/src/${rpmName}/hack/make/.build-rpm SPECS
WORKDIR /root/rpmbuild/SPECS
RUN tar -cz -C /usr/src -f /root/rpmbuild/SOURCES/${rpmName}.tar.gz ${rpmName}
RUN { echo '* $rpmDate $rpmPackager $rpmVersion-$rpmRelease'; echo '* Version: $VERSION'; } >> ${rpmName}.spec && tail >&2 ${rpmName}.spec
RUN { cat /usr/src/${rpmName}/contrib/builder/rpm/changelog; } >> ${rpmName}.spec && tail >&2 ${rpmName}.spec
RUN rpmbuild -ba --define '_release $rpmRelease' --define '_version $rpmVersion' --define '_origversion $VERSION' ${rpmName}.spec
EOF
# selinux policy referencing systemd things won't work on non-systemd versions
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
set -e
# This script generates index files for the directory structure
# of the apt and yum repos
: ${DOCKER_RELEASE_DIR:=$DEST}
APTDIR=$DOCKER_RELEASE_DIR/apt
YUMDIR=$DOCKER_RELEASE_DIR/yum
if [ ! -d $APTDIR ] && [ ! -d $YUMDIR ]; then
echo >&2 'release-rpm or release-deb must be run before generate-index-listing'
exit 1
fi
create_index() {
local directory=$1
local original=$2
local cleaned=${directory#$original}
# the index file to create
local index_file="${directory}/index"
# cd into dir & touch the index file
cd $directory
touch $index_file
# print the html header
cat <<-EOF > "$index_file"
<!DOCTYPE html>
<html>
<head><title>Index of ${cleaned}/</title></head>
<body bgcolor="white">
<h1>Index of ${cleaned}/</h1><hr>
<pre><a href="../">../</a>
EOF
# start of content output
(
# change IFS locally within subshell so the for loop saves line correctly to L var
IFS=$'\n';
# pretty sweet, will mimick the normal apache output
for L in $(find -L . -mount -depth -maxdepth 1 -type f ! -name 'index' -printf "<a href=\"%f\">%-44f@_@%Td-%Tb-%TY %Tk:%TM @%f@\n"|sort|sed 's,\([\ ]\+\)@_@,</a>\1,g');
do
# file
F=$(sed -e 's,^.*@\([^@]\+\)@.*$,\1,g'<<<"$L");
# file with file size
F=$(du -bh $F | cut -f1);
# output with correct format
sed -e 's,\ @.*$, '"$F"',g'<<<"$L";
done;
) >> $index_file;
# now output a list of all directories in this dir (maxdepth 1) other than '.' outputting in a sorted manner exactly like apache
find -L . -mount -depth -maxdepth 1 -type d ! -name '.' -printf "<a href=\"%f\">%-43f@_@%Td-%Tb-%TY %Tk:%TM -\n"|sort -d|sed 's,\([\ ]\+\)@_@,/</a>\1,g' >> $index_file
# print the footer html
echo "</pre><hr></body></html>" >> $index_file
}
get_dirs() {
local directory=$1
for d in `find ${directory} -type d`; do
create_index $d $directory
done
}
get_dirs $APTDIR
get_dirs $YUMDIR
+2
View File
@@ -104,6 +104,8 @@ for dir in contrib/builder/deb/*/; do
-name *~${codename#*-}*.deb > "$APTDIR/dists/$codename/$component/filelist"
done
# clean the databases
apt-ftparchive clean "$APTDIR/conf/apt-ftparchive.conf"
# run the apt-ftparchive commands so we can have pinning
apt-ftparchive generate "$APTDIR/conf/apt-ftparchive.conf"
+6 -5
View File
@@ -9,18 +9,19 @@ source 'hack/.vendor-helpers.sh'
clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe
clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1
clone git github.com/gorilla/context 14f550f51a
clone git github.com/gorilla/mux e444e69cbd
clone git github.com/kr/pty 5cf931ef8f
clone git github.com/mattn/go-sqlite3 v1.1.0
clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e
clone git github.com/microsoft/hcsshim 325e531f8c49dd78580d5fd197ddb972fa4610e7
clone git github.com/mistifyio/go-zfs v2.1.1
clone git github.com/tchap/go-patricia v2.1.0
clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git
#get libnetwork packages
clone git github.com/docker/libnetwork dd1c5f0ffe7697f75a82bd8e4bbd6f225ec5e383
clone git github.com/docker/libnetwork 2934f6bf585fa24c86048cc85f7506a5bb626bf5
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
@@ -41,8 +42,8 @@ clone git github.com/boltdb/bolt v1.0
clone git github.com/docker/distribution 20c4b7a1805a52753dfd593ee1cc35558722a0ce # docker/1.9 branch
clone git github.com/vbatts/tar-split v0.9.10
clone git github.com/docker/notary ac05822d7d71ef077df3fc24f506672282a1feea
clone git github.com/endophage/gotuf 9bcdad0308e34a49f38448b8ad436ad8860825ce
clone git github.com/docker/notary 089d8450d8928aa1c58fd03f09cabbde9bcb4590
clone git github.com/endophage/gotuf 876c31a61bc4aa0dae09bb8ef3946dc26dd04924
clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16
clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
+1
View File
@@ -31,6 +31,7 @@ func (s *DockerSuite) TearDownTest(c *check.C) {
deleteAllContainers()
deleteAllImages()
deleteAllVolumes()
deleteAllNetworks()
}
func init() {
+88 -116
View File
@@ -4,8 +4,8 @@ import (
"archive/tar"
"bytes"
"net/http"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -17,31 +17,29 @@ func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
defer tw.Close()
dockerfile := []byte("FROM busybox")
if err := tw.WriteHeader(&tar.Header{
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
c.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
c.Fatalf("failed to close tar archive: %v", err)
}
})
//failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
res, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
out, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
if !strings.Contains(string(out), "Forbidden path outside the build context") {
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
// Didn't complain about leaving build context
c.Assert(string(out), checker.Contains, "Forbidden path outside the build context")
}
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
@@ -53,27 +51,21 @@ COPY * /tmp/
RUN find / -name ba*
RUN find /tmp/`,
})
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
defer server.Close()
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
// Make sure Dockerfile exists.
// Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL
out := string(buf)
if !strings.Contains(out, "/tmp/Dockerfile") ||
strings.Contains(out, "baz") {
c.Fatalf("Incorrect output: %s", out)
}
c.Assert(out, checker.Contains, "/tmp/Dockerfile")
c.Assert(out, checker.Not(checker.Contains), "baz")
}
func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) {
@@ -83,29 +75,30 @@ func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) {
defer tw.Close()
dockerfile := []byte("FROM busybox")
if err := tw.WriteHeader(&tar.Header{
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
c.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
c.Fatalf("failed to close tar archive: %v", err)
}
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
"testT.tar": buffer,
})
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
defer server.Close()
res, b, err := sockRequestRaw("POST", "/build?remote="+server.URL()+"/testT.tar", nil, "application/tar")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
b.Close()
}
@@ -117,51 +110,52 @@ func (s *DockerSuite) TestBuildApiRemoteTarballContextWithCustomDockerfile(c *ch
dockerfile := []byte(`FROM busybox
RUN echo 'wrong'`)
if err := tw.WriteHeader(&tar.Header{
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
c.Fatalf("failed to write tar file content: %v", err)
}
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(dockerfile)
// failed to write tar file content
c.Assert(err, checker.IsNil)
custom := []byte(`FROM busybox
RUN echo 'right'
`)
if err := tw.WriteHeader(&tar.Header{
err = tw.WriteHeader(&tar.Header{
Name: "custom",
Size: int64(len(custom)),
}); err != nil {
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(custom); err != nil {
c.Fatalf("failed to write tar file content: %v", err)
}
})
if err := tw.Close(); err != nil {
c.Fatalf("failed to close tar archive: %v", err)
}
// failed to write tar file header
c.Assert(err, checker.IsNil)
_, err = tw.Write(custom)
// failed to write tar file content
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
"testT.tar": buffer,
})
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
defer server.Close()
url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar"
res, body, err := sockRequestRaw("POST", url, nil, "application/tar")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
defer body.Close()
content, err := readBody(body)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
if strings.Contains(string(content), "wrong") {
c.Fatalf("Build used the wrong dockerfile.")
}
// Build used the wrong dockerfile.
c.Assert(string(content), checker.Not(checker.Contains), "wrong")
}
func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
@@ -170,24 +164,18 @@ func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
defer git.Close()
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
out := string(buf)
if !strings.Contains(out, "from dockerfile") {
c.Fatalf("Incorrect output: %s", out)
}
c.Assert(out, checker.Contains, "from dockerfile")
}
func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
@@ -198,25 +186,19 @@ RUN echo from baz`,
"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
}, false)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
out := string(buf)
if !strings.Contains(out, "from baz") {
c.Fatalf("Incorrect output: %s", out)
}
c.Assert(out, checker.Contains, "from baz")
}
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
@@ -227,25 +209,19 @@ RUN echo from Dockerfile`,
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
buf, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
out := string(buf)
if !strings.Contains(out, "from Dockerfile") {
c.Fatalf("Incorrect output: %s", out)
}
c.Assert(out, checker.Contains, "from Dockerfile")
}
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
@@ -255,31 +231,27 @@ func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
tw := tar.NewWriter(buffer)
defer tw.Close()
if err := tw.WriteHeader(&tar.Header{
err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
}); err != nil {
c.Fatalf("failed to write tar file header: %v", err)
}
if err := tw.Close(); err != nil {
c.Fatalf("failed to close tar archive: %v", err)
}
})
// failed to write tar file header
c.Assert(err, checker.IsNil)
// failed to close tar archive
c.Assert(tw.Close(), checker.IsNil)
res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
c.Assert(err, check.IsNil)
c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
c.Assert(err, checker.IsNil)
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
out, err := readBody(body)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
// The reason the error is "Cannot locate specified Dockerfile" is because
// in the builder, the symlink is resolved within the context, therefore
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
c.Assert(string(out), checker.Contains, "Cannot locate specified Dockerfile: Dockerfile", check.Commentf("Didn't complain about leaving build context"))
}
+3 -2
View File
@@ -4,6 +4,7 @@ import (
"net/http"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -21,8 +22,8 @@ func (s *DockerSuite) TestEventsApiEmptyOutput(c *check.C) {
select {
case r := <-chResp:
c.Assert(r.err, check.IsNil)
c.Assert(r.resp.StatusCode, check.Equals, http.StatusOK)
c.Assert(r.err, checker.IsNil)
c.Assert(r.resp.StatusCode, checker.Equals, http.StatusOK)
case <-time.After(3 * time.Second):
c.Fatal("timeout waiting for events api to respond, should have responded immediately")
}
@@ -9,6 +9,7 @@ import (
"strings"
"sync"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -19,8 +20,8 @@ func (s *DockerSuite) TestExecResizeApiHeightWidthNoInt(c *check.C) {
endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
c.Assert(status, check.Equals, http.StatusInternalServerError)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, http.StatusInternalServerError)
}
// Part of #14845
+9 -8
View File
@@ -8,6 +8,7 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -15,7 +16,7 @@ func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "-t", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 1; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
c.Assert(waitRun(id), checker.IsNil)
type logOut struct {
out string
@@ -41,8 +42,8 @@ func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
select {
case l := <-chLog:
c.Assert(l.err, check.IsNil)
c.Assert(l.res.StatusCode, check.Equals, http.StatusOK)
c.Assert(l.err, checker.IsNil)
c.Assert(l.res.StatusCode, checker.Equals, http.StatusOK)
if !strings.HasSuffix(l.out, "hello") {
c.Fatalf("expected log output to container 'hello', but it does not")
}
@@ -57,8 +58,8 @@ func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
status, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs", name), nil)
c.Assert(status, check.Equals, http.StatusBadRequest)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusBadRequest)
c.Assert(err, checker.IsNil)
expected := "Bad parameters: you must choose at least one stream"
if !bytes.Contains(body, []byte(expected)) {
@@ -75,7 +76,7 @@ func (s *DockerSuite) TestLogsApiFollowEmptyOutput(c *check.C) {
_, body, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
t1 := time.Now()
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
body.Close()
elapsed := t1.Sub(t0).Seconds()
if elapsed > 5.0 {
@@ -86,6 +87,6 @@ func (s *DockerSuite) TestLogsApiFollowEmptyOutput(c *check.C) {
func (s *DockerSuite) TestLogsAPIContainerNotFound(c *check.C) {
name := "nonExistentContainer"
resp, _, err := sockRequestRaw("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name), bytes.NewBuffer(nil), "")
c.Assert(err, check.IsNil)
c.Assert(resp.StatusCode, check.Equals, http.StatusNotFound)
c.Assert(err, checker.IsNil)
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
}
+64 -59
View File
@@ -10,6 +10,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/daemon/network"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/parsers/filters"
"github.com/go-check/check"
)
@@ -18,7 +19,7 @@ func (s *DockerSuite) TestApiNetworkGetDefaults(c *check.C) {
// By default docker daemon creates 3 networks. check if they are present
defaults := []string{"bridge", "host", "none"}
for _, nn := range defaults {
c.Assert(isNetworkAvailable(c, nn), check.Equals, true)
c.Assert(isNetworkAvailable(c, nn), checker.Equals, true)
}
}
@@ -30,25 +31,25 @@ func (s *DockerSuite) TestApiNetworkCreateDelete(c *check.C) {
CheckDuplicate: true,
}
id := createNetwork(c, config, true)
c.Assert(isNetworkAvailable(c, name), check.Equals, true)
c.Assert(isNetworkAvailable(c, name), checker.Equals, true)
// POST another network with same name and CheckDuplicate must fail
createNetwork(c, config, false)
// delete the network and make sure it is deleted
deleteNetwork(c, id, true)
c.Assert(isNetworkAvailable(c, name), check.Equals, false)
c.Assert(isNetworkAvailable(c, name), checker.Equals, false)
}
func (s *DockerSuite) TestApiNetworkFilter(c *check.C) {
nr := getNetworkResource(c, getNetworkIDByName(c, "bridge"))
c.Assert(nr.Name, check.Equals, "bridge")
c.Assert(nr.Name, checker.Equals, "bridge")
}
func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
// Inspect default bridge network
nr := getNetworkResource(c, "bridge")
c.Assert(nr.Name, check.Equals, "bridge")
c.Assert(nr.Name, checker.Equals, "bridge")
// run a container and attach it to the default bridge network
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
@@ -57,15 +58,15 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
// inspect default bridge network again and make sure the container is connected
nr = getNetworkResource(c, nr.ID)
c.Assert(nr.Driver, check.Equals, "bridge")
c.Assert(nr.Scope, check.Equals, "local")
c.Assert(nr.IPAM.Driver, check.Equals, "default")
c.Assert(len(nr.Containers), check.Equals, 1)
c.Assert(nr.Containers[containerID], check.NotNil)
c.Assert(nr.Driver, checker.Equals, "bridge")
c.Assert(nr.Scope, checker.Equals, "local")
c.Assert(nr.IPAM.Driver, checker.Equals, "default")
c.Assert(len(nr.Containers), checker.Equals, 1)
c.Assert(nr.Containers[containerID], checker.NotNil)
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
c.Assert(err, check.IsNil)
c.Assert(ip.String(), check.Equals, containerIP)
c.Assert(err, checker.IsNil)
c.Assert(ip.String(), checker.Equals, containerIP)
// IPAM configuration inspect
ipam := network.IPAM{
@@ -73,21 +74,25 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
Config: []network.IPAMConfig{{Subnet: "172.28.0.0/16", IPRange: "172.28.5.0/24", Gateway: "172.28.5.254"}},
}
config := types.NetworkCreate{
Name: "br0",
Driver: "bridge",
IPAM: ipam,
Name: "br0",
Driver: "bridge",
IPAM: ipam,
Options: map[string]string{"foo": "bar", "opts": "dopts"},
}
id0 := createNetwork(c, config, true)
c.Assert(isNetworkAvailable(c, "br0"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
nr = getNetworkResource(c, id0)
c.Assert(len(nr.IPAM.Config), check.Equals, 1)
c.Assert(nr.IPAM.Config[0].Subnet, check.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, check.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, check.Equals, "172.28.5.254")
c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
c.Assert(nr.Options["foo"], checker.Equals, "bar")
c.Assert(nr.Options["opts"], checker.Equals, "dopts")
// delete the network and make sure it is deleted
deleteNetwork(c, id0, true)
c.Assert(isNetworkAvailable(c, "br0"), check.Equals, false)
c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, false)
}
func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
@@ -98,9 +103,9 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
}
id := createNetwork(c, config, true)
nr := getNetworkResource(c, id)
c.Assert(nr.Name, check.Equals, name)
c.Assert(nr.ID, check.Equals, id)
c.Assert(len(nr.Containers), check.Equals, 0)
c.Assert(nr.Name, checker.Equals, name)
c.Assert(nr.ID, checker.Equals, id)
c.Assert(len(nr.Containers), checker.Equals, 0)
// run a container
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
@@ -111,20 +116,20 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
// inspect the network to make sure container is connected
nr = getNetworkResource(c, nr.ID)
c.Assert(len(nr.Containers), check.Equals, 1)
c.Assert(nr.Containers[containerID], check.NotNil)
c.Assert(len(nr.Containers), checker.Equals, 1)
c.Assert(nr.Containers[containerID], checker.NotNil)
// check if container IP matches network inspect
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
containerIP := findContainerIP(c, "test")
c.Assert(ip.String(), check.Equals, containerIP)
c.Assert(ip.String(), checker.Equals, containerIP)
// disconnect container from the network
disconnectNetwork(c, nr.ID, containerID)
nr = getNetworkResource(c, nr.ID)
c.Assert(nr.Name, check.Equals, name)
c.Assert(len(nr.Containers), check.Equals, 0)
c.Assert(nr.Name, checker.Equals, name)
c.Assert(len(nr.Containers), checker.Equals, 0)
// delete the network
deleteNetwork(c, nr.ID, true)
@@ -142,7 +147,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
IPAM: ipam0,
}
id0 := createNetwork(c, config0, true)
c.Assert(isNetworkAvailable(c, "test0"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test0"), checker.Equals, true)
ipam1 := network.IPAM{
Driver: "default",
@@ -155,7 +160,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
IPAM: ipam1,
}
createNetwork(c, config1, false)
c.Assert(isNetworkAvailable(c, "test1"), check.Equals, false)
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, false)
ipam2 := network.IPAM{
Driver: "default",
@@ -168,20 +173,20 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
IPAM: ipam2,
}
createNetwork(c, config2, true)
c.Assert(isNetworkAvailable(c, "test2"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test2"), checker.Equals, true)
// remove test0 and retry to create test1
deleteNetwork(c, id0, true)
createNetwork(c, config1, true)
c.Assert(isNetworkAvailable(c, "test1"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, true)
// for networks w/o ipam specified, docker will choose proper non-overlapping subnets
createNetwork(c, types.NetworkCreate{Name: "test3"}, true)
c.Assert(isNetworkAvailable(c, "test3"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test3"), checker.Equals, true)
createNetwork(c, types.NetworkCreate{Name: "test4"}, true)
c.Assert(isNetworkAvailable(c, "test4"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test4"), checker.Equals, true)
createNetwork(c, types.NetworkCreate{Name: "test5"}, true)
c.Assert(isNetworkAvailable(c, "test5"), check.Equals, true)
c.Assert(isNetworkAvailable(c, "test5"), checker.Equals, true)
for i := 1; i < 6; i++ {
deleteNetwork(c, fmt.Sprintf("test%d", i), true)
@@ -190,12 +195,12 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
func isNetworkAvailable(c *check.C, name string) bool {
status, body, err := sockRequest("GET", "/networks", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
nJSON := []types.NetworkResource{}
err = json.Unmarshal(body, &nJSON)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
for _, n := range nJSON {
if n.Name == name {
@@ -212,28 +217,28 @@ func getNetworkIDByName(c *check.C, name string) string {
)
filterArgs["name"] = []string{name}
filterJSON, err := filters.ToParam(filterArgs)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
v.Set("filters", filterJSON)
status, body, err := sockRequest("GET", "/networks?"+v.Encode(), nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
nJSON := []types.NetworkResource{}
err = json.Unmarshal(body, &nJSON)
c.Assert(err, check.IsNil)
c.Assert(len(nJSON), check.Equals, 1)
c.Assert(err, checker.IsNil)
c.Assert(len(nJSON), checker.Equals, 1)
return nJSON[0].ID
}
func getNetworkResource(c *check.C, id string) *types.NetworkResource {
_, obj, err := sockRequest("GET", "/networks/"+id, nil)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
nr := types.NetworkResource{}
err = json.Unmarshal(obj, &nr)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
return &nr
}
@@ -241,16 +246,16 @@ func getNetworkResource(c *check.C, id string) *types.NetworkResource {
func createNetwork(c *check.C, config types.NetworkCreate, shouldSucceed bool) string {
status, resp, err := sockRequest("POST", "/networks/create", config)
if !shouldSucceed {
c.Assert(status, check.Not(check.Equals), http.StatusCreated)
c.Assert(status, checker.Not(checker.Equals), http.StatusCreated)
return ""
}
c.Assert(status, check.Equals, http.StatusCreated)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusCreated)
c.Assert(err, checker.IsNil)
var nr types.NetworkCreateResponse
err = json.Unmarshal(resp, &nr)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
return nr.ID
}
@@ -261,8 +266,8 @@ func connectNetwork(c *check.C, nid, cid string) {
}
status, _, err := sockRequest("POST", "/networks/"+nid+"/connect", config)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}
func disconnectNetwork(c *check.C, nid, cid string) {
@@ -271,17 +276,17 @@ func disconnectNetwork(c *check.C, nid, cid string) {
}
status, _, err := sockRequest("POST", "/networks/"+nid+"/disconnect", config)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}
func deleteNetwork(c *check.C, id string, shouldSucceed bool) {
status, _, err := sockRequest("DELETE", "/networks/"+id, nil)
if !shouldSucceed {
c.Assert(status, check.Not(check.Equals), http.StatusOK)
c.Assert(err, check.NotNil)
c.Assert(status, checker.Not(checker.Equals), http.StatusOK)
c.Assert(err, checker.NotNil)
return
}
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
}
+6 -8
View File
@@ -6,20 +6,18 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
func (s *DockerSuite) TestGetVersion(c *check.C) {
status, body, err := sockRequest("GET", "/version", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, checker.Equals, http.StatusOK)
c.Assert(err, checker.IsNil)
var v types.Version
if err := json.Unmarshal(body, &v); err != nil {
c.Fatal(err)
}
if v.Version != dockerversion.VERSION {
c.Fatal("Version mismatch")
}
c.Assert(json.Unmarshal(body, &v), checker.IsNil)
c.Assert(v.Version, checker.Equals, dockerversion.VERSION, check.Commentf("Version mismatch"))
}
+11 -36
View File
@@ -22,9 +22,8 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
endGroup.Add(3)
startGroup.Add(3)
if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil {
c.Fatal(err)
}
err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done")
c.Assert(err, check.IsNil)
startDone := make(chan struct{})
endDone := make(chan struct{})
@@ -84,7 +83,6 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
case <-time.After(attachWait):
c.Fatalf("Attaches did not finish properly")
}
}
func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
@@ -94,13 +92,6 @@ func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
defer func() {
cmd := exec.Command(dockerBinary, "kill", id)
if out, _, err := runCommandWithOutput(cmd); err != nil {
c.Fatalf("failed to kill container: %v (%v)", out, err)
}
}()
done := make(chan error)
go func() {
defer close(done)
@@ -141,37 +132,21 @@ func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
}
defer stdin.Close()
stdout, err := cmd.StdoutPipe()
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
defer stdout.Close()
if err := cmd.Start(); err != nil {
c.Fatal(err)
}
c.Assert(cmd.Start(), check.IsNil)
defer cmd.Process.Kill()
if _, err := stdin.Write([]byte("hello\n")); err != nil {
c.Fatal(err)
}
_, err = stdin.Write([]byte("hello\n"))
c.Assert(err, check.IsNil)
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
c.Fatalf("expected 'hello', got %q", out)
}
c.Assert(err, check.IsNil)
c.Assert(strings.TrimSpace(out), check.Equals, "hello")
if err := stdin.Close(); err != nil {
c.Fatal(err)
}
c.Assert(stdin.Close(), check.IsNil)
// Expect container to still be running after stdin is closed
running, err := inspectField(id, "State.Running")
if err != nil {
c.Fatal(err)
}
if running != "true" {
c.Fatal("expected container to still be running")
}
c.Assert(err, check.IsNil)
c.Assert(running, check.Equals, "true")
}
+7 -11
View File
@@ -3,6 +3,7 @@ package main
import (
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -22,9 +23,7 @@ func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
break
}
}
if !found {
c.Errorf("couldn't find the new file in docker diff's output: %v", out)
}
c.Assert(found, checker.True)
}
// test to ensure GH #3840 doesn't occur any more
@@ -43,9 +42,7 @@ func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
out, _ = dockerCmd(c, "diff", cleanCID)
for _, filename := range dockerinitFiles {
if strings.Contains(out, filename) {
c.Errorf("found file which should've been ignored %v in diff output", filename)
}
c.Assert(out, checker.Not(checker.Contains), filename)
}
}
}
@@ -61,6 +58,7 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
"C /dev": true,
"A /dev/full": true, // busybox
"C /dev/ptmx": true, // libcontainer
"A /dev/mqueue": true, // lxc
"A /dev/kmsg": true, // lxc
"A /dev/fd": true,
"A /dev/fuse": true,
@@ -77,15 +75,13 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
}
for _, line := range strings.Split(out, "\n") {
if line != "" && !expected[line] {
c.Errorf("%q is shown in the diff but shouldn't", line)
}
c.Assert(line == "" || expected[line], checker.True)
}
}
// https://github.com/docker/docker/pull/14381#discussion_r33859347
func (s *DockerSuite) TestDiffEmptyArgClientError(c *check.C) {
out, _, err := dockerCmdWithError("diff", "")
c.Assert(err, check.NotNil)
c.Assert(strings.TrimSpace(out), check.Equals, "Container name cannot be empty")
c.Assert(err, checker.NotNil)
c.Assert(strings.TrimSpace(out), checker.Equals, "Container name cannot be empty")
}
@@ -56,6 +56,7 @@ func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) {
func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) {
testRequires(c, DaemonIsLinux)
testRequires(c, NativeExecDriver)
testRequires(c, oomControl)
errChan := make(chan error)
@@ -103,6 +104,7 @@ func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) {
func (s *DockerSuite) TestEventsOOMDisableTrue(c *check.C) {
testRequires(c, DaemonIsLinux)
testRequires(c, NativeExecDriver)
testRequires(c, oomControl)
errChan := make(chan error)
+10 -14
View File
@@ -9,6 +9,7 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
"github.com/kr/pty"
)
@@ -21,9 +22,7 @@ func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
cmd := exec.Command(dockerBinary, "exec", "-i", contID, "echo", "-n", "hello")
p, err := pty.Start(cmd)
if err != nil {
c.Fatal(err)
}
c.Assert(err, checker.IsNil)
b := bytes.NewBuffer(nil)
go io.Copy(b, p)
@@ -33,12 +32,9 @@ func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
select {
case err := <-ch:
if err != nil {
c.Errorf("cmd finished with error %v", err)
}
if output := b.String(); strings.TrimSpace(output) != "hello" {
c.Fatalf("Unexpected output %s", output)
}
c.Assert(err, checker.IsNil)
output := b.String()
c.Assert(strings.TrimSpace(output), checker.Equals, "hello")
case <-time.After(1 * time.Second):
c.Fatal("timed out running docker exec")
}
@@ -50,11 +46,11 @@ func (s *DockerSuite) TestExecTTY(c *check.C) {
cmd := exec.Command(dockerBinary, "exec", "-it", "test", "sh")
p, err := pty.Start(cmd)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
defer p.Close()
_, err = p.Write([]byte("cat /foo && exit\n"))
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
chErr := make(chan error)
go func() {
@@ -62,13 +58,13 @@ func (s *DockerSuite) TestExecTTY(c *check.C) {
}()
select {
case err := <-chErr:
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
case <-time.After(3 * time.Second):
c.Fatal("timeout waiting for exec to exit")
}
buf := make([]byte, 256)
read, err := p.Read(buf)
c.Assert(err, check.IsNil)
c.Assert(bytes.Contains(buf, []byte("hello")), check.Equals, true, check.Commentf(string(buf[:read])))
c.Assert(err, checker.IsNil)
c.Assert(bytes.Contains(buf, []byte("hello")), checker.Equals, true, check.Commentf(string(buf[:read])))
}
@@ -7,6 +7,7 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
)
@@ -197,3 +198,9 @@ func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) {
c.Fatalf("expected 1 dangling image, got %d: %s", a, out)
}
}
func (s *DockerSuite) TestImagesWithIncorrectFilter(c *check.C) {
out, _, err := dockerCmdWithError("images", "-f", "dangling=invalid")
c.Assert(err, check.NotNil)
c.Assert(out, checker.Contains, "Invalid filter")
}
@@ -4,6 +4,7 @@ package main
import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -12,34 +13,22 @@ func (s *DockerSuite) TestInspectNamedMountPoint(c *check.C) {
dockerCmd(c, "run", "-d", "--name", "test", "-v", "data:/data", "busybox", "cat")
vol, err := inspectFieldJSON("test", "Mounts")
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
var mp []types.MountPoint
err = unmarshalJSON([]byte(vol), &mp)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
if len(mp) != 1 {
c.Fatalf("Expected 1 mount point, was %v\n", len(mp))
}
c.Assert(mp, checker.HasLen, 1, check.Commentf("Expected 1 mount point"))
m := mp[0]
if m.Name != "data" {
c.Fatalf("Expected name data, was %s\n", m.Name)
}
c.Assert(m.Name, checker.Equals, "data", check.Commentf("Expected name data"))
if m.Driver != "local" {
c.Fatalf("Expected driver local, was %s\n", m.Driver)
}
c.Assert(m.Driver, checker.Equals, "local", check.Commentf("Expected driver local"))
if m.Source == "" {
c.Fatalf("Expected source to not be empty")
}
c.Assert(m.Source, checker.Not(checker.Equals), "", check.Commentf("Expected source to not be empty"))
if m.RW != true {
c.Fatalf("Expected rw to be true")
}
c.Assert(m.RW, checker.Equals, true)
if m.Destination != "/data" {
c.Fatalf("Expected destination /data, was %s\n", m.Destination)
}
c.Assert(m.Destination, checker.Equals, "/data", check.Commentf("Expected destination /data"))
}
+85 -120
View File
@@ -10,6 +10,7 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/timeutils"
"github.com/go-check/check"
)
@@ -19,13 +20,13 @@ func (s *DockerSuite) TestLogsContainerSmallerThanPage(c *check.C) {
testRequires(c, DaemonIsLinux)
testLen := 32767
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
out, _ = dockerCmd(c, "logs", id)
c.Assert(out, checker.HasLen, testLen+1)
}
// Regression test: When going over the PageSize, it used to panic (gh#4851)
@@ -34,14 +35,12 @@ func (s *DockerSuite) TestLogsContainerBiggerThanPage(c *check.C) {
testLen := 32768
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
out, _ = dockerCmd(c, "logs", id)
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
c.Assert(out, checker.HasLen, testLen+1)
}
// Regression test: When going much over the PageSize, it used to block (gh#4851)
@@ -50,14 +49,12 @@ func (s *DockerSuite) TestLogsContainerMuchBiggerThanPage(c *check.C) {
testLen := 33000
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
out, _ = dockerCmd(c, "logs", id)
if len(out) != testLen+1 {
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
c.Assert(out, checker.HasLen, testLen+1)
}
func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
@@ -65,28 +62,23 @@ func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
testLen := 100
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
out, _ = dockerCmd(c, "logs", "-t", cleanedContainerID)
out, _ = dockerCmd(c, "logs", "-t", id)
lines := strings.Split(out, "\n")
if len(lines) != testLen+1 {
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
c.Assert(lines, checker.HasLen, testLen+1)
ts := regexp.MustCompile(`^.* `)
for _, l := range lines {
if l != "" {
_, err := time.Parse(timeutils.RFC3339NanoFixed+" ", ts.FindString(l))
if err != nil {
c.Fatalf("Failed to parse timestamp from %v: %v", l, err)
}
if l[29] != 'Z' { // ensure we have padded 0's
c.Fatalf("Timestamp isn't padded properly: %s", l)
}
c.Assert(err, checker.IsNil, check.Commentf("Failed to parse timestamp from %v", l))
// ensure we have padded 0's
c.Assert(l[29], checker.Equals, uint8('Z'))
}
}
}
@@ -96,19 +88,16 @@ func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
msg := "stderr_log"
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", cleanedContainerID)
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
if stdout != "" {
c.Fatalf("Expected empty stdout stream, got %v", stdout)
}
c.Assert(stdout, checker.Equals, "")
stderr = strings.TrimSpace(stderr)
if stderr != msg {
c.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
}
c.Assert(stderr, checker.Equals, msg)
}
func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
@@ -116,18 +105,14 @@ func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
msg := "stderr_log"
out, _ := dockerCmd(c, "run", "-d", "-t", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", cleanedContainerID)
if stderr != "" {
c.Fatalf("Expected empty stderr stream, got %v", stderr)
}
stdout, stderr, _ := dockerCmdWithStdoutStderr(c, "logs", id)
c.Assert(stderr, checker.Equals, "")
stdout = strings.TrimSpace(stdout)
if stdout != msg {
c.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
}
c.Assert(stdout, checker.Equals, msg)
}
func (s *DockerSuite) TestLogsTail(c *check.C) {
@@ -135,43 +120,37 @@ func (s *DockerSuite) TestLogsTail(c *check.C) {
testLen := 100
out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
out, _ = dockerCmd(c, "logs", "--tail", "5", cleanedContainerID)
out, _ = dockerCmd(c, "logs", "--tail", "5", id)
lines := strings.Split(out, "\n")
if len(lines) != 6 {
c.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
}
out, _ = dockerCmd(c, "logs", "--tail", "all", cleanedContainerID)
c.Assert(lines, checker.HasLen, 6)
out, _ = dockerCmd(c, "logs", "--tail", "all", id)
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", cleanedContainerID)
c.Assert(lines, checker.HasLen, testLen+1)
out, _, _ = dockerCmdWithStdoutStderr(c, "logs", "--tail", "random", id)
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
c.Assert(lines, checker.HasLen, testLen+1)
}
func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "echo", "hello")
cleanedContainerID := strings.TrimSpace(out)
dockerCmd(c, "wait", cleanedContainerID)
id := strings.TrimSpace(out)
dockerCmd(c, "wait", id)
logsCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
if err := logsCmd.Start(); err != nil {
c.Fatal(err)
}
logsCmd := exec.Command(dockerBinary, "logs", "-f", id)
c.Assert(logsCmd.Start(), checker.IsNil)
errChan := make(chan error)
go func() {
@@ -181,7 +160,7 @@ func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
select {
case err := <-errChan:
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
case <-time.After(1 * time.Second):
c.Fatal("Following logs is hanged")
}
@@ -194,16 +173,14 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
log2Line := strings.Split(strings.Split(out, "\n")[1], " ")
t, err := strconv.ParseInt(log2Line[0], 10, 64) // the timestamp log2 is written
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
since := t + 1 // add 1s so log1 & log2 doesn't show up
out, _ = dockerCmd(c, "logs", "-t", fmt.Sprintf("--since=%v", since), name)
// Skip 2 seconds
unexpected := []string{"log1", "log2"}
for _, v := range unexpected {
if strings.Contains(out, v) {
c.Fatalf("unexpected log message returned=%v, since=%v\nout=%v", v, since, out)
}
c.Assert(out, checker.Not(checker.Contains), v, check.Commentf("unexpected log message returned, since=%v", since))
}
// Test with default value specified and parameter omitted
expected := []string{"log1", "log2", "log3"}
@@ -212,13 +189,9 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
exec.Command(dockerBinary, "logs", "-t", "--since=0", name),
} {
out, _, err = runCommandWithOutput(cmd)
if err != nil {
c.Fatalf("failed to log container: %s, %v", out, err)
}
c.Assert(err, checker.IsNil, check.Commentf("failed to log container: %s", out))
for _, v := range expected {
if !strings.Contains(out, v) {
c.Fatalf("'%v' does not contain=%v\nout=%s", cmd.Args, v, out)
}
c.Assert(out, checker.Contains, v)
}
}
}
@@ -226,23 +199,17 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
func (s *DockerSuite) TestLogsSinceFutureFollow(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `for i in $(seq 1 5); do date +%s; sleep 1; done`)
cleanedContainerID := strings.TrimSpace(out)
id := strings.TrimSpace(out)
now := daemonTime(c).Unix()
since := now + 2
out, _ = dockerCmd(c, "logs", "-f", fmt.Sprintf("--since=%v", since), cleanedContainerID)
out, _ = dockerCmd(c, "logs", "-f", fmt.Sprintf("--since=%v", since), id)
lines := strings.Split(strings.TrimSpace(out), "\n")
if len(lines) == 0 {
c.Fatal("got no log lines")
}
c.Assert(lines, checker.Not(checker.HasLen), 0)
for _, v := range lines {
ts, err := strconv.ParseInt(v, 10, 64)
if err != nil {
c.Fatalf("cannot parse timestamp output from log: '%v'\nout=%s", v, out)
}
if ts < since {
c.Fatalf("earlier log found. since=%v logdate=%v", since, ts)
}
c.Assert(err, checker.IsNil, check.Commentf("cannot parse timestamp output from log: '%v'\nout=%s", v, out))
c.Assert(ts >= since, checker.Equals, true, check.Commentf("earlier log found. since=%v logdate=%v", since, ts))
}
}
@@ -251,33 +218,31 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", `usleep 200000;yes X | head -c 200000`)
cleanedContainerID := strings.TrimSpace(out)
id := strings.TrimSpace(out)
stopSlowRead := make(chan bool)
go func() {
exec.Command(dockerBinary, "wait", cleanedContainerID).Run()
exec.Command(dockerBinary, "wait", id).Run()
stopSlowRead <- true
}()
logCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
logCmd := exec.Command(dockerBinary, "logs", "-f", id)
stdout, err := logCmd.StdoutPipe()
c.Assert(err, check.IsNil)
c.Assert(logCmd.Start(), check.IsNil)
c.Assert(err, checker.IsNil)
c.Assert(logCmd.Start(), checker.IsNil)
// First read slowly
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
// After the container has finished we can continue reading fast
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
actual := bytes1 + bytes2
expected := 200000
if actual != expected {
c.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
}
c.Assert(actual, checker.Equals, expected)
}
@@ -285,7 +250,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
c.Assert(waitRun(id), checker.IsNil)
type info struct {
NGoroutines int
@@ -293,9 +258,9 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
getNGoroutines := func() int {
var i info
status, b, err := sockRequest("GET", "/info", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, 200)
c.Assert(json.Unmarshal(b, &i), check.IsNil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, 200)
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
return i.NGoroutines
}
@@ -304,7 +269,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
cmd := exec.Command(dockerBinary, "logs", "-f", id)
r, w := io.Pipe()
cmd.Stdout = w
c.Assert(cmd.Start(), check.IsNil)
c.Assert(cmd.Start(), checker.IsNil)
// Make sure pipe is written to
chErr := make(chan error)
@@ -313,17 +278,17 @@ func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
_, err := r.Read(b)
chErr <- err
}()
c.Assert(<-chErr, check.IsNil)
c.Assert(cmd.Process.Kill(), check.IsNil)
c.Assert(<-chErr, checker.IsNil)
c.Assert(cmd.Process.Kill(), checker.IsNil)
// NGoroutines is not updated right away, so we need to wait before failing
t := time.After(30 * time.Second)
for {
select {
case <-t:
if n := getNGoroutines(); n > nroutines {
c.Fatalf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n)
}
n := getNGoroutines()
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
default:
if n := getNGoroutines(); n <= nroutines {
return
@@ -337,7 +302,7 @@ func (s *DockerSuite) TestLogsFollowGoroutinesNoOutput(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 2; done")
id := strings.TrimSpace(out)
c.Assert(waitRun(id), check.IsNil)
c.Assert(waitRun(id), checker.IsNil)
type info struct {
NGoroutines int
@@ -345,27 +310,27 @@ func (s *DockerSuite) TestLogsFollowGoroutinesNoOutput(c *check.C) {
getNGoroutines := func() int {
var i info
status, b, err := sockRequest("GET", "/info", nil)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, 200)
c.Assert(json.Unmarshal(b, &i), check.IsNil)
c.Assert(err, checker.IsNil)
c.Assert(status, checker.Equals, 200)
c.Assert(json.Unmarshal(b, &i), checker.IsNil)
return i.NGoroutines
}
nroutines := getNGoroutines()
cmd := exec.Command(dockerBinary, "logs", "-f", id)
c.Assert(cmd.Start(), check.IsNil)
c.Assert(cmd.Start(), checker.IsNil)
time.Sleep(200 * time.Millisecond)
c.Assert(cmd.Process.Kill(), check.IsNil)
c.Assert(cmd.Process.Kill(), checker.IsNil)
// NGoroutines is not updated right away, so we need to wait before failing
t := time.After(30 * time.Second)
for {
select {
case <-t:
if n := getNGoroutines(); n > nroutines {
c.Fatalf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n)
}
n := getNGoroutines()
c.Assert(n <= nroutines, checker.Equals, true, check.Commentf("leaked goroutines: expected less than or equal to %d, got: %d", nroutines, n))
default:
if n := getNGoroutines(); n <= nroutines {
return
@@ -379,5 +344,5 @@ func (s *DockerSuite) TestLogsCLIContainerNotFound(c *check.C) {
name := "testlogsnocontainer"
out, _, _ := dockerCmdWithError("logs", name)
message := fmt.Sprintf(".*no such id: %s.*\n", name)
c.Assert(out, check.Matches, message)
c.Assert(out, checker.Matches, message)
}
+16 -30
View File
@@ -6,6 +6,7 @@ import (
"net"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -17,9 +18,7 @@ func startServerContainer(c *check.C, msg string, port int) string {
"busybox",
"sh", "-c", fmt.Sprintf("echo %q | nc -lp %d", msg, port),
}
if err := waitForContainer(name, cmd...); err != nil {
c.Fatalf("Failed to launch server container: %v", err)
}
c.Assert(waitForContainer(name, cmd...), check.IsNil)
return name
}
@@ -30,14 +29,11 @@ func getExternalAddress(c *check.C) net.IP {
}
ifaceAddrs, err := iface.Addrs()
if err != nil || len(ifaceAddrs) == 0 {
c.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
}
c.Assert(err, check.IsNil)
c.Assert(ifaceAddrs, checker.Not(checker.HasLen), 0)
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
if err != nil {
c.Fatalf("Error retrieving the up for eth0: %s", err)
}
c.Assert(err, check.IsNil)
return ifaceIP
}
@@ -60,18 +56,14 @@ func (s *DockerSuite) TestNetworkNat(c *check.C) {
startServerContainer(c, msg, 8080)
endpoint := getExternalAddress(c)
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", endpoint.String(), 8080))
if err != nil {
c.Fatalf("Failed to connect to container (%v)", err)
}
c.Assert(err, check.IsNil)
data, err := ioutil.ReadAll(conn)
conn.Close()
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
final := strings.TrimRight(string(data), "\n")
if final != msg {
c.Fatalf("Expected message %q but received %q", msg, final)
}
c.Assert(final, checker.Equals, msg)
}
func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
@@ -82,18 +74,14 @@ func (s *DockerSuite) TestNetworkLocalhostTCPNat(c *check.C) {
)
startServerContainer(c, msg, 8081)
conn, err := net.Dial("tcp", "localhost:8081")
if err != nil {
c.Fatalf("Failed to connect to container (%v)", err)
}
c.Assert(err, check.IsNil)
data, err := ioutil.ReadAll(conn)
conn.Close()
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
final := strings.TrimRight(string(data), "\n")
if final != msg {
c.Fatalf("Expected message %q but received %q", msg, final)
}
c.Assert(final, checker.Equals, msg)
}
func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
@@ -105,7 +93,5 @@ func (s *DockerSuite) TestNetworkLoopbackNat(c *check.C) {
out, _ := dockerCmd(c, "run", "-t", "--net=container:server", "busybox",
"sh", "-c", fmt.Sprintf("stty raw && nc -w 5 %s 8080", endpoint.String()))
final := strings.TrimRight(string(out), "\n")
if final != msg {
c.Fatalf("Expected message %q but received %q", msg, final)
}
c.Assert(final, checker.Equals, msg)
}
+48 -25
View File
@@ -13,12 +13,17 @@ import (
"strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/libnetwork/driverapi"
remoteapi "github.com/docker/libnetwork/drivers/remote/api"
"github.com/docker/libnetwork/netlabel"
"github.com/go-check/check"
)
const dummyNetworkDriver = "dummy-network-driver"
var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest
func init() {
check.Suite(&DockerNetworkSuite{
ds: &DockerSuite{},
@@ -43,9 +48,7 @@ func (s *DockerNetworkSuite) TearDownTest(c *check.C) {
func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
mux := http.NewServeMux()
s.server = httptest.NewServer(mux)
if s.server == nil {
c.Fatal("Failed to start a HTTP Server")
}
c.Assert(s.server, check.NotNil, check.Commentf("Failed to start a HTTP Server"))
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
@@ -58,6 +61,11 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
})
mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest)
if err != nil {
http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
fmt.Fprintf(w, "null")
})
@@ -67,14 +75,12 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
fmt.Fprintf(w, "null")
})
if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil {
c.Fatal(err)
}
err := os.MkdirAll("/etc/docker/plugins", 0755)
c.Assert(err, checker.IsNil)
fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", dummyNetworkDriver)
if err := ioutil.WriteFile(fileName, []byte(s.server.URL), 0644); err != nil {
c.Fatal(err)
}
err = ioutil.WriteFile(fileName, []byte(s.server.URL), 0644)
c.Assert(err, checker.IsNil)
}
func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
@@ -84,9 +90,8 @@ func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
s.server.Close()
if err := os.RemoveAll("/etc/docker/plugins"); err != nil {
c.Fatal(err)
}
err := os.RemoveAll("/etc/docker/plugins")
c.Assert(err, checker.IsNil)
}
func assertNwIsAvailable(c *check.C, name string) {
@@ -135,13 +140,18 @@ func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {
assertNwNotAvailable(c, "test")
}
func (s *DockerSuite) TestDockerNetworkDeleteNotExists(c *check.C) {
out, _, err := dockerCmdWithError("network", "rm", "test")
c.Assert(err, checker.NotNil, check.Commentf("%v", out))
}
func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
dockerCmd(c, "network", "create", "test")
assertNwIsAvailable(c, "test")
nr := getNwResource(c, "test")
c.Assert(nr.Name, check.Equals, "test")
c.Assert(len(nr.Containers), check.Equals, 0)
c.Assert(nr.Name, checker.Equals, "test")
c.Assert(len(nr.Containers), checker.Equals, 0)
// run a container
out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
@@ -153,20 +163,20 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
// inspect the network to make sure container is connected
nr = getNetworkResource(c, nr.ID)
c.Assert(len(nr.Containers), check.Equals, 1)
c.Assert(len(nr.Containers), checker.Equals, 1)
c.Assert(nr.Containers[containerID], check.NotNil)
// check if container IP matches network inspect
ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
c.Assert(err, check.IsNil)
containerIP := findContainerIP(c, "test")
c.Assert(ip.String(), check.Equals, containerIP)
c.Assert(ip.String(), checker.Equals, containerIP)
// disconnect container from the network
dockerCmd(c, "network", "disconnect", "test", containerID)
nr = getNwResource(c, "test")
c.Assert(nr.Name, check.Equals, "test")
c.Assert(len(nr.Containers), check.Equals, 0)
c.Assert(nr.Name, checker.Equals, "test")
c.Assert(len(nr.Containers), checker.Equals, 0)
// check if network connect fails for inactive containers
dockerCmd(c, "stop", containerID)
@@ -223,13 +233,13 @@ func (s *DockerNetworkSuite) TestDockerNetworkInspect(c *check.C) {
assertNwIsAvailable(c, "br0")
nr := getNetworkResource(c, "br0")
c.Assert(nr.Driver, check.Equals, "bridge")
c.Assert(nr.Scope, check.Equals, "local")
c.Assert(nr.IPAM.Driver, check.Equals, "default")
c.Assert(len(nr.IPAM.Config), check.Equals, 1)
c.Assert(nr.IPAM.Config[0].Subnet, check.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, check.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, check.Equals, "172.28.5.254")
c.Assert(nr.Driver, checker.Equals, "bridge")
c.Assert(nr.Scope, checker.Equals, "local")
c.Assert(nr.IPAM.Driver, checker.Equals, "default")
c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
dockerCmd(c, "network", "rm", "br0")
}
@@ -255,3 +265,16 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpamInvalidCombinations(c *check.C
c.Assert(err, check.NotNil)
dockerCmd(c, "network", "rm", "test0")
}
func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
assertNwIsAvailable(c, "testopt")
gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
c.Assert(gopts, checker.NotNil)
opts, ok := gopts.(map[string]interface{})
c.Assert(ok, checker.Equals, true)
c.Assert(opts["opt1"], checker.Equals, "drv1")
c.Assert(opts["opt2"], checker.Equals, "drv2")
dockerCmd(c, "network", "rm", "testopt")
}
+11 -30
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -16,30 +17,20 @@ func (s *DockerSuite) TestPause(c *check.C) {
dockerCmd(c, "pause", name)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 {
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
}
c.Assert(err, checker.IsNil)
c.Assert(len(pausedContainers), checker.Equals, 1)
dockerCmd(c, "unpause", name)
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
if len(events) <= 1 {
c.Fatalf("Missing expected event")
}
c.Assert(len(events) > 1, checker.Equals, true)
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
c.Assert(pauseEvent[len(pauseEvent)-1], checker.Equals, "pause")
c.Assert(unpauseEvent[len(unpauseEvent)-1], checker.Equals, "unpause")
}
@@ -56,20 +47,14 @@ func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
}
dockerCmd(c, append([]string{"pause"}, containers...)...)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != len(containers) {
c.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
}
c.Assert(err, checker.IsNil)
c.Assert(len(pausedContainers), checker.Equals, len(containers))
dockerCmd(c, append([]string{"unpause"}, containers...)...)
out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
events := strings.Split(out, "\n")
if len(events) <= len(containers)*3-2 {
c.Fatalf("Missing expected event")
}
c.Assert(len(events) > len(containers)*3-2, checker.Equals, true)
pauseEvents := make([][]string, len(containers))
unpauseEvents := make([][]string, len(containers))
@@ -79,14 +64,10 @@ func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
}
for _, pauseEvent := range pauseEvents {
if pauseEvent[len(pauseEvent)-1] != "pause" {
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
c.Assert(pauseEvent[len(pauseEvent)-1], checker.Equals, "pause")
}
for _, unpauseEvent := range unpauseEvents {
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
c.Assert(unpauseEvent[len(unpauseEvent)-1], checker.Equals, "unpause")
}
}
+76 -78
View File
@@ -7,6 +7,7 @@ import (
"sort"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -18,15 +19,16 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", firstID, "80")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", firstID)
if !assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
err = assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", firstID)
// three port
@@ -39,18 +41,19 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", ID, "80")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
err = assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", ID)
if !assertPortList(c, out, []string{
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) {
c.Error("Port list is not correct")
}
"82/tcp -> 0.0.0.0:9878"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
// more and one port mapped to the same container port
@@ -64,19 +67,19 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", ID, "80")
if !assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
c.Error("Port list is not correct")
}
err = assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"})
// Port list is not correct
c.Assert(err, checker.IsNil)
out, _ = dockerCmd(c, "port", ID)
if !assertPortList(c, out, []string{
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"80/tcp -> 0.0.0.0:9999",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) {
c.Error("Port list is not correct\n", out)
}
"82/tcp -> 0.0.0.0:9878"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
testRange := func() {
@@ -90,19 +93,17 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", IDs[i])
if !assertPortList(c, out, []string{
fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)}) {
c.Error("Port list is not correct\n", out)
}
err = assertPortList(c, out, []string{fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i)})
// Port list is not correct
c.Assert(err, checker.IsNil)
}
// test port range exhaustion
out, _, err := dockerCmdWithError("run", "-d",
out, _, err = dockerCmdWithError("run", "-d",
"-p", "9090-9092:80",
"busybox", "top")
if err == nil {
c.Errorf("Exhausted port range did not return an error. Out: %s", out)
}
// Exhausted port range did not return an error
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
for i := 0; i < 3; i++ {
dockerCmd(c, "rm", "-f", IDs[i])
@@ -114,12 +115,11 @@ func (s *DockerSuite) TestPortList(c *check.C) {
// test invalid port ranges
for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} {
out, _, err := dockerCmdWithError("run", "-d",
out, _, err = dockerCmdWithError("run", "-d",
"-p", invalidRange,
"busybox", "top")
if err == nil {
c.Errorf("Port range should have returned an error. Out: %s", out)
}
// Port range should have returned an error
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
}
// test host range:container range spec.
@@ -130,13 +130,13 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", ID)
if !assertPortList(c, out, []string{
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9800",
"81/tcp -> 0.0.0.0:9801",
"82/tcp -> 0.0.0.0:9802",
"83/tcp -> 0.0.0.0:9803"}) {
c.Error("Port list is not correct\n", out)
}
"83/tcp -> 0.0.0.0:9803"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
// test mixing protocols in same port range
@@ -148,32 +148,29 @@ func (s *DockerSuite) TestPortList(c *check.C) {
out, _ = dockerCmd(c, "port", ID)
if !assertPortList(c, out, []string{
err = assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:8000",
"80/udp -> 0.0.0.0:8000"}) {
c.Error("Port list is not correct\n", out)
}
"80/udp -> 0.0.0.0:8000"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "rm", "-f", ID)
}
func assertPortList(c *check.C, out string, expected []string) bool {
//lines := strings.Split(out, "\n")
func assertPortList(c *check.C, out string, expected []string) error {
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != len(expected) {
c.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
return false
return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
}
sort.Strings(lines)
sort.Strings(expected)
for i := 0; i < len(expected); i++ {
if lines[i] != expected[i] {
c.Error("|" + lines[i] + "!=" + expected[i] + "|")
return false
return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|")
}
}
return true
return nil
}
func stopRemoveContainer(id string, c *check.C) {
@@ -193,9 +190,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
unpPort1 := fmt.Sprintf("%d/tcp", port1)
unpPort2 := fmt.Sprintf("%d/tcp", port2)
out, _ := dockerCmd(c, "ps", "-n=1")
if !strings.Contains(out, unpPort1) || !strings.Contains(out, unpPort2) {
c.Errorf("Missing unpublished ports(s) (%s, %s) in docker ps output: %s", unpPort1, unpPort2, out)
}
// Missing unpublished ports in docker ps output
c.Assert(out, checker.Contains, unpPort1)
// Missing unpublished ports in docker ps output
c.Assert(out, checker.Contains, unpPort2)
// Run the container forcing to publish the exposed ports
dockerCmd(c, "run", "-d", "-P", expose1, expose2, "busybox", "sleep", "5")
@@ -204,10 +202,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
expBndRegx1 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort1)
expBndRegx2 := regexp.MustCompile(`0.0.0.0:\d\d\d\d\d->` + unpPort2)
out, _ = dockerCmd(c, "ps", "-n=1")
if !expBndRegx1.MatchString(out) || !expBndRegx2.MatchString(out) {
c.Errorf("Cannot find expected port binding ports(s) (0.0.0.0:xxxxx->%s, 0.0.0.0:xxxxx->%s) in docker ps output:\n%s",
unpPort1, unpPort2, out)
}
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort1) in docker ps output
c.Assert(expBndRegx1.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort1: %s", out, unpPort1))
// Cannot find expected port binding port (0.0.0.0:xxxxx->unpPort2) in docker ps output
c.Assert(expBndRegx2.MatchString(out), checker.Equals, true, check.Commentf("out: %s; unpPort2: %s", out, unpPort2))
// Run the container specifying explicit port bindings for the exposed ports
offset := 10000
@@ -220,9 +218,11 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
expBnd1 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port1, unpPort1)
expBnd2 := fmt.Sprintf("0.0.0.0:%d->%s", offset+port2, unpPort2)
out, _ = dockerCmd(c, "ps", "-n=1")
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
}
// Cannot find expected port binding (expBnd1) in docker ps output
c.Assert(out, checker.Contains, expBnd1)
// Cannot find expected port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
// Remove container now otherwise it will interfeer with next test
stopRemoveContainer(id, c)
@@ -232,9 +232,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
// Check docker ps o/p for last created container reports the specified port mappings
out, _ = dockerCmd(c, "ps", "-n=1")
if !strings.Contains(out, expBnd1) || !strings.Contains(out, expBnd2) {
c.Errorf("Cannot find expected port binding(s) (%s, %s) in docker ps output: %s", expBnd1, expBnd2, out)
}
// Cannot find expected port binding (expBnd1) in docker ps output
c.Assert(out, checker.Contains, expBnd1)
// Cannot find expected port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
// Remove container now otherwise it will interfeer with next test
stopRemoveContainer(id, c)
@@ -243,9 +244,10 @@ func (s *DockerSuite) TestUnpublishedPortsInPsOutput(c *check.C) {
// Check docker ps o/p for last created container reports the specified unpublished port and port mapping
out, _ = dockerCmd(c, "ps", "-n=1")
if !strings.Contains(out, unpPort1) || !strings.Contains(out, expBnd2) {
c.Errorf("Missing unpublished ports or port binding (%s, %s) in docker ps output: %s", unpPort1, expBnd2, out)
}
// Missing unpublished exposed ports (unpPort1) in docker ps output
c.Assert(out, checker.Contains, unpPort1)
// Missing port binding (expBnd2) in docker ps output
c.Assert(out, checker.Contains, expBnd2)
}
func (s *DockerSuite) TestPortHostBinding(c *check.C) {
@@ -256,19 +258,18 @@ func (s *DockerSuite) TestPortHostBinding(c *check.C) {
out, _ = dockerCmd(c, "port", firstID, "80")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
err := assertPortList(c, out, []string{"0.0.0.0:9876"})
// Port list is not correct
c.Assert(err, checker.IsNil)
dockerCmd(c, "run", "--net=host", "busybox",
"nc", "localhost", "9876")
dockerCmd(c, "rm", "-f", firstID)
if _, _, err := dockerCmdWithError("run", "--net=host", "busybox",
"nc", "localhost", "9876"); err == nil {
c.Error("Port is still bound after the Container is removed")
}
out, _, err = dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "9876")
// Port is still bound after the Container is removed
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
}
func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
@@ -280,18 +281,15 @@ func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
out, _ = dockerCmd(c, "port", firstID, "80")
_, exposedPort, err := net.SplitHostPort(out)
if err != nil {
c.Fatal(out, err)
}
c.Assert(err, checker.IsNil, check.Commentf("out: %s", out))
dockerCmd(c, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
dockerCmd(c, "rm", "-f", firstID)
if _, _, err = dockerCmdWithError("run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort)); err == nil {
c.Error("Port is still bound after the Container is removed")
}
out, _, err = dockerCmdWithError("run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
// Port is still bound after the Container is removed
c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
}
+30 -54
View File
@@ -4,6 +4,7 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -15,16 +16,12 @@ func (s *DockerSuite) TestRestartStoppedContainer(c *check.C) {
dockerCmd(c, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
if out != "foobar\n" {
c.Errorf("container should've printed 'foobar'")
}
c.Assert(out, checker.Equals, "foobar\n")
dockerCmd(c, "restart", cleanedContainerID)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
if out != "foobar\nfoobar\n" {
c.Errorf("container should've printed 'foobar' twice, got %v", out)
}
c.Assert(out, checker.Equals, "foobar\nfoobar\n")
}
func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
@@ -33,22 +30,18 @@ func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
cleanedContainerID := strings.TrimSpace(out)
c.Assert(waitRun(cleanedContainerID), check.IsNil)
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
if out != "foobar\n" {
c.Errorf("container should've printed 'foobar'")
}
c.Assert(out, checker.Equals, "foobar\n")
dockerCmd(c, "restart", "-t", "1", cleanedContainerID)
out, _ = dockerCmd(c, "logs", cleanedContainerID)
c.Assert(waitRun(cleanedContainerID), check.IsNil)
c.Assert(waitRun(cleanedContainerID), checker.IsNil)
if out != "foobar\nfoobar\n" {
c.Errorf("container should've printed 'foobar' twice")
}
c.Assert(out, checker.Equals, "foobar\nfoobar\n")
}
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
@@ -58,27 +51,21 @@ func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
cleanedContainerID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "inspect", "--format", "{{ len .Mounts }}", cleanedContainerID)
if out = strings.Trim(out, " \n\r"); out != "1" {
c.Errorf("expect 1 volume received %s", out)
}
out = strings.Trim(out, " \n\r")
c.Assert(out, checker.Equals, "1")
source, err := inspectMountSourceField(cleanedContainerID, "/test")
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
dockerCmd(c, "restart", cleanedContainerID)
out, _ = dockerCmd(c, "inspect", "--format", "{{ len .Mounts }}", cleanedContainerID)
if out = strings.Trim(out, " \n\r"); out != "1" {
c.Errorf("expect 1 volume after restart received %s", out)
}
out = strings.Trim(out, " \n\r")
c.Assert(out, checker.Equals, "1")
sourceAfterRestart, err := inspectMountSourceField(cleanedContainerID, "/test")
c.Assert(err, check.IsNil)
if source != sourceAfterRestart {
c.Errorf("expected volume path: %s Actual path: %s", source, sourceAfterRestart)
}
c.Assert(err, checker.IsNil)
c.Assert(source, checker.Equals, sourceAfterRestart)
}
func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
@@ -87,10 +74,8 @@ func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
c.Assert(err, check.IsNil)
if name != "no" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "no")
}
c.Assert(err, checker.IsNil)
c.Assert(name, checker.Equals, "no")
}
func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
@@ -99,18 +84,14 @@ func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
c.Assert(err, check.IsNil)
if name != "always" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "always")
}
c.Assert(err, checker.IsNil)
c.Assert(name, checker.Equals, "always")
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
// MaximumRetryCount=0 if the restart policy is always
if MaximumRetryCount != "0" {
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
}
c.Assert(MaximumRetryCount, checker.Equals, "0")
}
func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
@@ -119,10 +100,8 @@ func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
c.Assert(err, check.IsNil)
if name != "on-failure" {
c.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
}
c.Assert(err, checker.IsNil)
c.Assert(name, checker.Equals, "on-failure")
}
@@ -133,18 +112,15 @@ func (s *DockerSuite) TestContainerRestartwithGoodContainer(c *check.C) {
out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "true")
id := strings.TrimSpace(string(out))
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5*time.Second); err != nil {
c.Fatal(err)
}
err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5*time.Second)
c.Assert(err, checker.IsNil)
count, err := inspectField(id, "RestartCount")
c.Assert(err, check.IsNil)
if count != "0" {
c.Fatalf("Container was restarted %s times, expected %d", count, 0)
}
c.Assert(err, checker.IsNil)
c.Assert(count, checker.Equals, "0")
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
c.Assert(err, check.IsNil)
if MaximumRetryCount != "3" {
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
}
c.Assert(err, checker.IsNil)
c.Assert(MaximumRetryCount, checker.Equals, "3")
}
+14 -26
View File
@@ -4,6 +4,7 @@ import (
"os"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -13,9 +14,8 @@ func (s *DockerSuite) TestRmContainerWithRemovedVolume(c *check.C) {
dockerCmd(c, "run", "--name", "losemyvolumes", "-v", "/tmp/testing:/test", "busybox", "true")
if err := os.Remove("/tmp/testing"); err != nil {
c.Fatal(err)
}
err := os.Remove("/tmp/testing")
c.Assert(err, check.IsNil)
dockerCmd(c, "rm", "-v", "losemyvolumes")
}
@@ -31,9 +31,8 @@ func (s *DockerSuite) TestRmRunningContainer(c *check.C) {
testRequires(c, DaemonIsLinux)
createRunningContainer(c, "foo")
if _, _, err := dockerCmdWithError("rm", "foo"); err == nil {
c.Fatalf("Expected error, can't rm a running container")
}
_, _, err := dockerCmdWithError("rm", "foo")
c.Assert(err, checker.NotNil, check.Commentf("Expected error, can't rm a running container"))
}
func (s *DockerSuite) TestRmForceRemoveRunningContainer(c *check.C) {
@@ -55,31 +54,20 @@ func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
// build first dockerfile
img1, err := buildImage(img, dockerfile1, true)
if err != nil {
c.Fatalf("Could not build image %s: %v", img, err)
}
c.Assert(err, check.IsNil, check.Commentf("Could not build image %s", img))
// run container on first image
if out, _, err := dockerCmdWithError("run", img); err != nil {
c.Fatalf("Could not run image %s: %v: %s", img, err, out)
}
dockerCmd(c, "run", img)
// rebuild dockerfile with a small addition at the end
if _, err := buildImage(img, dockerfile2, true); err != nil {
c.Fatalf("Could not rebuild image %s: %v", img, err)
}
_, err = buildImage(img, dockerfile2, true)
c.Assert(err, check.IsNil, check.Commentf("Could not rebuild image %s", img))
// try to remove the image, should error out.
if out, _, err := dockerCmdWithError("rmi", img); err == nil {
c.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
}
out, _, err := dockerCmdWithError("rmi", img)
c.Assert(err, check.NotNil, check.Commentf("Expected to error out removing the image, but succeeded: %s", out))
// check if we deleted the first image
out, _, err := dockerCmdWithError("images", "-q", "--no-trunc")
if err != nil {
c.Fatalf("%v: %s", err, out)
}
if !strings.Contains(out, img1) {
c.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
}
out, _ = dockerCmd(c, "images", "-q", "--no-trunc")
c.Assert(out, checker.Contains, img1, check.Commentf("Orphaned container (could not find %q in docker images): %s", img1, out))
}
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
+76 -146
View File
@@ -5,6 +5,7 @@ import (
"os/exec"
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -13,27 +14,21 @@ func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
errSubstr := "is using it"
// create a container
out, _, err := dockerCmdWithError("run", "-d", "busybox", "true")
if err != nil {
c.Fatalf("failed to create a container: %s, %v", out, err)
}
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
cleanedContainerID := strings.TrimSpace(out)
// try to delete the image
out, _, err = dockerCmdWithError("rmi", "busybox")
if err == nil {
c.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
}
if !strings.Contains(out, errSubstr) {
c.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
}
out, _, err := dockerCmdWithError("rmi", "busybox")
// Container is using image, should not be able to rmi
c.Assert(err, checker.NotNil)
// Container is using image, error message should contain errSubstr
c.Assert(out, checker.Contains, errSubstr, check.Commentf("Container: %q", cleanedContainerID))
// make sure it didn't delete the busybox name
images, _ := dockerCmd(c, "images")
if !strings.Contains(images, "busybox") {
c.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
}
// The name 'busybox' should not have been removed from images
c.Assert(images, checker.Contains, "busybox")
}
func (s *DockerSuite) TestRmiTag(c *check.C) {
@@ -44,97 +39,71 @@ func (s *DockerSuite) TestRmiTag(c *check.C) {
dockerCmd(c, "tag", "busybox", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+3 {
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+3, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
}
dockerCmd(c, "rmi", "utest/docker:tag2")
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
}
dockerCmd(c, "rmi", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+1 {
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+1, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
}
dockerCmd(c, "rmi", "utest:tag1")
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+0 {
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n"), check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
}
}
func (s *DockerSuite) TestRmiImgIDMultipleTag(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _, err := dockerCmdWithError("run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'")
if err != nil {
c.Fatalf("failed to create a container:%s, %v", out, err)
}
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-one'")
containerID := strings.TrimSpace(out)
out, _, err = dockerCmdWithError("commit", containerID, "busybox-one")
if err != nil {
c.Fatalf("failed to commit a new busybox-one:%s, %v", out, err)
}
dockerCmd(c, "commit", containerID, "busybox-one")
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox-one", "busybox-one:tag1")
dockerCmd(c, "tag", "busybox-one", "busybox-one:tag2")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
c.Fatalf("tag busybox to create 2 more images with same imageID; docker images shows: %q\n", imagesAfter)
}
// tag busybox to create 2 more images with same imageID
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+2, check.Commentf("docker images shows: %q\n", imagesAfter))
imgID, err := inspectField("busybox-one:tag1", "Id")
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
// run a container with the image
out, _, err = dockerCmdWithError("run", "-d", "busybox-one", "top")
if err != nil {
c.Fatalf("failed to create a container:%s, %v", out, err)
}
out, _ = dockerCmd(c, "run", "-d", "busybox-one", "top")
containerID = strings.TrimSpace(out)
// first checkout without force it fails
out, _, err = dockerCmdWithError("rmi", imgID)
expected := fmt.Sprintf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", imgID[:12], containerID[:12])
if err == nil || !strings.Contains(out, expected) {
c.Fatalf("rmi tagged in multiple repos should have failed without force: %s, %v, expected: %s", out, err, expected)
}
// rmi tagged in multiple repos should have failed without force
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, expected)
dockerCmd(c, "stop", containerID)
dockerCmd(c, "rmi", "-f", imgID)
imagesAfter, _ = dockerCmd(c, "images", "-a")
if strings.Contains(imagesAfter, imgID[:12]) {
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
}
// rmi -f failed, image still exists
c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12], check.Commentf("ImageID:%q; ImagesAfter: %q", imgID, imagesAfter))
}
func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
testRequires(c, DaemonIsLinux)
out, _, err := dockerCmdWithError("run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
if err != nil {
c.Fatalf("failed to create a container:%s, %v", out, err)
}
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
containerID := strings.TrimSpace(out)
out, _, err = dockerCmdWithError("commit", containerID, "busybox-test")
if err != nil {
c.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
}
dockerCmd(c, "commit", containerID, "busybox-test")
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox-test", "utest:tag1")
@@ -143,25 +112,23 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
dockerCmd(c, "tag", "busybox-test", "utest:5000/docker:tag4")
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+4 {
c.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
}
c.Assert(strings.Count(imagesAfter, "\n"), checker.Equals, strings.Count(imagesBefore, "\n")+4, check.Commentf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter))
}
imgID, err := inspectField("busybox-test", "Id")
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
// first checkout without force it fails
out, _, err = dockerCmdWithError("rmi", imgID)
if err == nil || !strings.Contains(out, "(must be forced) - image is referenced in one or more repositories") {
c.Fatalf("rmi tagged in multiple repos should have failed without force:%s, %v", out, err)
}
// rmi tagged in multiple repos should have failed without force
c.Assert(err, checker.NotNil)
// rmi tagged in multiple repos should have failed without force
c.Assert(out, checker.Contains, "(must be forced) - image is referenced in one or more repositories", check.Commentf("out: %s; err: %v;", out, err))
dockerCmd(c, "rmi", "-f", imgID)
{
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Contains(imagesAfter, imgID[:12]) {
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
}
// rmi failed, image still exists
c.Assert(imagesAfter, checker.Not(checker.Contains), imgID[:12])
}
}
@@ -170,17 +137,16 @@ func (s *DockerSuite) TestRmiImageIDForceWithRunningContainersAndMultipleTags(c
testRequires(c, DaemonIsLinux)
dockerfile := "FROM busybox\nRUN echo test 14116\n"
imgID, err := buildImage("test-14116", dockerfile, false)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
newTag := "newtag"
dockerCmd(c, "tag", imgID, newTag)
dockerCmd(c, "run", "-d", imgID, "top")
out, _, err := dockerCmdWithError("rmi", "-f", imgID)
if err == nil || !strings.Contains(out, "(cannot be forced) - image is being used by running container") {
c.Log(out)
c.Fatalf("rmi -f should not delete image with running containers")
}
// rmi -f should not delete image with running containers
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "(cannot be forced) - image is being used by running container")
}
func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
@@ -188,19 +154,12 @@ func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
container := "test-delete-tag"
newtag := "busybox:newtag"
bb := "busybox:latest"
if out, _, err := dockerCmdWithError("tag", bb, newtag); err != nil {
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
if out, _, err := dockerCmdWithError("run", "--name", container, bb, "/bin/true"); err != nil {
c.Fatalf("Could not run busybox: %v: %s", err, out)
}
out, _, err := dockerCmdWithError("rmi", newtag)
if err != nil {
c.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
}
if d := strings.Count(out, "Untagged: "); d != 1 {
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
}
dockerCmd(c, "tag", bb, newtag)
dockerCmd(c, "run", "--name", container, bb, "/bin/true")
out, _ := dockerCmd(c, "rmi", newtag)
c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1)
}
func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
@@ -211,17 +170,12 @@ func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
cmd.Stdin = strings.NewReader(`FROM busybox
MAINTAINER foo`)
if out, _, err := runCommandWithOutput(cmd); err != nil {
c.Fatalf("Could not build %s: %s, %v", image, out, err)
}
out, _, err := runCommandWithOutput(cmd)
c.Assert(err, checker.IsNil, check.Commentf("Could not build %s: %s", image, out))
if out, _, err := dockerCmdWithError("run", "--name", "test-force-rmi", image, "/bin/true"); err != nil {
c.Fatalf("Could not run container: %s, %v", out, err)
}
dockerCmd(c, "run", "--name", "test-force-rmi", image, "/bin/true")
if out, _, err := dockerCmdWithError("rmi", "-f", image); err != nil {
c.Fatalf("Could not remove image %s: %s, %v", image, out, err)
}
dockerCmd(c, "rmi", "-f", image)
}
func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
@@ -229,51 +183,32 @@ func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
newRepo := "127.0.0.1:5000/busybox"
oldRepo := "busybox"
newTag := "busybox:test"
out, _, err := dockerCmdWithError("tag", oldRepo, newRepo)
if err != nil {
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
dockerCmd(c, "tag", oldRepo, newRepo)
out, _, err = dockerCmdWithError("run", "--name", "test", oldRepo, "touch", "/home/abcd")
if err != nil {
c.Fatalf("failed to run container: %v, output: %s", err, out)
}
dockerCmd(c, "run", "--name", "test", oldRepo, "touch", "/home/abcd")
out, _, err = dockerCmdWithError("commit", "test", newTag)
if err != nil {
c.Fatalf("failed to commit container: %v, output: %s", err, out)
}
dockerCmd(c, "commit", "test", newTag)
out, _, err = dockerCmdWithError("rmi", newTag)
if err != nil {
c.Fatalf("failed to remove image: %v, output: %s", err, out)
}
if !strings.Contains(out, "Untagged: "+newTag) {
c.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
}
out, _ := dockerCmd(c, "rmi", newTag)
c.Assert(out, checker.Contains, "Untagged: "+newTag)
}
func (s *DockerSuite) TestRmiBlank(c *check.C) {
testRequires(c, DaemonIsLinux)
// try to delete a blank image name
out, _, err := dockerCmdWithError("rmi", "")
if err == nil {
c.Fatal("Should have failed to delete '' image")
}
if strings.Contains(out, "no such id") {
c.Fatalf("Wrong error message generated: %s", out)
}
if !strings.Contains(out, "image name cannot be blank") {
c.Fatalf("Expected error message not generated: %s", out)
}
// Should have failed to delete '' image
c.Assert(err, checker.NotNil)
// Wrong error message generated
c.Assert(out, checker.Not(checker.Contains), "no such id", check.Commentf("out: %s", out))
// Expected error message not generated
c.Assert(out, checker.Contains, "image name cannot be blank", check.Commentf("out: %s", out))
out, _, err = dockerCmdWithError("rmi", " ")
if err == nil {
c.Fatal("Should have failed to delete '' image")
}
if !strings.Contains(out, "no such id") {
c.Fatalf("Expected error message not generated: %s", out)
}
// Should have failed to delete '' image
c.Assert(err, checker.NotNil)
// Expected error message not generated
c.Assert(out, checker.Contains, "no such id", check.Commentf("out: %s", out))
}
func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
@@ -284,7 +219,7 @@ func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
for i, name := range imageNames {
dockerfile := fmt.Sprintf("FROM busybox\nMAINTAINER %s\nRUN echo %s\n", name, name)
id, err := buildImage(name, dockerfile, false)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
imageIds[i] = id
}
@@ -297,10 +232,9 @@ func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
// Try to remove the image of the running container and see if it fails as expected.
out, _, err := dockerCmdWithError("rmi", "-f", imageIds[0])
if err == nil || !strings.Contains(out, "image is being used by running container") {
c.Log(out)
c.Fatal("The image of the running container should not be removed.")
}
// The image of the running container should not be removed.
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, "image is being used by running container", check.Commentf("out: %s", out))
}
// #13422
@@ -315,7 +249,7 @@ RUN echo 1 #layer1
RUN echo 2 #layer2
`
_, err := buildImage(image, dockerfile, false)
c.Assert(err, check.IsNil)
c.Assert(err, checker.IsNil)
out, _ := dockerCmd(c, "history", "-q", image)
ids := strings.Split(out, "\n")
@@ -329,10 +263,8 @@ RUN echo 2 #layer2
// See if the "tmp2" can be untagged.
out, _ = dockerCmd(c, "rmi", newTag)
if d := strings.Count(out, "Untagged: "); d != 1 {
c.Log(out)
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
}
// Expected 1 untagged entry
c.Assert(strings.Count(out, "Untagged: "), checker.Equals, 1, check.Commentf("out: %s", out))
// Now let's add the tag again and create a container based on it.
dockerCmd(c, "tag", idToTag, newTag)
@@ -342,15 +274,13 @@ RUN echo 2 #layer2
// At this point we have 2 containers, one based on layer2 and another based on layer0.
// Try to untag "tmp2" without the -f flag.
out, _, err = dockerCmdWithError("rmi", newTag)
if err == nil || !strings.Contains(out, cid[:12]) || !strings.Contains(out, "(must force)") {
c.Log(out)
c.Fatalf("%q should not be untagged without the -f flag", newTag)
}
// should not be untagged without the -f flag
c.Assert(err, checker.NotNil)
c.Assert(out, checker.Contains, cid[:12])
c.Assert(out, checker.Contains, "(must force)")
// Add the -f flag and test again.
out, _ = dockerCmd(c, "rmi", "-f", newTag)
if !strings.Contains(out, fmt.Sprintf("Untagged: %s:latest", newTag)) {
c.Log(out)
c.Fatalf("%q should be allowed to untag with the -f flag", newTag)
}
// should be allowed to untag with the -f flag
c.Assert(out, checker.Contains, fmt.Sprintf("Untagged: %s:latest", newTag))
}
+5 -35
View File
@@ -1197,7 +1197,7 @@ func (s *DockerSuite) TestRunNonRootUserResolvName(c *check.C) {
// uses the host's /etc/resolv.conf and does not have any dns options provided.
func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
// Not applicable on Windows as testing unix specific functionality
testRequires(c, SameHostDaemon, DaemonIsLinux)
testRequires(c, SameHostDaemon, DaemonIsLinux, NativeExecDriver)
tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\n")
tmpLocalhostResolvConf := []byte("nameserver 127.0.0.1")
@@ -3425,13 +3425,10 @@ func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
dockerCmd(c, "run", "-t", "--net=testnetwork", "--name=second", "busybox", "ping", "-c", "1", "first")
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork")
}
func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
// Create 2 networks using bridge driver
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
@@ -3447,14 +3444,10 @@ func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
dockerCmd(c, "network", "connect", "testnetwork2", "second")
// Check connectivity between containers
dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork1")
dockerCmd(c, "network", "rm", "testnetwork2")
}
func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
// Create 2 networks using bridge driver
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
@@ -3478,11 +3471,6 @@ func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
// ping must fail again
_, _, err = dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
c.Assert(err, check.NotNil)
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork1")
dockerCmd(c, "network", "rm", "testnetwork2")
}
func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
@@ -3501,17 +3489,14 @@ func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
dockerCmd(c, "stop", "first")
_, _, err = dockerCmdWithError("network", "rm", "testnetwork1")
c.Assert(err, check.NotNil)
dockerCmd(c, "stop", "second")
// Network delete must succeed after all the connected containers are inactive
dockerCmd(c, "network", "rm", "testnetwork1")
}
func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
testRequires(c, DaemonIsLinux, NotUserNamespace)
testRequires(c, DaemonIsLinux, NotUserNamespace, NativeExecDriver)
// Create 2 networks using bridge driver
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1")
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2")
// Run and connect containers to testnetwork1
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top")
c.Assert(waitRun("first"), check.IsNil)
@@ -3536,11 +3521,6 @@ func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
dockerCmd(c, "start", "second")
dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1")
dockerCmd(c, "exec", "second", "ping", "-c", "1", "first.testnetwork2")
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork1")
dockerCmd(c, "network", "rm", "testnetwork2")
}
func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
@@ -3555,8 +3535,6 @@ func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
// Connecting to the user defined network must fail
_, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first")
c.Assert(err, check.NotNil)
dockerCmd(c, "stop", "first")
dockerCmd(c, "network", "rm", "testnetwork1")
}
func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
@@ -3574,10 +3552,6 @@ func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second")
c.Assert(err, check.NotNil)
c.Assert(out, checker.Contains, runconfig.ErrConflictSharedNetwork.Error())
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork1")
}
func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
@@ -3600,10 +3574,6 @@ func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
// Connect second container to none network. it must fail as well
_, _, err = dockerCmdWithError("network", "connect", "none", "second")
c.Assert(err, check.NotNil)
dockerCmd(c, "stop", "first")
dockerCmd(c, "stop", "second")
dockerCmd(c, "network", "rm", "testnetwork1")
}
// #11957 - stdin with no tty does not exit if stdin is not closed even though container exited
+25 -4
View File
@@ -17,6 +17,7 @@ import (
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/units"
"github.com/go-check/check"
"github.com/kr/pty"
)
@@ -272,9 +273,10 @@ func (s *DockerSuite) TestRunWithBlkioWeight(c *check.C) {
func (s *DockerSuite) TestRunWithBlkioInvalidWeight(c *check.C) {
testRequires(c, blkioWeight)
if _, _, err := dockerCmdWithError("run", "--blkio-weight", "5", "busybox", "true"); err == nil {
c.Fatalf("run with invalid blkio-weight should failed")
}
out, _, err := dockerCmdWithError("run", "--blkio-weight", "5", "busybox", "true")
c.Assert(err, check.NotNil, check.Commentf(out))
expected := "Range of blkio weight is from 10 to 1000"
c.Assert(out, checker.Contains, expected)
}
func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
@@ -419,7 +421,7 @@ func (s *DockerSuite) TestRunInvalidCpusetMemsFlagValue(c *check.C) {
}
func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) {
testRequires(c, cpuShare)
testRequires(c, cpuShare, NativeExecDriver)
out, _, err := dockerCmdWithError("run", "--cpu-shares", "1", "busybox", "echo", "test")
c.Assert(err, check.NotNil, check.Commentf(out))
expected := "The minimum allowed cpu-shares is 2"
@@ -435,3 +437,22 @@ func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) {
expected = "The maximum allowed cpu-shares is"
c.Assert(out, checker.Contains, expected)
}
func (s *DockerSuite) TestRunWithCorrectMemorySwapOnLXC(c *check.C) {
testRequires(c, memoryLimitSupport)
testRequires(c, swapMemorySupport)
testRequires(c, SameHostDaemon)
out, _ := dockerCmd(c, "run", "-d", "-m", "16m", "--memory-swap", "64m", "busybox", "top")
if _, err := os.Stat("/sys/fs/cgroup/memory/lxc"); err != nil {
c.Skip("Excecution driver must be LXC for this test")
}
id := strings.TrimSpace(out)
memorySwap, err := ioutil.ReadFile(fmt.Sprintf("/sys/fs/cgroup/memory/lxc/%s/memory.memsw.limit_in_bytes", id))
c.Assert(err, check.IsNil)
cgSwap, err := strconv.ParseInt(strings.TrimSpace(string(memorySwap)), 10, 64)
c.Assert(err, check.IsNil)
swap, err := units.RAMInBytes("64m")
c.Assert(err, check.IsNil)
c.Assert(cgSwap, check.Equals, swap)
}
+12 -33
View File
@@ -37,9 +37,7 @@ func makefile(contents string) (string, func(), error) {
// attempt to contact any v1 registry endpoints.
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
reg, err := newTestRegistry(c)
if err != nil {
c.Fatal(err.Error())
}
c.Assert(err, check.IsNil)
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)
@@ -52,14 +50,10 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
err = s.d.Start("--insecure-registry", reg.hostport, "--disable-legacy-registry=true")
if err != nil {
c.Fatalf("Error starting daemon: %s", err.Error())
}
c.Assert(err, check.IsNil)
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
if err != nil {
c.Fatalf("Unable to create test dockerfile")
}
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
defer cleanup()
s.d.Cmd("build", "--file", dockerfileName, ".")
@@ -76,9 +70,7 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
// login, push, pull, build & run
func (s *DockerRegistrySuite) TestV1(c *check.C) {
reg, err := newTestRegistry(c)
if err != nil {
c.Fatal(err.Error())
}
c.Assert(err, check.IsNil)
v2Pings := 0
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
@@ -107,42 +99,29 @@ func (s *DockerRegistrySuite) TestV1(c *check.C) {
})
err = s.d.Start("--insecure-registry", reg.hostport, "--disable-legacy-registry=false")
if err != nil {
c.Fatalf("Error starting daemon: %s", err.Error())
}
c.Assert(err, check.IsNil)
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
if err != nil {
c.Fatalf("Unable to create test dockerfile")
}
c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
defer cleanup()
s.d.Cmd("build", "--file", dockerfileName, ".")
if v1Repo == 0 {
c.Errorf("Expected v1 repository access after build")
}
c.Assert(v1Repo, check.Not(check.Equals), 0, check.Commentf("Expected v1 repository access after build"))
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
s.d.Cmd("run", repoName)
if v1Repo == 1 {
c.Errorf("Expected v1 repository access after run")
}
c.Assert(v1Repo, check.Not(check.Equals), 1, check.Commentf("Expected v1 repository access after run"))
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport)
if v1Logins == 0 {
c.Errorf("Expected v1 login attempt")
}
c.Assert(v1Logins, check.Not(check.Equals), 0, check.Commentf("Expected v1 login attempt"))
s.d.Cmd("tag", "busybox", repoName)
s.d.Cmd("push", repoName)
if v1Repo != 2 || v1Pings != 1 {
c.Error("Not all endpoints contacted after push", v1Repo, v1Pings)
}
c.Assert(v1Repo, check.Equals, 2)
c.Assert(v1Pings, check.Equals, 1)
s.d.Cmd("pull", repoName)
if v1Repo != 3 {
c.Errorf("Expected v1 repository access after pull")
}
c.Assert(v1Repo, check.Equals, 3, check.Commentf("Expected v1 repository access after pull"))
}
+4 -9
View File
@@ -3,6 +3,7 @@ package main
import (
"strings"
"github.com/docker/docker/pkg/integration/checker"
"github.com/go-check/check"
)
@@ -21,9 +22,7 @@ func (s *DockerSuite) TestVersionEnsureSucceeds(c *check.C) {
}
for k, v := range stringsToCheck {
if strings.Count(out, k) != v {
c.Errorf("%v expected %d instances found %d", k, v, strings.Count(out, k))
}
c.Assert(strings.Count(out, k), checker.Equals, v, check.Commentf("The count of %v in %s does not match excepted", k, out))
}
}
@@ -44,9 +43,7 @@ func testVersionPlatform(c *check.C, platform string) {
expected := "OS/Arch: " + platform
split := strings.Split(out, "\n")
if len(split) < 14 { // To avoid invalid indexing in loop below
c.Errorf("got %d lines from version", len(split))
}
c.Assert(len(split) >= 14, checker.Equals, true, check.Commentf("got %d lines from version", len(split)))
// Verify the second 'OS/Arch' matches the platform. Experimental has
// more lines of output than 'regular'
@@ -57,7 +54,5 @@ func testVersionPlatform(c *check.C, platform string) {
break
}
}
if !bFound {
c.Errorf("Could not find server '%s' in '%s'", expected, out)
}
c.Assert(bFound, checker.Equals, true, check.Commentf("Could not find server '%s' in '%s'", expected, out))
}
+57 -55
View File
@@ -57,21 +57,15 @@ type Daemon struct {
// The daemon will not automatically start.
func NewDaemon(c *check.C) *Daemon {
dest := os.Getenv("DEST")
if dest == "" {
c.Fatal("Please set the DEST environment variable")
}
c.Assert(dest, check.Not(check.Equals), "", check.Commentf("Please set the DEST environment variable"))
id := fmt.Sprintf("d%d", time.Now().UnixNano()%100000000)
dir := filepath.Join(dest, id)
daemonFolder, err := filepath.Abs(dir)
if err != nil {
c.Fatalf("Could not make %q an absolute path: %v", dir, err)
}
c.Assert(err, check.IsNil, check.Commentf("Could not make %q an absolute path", dir))
daemonRoot := filepath.Join(daemonFolder, "root")
if err := os.MkdirAll(daemonRoot, 0755); err != nil {
c.Fatalf("Could not create daemon root %q: %v", dir, err)
}
c.Assert(os.MkdirAll(daemonRoot, 0755), check.IsNil, check.Commentf("Could not create daemon root %q", dir))
userlandProxy := true
if env := os.Getenv("DOCKER_USERLANDPROXY"); env != "" {
@@ -96,9 +90,7 @@ func NewDaemon(c *check.C) *Daemon {
// You can specify additional daemon flags.
func (d *Daemon) Start(arg ...string) error {
dockerBinary, err := exec.LookPath(dockerBinary)
if err != nil {
d.c.Fatalf("[%s] could not find docker binary in $PATH: %v", d.id, err)
}
d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not find docker binary in $PATH", d.id))
args := append(d.GlobalFlags,
d.Command,
@@ -136,9 +128,7 @@ func (d *Daemon) Start(arg ...string) error {
d.cmd = exec.Command(dockerBinary, args...)
d.logFile, err = os.OpenFile(filepath.Join(d.folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
d.c.Fatalf("[%s] Could not create %s/docker.log: %v", d.id, d.folder, err)
}
d.c.Assert(err, check.IsNil, check.Commentf("[%s] Could not create %s/docker.log", d.id, d.folder))
d.cmd.Stdout = d.logFile
d.cmd.Stderr = d.logFile
@@ -187,9 +177,7 @@ func (d *Daemon) Start(arg ...string) error {
defer client.Close()
req, err := http.NewRequest("GET", "/_ping", nil)
if err != nil {
d.c.Fatalf("[%s] could not create new request: %v", d.id, err)
}
d.c.Assert(err, check.IsNil, check.Commentf("[%s] could not create new request", d.id))
resp, err := client.Do(req)
if err != nil {
@@ -506,6 +494,42 @@ func deleteAllContainers() error {
return nil
}
func deleteAllNetworks() error {
networks, err := getAllNetworks()
if err != nil {
return err
}
var errors []string
for _, n := range networks {
if n.Name != "bridge" {
status, b, err := sockRequest("DELETE", "/networks/"+n.Name, nil)
if err != nil {
errors = append(errors, err.Error())
continue
}
if status != http.StatusNoContent {
errors = append(errors, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
}
}
}
if len(errors) > 0 {
return fmt.Errorf(strings.Join(errors, "\n"))
}
return nil
}
func getAllNetworks() ([]types.NetworkResource, error) {
var networks []types.NetworkResource
_, b, err := sockRequest("GET", "/networks", nil)
if err != nil {
return nil, err
}
if err := json.Unmarshal(b, &networks); err != nil {
return nil, err
}
return networks, nil
}
func deleteAllVolumes() error {
volumes, err := getAllVolumes()
if err != nil {
@@ -718,13 +742,7 @@ func dockerCmdInDirWithTimeout(timeout time.Duration, path string, args ...strin
}
func findContainerIP(c *check.C, id string, vargs ...string) string {
args := append(vargs, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
cmd := exec.Command(dockerBinary, args...)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
c.Fatal(err, out)
}
out, _ := dockerCmd(c, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
return strings.Trim(out, " \r\n'")
}
@@ -1276,30 +1294,23 @@ func newFakeGit(name string, files map[string]string, enforceLocalServer bool) (
// Write `content` to the file at path `dst`, creating it if necessary,
// as well as any missing directories.
// The file is truncated if it already exists.
// Call c.Fatal() at the first error.
// Fail the test when error occures.
func writeFile(dst, content string, c *check.C) {
// Create subdirectories if necessary
if err := os.MkdirAll(path.Dir(dst), 0700); err != nil {
c.Fatal(err)
}
c.Assert(os.MkdirAll(path.Dir(dst), 0700), check.IsNil)
f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700)
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
defer f.Close()
// Write content (truncate if it exists)
if _, err := io.Copy(f, strings.NewReader(content)); err != nil {
c.Fatal(err)
}
_, err = io.Copy(f, strings.NewReader(content))
c.Assert(err, check.IsNil)
}
// Return the contents of file at path `src`.
// Call c.Fatal() at the first error (including if the file doesn't exist)
// Fail the test when error occures.
func readFile(src string, c *check.C) (content string) {
data, err := ioutil.ReadFile(src)
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
return string(data)
}
@@ -1351,30 +1362,25 @@ func daemonTime(c *check.C) time.Time {
}
status, body, err := sockRequest("GET", "/info", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusOK)
type infoJSON struct {
SystemTime string
}
var info infoJSON
if err = json.Unmarshal(body, &info); err != nil {
c.Fatalf("unable to unmarshal /info response: %v", err)
}
err = json.Unmarshal(body, &info)
c.Assert(err, check.IsNil, check.Commentf("unable to unmarshal GET /info response"))
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil, check.Commentf("invalid time format in GET /info response"))
return dt
}
func setupRegistry(c *check.C) *testRegistryV2 {
testRequires(c, RegistryHosting)
reg, err := newTestRegistryV2(c)
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
// Wait for registry to be ready to serve requests.
for i := 0; i != 5; i++ {
@@ -1384,18 +1390,14 @@ func setupRegistry(c *check.C) *testRegistryV2 {
time.Sleep(100 * time.Millisecond)
}
if err != nil {
c.Fatal("Timeout waiting for test registry to become available")
}
c.Assert(err, check.IsNil, check.Commentf("Timeout waiting for test registry to become available"))
return reg
}
func setupNotary(c *check.C) *testNotary {
testRequires(c, NotaryHosting)
ts, err := newTestNotary(c)
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
return ts
}
+2 -2
View File
@@ -7,7 +7,7 @@ docker-build - Build a new image from the source code at PATH
# SYNOPSIS
**docker build**
[**--build-arg**[=*[]*]]
[**-c**|**--cpu-shares**[=*0*]]
[**--cpu-shares**[=*0*]]
[**--cgroup-parent**[=*CGROUP-PARENT*]]
[**--help**]
[**-f**|**--file**[=*PATH/Dockerfile*]]
@@ -90,7 +90,7 @@ set as the **URL**, the repository is cloned locally and then sent as the contex
**--memory-swap**=*MEMORY-SWAP*
Total memory (memory + swap), '-1' to disable swap.
**-c**, **--cpu-shares**=*0*
**--cpu-shares**=*0*
CPU shares (relative weight).
By default, all containers get the same proportion of CPU cycles.
+2 -2
View File
@@ -9,7 +9,7 @@ docker-create - Create a new container
[**-a**|**--attach**[=*[]*]]
[**--add-host**[=*[]*]]
[**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
[**-c**|**--cpu-shares**[=*0*]]
[**--cpu-shares**[=*0*]]
[**--cap-add**[=*[]*]]
[**--cap-drop**[=*[]*]]
[**--cgroup-parent**[=*CGROUP-PATH*]]
@@ -83,7 +83,7 @@ The initial status of the container created with **docker create** is 'created'.
**--blkio-weight**=0
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
**-c**, **--cpu-shares**=0
**--cpu-shares**=0
CPU shares (relative weight)
**--cap-add**=[]
+1 -1
View File
@@ -33,7 +33,7 @@ Here is a sample output:
# docker info
Containers: 14
Images: 52
Engine Version: 1.9.0
Server Version: 1.9.0
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Dirs: 80
+11 -7
View File
@@ -9,7 +9,7 @@ docker-run - Run a command in a new container
[**-a**|**--attach**[=*[]*]]
[**--add-host**[=*[]*]]
[**--blkio-weight**[=*[BLKIO-WEIGHT]*]]
[**-c**|**--cpu-shares**[=*0*]]
[**--cpu-shares**[=*0*]]
[**--cap-add**[=*[]*]]
[**--cap-drop**[=*[]*]]
[**--cgroup-parent**[=*CGROUP-PATH*]]
@@ -100,14 +100,14 @@ option can be set multiple times.
**--blkio-weight**=0
Block IO weight (relative weight) accepts a weight value between 10 and 1000.
**-c**, **--cpu-shares**=0
**--cpu-shares**=0
CPU shares (relative weight)
By default, all containers get the same proportion of CPU cycles. This proportion
can be modified by changing the container's CPU share weighting relative
to the weighting of all other running containers.
To modify the proportion from the default of 1024, use the **-c** or **--cpu-shares**
To modify the proportion from the default of 1024, use the **--cpu-shares**
flag to set the weighting to 2 or higher.
The proportion will only apply when CPU-intensive processes are running.
@@ -353,10 +353,14 @@ ports and the exposed ports, use `docker port`.
**-p**, **--publish**=[]
Publish a container's port, or range of ports, to the host.
format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
Both hostPort and containerPort can be specified as a range of ports.
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. (e.g., `-p 1234-1236:1234-1236/tcp`)
(use 'docker port' to see the actual mapping)
Format: `ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort`
Both hostPort and containerPort can be specified as a range of ports.
When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range.
(e.g., `docker run -p 1234-1236:1222-1224 --name thisWorks -t busybox`
but not `docker run -p 1230-1236:1230-1240 --name RangeContainerPortsBiggerThanRangeHostPorts -t busybox`)
With ip: `docker run -p 127.0.0.1:$HOSTPORT:$CONTAINERPORT --name CONTAINER -t someimage`
Use `docker port` to see the actual mapping: `docker port CONTAINER $CONTAINERPORT`
**--pid**=host
Set the PID mode for the container
+28 -48
View File
@@ -20,6 +20,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/pools"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/pkg/system"
@@ -116,10 +117,10 @@ func DetectCompression(source []byte) Compression {
return Uncompressed
}
func xzDecompress(archive io.Reader) (io.ReadCloser, error) {
func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) {
args := []string{"xz", "-d", "-c", "-q"}
return CmdStream(exec.Command(args[0], args[1:]...), archive)
return cmdStream(exec.Command(args[0], args[1:]...), archive)
}
// DecompressStream decompress the archive and returns a ReaderCloser with the decompressed archive.
@@ -148,12 +149,15 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader)
return readBufWrapper, nil
case Xz:
xzReader, err := xzDecompress(buf)
xzReader, chdone, err := xzDecompress(buf)
if err != nil {
return nil, err
}
readBufWrapper := p.NewReadCloserWrapper(buf, xzReader)
return readBufWrapper, nil
return ioutils.NewReadCloserWrapper(readBufWrapper, func() error {
<-chdone
return readBufWrapper.Close()
}), nil
default:
return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
}
@@ -245,14 +249,14 @@ func (ta *tarAppender) addTarFile(path, name string) error {
}
hdr.Name = name
nlink, inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
if err != nil {
return err
}
// if it's a regular file and has more than 1 link,
// if it's not a directory and has more than 1 link,
// it's hardlinked, so set the type flag accordingly
if fi.Mode().IsRegular() && nlink > 1 {
if !fi.IsDir() && hasHardlinks(fi) {
// a link should have a name that it links too
// and that linked name should be first in the tar archive
if oldpath, ok := ta.SeenFiles[inode]; ok {
@@ -925,57 +929,33 @@ func CopyFileWithTar(src, dst string) (err error) {
return defaultArchiver.CopyFileWithTar(src, dst)
}
// CmdStream executes a command, and returns its stdout as a stream.
// cmdStream executes a command, and returns its stdout as a stream.
// If the command fails to run or doesn't complete successfully, an error
// will be returned, including anything written on stderr.
func CmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) {
if input != nil {
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
// Write stdin if any
go func() {
io.Copy(stdin, input)
stdin.Close()
}()
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) {
chdone := make(chan struct{})
cmd.Stdin = input
pipeR, pipeW := io.Pipe()
errChan := make(chan []byte)
// Collect stderr, we will use it in case of an error
go func() {
errText, e := ioutil.ReadAll(stderr)
if e != nil {
errText = []byte("(...couldn't fetch stderr: " + e.Error() + ")")
}
errChan <- errText
}()
cmd.Stdout = pipeW
var errBuf bytes.Buffer
cmd.Stderr = &errBuf
// Run the command and return the pipe
if err := cmd.Start(); err != nil {
return nil, nil, err
}
// Copy stdout to the returned pipe
go func() {
_, err := io.Copy(pipeW, stdout)
if err != nil {
pipeW.CloseWithError(err)
}
errText := <-errChan
if err := cmd.Wait(); err != nil {
pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errText))
pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
} else {
pipeW.Close()
}
close(chdone)
}()
// Run the command and return the pipe
if err := cmd.Start(); err != nil {
return nil, err
}
return pipeR, nil
return pipeR, chdone, nil
}
// NewTempArchive reads the content of src into a temporary file, and returns the contents
+3 -3
View File
@@ -160,7 +160,7 @@ func TestExtensionXz(t *testing.T) {
func TestCmdStreamLargeStderr(t *testing.T) {
cmd := exec.Command("/bin/sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
out, err := CmdStream(cmd, nil)
out, _, err := cmdStream(cmd, nil)
if err != nil {
t.Fatalf("Failed to start command: %s", err)
}
@@ -181,7 +181,7 @@ func TestCmdStreamLargeStderr(t *testing.T) {
func TestCmdStreamBad(t *testing.T) {
badCmd := exec.Command("/bin/sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
out, err := CmdStream(badCmd, nil)
out, _, err := cmdStream(badCmd, nil)
if err != nil {
t.Fatalf("Failed to start command: %s", err)
}
@@ -196,7 +196,7 @@ func TestCmdStreamBad(t *testing.T) {
func TestCmdStreamGood(t *testing.T) {
cmd := exec.Command("/bin/sh", "-c", "echo hello; exit 0")
out, err := CmdStream(cmd, nil)
out, _, err := cmdStream(cmd, nil)
if err != nil {
t.Fatal(err)
}
+1 -2
View File
@@ -40,7 +40,7 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
return perm // noop for unix as golang APIs provide perm bits correctly
}
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
s, ok := stat.(*syscall.Stat_t)
if !ok {
@@ -48,7 +48,6 @@ func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, st
return
}
nlink = uint32(s.Nlink)
inode = uint64(s.Ino)
// Currently go does not fill in the major/minors
+1 -1
View File
@@ -49,7 +49,7 @@ func chmodTarEntry(perm os.FileMode) os.FileMode {
return perm
}
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
// do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
return
}

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