From 6d6c11dcebbdaa40b009f4416d41e3d4abad998f Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 23 Dec 2016 22:57:30 -0800 Subject: [PATCH 01/26] Fix inspect object by invalid reference Signed-off-by: Tonis Tiigi (cherry picked from commit 3cd39aaeab37102e4b12decc0c36042e477e2fa6) Signed-off-by: Victor Vieux --- integration-cli/docker_cli_inspect_test.go | 8 ++++++++ plugin/store.go | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index 4e732c5ba8..32ed28afe1 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/integration-cli/docker_cli_inspect_test.go @@ -456,3 +456,11 @@ func (s *DockerSuite) TestInspectUnknownObject(c *check.C) { c.Assert(out, checker.Contains, "Error: No such object: foobar") c.Assert(err.Error(), checker.Contains, "Error: No such object: foobar") } + +func (s *DockerSuite) TestInpectInvalidReference(c *check.C) { + // This test should work on both Windows and Linux + out, _, err := dockerCmdWithError("inspect", "FooBar") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "Error: No such object: FooBar") + c.Assert(err.Error(), checker.Contains, "Error: No such object: FooBar") +} diff --git a/plugin/store.go b/plugin/store.go index ba0eb03400..bb57e80665 100644 --- a/plugin/store.go +++ b/plugin/store.go @@ -227,7 +227,7 @@ func (ps *Store) resolvePluginID(idOrName string) (string, error) { ref, err := reference.ParseNamed(idOrName) if err != nil { - return "", errors.Wrapf(err, "failed to parse %v", idOrName) + return "", errors.WithStack(ErrNotFound(idOrName)) } if _, ok := ref.(reference.Canonical); ok { logrus.Warnf("canonical references cannot be resolved: %v", ref.String()) From 97b0bb730eecf9031ba57f0028833104ea442275 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Mon, 26 Dec 2016 15:18:03 +0100 Subject: [PATCH 02/26] fix swagger description for `DELETE /plugin/{name}` Signed-off-by: Tobias Gesellchen (cherry picked from commit e6b2829a7f59b59eb1c3653313bc3c6a56b47b0c) Signed-off-by: Victor Vieux --- api/swagger.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/api/swagger.yaml b/api/swagger.yaml index b44f0adb7a..871fe0c225 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -6582,6 +6582,7 @@ paths: required: true type: "string" tags: ["Plugin"] + /plugins/{name}: delete: summary: "Remove a plugin" operationId: "PluginDelete" From 1c5cb466492535b6aad217e92896c65ed5f65446 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 8 Nov 2016 10:31:09 +0000 Subject: [PATCH 03/26] update experimental/README.md Signed-off-by: Akihiro Suda (cherry picked from commit eb11a10ddf5169c8c761005ebd921505fdb309a4) Signed-off-by: Victor Vieux --- experimental/README.md | 71 ++++++++++-------------------------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/experimental/README.md b/experimental/README.md index 0ee893deaf..796080cca5 100644 --- a/experimental/README.md +++ b/experimental/README.md @@ -9,65 +9,26 @@ issues associated with it. If necessary, links are provided to additional documentation on an issue. As an active Docker user and community member, please feel free to provide any feedback on these features you wish. -## Install Docker experimental +## Use Docker experimental -Unlike the regular Docker binary, the experimental channels is built and -updated nightly on https://experimental.docker.com. From one day to the -next, new features may appear, while existing experimental features may be -refined or entirely removed. +Experimental features are now included in the standard Docker binaries as of +version 1.13.0. +For enabling experimental features, you need to start the Docker daemon with +`--experimental` flag. +You can also enable the daemon flag via `/etc/docker/daemon.json`. e.g. -1. Verify that you have `curl` installed. +```json +{ + "experimental": true +} +``` - $ which curl +Then make sure the experimental flag is enabled: - If `curl` isn't installed, install it after updating your manager: - - $ sudo apt-get update - $ sudo apt-get install curl - -2. Get the latest Docker package. - - $ curl -sSL https://experimental.docker.com/ | sh - - The system prompts you for your `sudo` password. Then, it downloads and - installs Docker and its dependencies. - - >**Note**: If your company is behind a filtering proxy, you may find that the - >`apt-key` - >command fails for the Docker repo during installation. To work around this, - >add the key directly using the following: - > - > $ curl -sSL https://experimental.docker.com/gpg | sudo apt-key add - - -3. Verify `docker` is installed correctly. - - $ sudo docker run hello-world - - This command downloads a test image and runs it in a container. - -### Get the Linux binary -To download the latest experimental `docker` binary for Linux, -use the following URLs: - - https://experimental.docker.com/builds/Linux/i386/docker-latest.tgz - - https://experimental.docker.com/builds/Linux/x86_64/docker-latest.tgz - -After downloading the appropriate binary, you can follow the instructions -[here](https://docs.docker.com/engine/installation/binaries/#/get-the-docker-engine-binaries) to run the `docker` daemon. - -> **Note** -> -> 1) You can get the MD5 and SHA256 hashes by appending .md5 and .sha256 to the URLs respectively -> -> 2) You can get the compressed binaries by appending .tgz to the URLs - -### Build an experimental binary -You can also build the experimental binary from the standard development environment by adding -`DOCKER_EXPERIMENTAL=1` to the environment where you run `make` to build Docker binaries. For example, -to build a Docker binary with the experimental features enabled: - - $ DOCKER_EXPERIMENTAL=1 make binary +```bash +$ docker version -f '{{.Server.Experimental}}' +true +``` ## Current experimental features From 2c53989b4b39ed780076cb93f6d29762e03c1a6e Mon Sep 17 00:00:00 2001 From: Zhang Wei Date: Sat, 17 Dec 2016 22:01:59 +0800 Subject: [PATCH 04/26] Add missing "--default-runtime" flag in manpage Add missing flag and more descriptions in manpage. Signed-off-by: Zhang Wei (cherry picked from commit 977fd439857006ab34deebac384b621bf4dae7da) Signed-off-by: Victor Vieux --- docs/reference/commandline/dockerd.md | 22 +++++++++-------- man/dockerd.8.md | 34 ++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/docs/reference/commandline/dockerd.md b/docs/reference/commandline/dockerd.md index b8bc8b712c..24ac77611d 100644 --- a/docs/reference/commandline/dockerd.md +++ b/docs/reference/commandline/dockerd.md @@ -684,16 +684,18 @@ configuration file or using the `--add-runtime` command line argument. The following is an example adding 2 runtimes via the configuration: ```json -"default-runtime": "runc", -"runtimes": { - "runc": { - "path": "runc" - }, - "custom": { - "path": "/usr/local/bin/my-runc-replacement", - "runtimeArgs": [ - "--debug" - ] +{ + "default-runtime": "runc", + "runtimes": { + "runc": { + "path": "runc" + }, + "custom": { + "path": "/usr/local/bin/my-runc-replacement", + "runtimeArgs": [ + "--debug" + ] + } } } ``` diff --git a/man/dockerd.8.md b/man/dockerd.8.md index f99e7a7cab..761dc6b9be 100644 --- a/man/dockerd.8.md +++ b/man/dockerd.8.md @@ -20,6 +20,7 @@ dockerd - Enable daemon mode [**-D**|**--debug**] [**--default-gateway**[=*DEFAULT-GATEWAY*]] [**--default-gateway-v6**[=*DEFAULT-GATEWAY-V6*]] +[**--default-runtime**[=*runc*]] [**--default-ulimit**[=*[]*]] [**--disable-legacy-registry**] [**--dns**[=*[]*]] @@ -84,7 +85,35 @@ following format. # OPTIONS **--add-runtime**=[] - Set additional OCI compatible runtime. + Runtimes can be registered with the daemon either via the +configuration file or using the `--add-runtime` command line argument. + + The following is an example adding 2 runtimes via the configuration: + +```json +{ + "default-runtime": "runc", + "runtimes": { + "runc": { + "path": "runc" + }, + "custom": { + "path": "/usr/local/bin/my-runc-replacement", + "runtimeArgs": [ + "--debug" + ] + } + } +} +``` + + This is the same example via the command line: + +```bash +$ sudo dockerd --add-runtime runc=runc --add-runtime custom=/usr/local/bin/my-runc-replacement +``` + + **Note**: defining runtime arguments via the command line is not supported. **--api-cors-header**="" Set CORS headers in the Engine API. Default is cors disabled. Give urls like @@ -132,6 +161,9 @@ following format. **--default-gateway-v6**="" IPv6 address of the container default gateway +**--default-runtime**="runc" + Set default runtime if there're more than one specified by `--add-runtime`. + **--default-ulimit**=[] Default ulimits for containers. From c25a4762efcaad8b113ab48f7d10409057c153af Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sun, 18 Dec 2016 06:31:25 -0800 Subject: [PATCH 05/26] Remove bash completion for `docker node ps --all|-a` Signed-off-by: Harald Albers (cherry picked from commit a54cc4f88da67175938ac2a3d643e3de6cb4d4de) Signed-off-by: Victor Vieux --- contrib/completion/bash/docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index e04bb231ee..dddee35195 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -3139,7 +3139,7 @@ _docker_node_ps() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--filter -f --help --no-resolve --no-trunc" -- "$cur" ) ) ;; *) __docker_complete_nodes_plus_self From e7960584f219f1a016b360f6432f3cf7e42c8052 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sun, 18 Dec 2016 06:47:54 -0800 Subject: [PATCH 06/26] Remove `--all|-a` from `docker node ps` reference Signed-off-by: Harald Albers (cherry picked from commit 364e9002375fca1799180dd76e8074d922dd4044) Signed-off-by: Victor Vieux --- docs/reference/commandline/node_ps.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/reference/commandline/node_ps.md b/docs/reference/commandline/node_ps.md index 48c3abd6a0..7f07c5ea64 100644 --- a/docs/reference/commandline/node_ps.md +++ b/docs/reference/commandline/node_ps.md @@ -22,7 +22,6 @@ Usage: docker node ps [OPTIONS] [NODE...] List tasks running on one or more nodes, defaults to current node. Options: - -a, --all Display all instances -f, --filter value Filter output based on conditions provided --help Print usage --no-resolve Do not map IDs to Names From 39b3e39c40f4c7a94ad97af227757766c691038a Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Mon, 19 Dec 2016 11:40:59 -0800 Subject: [PATCH 07/26] Remove bash completion for deprecated `docker daemon` Signed-off-by: Harald Albers (cherry picked from commit 536a9ec698b8a2f51102b2c57cd9c675873b9af4) Signed-off-by: Victor Vieux --- contrib/completion/bash/docker | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index dddee35195..246cd5f62e 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -3955,7 +3955,6 @@ _docker() { container cp create - daemon diff events exec From 994b3928f6ebc09f183a562e01f799e4adf903fb Mon Sep 17 00:00:00 2001 From: Yanqiang Miao Date: Sat, 24 Dec 2016 15:03:38 +0800 Subject: [PATCH 08/26] Add 'volume prune' to the volume commands index Signed-off-by: Yanqiang Miao (cherry picked from commit 3d4ea98971d319e9dbbeefbd1e82a9c0feae8c70) Signed-off-by: Victor Vieux --- docs/reference/commandline/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/commandline/index.md b/docs/reference/commandline/index.md index 3402f24190..0374645708 100644 --- a/docs/reference/commandline/index.md +++ b/docs/reference/commandline/index.md @@ -106,6 +106,7 @@ read the [`dockerd`](dockerd.md) reference page. | [volume create](volume_create.md) | Creates a new volume where containers can consume and store data | | [volume inspect](volume_inspect.md) | Display information about a volume | | [volume ls](volume_ls.md) | Lists all the volumes Docker knows about | +| [volume prune](volume_prune.md) | Remove all unused volumes | | [volume rm](volume_rm.md) | Remove one or more volumes | From c809c40647207995a3b9f502283320801fa45a59 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sun, 25 Dec 2016 05:32:50 -0800 Subject: [PATCH 09/26] Add bash completion for `plugin install --alias` Signed-off-by: Harald Albers (cherry picked from commit 83158f8aff3ec01fa027556c48e364c5311a6839) Signed-off-by: Victor Vieux --- contrib/completion/bash/docker | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 246cd5f62e..71a188b9c5 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -3266,9 +3266,15 @@ _docker_plugin_inspect() { } _docker_plugin_install() { + case "$prev" in + --alias) + return + ;; + esac + case "$cur" in -*) - COMPREPLY=( $( compgen -W "--disable --grant-all-permissions--help" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--alias --disable --grant-all-permissions --help" -- "$cur" ) ) ;; esac } From 8b155a910975c2c99c043587b7c9b5f559d67f87 Mon Sep 17 00:00:00 2001 From: yuexiao-wang Date: Tue, 27 Dec 2016 02:17:35 +0800 Subject: [PATCH 10/26] Update 'ID' field for 'docker plugin ls' Signed-off-by: yuexiao-wang (cherry picked from commit 1e6587ff280dc3dcac405a67af2ddfd83c78f983) Signed-off-by: Victor Vieux --- docs/extend/index.md | 4 ++-- docs/reference/commandline/plugin_disable.md | 8 ++++---- docs/reference/commandline/plugin_enable.md | 8 ++++---- docs/reference/commandline/plugin_install.md | 4 ++-- docs/reference/commandline/plugin_push.md | 5 ++--- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/extend/index.md b/docs/extend/index.md index fc31e74ce4..e7a62ba758 100644 --- a/docs/extend/index.md +++ b/docs/extend/index.md @@ -69,8 +69,8 @@ enabled, and use it to create a volume. ```bash $ docker plugin ls - NAME TAG ENABLED - vieux/sshfs latest true + ID NAME TAG DESCRIPTION ENABLED + 69553ca1d789 vieux/sshfs latest the `sshfs` plugin true ``` 3. Create a volume using the plugin. diff --git a/docs/reference/commandline/plugin_disable.md b/docs/reference/commandline/plugin_disable.md index 0d4ab7d308..66b0ca9466 100644 --- a/docs/reference/commandline/plugin_disable.md +++ b/docs/reference/commandline/plugin_disable.md @@ -36,8 +36,8 @@ and enabled: ```bash $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true ``` To disable the plugin, use the following command: @@ -49,8 +49,8 @@ tiborvass/no-remove $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -tiborvass/no-remove latest A test plugin for Docker false +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/no-remove latest A test plugin for Docker false ``` ## Related information diff --git a/docs/reference/commandline/plugin_enable.md b/docs/reference/commandline/plugin_enable.md index a1f94df051..36fb7640ac 100644 --- a/docs/reference/commandline/plugin_enable.md +++ b/docs/reference/commandline/plugin_enable.md @@ -35,8 +35,8 @@ but disabled: ```bash $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -tiborvass/no-remove latest A test plugin for Docker false +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/no-remove latest A test plugin for Docker false ``` To enable the plugin, use the following command: @@ -48,8 +48,8 @@ tiborvass/no-remove $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true ``` ## Related information diff --git a/docs/reference/commandline/plugin_install.md b/docs/reference/commandline/plugin_install.md index 3a48aef209..502eb441bf 100644 --- a/docs/reference/commandline/plugin_install.md +++ b/docs/reference/commandline/plugin_install.md @@ -54,8 +54,8 @@ After the plugin is installed, it appears in the list of plugins: ```bash $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true ``` ## Related information diff --git a/docs/reference/commandline/plugin_push.md b/docs/reference/commandline/plugin_push.md index 07f2a66a37..2747f4c4a9 100644 --- a/docs/reference/commandline/plugin_push.md +++ b/docs/reference/commandline/plugin_push.md @@ -32,9 +32,8 @@ The following example shows how to push a sample `user/plugin`. ```bash $ docker plugin ls -NAME TAG DESCRIPTION ENABLED -user/plugin latest A sample plugin for Docker false - +ID NAME TAG DESCRIPTION ENABLED +69553ca1d456 user/plugin latest A sample plugin for Docker false $ docker plugin push user/plugin ``` From eefb2220c0c38cd036e5dec227fc4a7b7cf467e9 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Thu, 22 Dec 2016 11:49:47 -0500 Subject: [PATCH 11/26] Fix usage of boltdb in volume restore bolt k/v pairs are only valid for the life of a transaction. This means the memory that the k/v pair is referencing may be invalid if it is accessed outside of the transaction. This can potentially cause a panic. For reference: https://godoc.org/github.com/boltdb/bolt#hdr-Caveats To fix this issue, unmarshal the stored data into volume meta before closing the transaction. Signed-off-by: Brian Goff (cherry picked from commit 4876a9047ebfd66294d88482a1b4b24634a632e6) Signed-off-by: Victor Vieux --- volume/store/db.go | 28 +++++++++++++++++++--------- volume/store/restore.go | 36 ++++++++++++++---------------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/volume/store/db.go b/volume/store/db.go index 0dc41509a4..c5fd1643f5 100644 --- a/volume/store/db.go +++ b/volume/store/db.go @@ -3,17 +3,13 @@ package store import ( "encoding/json" + "github.com/Sirupsen/logrus" "github.com/boltdb/bolt" "github.com/pkg/errors" ) var volumeBucketName = []byte("volumes") -type dbEntry struct { - Key []byte - Value []byte -} - type volumeMetadata struct { Name string Driver string @@ -67,12 +63,26 @@ func removeMeta(tx *bolt.Tx, name string) error { return errors.Wrap(b.Delete([]byte(name)), "error removing volume metadata") } -func listEntries(tx *bolt.Tx) []*dbEntry { - var entries []*dbEntry +// listMeta is used during restore to get the list of volume metadata +// from the on-disk database. +// Any errors that occur are only logged. +func listMeta(tx *bolt.Tx) []volumeMetadata { + var ls []volumeMetadata b := tx.Bucket(volumeBucketName) b.ForEach(func(k, v []byte) error { - entries = append(entries, &dbEntry{k, v}) + if len(v) == 0 { + // don't try to unmarshal an empty value + return nil + } + + var m volumeMetadata + if err := json.Unmarshal(v, &m); err != nil { + // Just log the error + logrus.Errorf("Error while reading volume metadata for volume %q: %v", string(k), err) + return nil + } + ls = append(ls, m) return nil }) - return entries + return ls } diff --git a/volume/store/restore.go b/volume/store/restore.go index e20740ba30..c0c5b519bc 100644 --- a/volume/store/restore.go +++ b/volume/store/restore.go @@ -1,7 +1,6 @@ package store import ( - "encoding/json" "sync" "github.com/Sirupsen/logrus" @@ -17,45 +16,38 @@ import ( // It does not probe the available drivers to find anything that may have been added // out of band. func (s *VolumeStore) restore() { - var entries []*dbEntry + var ls []volumeMetadata s.db.View(func(tx *bolt.Tx) error { - entries = listEntries(tx) + ls = listMeta(tx) return nil }) - chRemove := make(chan []byte, len(entries)) + chRemove := make(chan *volumeMetadata, len(ls)) var wg sync.WaitGroup - for _, entry := range entries { + for _, meta := range ls { wg.Add(1) // this is potentially a very slow operation, so do it in a goroutine - go func(entry *dbEntry) { + go func(meta volumeMetadata) { defer wg.Done() - var meta volumeMetadata - if len(entry.Value) != 0 { - if err := json.Unmarshal(entry.Value, &meta); err != nil { - logrus.Errorf("Error while reading volume metadata for volume %q: %v", string(entry.Key), err) - // don't return here, we can try with `getVolume` below - } - } var v volume.Volume var err error if meta.Driver != "" { - v, err = lookupVolume(meta.Driver, string(entry.Key)) + v, err = lookupVolume(meta.Driver, meta.Name) if err != nil && err != errNoSuchVolume { - logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", string(entry.Key)).Warn("Error restoring volume") + logrus.WithError(err).WithField("driver", meta.Driver).WithField("volume", meta.Name).Warn("Error restoring volume") return } if v == nil { // doesn't exist in the driver, remove it from the db - chRemove <- entry.Key + chRemove <- &meta return } } else { - v, err = s.getVolume(string(entry.Key)) + v, err = s.getVolume(meta.Name) if err != nil { if err == errNoSuchVolume { - chRemove <- entry.Key + chRemove <- &meta } return } @@ -75,15 +67,15 @@ func (s *VolumeStore) restore() { s.labels[v.Name()] = meta.Labels s.names[v.Name()] = v s.globalLock.Unlock() - }(entry) + }(meta) } wg.Wait() close(chRemove) s.db.Update(func(tx *bolt.Tx) error { - for k := range chRemove { - if err := removeMeta(tx, string(k)); err != nil { - logrus.Warnf("Error removing stale entry from volume db: %v", err) + for meta := range chRemove { + if err := removeMeta(tx, meta.Name); err != nil { + logrus.WithField("volume", meta.Name).Warnf("Error removing stale entry from volume db: %v", err) } } return nil From 428ae707599aa343aa058cb54c10bc65b50d5856 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Mon, 19 Dec 2016 09:56:20 -0800 Subject: [PATCH 12/26] commit: do not change container labels on commit Fix #29547 Signed-off-by: Alexander Morozov (cherry picked from commit ca6c6f0765aeccdb2730d03c05bd965906df8cd4) Signed-off-by: Victor Vieux --- daemon/commit.go | 7 +++---- integration-cli/docker_cli_commit_test.go | 13 +++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/daemon/commit.go b/daemon/commit.go index 333f7f2f93..1e7bffb1dc 100644 --- a/daemon/commit.go +++ b/daemon/commit.go @@ -65,11 +65,10 @@ func merge(userConf, imageConf *containertypes.Config) error { if userConf.Labels == nil { userConf.Labels = map[string]string{} } - if imageConf.Labels != nil { - for l := range userConf.Labels { - imageConf.Labels[l] = userConf.Labels[l] + for l, v := range imageConf.Labels { + if _, ok := userConf.Labels[l]; !ok { + userConf.Labels[l] = v } - userConf.Labels = imageConf.Labels } if len(userConf.Entrypoint) == 0 { diff --git a/integration-cli/docker_cli_commit_test.go b/integration-cli/docker_cli_commit_test.go index 72ff89f3dc..8008ae1716 100644 --- a/integration-cli/docker_cli_commit_test.go +++ b/integration-cli/docker_cli_commit_test.go @@ -142,3 +142,16 @@ func (s *DockerSuite) TestCommitChange(c *check.C) { } } } + +func (s *DockerSuite) TestCommitChangeLabels(c *check.C) { + dockerCmd(c, "run", "--name", "test", "--label", "some=label", "busybox", "true") + + imageID, _ := dockerCmd(c, "commit", + "--change", "LABEL some=label2", + "test", "test-commit") + imageID = strings.TrimSpace(imageID) + + c.Assert(inspectField(c, imageID, "Config.Labels"), checker.Equals, "map[some:label2]") + // check that container labels didn't change + c.Assert(inspectField(c, "test", "Config.Labels"), checker.Equals, "map[some:label]") +} From 5903ead08e3331c8368161078af0a0a3200a0ae5 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sat, 31 Dec 2016 09:23:27 -0800 Subject: [PATCH 13/26] Fix bash completion for `plugin enable|disable` `docker plugin enable` and `docker plugin disable` only accept one plugin. Signed-off-by: Harald Albers (cherry picked from commit 390effdd11a64f445d9932b6dbc04113b4687dea) Signed-off-by: Victor Vieux --- contrib/completion/bash/docker | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 71a188b9c5..16c69e6ffb 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -3226,7 +3226,10 @@ _docker_plugin_disable() { COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) ;; *) - __docker_complete_plugins_installed + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_plugins_installed + fi ;; esac } @@ -3243,7 +3246,10 @@ _docker_plugin_enable() { COMPREPLY=( $( compgen -W "--help --timeout" -- "$cur" ) ) ;; *) - __docker_complete_plugins_installed + local counter=$(__docker_pos_first_nonflag '--timeout') + if [ $cword -eq $counter ]; then + __docker_complete_plugins_installed + fi ;; esac } From ea00b1417094cc8dc15d2bc2320fde5fda6cf258 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sat, 31 Dec 2016 09:28:03 -0800 Subject: [PATCH 14/26] Add bash completion for `plugin disable --force` Signed-off-by: Harald Albers (cherry picked from commit e1403453f0a173464ef209e18e661320100a7b42) Signed-off-by: Victor Vieux --- contrib/completion/bash/docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/completion/bash/docker b/contrib/completion/bash/docker index 16c69e6ffb..52956f2ca8 100644 --- a/contrib/completion/bash/docker +++ b/contrib/completion/bash/docker @@ -3223,7 +3223,7 @@ _docker_plugin_create() { _docker_plugin_disable() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--force -f --help" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag) From e2b04a78182695473aab8a61641ba9e5a2fe2007 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 23 Dec 2016 11:16:15 -0800 Subject: [PATCH 15/26] Fix image's `CMD` after `WORKDIR` in Dockerfile This fix tries to fix 29667 where image's `CMD` is modified after `WORKDIR` in Dockerfile. The value of `b.runConfig.Cmd` was modified in the processing of `WORKDIR`, in order to fix 28902. However, the same `b.runConfig.Cmd` is passed to `commit()`. This fix restored the `b.runConfig.Cmd` before `commit()` the image for `WORKDIR`. A test has been added. This fix fixes 29667. This fix is related to 28902, 28909, 28514. Signed-off-by: Yong Tang (cherry picked from commit 083602384737635af9a89b75a6ca6d27f7515dc6) Signed-off-by: Victor Vieux --- builder/dockerfile/dispatchers.go | 10 +++--- integration-cli/docker_cli_build_test.go | 40 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/builder/dockerfile/dispatchers.go b/builder/dockerfile/dispatchers.go index 4f3dcd8cd3..42eebd050d 100644 --- a/builder/dockerfile/dispatchers.go +++ b/builder/dockerfile/dispatchers.go @@ -297,17 +297,17 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str } b.runConfig.Image = b.image - cmd := b.runConfig.Cmd - b.runConfig.Cmd = strslice.StrSlice(append(getShell(b.runConfig), fmt.Sprintf("#(nop) WORKDIR %s", b.runConfig.WorkingDir))) - defer func(cmd strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd) - if hit, err := b.probeCache(); err != nil { return err } else if hit { return nil } - container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}) + // Actually copy the struct + workdirConfig := *b.runConfig + workdirConfig.Cmd = strslice.StrSlice(append(getShell(b.runConfig), fmt.Sprintf("#(nop) WORKDIR %s", b.runConfig.WorkingDir))) + + container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: &workdirConfig}) if err != nil { return err } diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index c05e545b01..4bb4e65987 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -7357,3 +7357,43 @@ func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) { c.Fatalf("Case insensitive environment variables on Windows failed. Got %s", res) } } + +// Test case for 29667 +func (s *DockerSuite) TestBuildWorkdirImageCmd(c *check.C) { + testRequires(c, DaemonIsLinux) + + image := "testworkdirimagecmd" + dockerfile := ` +FROM busybox +WORKDIR /foo/bar +` + out, err := buildImage(image, dockerfile, true) + c.Assert(err, checker.IsNil, check.Commentf("Output: %s", out)) + + out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image) + c.Assert(strings.TrimSpace(out), checker.Equals, `["sh"]`) + + image = "testworkdirlabelimagecmd" + dockerfile = ` +FROM busybox +WORKDIR /foo/bar +LABEL a=b +` + out, err = buildImage(image, dockerfile, true) + c.Assert(err, checker.IsNil, check.Commentf("Output: %s", out)) + + out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image) + c.Assert(strings.TrimSpace(out), checker.Equals, `["sh"]`) +} + +// Test case for 28902/28090 +func (s *DockerSuite) TestBuildWorkdirCmd(c *check.C) { + testRequires(c, DaemonIsLinux) + + dockerFile := ` + FROM golang:1.7-alpine + WORKDIR / + ` + _, err := buildImage("testbuildworkdircmd", dockerFile, false) + c.Assert(err, checker.IsNil) +} From 7cbc4cb7f2c1b84241647650ec0f81beee7e8448 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 16 Dec 2016 23:48:27 +0100 Subject: [PATCH 16/26] fix powershell dco check Signed-off-by: Sebastiaan van Stijn (cherry picked from commit 611a633ba4e11215a23d8b405a537346b10d9657) Signed-off-by: Victor Vieux --- hack/make.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/make.ps1 b/hack/make.ps1 index c085902ab6..335619d174 100644 --- a/hack/make.ps1 +++ b/hack/make.ps1 @@ -184,7 +184,7 @@ Function Validate-DCO($headCommit, $upstreamCommit) { $usernameRegex='[a-zA-Z0-9][a-zA-Z0-9-]+' $dcoPrefix="Signed-off-by:" - $dcoRegex="^(Docker-DCO-1.1-)?$dcoPrefix ([^<]+) <([^<>@]+@[^<>]+)>( \\(github: ($githubUsernameRegex)\\))?$" + $dcoRegex="^(Docker-DCO-1.1-)?$dcoPrefix ([^<]+) <([^<>@]+@[^<>]+)>( \\(github: ($usernameRegex)\\))?$" $counts = Invoke-Expression "git diff --numstat $upstreamCommit...$headCommit" if ($LASTEXITCODE -ne 0) { Throw "Failed git diff --numstat" } From a2dc349c74b31ab167d8502178ffee7caae956ae Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Thu, 29 Dec 2016 17:28:28 -0500 Subject: [PATCH 17/26] Add quoted string flag Value. Signed-off-by: Daniel Nephin (cherry picked from commit e4c1f0772923c3069ce14a82d445cd55af3382bc) Signed-off-by: Victor Vieux --- opts/quotedstring.go | 30 ++++++++++++++++++++++++++++++ opts/quotedstring_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 opts/quotedstring.go create mode 100644 opts/quotedstring_test.go diff --git a/opts/quotedstring.go b/opts/quotedstring.go new file mode 100644 index 0000000000..8ddeee8085 --- /dev/null +++ b/opts/quotedstring.go @@ -0,0 +1,30 @@ +package opts + +// QuotedString is a string that may have extra quotes around the value. The +// quotes are stripped from the value. +type QuotedString string + +// Set sets a new value +func (s *QuotedString) Set(val string) error { + *s = QuotedString(trimQuotes(val)) + return nil +} + +// Type returns the type of the value +func (s *QuotedString) Type() string { + return "string" +} + +func (s *QuotedString) String() string { + return string(*s) +} + +func trimQuotes(value string) string { + lastIndex := len(value) - 1 + for _, char := range []byte{'\'', '"'} { + if value[0] == char && value[lastIndex] == char { + return value[1:lastIndex] + } + } + return value +} diff --git a/opts/quotedstring_test.go b/opts/quotedstring_test.go new file mode 100644 index 0000000000..a508b9d210 --- /dev/null +++ b/opts/quotedstring_test.go @@ -0,0 +1,24 @@ +package opts + +import ( + "github.com/docker/docker/pkg/testutil/assert" + "testing" +) + +func TestQuotedStringSetWithQuotes(t *testing.T) { + qs := QuotedString("") + assert.NilError(t, qs.Set("\"something\"")) + assert.Equal(t, qs.String(), "something") +} + +func TestQuotedStringSetWithMismatchedQuotes(t *testing.T) { + qs := QuotedString("") + assert.NilError(t, qs.Set("\"something'")) + assert.Equal(t, qs.String(), "\"something'") +} + +func TestQuotedStringSetWithNoQuotes(t *testing.T) { + qs := QuotedString("") + assert.NilError(t, qs.Set("something")) + assert.Equal(t, qs.String(), "something") +} From 045e9834a55c142889958126b9c0583a1d13d61f Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 3 Jan 2017 15:58:41 -0500 Subject: [PATCH 18/26] Trim quotes from TLS flags. Signed-off-by: Daniel Nephin (cherry picked from commit abe32de6b46825300f612864e6b4c98606a5bb0e) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- cli/flags/common.go | 12 +++++++---- cli/flags/common_test.go | 42 +++++++++++++++++++++++++++++++++++++++ opts/quotedstring.go | 13 +++++++++--- opts/quotedstring_test.go | 10 +++++++--- 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 cli/flags/common_test.go diff --git a/cli/flags/common.go b/cli/flags/common.go index 690e8da4b8..e2f9da0732 100644 --- a/cli/flags/common.go +++ b/cli/flags/common.go @@ -59,11 +59,15 @@ func (commonOpts *CommonOptions) InstallFlags(flags *pflag.FlagSet) { // TODO use flag flags.String("identity"}, "i", "", "Path to libtrust key file") - commonOpts.TLSOptions = &tlsconfig.Options{} + commonOpts.TLSOptions = &tlsconfig.Options{ + CAFile: filepath.Join(dockerCertPath, DefaultCaFile), + CertFile: filepath.Join(dockerCertPath, DefaultCertFile), + KeyFile: filepath.Join(dockerCertPath, DefaultKeyFile), + } tlsOptions := commonOpts.TLSOptions - flags.StringVar(&tlsOptions.CAFile, "tlscacert", filepath.Join(dockerCertPath, DefaultCaFile), "Trust certs signed only by this CA") - flags.StringVar(&tlsOptions.CertFile, "tlscert", filepath.Join(dockerCertPath, DefaultCertFile), "Path to TLS certificate file") - flags.StringVar(&tlsOptions.KeyFile, "tlskey", filepath.Join(dockerCertPath, DefaultKeyFile), "Path to TLS key file") + flags.Var(opts.NewQuotedString(&tlsOptions.CAFile), "tlscacert", "Trust certs signed only by this CA") + flags.Var(opts.NewQuotedString(&tlsOptions.CertFile), "tlscert", "Path to TLS certificate file") + flags.Var(opts.NewQuotedString(&tlsOptions.KeyFile), "tlskey", "Path to TLS key file") hostOpt := opts.NewNamedListOptsRef("hosts", &commonOpts.Hosts, opts.ValidateHost) flags.VarP(hostOpt, "host", "H", "Daemon socket(s) to connect to") diff --git a/cli/flags/common_test.go b/cli/flags/common_test.go new file mode 100644 index 0000000000..81eaa38f43 --- /dev/null +++ b/cli/flags/common_test.go @@ -0,0 +1,42 @@ +package flags + +import ( + "path/filepath" + "testing" + + "github.com/docker/docker/cliconfig" + "github.com/docker/docker/pkg/testutil/assert" + "github.com/spf13/pflag" +) + +func TestCommonOptionsInstallFlags(t *testing.T) { + flags := pflag.NewFlagSet("testing", pflag.ContinueOnError) + opts := NewCommonOptions() + opts.InstallFlags(flags) + + err := flags.Parse([]string{ + "--tlscacert=\"/foo/cafile\"", + "--tlscert=\"/foo/cert\"", + "--tlskey=\"/foo/key\"", + }) + assert.NilError(t, err) + assert.Equal(t, opts.TLSOptions.CAFile, "/foo/cafile") + assert.Equal(t, opts.TLSOptions.CertFile, "/foo/cert") + assert.Equal(t, opts.TLSOptions.KeyFile, "/foo/key") +} + +func defaultPath(filename string) string { + return filepath.Join(cliconfig.ConfigDir(), filename) +} + +func TestCommonOptionsInstallFlagsWithDefaults(t *testing.T) { + flags := pflag.NewFlagSet("testing", pflag.ContinueOnError) + opts := NewCommonOptions() + opts.InstallFlags(flags) + + err := flags.Parse([]string{}) + assert.NilError(t, err) + assert.Equal(t, opts.TLSOptions.CAFile, defaultPath("ca.pem")) + assert.Equal(t, opts.TLSOptions.CertFile, defaultPath("cert.pem")) + assert.Equal(t, opts.TLSOptions.KeyFile, defaultPath("key.pem")) +} diff --git a/opts/quotedstring.go b/opts/quotedstring.go index 8ddeee8085..fb1e5374bc 100644 --- a/opts/quotedstring.go +++ b/opts/quotedstring.go @@ -2,11 +2,13 @@ package opts // QuotedString is a string that may have extra quotes around the value. The // quotes are stripped from the value. -type QuotedString string +type QuotedString struct { + value *string +} // Set sets a new value func (s *QuotedString) Set(val string) error { - *s = QuotedString(trimQuotes(val)) + *s.value = trimQuotes(val) return nil } @@ -16,7 +18,7 @@ func (s *QuotedString) Type() string { } func (s *QuotedString) String() string { - return string(*s) + return string(*s.value) } func trimQuotes(value string) string { @@ -28,3 +30,8 @@ func trimQuotes(value string) string { } return value } + +// NewQuotedString returns a new quoted string option +func NewQuotedString(value *string) *QuotedString { + return &QuotedString{value: value} +} diff --git a/opts/quotedstring_test.go b/opts/quotedstring_test.go index a508b9d210..0ebf04bbe0 100644 --- a/opts/quotedstring_test.go +++ b/opts/quotedstring_test.go @@ -6,19 +6,23 @@ import ( ) func TestQuotedStringSetWithQuotes(t *testing.T) { - qs := QuotedString("") + value := "" + qs := NewQuotedString(&value) assert.NilError(t, qs.Set("\"something\"")) assert.Equal(t, qs.String(), "something") + assert.Equal(t, value, "something") } func TestQuotedStringSetWithMismatchedQuotes(t *testing.T) { - qs := QuotedString("") + value := "" + qs := NewQuotedString(&value) assert.NilError(t, qs.Set("\"something'")) assert.Equal(t, qs.String(), "\"something'") } func TestQuotedStringSetWithNoQuotes(t *testing.T) { - qs := QuotedString("") + value := "" + qs := NewQuotedString(&value) assert.NilError(t, qs.Set("something")) assert.Equal(t, qs.String(), "something") } From ff7934faf29a33e254a066b4a535d56627ea8a76 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Sat, 31 Dec 2016 09:55:04 -0800 Subject: [PATCH 19/26] Fix usage message of `plugin inspect` Signed-off-by: Harald Albers (cherry picked from commit 1b58d0bc51e2bfc9e268dab762d1d891c18890c9) Signed-off-by: Victor Vieux --- cli/command/plugin/inspect.go | 2 +- docs/reference/commandline/plugin_inspect.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/command/plugin/inspect.go b/cli/command/plugin/inspect.go index 46ec7b229b..c2c7a0d6bc 100644 --- a/cli/command/plugin/inspect.go +++ b/cli/command/plugin/inspect.go @@ -17,7 +17,7 @@ func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { var opts inspectOptions cmd := &cobra.Command{ - Use: "inspect [OPTIONS] PLUGIN|ID [PLUGIN|ID...]", + Use: "inspect [OPTIONS] PLUGIN [PLUGIN...]", Short: "Display detailed information on one or more plugins", Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/docs/reference/commandline/plugin_inspect.md b/docs/reference/commandline/plugin_inspect.md index ded6bd2ee2..01e231bf06 100644 --- a/docs/reference/commandline/plugin_inspect.md +++ b/docs/reference/commandline/plugin_inspect.md @@ -16,7 +16,7 @@ keywords: "plugin, inspect" # plugin inspect ```markdown -Usage: docker plugin inspect [OPTIONS] PLUGIN|ID [PLUGIN|ID...] +Usage: docker plugin inspect [OPTIONS] PLUGIN [PLUGIN...] Display detailed information on one or more plugins From def75b2c2c16ea809b5626930a62080897cbefed Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Thu, 15 Dec 2016 13:07:27 -0500 Subject: [PATCH 20/26] Fixes a race condition in client events monitoring In cases where there is high latency (ie, not-local network) `waitExitOrRemoved` was not receiving events for short-lived containers. This caused the client to hang while waiting for a notification that the container has stopped. This happens because `client.Events()` returns immediately and spins a goroutine up to process events. The problem here is it returns before the request to the events endpoint is even made. Even without high-latency issues, there is no guarantee that the goroutine is even scheduled by the time the function returns. Signed-off-by: Brian Goff (cherry picked from commit 47585996bf72bcfde9ef058522059bef352e83e0) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- client/events.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/events.go b/client/events.go index c154f7dcf9..af47aefa74 100644 --- a/client/events.go +++ b/client/events.go @@ -22,17 +22,20 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c messages := make(chan events.Message) errs := make(chan error, 1) + started := make(chan struct{}) go func() { defer close(errs) query, err := buildEventsQueryParams(cli.version, options) if err != nil { + close(started) errs <- err return } resp, err := cli.get(ctx, "/events", query, nil) if err != nil { + close(started) errs <- err return } @@ -40,6 +43,7 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c decoder := json.NewDecoder(resp.body) + close(started) for { select { case <-ctx.Done(): @@ -61,6 +65,7 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c } } }() + <-started return messages, errs } From d01138c16238457b02afd2166e72bc354d465dbd Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Mon, 26 Dec 2016 13:47:43 -0800 Subject: [PATCH 21/26] Remove `docker stack ps -a` to match removal of `docker service/node ps -a` In #28507 and #28885, `docker service/node ps -a` has been removed so that information about slots are show up even without `-a` flag. The output of `docker stack ps` reused the same output as `docker service/node ps`. However, the `-a` was still there. It might make sense to remove `docker stack ps -a` as well to bring consistency with `docker service/node ps`. This fix is related to #28507, #28885, and #25983. Signed-off-by: Yong Tang (cherry picked from commit 9155e14e77a8235791a6de752f6f43e83308e23d) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- cli/command/stack/ps.go | 7 ------- docs/reference/commandline/stack_ps.md | 8 ++++---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/cli/command/stack/ps.go b/cli/command/stack/ps.go index 7a5e069cbe..73ceb33128 100644 --- a/cli/command/stack/ps.go +++ b/cli/command/stack/ps.go @@ -6,7 +6,6 @@ import ( "golang.org/x/net/context" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command/idresolver" @@ -16,7 +15,6 @@ import ( ) type psOptions struct { - all bool filter opts.FilterOpt noTrunc bool namespace string @@ -36,7 +34,6 @@ func newPsCommand(dockerCli *command.DockerCli) *cobra.Command { }, } flags := cmd.Flags() - flags.BoolVarP(&opts.all, "all", "a", false, "Display all tasks") flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output") flags.BoolVar(&opts.noResolve, "no-resolve", false, "Do not map IDs to Names") flags.VarP(&opts.filter, "filter", "f", "Filter output based on conditions provided") @@ -51,10 +48,6 @@ func runPS(dockerCli *command.DockerCli, opts psOptions) error { filter := opts.filter.Value() filter.Add("label", labelNamespace+"="+opts.namespace) - if !opts.all && !filter.Include("desired-state") { - filter.Add("desired-state", string(swarm.TaskStateRunning)) - filter.Add("desired-state", string(swarm.TaskStateAccepted)) - } tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) if err != nil { diff --git a/docs/reference/commandline/stack_ps.md b/docs/reference/commandline/stack_ps.md index 75223e07d9..01dc63b7d9 100644 --- a/docs/reference/commandline/stack_ps.md +++ b/docs/reference/commandline/stack_ps.md @@ -21,10 +21,10 @@ Usage: docker stack ps [OPTIONS] STACK List the tasks in the stack Options: - -a, --all Display all tasks - -f, --filter value Filter output based on conditions provided - --no-resolve Do not map IDs to Names - --no-trunc Do not truncate output + -f, --filter filter Filter output based on conditions provided + --help Print usage + --no-resolve Do not map IDs to Names + --no-trunc Do not truncate output ``` Lists the tasks that are running as part of the specified stack. This From aa5ac38f41ae6fba5ce36f9c3dcc499d97badf0b Mon Sep 17 00:00:00 2001 From: Yanqiang Miao Date: Fri, 30 Dec 2016 11:58:39 +0800 Subject: [PATCH 22/26] Optimization a error description Signed-off-by: Yanqiang Miao (cherry picked from commit 6c021893aa12088c0ad5b18111cfa80d6008a78f) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- plugin/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/store.go b/plugin/store.go index bb57e80665..5f95defdde 100644 --- a/plugin/store.go +++ b/plugin/store.go @@ -58,7 +58,7 @@ func (ps *Store) GetV2Plugin(refOrID string) (*v2.Plugin, error) { func (ps *Store) validateName(name string) error { for _, p := range ps.plugins { if p.Name() == name { - return errors.Errorf("%v already exists", name) + return errors.Errorf("plugin %q already exists", name) } } return nil From 68418871329441cc1267fe4e8178f0419ab28c50 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 19 Nov 2016 17:41:11 -0800 Subject: [PATCH 23/26] Add `--file` flag for `docker secret create` command This fix tries to address the issue raised in 28581 and 28927 where it is not possible to create a secret from a file (only through STDIN). This fix add a flag `--file` to `docker secret create` so that it is possible to create a secret from a file with: ``` docker secret create --file secret.in secret.name ``` or ``` echo TEST | docker secret create --file - secret.name ``` Related docs has been updated. An integration test has been added to cover the changes. This fix fixes 28581. This fix is related to 28927. Signed-off-by: Yong Tang (cherry picked from commit c6f0b7f448fac4d037d00f944a7908c60c04dff2) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- cli/command/secret/create.go | 25 +++++++++++--- docs/reference/commandline/secret_create.md | 27 +++++++++++---- .../docker_cli_secret_create_test.go | 34 +++++++++++++++++++ 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/cli/command/secret/create.go b/cli/command/secret/create.go index 381a931415..5d4dc34d12 100644 --- a/cli/command/secret/create.go +++ b/cli/command/secret/create.go @@ -2,13 +2,14 @@ package secret import ( "fmt" + "io" "io/ioutil" - "os" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/opts" + "github.com/docker/docker/pkg/system" runconfigopts "github.com/docker/docker/runconfig/opts" "github.com/spf13/cobra" "golang.org/x/net/context" @@ -16,6 +17,7 @@ import ( type createOptions struct { name string + file string labels opts.ListOpts } @@ -26,7 +28,7 @@ func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command { cmd := &cobra.Command{ Use: "create [OPTIONS] SECRET", - Short: "Create a secret using stdin as content", + Short: "Create a secret from a file or STDIN as content", Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { createOpts.name = args[0] @@ -35,6 +37,7 @@ func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command { } flags := cmd.Flags() flags.VarP(&createOpts.labels, "label", "l", "Secret labels") + flags.StringVarP(&createOpts.file, "file", "f", "", "Read from a file or STDIN ('-')") return cmd } @@ -43,9 +46,23 @@ func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error client := dockerCli.Client() ctx := context.Background() - secretData, err := ioutil.ReadAll(os.Stdin) + if options.file == "" { + return fmt.Errorf("Please specify either a file name or STDIN ('-') with --file") + } + + var in io.Reader = dockerCli.In() + if options.file != "-" { + file, err := system.OpenSequential(options.file) + if err != nil { + return err + } + in = file + defer file.Close() + } + + secretData, err := ioutil.ReadAll(in) if err != nil { - return fmt.Errorf("Error reading content from STDIN: %v", err) + return fmt.Errorf("Error reading content from %q: %v", options.file, err) } spec := swarm.SecretSpec{ diff --git a/docs/reference/commandline/secret_create.md b/docs/reference/commandline/secret_create.md index 952ad26b2c..ef2641a91c 100644 --- a/docs/reference/commandline/secret_create.md +++ b/docs/reference/commandline/secret_create.md @@ -16,15 +16,17 @@ keywords: ["secret, create"] # secret create ```Markdown -Usage: docker secret create [OPTIONS] SECRET +Usage: docker secret create [OPTIONS] SECRET + +Create a secret from a file or STDIN as content -Create a secret using stdin as content Options: - --help Print usage - -l, --label list Secret labels (default []) + -f, --file string Read from a file or STDIN ('-') + --help Print usage + -l, --label list Secret labels (default []) ``` -Creates a secret using standard input for the secret content. You must run this +Creates a secret using standard input or from a file for the secret content. You must run this command on a manager node. ## Examples @@ -32,7 +34,18 @@ command on a manager node. ### Create a secret ```bash -$ cat secret.json | docker secret create secret.json +$ cat secret.json | docker secret create -f - secret.json +mhv17xfe3gh6xc4rij5orpfds + +$ docker secret ls +ID NAME CREATED UPDATED SIZE +mhv17xfe3gh6xc4rij5orpfds secret.json 2016-10-27 23:25:43.909181089 +0000 UTC 2016-10-27 23:25:43.909181089 +0000 UTC 1679 +``` + +### Create a secret with a file + +```bash +$ docker secret create --file secret.in secret.json mhv17xfe3gh6xc4rij5orpfds $ docker secret ls @@ -43,7 +56,7 @@ mhv17xfe3gh6xc4rij5orpfds secret.json 2016-10-27 23:25:43.90918108 ### Create a secret with labels ```bash -$ cat secret.json | docker secret create secret.json --label env=dev --label rev=20161102 +$ cat secret.json | docker secret create secret.json -f - --label env=dev --label rev=20161102 jtn7g6aukl5ky7nr9gvwafoxh $ docker secret inspect secret.json diff --git a/integration-cli/docker_cli_secret_create_test.go b/integration-cli/docker_cli_secret_create_test.go index 9c45f8a0ae..5097f1e707 100644 --- a/integration-cli/docker_cli_secret_create_test.go +++ b/integration-cli/docker_cli_secret_create_test.go @@ -3,6 +3,10 @@ package main import ( + "io/ioutil" + "os" + "strings" + "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/pkg/integration/checker" "github.com/go-check/check" @@ -104,3 +108,33 @@ func (s *DockerSwarmSuite) TestSecretCreateResolve(c *check.C) { c.Assert(out, checker.Not(checker.Contains), id) c.Assert(out, checker.Not(checker.Contains), fake) } + +func (s *DockerSwarmSuite) TestSecretCreateWithFile(c *check.C) { + d := s.AddDaemon(c, true, true) + + testFile, err := ioutil.TempFile("", "secretCreateTest") + c.Assert(err, checker.IsNil, check.Commentf("failed to create temporary file")) + defer os.Remove(testFile.Name()) + + testData := "TESTINGDATA" + _, err = testFile.Write([]byte(testData)) + c.Assert(err, checker.IsNil, check.Commentf("failed to write to temporary file")) + + testName := "test_secret" + out, err := d.Cmd("secret", "create", "--file", testFile.Name(), testName) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "", check.Commentf(out)) + + id := strings.TrimSpace(out) + secret := d.getSecret(c, id) + c.Assert(secret.Spec.Name, checker.Equals, testName) + + testName = "test_secret_2" + out, err = d.Cmd("secret", "create", testName, "-f", testFile.Name()) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "", check.Commentf(out)) + + id = strings.TrimSpace(out) + secret = d.getSecret(c, id) + c.Assert(secret.Spec.Name, checker.Equals, testName) +} From 84f25c7cb821fbef70a87c432ce474b7b75be4ba Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Tue, 27 Dec 2016 11:07:22 -0500 Subject: [PATCH 24/26] Fix race/deadlock in v1 plugin handlers When a plugin is activated, and then `plugins.Handle` is called to register a new handler for a given plugin type, a deadlock occurs when for anything which calls `waitActive`, including `Get`, and `GetAll`. This happens because `Handle()` is setting `activated` to `false` to ensure that plugin handlers are run on next activation. Maybe these handlers should be called immediately for any plugins which are already registered... but to preserve the existing behavior while fixing the deadlock, track if handlers have been run on plugins and reset when a new handler is registered. The simplest way to reproduce the deadlock with Docker is to add a `-v /foo` to the test container created for the external graphdriver tests. Signed-off-by: Brian Goff (cherry picked from commit 2938dce794be7559ba73b4e9630015020a7fa937) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- ...cker_cli_external_graphdriver_unix_test.go | 4 + pkg/plugins/plugin_test.go | 37 ++++++++++ pkg/plugins/plugins.go | 74 +++++++++++++------ 3 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 pkg/plugins/plugin_test.go diff --git a/integration-cli/docker_cli_external_graphdriver_unix_test.go b/integration-cli/docker_cli_external_graphdriver_unix_test.go index 65814d19da..a794ca742d 100644 --- a/integration-cli/docker_cli_external_graphdriver_unix_test.go +++ b/integration-cli/docker_cli_external_graphdriver_unix_test.go @@ -54,6 +54,10 @@ func (s *DockerExternalGraphdriverSuite) SetUpTest(c *check.C) { s.d = NewDaemon(c) } +func (s *DockerExternalGraphdriverSuite) OnTimeout(c *check.C) { + s.d.DumpStackAndQuit() +} + func (s *DockerExternalGraphdriverSuite) TearDownTest(c *check.C) { s.d.Stop() s.ds.TearDownTest(c) diff --git a/pkg/plugins/plugin_test.go b/pkg/plugins/plugin_test.go new file mode 100644 index 0000000000..ac810565f7 --- /dev/null +++ b/pkg/plugins/plugin_test.go @@ -0,0 +1,37 @@ +package plugins + +import ( + "path/filepath" + "runtime" + "sync" + "testing" + "time" +) + +// regression test for deadlock in handlers +func TestPluginAddHandler(t *testing.T) { + // make a plugin which is pre-activated + p := &Plugin{activateWait: sync.NewCond(&sync.Mutex{})} + p.Manifest = &Manifest{Implements: []string{"bananas"}} + storage.plugins["qwerty"] = p + + testActive(t, p) + Handle("bananas", func(_ string, _ *Client) {}) + testActive(t, p) +} + +func testActive(t *testing.T, p *Plugin) { + done := make(chan struct{}) + go func() { + p.waitActive() + close(done) + }() + + select { + case <-time.After(100 * time.Millisecond): + _, f, l, _ := runtime.Caller(1) + t.Fatalf("%s:%d: deadlock in waitActive", filepath.Base(f), l) + case <-done: + } + +} diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index acfb209992..125e6c7d66 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -70,12 +70,12 @@ type Plugin struct { // Manifest of the plugin (see above) Manifest *Manifest `json:"-"` - // error produced by activation - activateErr error - // specifies if the activation sequence is completed (not if it is successful or not) - activated bool // wait for activation to finish activateWait *sync.Cond + // error produced by activation + activateErr error + // keeps track of callback handlers run against this plugin + handlersRun bool } // BasePath returns the path to which all paths returned by the plugin are relative to. @@ -112,19 +112,51 @@ func NewLocalPlugin(name, addr string) *Plugin { func (p *Plugin) activate() error { p.activateWait.L.Lock() - if p.activated { + + if p.activated() { + p.runHandlers() p.activateWait.L.Unlock() return p.activateErr } p.activateErr = p.activateWithLock() - p.activated = true + p.runHandlers() p.activateWait.L.Unlock() p.activateWait.Broadcast() return p.activateErr } +// runHandlers runs the registered handlers for the implemented plugin types +// This should only be run after activation, and while the activation lock is held. +func (p *Plugin) runHandlers() { + if !p.activated() { + return + } + + handlers.RLock() + if !p.handlersRun { + for _, iface := range p.Manifest.Implements { + hdlrs, handled := handlers.extpointHandlers[iface] + if !handled { + continue + } + for _, handler := range hdlrs { + handler(p.name, p.client) + } + } + p.handlersRun = true + } + handlers.RUnlock() + +} + +// activated returns if the plugin has already been activated. +// This should only be called with the activation lock held +func (p *Plugin) activated() bool { + return p.Manifest != nil +} + func (p *Plugin) activateWithLock() error { c, err := NewClient(p.Addr, p.TLSConfig) if err != nil { @@ -138,24 +170,12 @@ func (p *Plugin) activateWithLock() error { } p.Manifest = m - - handlers.RLock() - for _, iface := range m.Implements { - hdlrs, handled := handlers.extpointHandlers[iface] - if !handled { - continue - } - for _, handler := range hdlrs { - handler(p.name, p.client) - } - } - handlers.RUnlock() return nil } func (p *Plugin) waitActive() error { p.activateWait.L.Lock() - for !p.activated { + for !p.activated() { p.activateWait.Wait() } p.activateWait.L.Unlock() @@ -163,7 +183,7 @@ func (p *Plugin) waitActive() error { } func (p *Plugin) implements(kind string) bool { - if err := p.waitActive(); err != nil { + if p.Manifest == nil { return false } for _, driver := range p.Manifest.Implements { @@ -232,7 +252,7 @@ func Get(name, imp string) (*Plugin, error) { if err != nil { return nil, err } - if pl.implements(imp) { + if err := pl.waitActive(); err == nil && pl.implements(imp) { logrus.Debugf("%s implements: %s", name, imp) return pl, nil } @@ -249,9 +269,17 @@ func Handle(iface string, fn func(string, *Client)) { hdlrs = append(hdlrs, fn) handlers.extpointHandlers[iface] = hdlrs + + storage.Lock() for _, p := range storage.plugins { - p.activated = false + p.activateWait.L.Lock() + if p.activated() && p.implements(iface) { + p.handlersRun = false + } + p.activateWait.L.Unlock() } + storage.Unlock() + handlers.Unlock() } @@ -292,7 +320,7 @@ func GetAll(imp string) ([]*Plugin, error) { logrus.Error(pl.err) continue } - if pl.pl.implements(imp) { + if err := pl.pl.waitActive(); err == nil && pl.pl.implements(imp) { out = append(out, pl.pl) } } From 4e9dd0e51c684f188028b94af13e7ab6810703d9 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Wed, 14 Dec 2016 00:35:34 -0800 Subject: [PATCH 25/26] replace no-remove by sample-volume-plugin in docs Signed-off-by: Victor Vieux (cherry picked from commit bcead9282e17f51b01c4edfa59221546f02aaa33) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- api/swagger.yaml | 126 +++++-------------- docs/extend/config.md | 85 ++++++------- docs/reference/commandline/events.md | 4 +- docs/reference/commandline/plugin_disable.md | 14 +-- docs/reference/commandline/plugin_enable.md | 14 +-- docs/reference/commandline/plugin_inspect.md | 8 +- docs/reference/commandline/plugin_install.md | 14 +-- docs/reference/commandline/plugin_ls.md | 4 +- docs/reference/commandline/plugin_rm.md | 10 +- docs/reference/commandline/plugin_set.md | 8 +- man/docker-events.1.md | 4 +- 11 files changed, 109 insertions(+), 182 deletions(-) diff --git a/api/swagger.yaml b/api/swagger.yaml index 871fe0c225..68a5420477 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -1497,74 +1497,39 @@ definitions: type: "string" example: Id: "5724e2c8652da337ab2eedd19fc6fc0ec908e4bd907c7421bf6a8dfc70c4c078" - Name: "tiborvass/no-remove" + Name: "tiborvass/sample-volume-plugin" Tag: "latest" Active: true - Config: - Mounts: - - Name: "" - Description: "" - Settable: null - Source: "/data" - Destination: "/data" - Type: "bind" - Options: - - "shared" - - "rbind" - - Name: "" - Description: "" - Settable: null - Source: null - Destination: "/foobar" - Type: "tmpfs" - Options: null + Settings: Env: - - "DEBUG=1" + - "DEBUG=0" Args: null Devices: null - Manifest: - ManifestVersion: "v0" - Description: "A test plugin for Docker" + Config: + Description: "A sample volume plugin for Docker" Documentation: "https://docs.docker.com/engine/extend/plugins/" Interface: Types: - "docker.volumedriver/1.0" Socket: "plugins.sock" Entrypoint: - - "plugin-no-remove" + - "/usr/bin/sample-volume-plugin" - "/data" WorkDir: "" User: {} Network: - Type: "host" - Capabilities: null - Mounts: - - Name: "" - Description: "" - Settable: null - Source: "/data" - Destination: "/data" - Type: "bind" - Options: - - "shared" - - "rbind" - - Name: "" - Description: "" - Settable: null - Source: null - Destination: "/foobar" - Type: "tmpfs" - Options: null - Devices: - - Name: "device" - Description: "a host device to mount" - Settable: null - Path: "/dev/cpu_dma_latency" + Type: "" + Linux: + Capabilities: null + DeviceCreation: false + Devices: null + Mounts: null + PropagatedMount: "/data" Env: - Name: "DEBUG" Description: "If set, prints debug messages" Settable: null - Value: "1" + Value: "0" Args: Name: "args" Description: "command line arguments" @@ -6366,74 +6331,39 @@ paths: $ref: "#/definitions/Plugin" example: - Id: "5724e2c8652da337ab2eedd19fc6fc0ec908e4bd907c7421bf6a8dfc70c4c078" - Name: "tiborvass/no-remove" + Name: "tiborvass/sample-volume-plugin" Tag: "latest" Active: true - Config: - Mounts: - - Name: "" - Description: "" - Settable: null - Source: "/data" - Destination: "/data" - Type: "bind" - Options: - - "shared" - - "rbind" - - Name: "" - Description: "" - Settable: null - Source: null - Destination: "/foobar" - Type: "tmpfs" - Options: null + Settings: Env: - - "DEBUG=1" + - "DEBUG=0" Args: null Devices: null - Manifest: - ManifestVersion: "v0" - Description: "A test plugin for Docker" + Config: + Description: "A sample volume plugin for Docker" Documentation: "https://docs.docker.com/engine/extend/plugins/" Interface: Types: - "docker.volumedriver/1.0" Socket: "plugins.sock" Entrypoint: - - "plugin-no-remove" + - "/usr/bin/sample-volume-plugin" - "/data" WorkDir: "" User: {} Network: - Type: "host" - Capabilities: null - Mounts: - - Name: "" - Description: "" - Settable: null - Source: "/data" - Destination: "/data" - Type: "bind" - Options: - - "shared" - - "rbind" - - Name: "" - Description: "" - Settable: null - Source: null - Destination: "/foobar" - Type: "tmpfs" - Options: null - Devices: - - Name: "device" - Description: "a host device to mount" - Settable: null - Path: "/dev/cpu_dma_latency" + Type: "" + Linux: + Capabilities: null + DeviceCreation: false + Devices: null + Mounts: null + PropagatedMount: "/data" Env: - Name: "DEBUG" Description: "If set, prints debug messages" Settable: null - Value: "1" + Value: "0" Args: Name: "args" Description: "command line arguments" diff --git a/docs/extend/config.md b/docs/extend/config.md index eca33803c2..538dc6ac47 100644 --- a/docs/extend/config.md +++ b/docs/extend/config.md @@ -171,52 +171,49 @@ Config provides the base accessible fields for working with V0 plugin format ## Example Config -*Example showing the 'tiborvass/no-remove' plugin config.* +*Example showing the 'tiborvass/sample-volume-plugin' plugin config.* ```json { - "description": "A test plugin for Docker", - "documentation": "https://docs.docker.com/engine/extend/plugins/", - "entrypoint": ["plugin-no-remove", "/data"], - "interface": { - "types": ["docker.volumedriver/1.0"], - "socket": "plugins.sock" - }, - "network": { - "type": "host" - }, - "mounts": [ - { - "source": "/data", - "destination": "/data", - "type": "bind", - "options": ["shared", "rbind"] - }, - { - "destination": "/foobar", - "type": "tmpfs" - } - ], - "args": { - "name": "args", - "description": "command line arguments", - "value": [] - }, - "env": [ - { - "name": "DEBUG", - "description": "If set, prints debug messages", - "value": "1" - } - ], - "linux": { - "devices": [ - { - "name": "device", - "description": "a host device to mount", - "path": "/dev/cpu_dma_latency" - } - ] - } + "Args": { + "Description": "", + "Name": "", + "Settable": null, + "Value": null + }, + "Description": "A sample volume plugin for Docker", + "Documentation": "https://docs.docker.com/engine/extend/plugins/", + "Entrypoint": [ + "/usr/bin/sample-volume-plugin", + "/data" + ], + "Env": [ + { + "Description": "", + "Name": "DEBUG", + "Settable": [ + "value" + ], + "Value": "0" + } + ], + "Interface": { + "Socket": "plugin.sock", + "Types": [ + "docker.volumedriver/1.0" + ] + }, + "Linux": { + "Capabilities": null, + "DeviceCreation": false, + "Devices": null + }, + "Mounts": null, + "Network": { + "Type": "" + }, + "PropagatedMount": "/data", + "User": {}, + "Workdir": "" } ``` diff --git a/docs/reference/commandline/events.md b/docs/reference/commandline/events.md index 24af2ab482..64c1536eaa 100644 --- a/docs/reference/commandline/events.md +++ b/docs/reference/commandline/events.md @@ -194,8 +194,8 @@ relative to the current time on the client machine: 2015-12-23T21:38:25.119625123Z network connect 8b111217944ba0ba844a65b13efcd57dc494932ee2527577758f939315ba2c5b (name=test-event-network-local, container=b4be644031a3d90b400f88ab3d4bdf4dc23adb250e696b6328b85441abe2c54e, type=bridge) $ docker events --filter 'type=plugin' (experimental) - 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) - 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) + 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) + 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) **Format:** diff --git a/docs/reference/commandline/plugin_disable.md b/docs/reference/commandline/plugin_disable.md index 66b0ca9466..f054fd066a 100644 --- a/docs/reference/commandline/plugin_disable.md +++ b/docs/reference/commandline/plugin_disable.md @@ -30,27 +30,27 @@ see [`docker plugin install`](plugin_install.md). Without the `-f` option, a plugin that has references (eg, volumes, networks) cannot be disabled. -The following example shows that the `no-remove` plugin is installed +The following example shows that the `sample-volume-plugin` plugin is installed and enabled: ```bash $ docker plugin ls -ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/sample-volume-plugin latest A test plugin for Docker true ``` To disable the plugin, use the following command: ```bash -$ docker plugin disable tiborvass/no-remove +$ docker plugin disable tiborvass/sample-volume-plugin -tiborvass/no-remove +tiborvass/sample-volume-plugin $ docker plugin ls -ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker false +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/sample-volume-plugin latest A test plugin for Docker false ``` ## Related information diff --git a/docs/reference/commandline/plugin_enable.md b/docs/reference/commandline/plugin_enable.md index 36fb7640ac..060592ef07 100644 --- a/docs/reference/commandline/plugin_enable.md +++ b/docs/reference/commandline/plugin_enable.md @@ -29,27 +29,27 @@ Enables a plugin. The plugin must be installed before it can be enabled, see [`docker plugin install`](plugin_install.md). -The following example shows that the `no-remove` plugin is installed, +The following example shows that the `sample-volume-plugin` plugin is installed, but disabled: ```bash $ docker plugin ls -ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker false +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/sample-volume-plugin latest A test plugin for Docker false ``` To enable the plugin, use the following command: ```bash -$ docker plugin enable tiborvass/no-remove +$ docker plugin enable tiborvass/sample-volume-plugin -tiborvass/no-remove +tiborvass/sample-volume-plugin $ docker plugin ls -ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/sample-volume-plugin latest A test plugin for Docker true ``` ## Related information diff --git a/docs/reference/commandline/plugin_inspect.md b/docs/reference/commandline/plugin_inspect.md index 01e231bf06..d40cd40e75 100644 --- a/docs/reference/commandline/plugin_inspect.md +++ b/docs/reference/commandline/plugin_inspect.md @@ -31,12 +31,12 @@ in a JSON array. Example output: ```bash -$ docker plugin inspect tiborvass/no-remove:latest +$ docker plugin inspect tiborvass/sample-volume-plugin:latest ``` ```JSON { "Id": "8c74c978c434745c3ade82f1bc0acf38d04990eaf494fa507c16d9f1daa99c21", - "Name": "tiborvass/no-remove:latest", + "Name": "tiborvass/sample-volume-plugin:latest", "Enabled": true, "Config": { "Mounts": [ @@ -79,7 +79,7 @@ $ docker plugin inspect tiborvass/no-remove:latest "Socket": "plugins.sock" }, "Entrypoint": [ - "plugin-no-remove", + "plugin-sample-volume-plugin", "/data" ], "Workdir": "", @@ -143,7 +143,7 @@ $ docker plugin inspect tiborvass/no-remove:latest ```bash -$ docker plugin inspect -f '{{.Id}}' tiborvass/no-remove:latest +$ docker plugin inspect -f '{{.Id}}' tiborvass/sample-volume-plugin:latest ``` ``` 8c74c978c434745c3ade82f1bc0acf38d04990eaf494fa507c16d9f1daa99c21 diff --git a/docs/reference/commandline/plugin_install.md b/docs/reference/commandline/plugin_install.md index 502eb441bf..78dd23825f 100644 --- a/docs/reference/commandline/plugin_install.md +++ b/docs/reference/commandline/plugin_install.md @@ -33,20 +33,20 @@ the registry. Note that the minimum required registry version to distribute plugins is 2.3.0 -The following example installs `no-remove` plugin and [set](plugin_set.md) it's env variable +The following example installs `vieus/sshfs` plugin and [set](plugin_set.md) it's env variable `DEBUG` to 1. Install consists of pulling the plugin from Docker Hub, prompting the user to accept the list of privileges that the plugin needs, settings parameters and enabling the plugin. ```bash -$ docker plugin install tiborvass/no-remove DEBUG=1 +$ docker plugin install vieux/sshfs DEBUG=1 -Plugin "tiborvass/no-remove" is requesting the following privileges: +Plugin "vieux/sshfs" is requesting the following privileges: - network: [host] - - mount: [/data] - - device: [/dev/cpu_dma_latency] + - device: [/dev/fuse] + - capabilities: [CAP_SYS_ADMIN] Do you grant the above permissions? [y/N] y -tiborvass/no-remove +vieux/sshfs ``` After the plugin is installed, it appears in the list of plugins: @@ -55,7 +55,7 @@ After the plugin is installed, it appears in the list of plugins: $ docker plugin ls ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true +69553ca1d123 vieux/sshfs latest sshFS plugin for Docker true ``` ## Related information diff --git a/docs/reference/commandline/plugin_ls.md b/docs/reference/commandline/plugin_ls.md index b727b53341..e436213ecc 100644 --- a/docs/reference/commandline/plugin_ls.md +++ b/docs/reference/commandline/plugin_ls.md @@ -36,8 +36,8 @@ Example output: ```bash $ docker plugin ls -ID NAME TAG DESCRIPTION ENABLED -69553ca1d123 tiborvass/no-remove latest A test plugin for Docker true +ID NAME TAG DESCRIPTION ENABLED +69553ca1d123 tiborvass/sample-volume-plugin latest A test plugin for Docker true ``` ## Related information diff --git a/docs/reference/commandline/plugin_rm.md b/docs/reference/commandline/plugin_rm.md index 5a01dcaa1e..31029324b6 100644 --- a/docs/reference/commandline/plugin_rm.md +++ b/docs/reference/commandline/plugin_rm.md @@ -33,14 +33,14 @@ a plugin using the [`docker plugin disable`](plugin_disable.md) before removing it (or use --force, use of force is not recommended, since it can affect functioning of running containers using the plugin). -The following example disables and removes the `no-remove:latest` plugin; +The following example disables and removes the `sample-volume-plugin:latest` plugin; ```bash -$ docker plugin disable tiborvass/no-remove -tiborvass/no-remove +$ docker plugin disable tiborvass/sample-volume-plugin +tiborvass/sample-volume-plugin -$ docker plugin rm tiborvass/no-remove:latest -tiborvass/no-remove +$ docker plugin rm tiborvass/sample-volume-plugin:latest +tiborvass/sample-volume-plugin ``` ## Related information diff --git a/docs/reference/commandline/plugin_set.md b/docs/reference/commandline/plugin_set.md index 9ea93aecf9..c206a8a760 100644 --- a/docs/reference/commandline/plugin_set.md +++ b/docs/reference/commandline/plugin_set.md @@ -33,15 +33,15 @@ The settings currently supported are: * args The following example change the env variable `DEBUG` on the -`no-remove` plugin. +`sample-volume-plugin` plugin. ```bash -$ docker plugin inspect -f {{.Settings.Env}} tiborvass/no-remove +$ docker plugin inspect -f {{.Settings.Env}} tiborvass/sample-volume-plugin [DEBUG=0] -$ docker plugin set tiborvass/no-remove DEBUG=1 +$ docker plugin set tiborvass/sample-volume-plugin DEBUG=1 -$ docker plugin inspect -f {{.Settings.Env}} tiborvass/no-remove +$ docker plugin inspect -f {{.Settings.Env}} tiborvass/sample-volume-plugin [DEBUG=1] ``` diff --git a/man/docker-events.1.md b/man/docker-events.1.md index c0909c6817..51b042775a 100644 --- a/man/docker-events.1.md +++ b/man/docker-events.1.md @@ -168,8 +168,8 @@ Lines. For information about JSON Lines, please refer to http://jsonlines.org/ . 2015-12-23T21:38:25.119625123Z network connect 8b111217944ba0ba844a65b13efcd57dc494932ee2527577758f939315ba2c5b (name=test-event-network-local, container=b4be644031a3d90b400f88ab3d4bdf4dc23adb250e696b6328b85441abe2c54e, type=bridge) $ docker events --filter 'type=plugin' (experimental) - 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) - 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) + 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) + 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) # HISTORY From a46dbbded906bc49ec58597375cca48d2922bbc5 Mon Sep 17 00:00:00 2001 From: Lei Jitang Date: Fri, 16 Dec 2016 20:57:05 -0500 Subject: [PATCH 26/26] Fix update clear the restart policy of monitor Signed-off-by: Lei Jitang (cherry picked from commit 737b5b1781da9d7f286bb2425720add0ff69e3e3) Signed-off-by: Victor Vieux Signed-off-by: Vincent Demeester --- daemon/update.go | 4 ++- .../docker_cli_update_unix_test.go | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/daemon/update.go b/daemon/update.go index 67c0e59bf1..6e26eeb96a 100644 --- a/daemon/update.go +++ b/daemon/update.go @@ -67,7 +67,9 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro } // if Restart Policy changed, we need to update container monitor - container.UpdateMonitor(hostConfig.RestartPolicy) + if hostConfig.RestartPolicy.Name != "" { + container.UpdateMonitor(hostConfig.RestartPolicy) + } // If container is not running, update hostConfig struct is enough, // resources will be updated when the container is started again. diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index fb695372f1..580ff02602 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -5,7 +5,10 @@ package main import ( "encoding/json" "fmt" + "github.com/kr/pty" + "os/exec" "strings" + "time" "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/integration/checker" @@ -250,3 +253,31 @@ func (s *DockerSuite) TestUpdateMemoryWithSwapMemory(c *check.C) { dockerCmd(c, "update", "--memory", "800M", "--memory-swap", "1000M", name) } + +func (s *DockerSuite) TestUpdateNotAffectMonitorRestartPolicy(c *check.C) { + testRequires(c, DaemonIsLinux, cpuShare) + + out, _ := dockerCmd(c, "run", "-tid", "--restart=always", "busybox", "sh") + id := strings.TrimSpace(string(out)) + dockerCmd(c, "update", "--cpu-shares", "512", id) + + cpty, tty, err := pty.Open() + c.Assert(err, checker.IsNil) + defer cpty.Close() + + cmd := exec.Command(dockerBinary, "attach", id) + cmd.Stdin = tty + + c.Assert(cmd.Start(), checker.IsNil) + defer cmd.Process.Kill() + + _, err = cpty.Write([]byte("exit\n")) + c.Assert(err, checker.IsNil) + + c.Assert(cmd.Wait(), checker.IsNil) + + // container should restart again and keep running + err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second) + c.Assert(err, checker.IsNil) + c.Assert(waitRun(id), checker.IsNil) +}