From 4a5cd1b31a416b342ccb7abd05c1d9eaa489fd7d Mon Sep 17 00:00:00 2001 From: Nicolas Degory Date: Wed, 7 Dec 2016 14:31:26 +0100 Subject: [PATCH] update vendors (huge diff) --- glide.lock | 4 +- vendor/github.com/blang/semver/LICENSE | 22 + vendor/github.com/blang/semver/README.md | 191 +++++++ .../github.com/blang/semver/examples/main.go | 83 +++ vendor/github.com/blang/semver/json.go | 23 + vendor/github.com/blang/semver/json_test.go | 45 ++ vendor/github.com/blang/semver/range.go | 233 +++++++++ vendor/github.com/blang/semver/range_test.go | 459 ++++++++++++++++ vendor/github.com/blang/semver/semver.go | 418 +++++++++++++++ vendor/github.com/blang/semver/semver_test.go | 458 ++++++++++++++++ vendor/github.com/blang/semver/sort.go | 28 + vendor/github.com/blang/semver/sort_test.go | 30 ++ vendor/github.com/blang/semver/sql.go | 30 ++ vendor/github.com/blang/semver/sql_test.go | 38 ++ vendor/github.com/docker/docker/CHANGELOG.md | 1 - .../docker/docker/Dockerfile.ppc64le | 4 + .../docker/docker/Dockerfile.windows | 188 +++++-- vendor/github.com/docker/docker/Makefile | 2 +- vendor/github.com/docker/docker/VERSION | 2 +- .../api/server/router/container/backend.go | 6 +- .../router/container/container_routes.go | 10 +- .../api/server/router/swarm/cluster_routes.go | 1 + .../github.com/docker/docker/api/swagger.yaml | 492 +++++++++--------- .../docker/docker/builder/builder.go | 4 +- .../docker/builder/dockerfile/dispatchers.go | 12 +- .../docker/builder/dockerfile/envVarTest | 228 ++++---- .../docker/builder/dockerfile/internals.go | 6 +- .../builder/dockerfile/parser/parser.go | 11 +- .../builder/dockerfile/parser/parser_test.go | 6 +- .../parser/testfile-line/Dockerfile | 4 + .../testfiles/brimstone-consuldock/Dockerfile | 2 + .../brimstone-docker-consul/Dockerfile | 4 + .../testfiles/continueIndent/Dockerfile | 7 +- .../parser/testfiles/continueIndent/result | 3 +- .../empty-line-after-escape/Dockerfile | 15 - .../testfiles/empty-line-after-escape/result | 3 - .../parser/testfiles/escapes/Dockerfile | 2 + .../docker/builder/dockerfile/shell_parser.go | 14 +- .../builder/dockerfile/shell_parser_test.go | 26 +- .../docker/docker/cli/command/node/ps.go | 7 - .../docker/cli/command/plugin/inspect.go | 21 +- .../docker/docker/cli/command/plugin/list.go | 7 +- .../docker/cli/command/secret/create.go | 4 +- .../docker/cli/command/secret/inspect.go | 2 +- .../docker/docker/cli/command/secret/ls.go | 7 +- .../docker/cli/command/secret/remove.go | 7 +- .../docker/docker/cli/command/service/ps.go | 8 - .../docker/docker/cli/command/stack/common.go | 2 +- .../docker/docker/cli/command/stack/deploy.go | 66 ++- .../docker/docker/cli/command/stack/remove.go | 2 +- .../docker/cli/command/system/inspect.go | 9 +- .../github.com/docker/docker/client/errors.go | 21 + .../docker/docker/client/plugin_inspect.go | 4 + .../docker/docker/container/stream/streams.go | 2 +- .../builder/rpm/amd64/fedora-23/Dockerfile | 1 + .../builder/rpm/amd64/fedora-24/Dockerfile | 1 + .../builder/rpm/amd64/fedora-25/Dockerfile | 1 + .../contrib/builder/rpm/amd64/generate.sh | 3 + .../docker/contrib/completion/bash/docker | 235 ++++++++- .../contrib/completion/fish/docker.fish | 2 - .../docker/contrib/completion/zsh/_docker | 159 +++++- .../docker/docker/daemon/cluster/cluster.go | 4 + .../daemon/cluster/convert/container.go | 16 +- .../docker/daemon/cluster/executor/backend.go | 4 +- .../cluster/executor/container/adapter.go | 16 +- .../github.com/docker/docker/daemon/commit.go | 5 + .../docker/docker/daemon/container.go | 21 +- .../github.com/docker/docker/daemon/create.go | 12 +- .../github.com/docker/docker/daemon/daemon.go | 39 +- .../github.com/docker/docker/daemon/links.go | 41 -- .../docker/docker/daemon/links_linux.go | 72 +++ .../{links_test.go => links_linux_test.go} | 0 .../docker/docker/daemon/links_notlinux.go | 10 + .../docker/docker/daemon/logger/logger.go | 2 +- .../docker/daemon/logger/logger_test.go | 26 + .../github.com/docker/docker/daemon/start.go | 4 +- .../github.com/docker/docker/daemon/update.go | 4 +- .../docker/docker/distribution/errors.go | 4 + .../docker/docker/distribution/pull_v2.go | 3 - .../docker/docker/distribution/push_v2.go | 6 +- .../docker/distribution/push_v2_test.go | 13 +- .../docker/docker/docs/api/v1.18.md | 108 ++-- .../docker/docker/docs/api/v1.19.md | 106 ++-- .../docker/docker/docs/api/v1.20.md | 114 ++-- .../docker/docker/docs/api/v1.21.md | 136 +++-- .../docker/docker/docs/api/v1.22.md | 140 +++-- .../docker/docker/docs/api/v1.23.md | 138 +++-- .../docker/docker/docs/api/v1.24.md | 265 +++++----- .../docker/docker/docs/api/version-history.md | 6 +- .../docker/docker/docs/deprecated.md | 2 +- .../docs/reference/commandline/create.md | 1 - .../docker/docs/reference/commandline/logs.md | 2 +- .../docs/reference/commandline/node_ps.md | 2 +- .../reference/commandline/plugin_inspect.md | 6 +- .../docs/reference/commandline/plugin_ls.md | 4 +- .../docker/docs/reference/commandline/run.md | 18 +- .../docs/reference/commandline/secret_ls.md | 4 +- .../reference/commandline/service_logs.md | 2 +- .../docs/reference/commandline/service_ps.md | 1 - .../docker/docker/docs/reference/glossary.md | 2 +- vendor/github.com/docker/docker/hack/make.ps1 | 401 ++++++++++++++ .../docker/docker/hack/make/.go-autogen.ps1 | 8 +- .../docker/docker/hack/validate/swagger-gen | 4 +- .../docker/docker/image/tarexport/save.go | 4 +- .../docker/integration-cli/daemon_swarm.go | 2 +- .../docker_api_containers_test.go | 26 +- .../integration-cli/docker_cli_build_test.go | 53 +- ...er_cli_external_volume_driver_unix_test.go | 28 + .../docker_cli_inspect_test.go | 30 ++ .../docker_cli_plugins_test.go | 49 ++ .../integration-cli/docker_cli_rename_test.go | 4 +- .../docker_cli_restart_test.go | 30 +- .../integration-cli/docker_cli_run_test.go | 214 -------- .../docker_cli_service_create_test.go | 5 +- .../integration-cli/docker_cli_swarm_test.go | 82 --- .../docker/libcontainerd/client_linux.go | 55 +- .../docker/libcontainerd/process_unix.go | 4 + .../docker/docker/man/docker-build.1.md | 2 +- .../docker/docker/man/docker-create.1.md | 1 - .../docker/docker/man/docker-login.1.md | 2 +- .../docker/docker/man/docker-pause.1.md | 2 +- .../docker/docker/man/docker-run.1.md | 1 - .../docker/docker/man/docker-unpause.1.md | 2 +- .../docker/docker/man/docker-version.1.md | 2 +- ...{conn_sqlite3.go => conn_sqlite3_linux.go} | 6 +- .../docker/pkg/graphdb/conn_sqlite3_unix.go | 7 - .../pkg/graphdb/conn_sqlite3_windows.go | 7 - .../docker/pkg/graphdb/conn_unsupported.go | 8 - .../graphdb/{graphdb.go => graphdb_linux.go} | 0 ...{graphdb_test.go => graphdb_linux_test.go} | 0 .../pkg/graphdb/{sort.go => sort_linux.go} | 0 .../{sort_test.go => sort_linux_test.go} | 0 .../docker/docker/pkg/graphdb/unsupported.go | 3 + .../pkg/graphdb/{utils.go => utils_linux.go} | 0 .../pkg/namesgenerator/names-generator.go | 59 ++- .../docker/docker/pkg/signal/trap.go | 20 +- .../docker/docker/plugin/backend_linux.go | 49 +- .../docker/docker/plugin/store/store.go | 29 ++ .../docker/docker/runconfig/opts/parse.go | 5 - vendor/github.com/docker/docker/vendor.conf | 4 +- .../github.com/docker/libnetwork/agent.go | 137 +++-- .../docker/libnetwork/controller.go | 11 +- .../drivers/overlay/ovmanager/ovmanager.go | 2 +- .../github.com/docker/libnetwork/idm/idm.go | 8 +- .../docker/libnetwork/iptables/iptables.go | 3 +- .../github.com/docker/libnetwork/network.go | 13 +- .../docker/libnetwork/networkdb/cluster.go | 6 + .../github.com/docker/libnetwork/resolver.go | 8 +- .../docker/libnetwork/service_common.go | 5 +- .../docker/libnetwork/service_linux.go | 2 +- .../agent/exec/controller_test.mock.go | 7 +- .../docker/swarmkit/agent/session.go | 20 +- .../docker/swarmkit/agent/worker.go | 4 +- .../github.com/docker/swarmkit/api/ca.pb.go | 133 +++-- .../github.com/docker/swarmkit/api/ca.proto | 1 + .../docker/swarmkit/ca/certificates.go | 108 ++-- .../github.com/docker/swarmkit/ca/config.go | 13 +- .../github.com/docker/swarmkit/ca/server.go | 10 +- .../networkallocator/networkallocator.go | 13 +- .../swarmkit/manager/state/raft/raft.go | 48 +- .../docker/docker/volume/store/store.go | 91 ++-- 161 files changed, 5001 insertions(+), 1895 deletions(-) create mode 100644 vendor/github.com/blang/semver/LICENSE create mode 100644 vendor/github.com/blang/semver/README.md create mode 100644 vendor/github.com/blang/semver/examples/main.go create mode 100644 vendor/github.com/blang/semver/json.go create mode 100644 vendor/github.com/blang/semver/json_test.go create mode 100644 vendor/github.com/blang/semver/range.go create mode 100644 vendor/github.com/blang/semver/range_test.go create mode 100644 vendor/github.com/blang/semver/semver.go create mode 100644 vendor/github.com/blang/semver/semver_test.go create mode 100644 vendor/github.com/blang/semver/sort.go create mode 100644 vendor/github.com/blang/semver/sort_test.go create mode 100644 vendor/github.com/blang/semver/sql.go create mode 100644 vendor/github.com/blang/semver/sql_test.go delete mode 100644 vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/Dockerfile delete mode 100644 vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/result create mode 100644 vendor/github.com/docker/docker/daemon/links_linux.go rename vendor/github.com/docker/docker/daemon/{links_test.go => links_linux_test.go} (100%) create mode 100644 vendor/github.com/docker/docker/daemon/links_notlinux.go create mode 100644 vendor/github.com/docker/docker/daemon/logger/logger_test.go create mode 100644 vendor/github.com/docker/docker/hack/make.ps1 rename vendor/github.com/docker/docker/pkg/graphdb/{conn_sqlite3.go => conn_sqlite3_linux.go} (75%) delete mode 100644 vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_unix.go delete mode 100644 vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_windows.go delete mode 100644 vendor/github.com/docker/docker/pkg/graphdb/conn_unsupported.go rename vendor/github.com/docker/docker/pkg/graphdb/{graphdb.go => graphdb_linux.go} (100%) rename vendor/github.com/docker/docker/pkg/graphdb/{graphdb_test.go => graphdb_linux_test.go} (100%) rename vendor/github.com/docker/docker/pkg/graphdb/{sort.go => sort_linux.go} (100%) rename vendor/github.com/docker/docker/pkg/graphdb/{sort_test.go => sort_linux_test.go} (100%) create mode 100644 vendor/github.com/docker/docker/pkg/graphdb/unsupported.go rename vendor/github.com/docker/docker/pkg/graphdb/{utils.go => utils_linux.go} (100%) diff --git a/glide.lock b/glide.lock index af90fbba8..b9a2e5669 100644 --- a/glide.lock +++ b/glide.lock @@ -20,7 +20,7 @@ imports: - digest - reference - name: github.com/docker/docker - version: 005a5428ee1b3f7f2efca2d761f27bd168356fa1 + version: 4d92237de1b34c8bf99e549db27b83fd087cd765 subpackages: - api/types - api/types/blkiodev @@ -49,6 +49,8 @@ imports: - tlsconfig - name: github.com/docker/go-units version: e30f1e79f3cd72542f2026ceec18d3bd67ab859c +- name: github.com/blang/semver + version: 60ec3488bfea7cca02b021d106d9911120d25fe9 - name: github.com/fatih/color version: dea9d3a26a087187530244679c1cfb3a42937794 - name: github.com/fatih/structs diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE new file mode 100644 index 000000000..5ba5c86fc --- /dev/null +++ b/vendor/github.com/blang/semver/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2014 Benedikt Lang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md new file mode 100644 index 000000000..4399639e2 --- /dev/null +++ b/vendor/github.com/blang/semver/README.md @@ -0,0 +1,191 @@ +semver for golang [![Build Status](https://drone.io/github.com/blang/semver/status.png)](https://drone.io/github.com/blang/semver/latest) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master) +====== + +semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. + +Usage +----- +```bash +$ go get github.com/blang/semver +``` +Note: Always vendor your dependencies or fix on a specific version tag. + +```go +import github.com/blang/semver +v1, err := semver.Make("1.0.0-beta") +v2, err := semver.Make("2.0.0-beta") +v1.Compare(v2) +``` + +Also check the [GoDocs](http://godoc.org/github.com/blang/semver). + +Why should I use this lib? +----- + +- Fully spec compatible +- No reflection +- No regex +- Fully tested (Coverage >99%) +- Readable parsing/validation errors +- Fast (See [Benchmarks](#benchmarks)) +- Only Stdlib +- Uses values instead of pointers +- Many features, see below + + +Features +----- + +- Parsing and validation at all levels +- Comparator-like comparisons +- Compare Helper Methods +- InPlace manipulation +- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1` +- Sortable (implements sort.Interface) +- database/sql compatible (sql.Scanner/Valuer) +- encoding/json compatible (json.Marshaler/Unmarshaler) + +Ranges +------ + +A `Range` is a set of conditions which specify which versions satisfy the range. + +A condition is composed of an operator and a version. The supported operators are: + +- `<1.0.0` Less than `1.0.0` +- `<=1.0.0` Less than or equal to `1.0.0` +- `>1.0.0` Greater than `1.0.0` +- `>=1.0.0` Greater than or equal to `1.0.0` +- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0` +- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`. + +A `Range` can link multiple `Ranges` separated by space: + +Ranges can be linked by logical AND: + + - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0` + - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2` + +Ranges can also be linked by logical OR: + + - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x` + +AND has a higher precedence than OR. It's not possible to use brackets. + +Ranges can be combined by both AND and OR + + - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` + +Range usage: + +``` +v, err := semver.Parse("1.2.3") +range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0") +if range(v) { + //valid +} + +``` + +Example +----- + +Have a look at full examples in [examples/main.go](examples/main.go) + +```go +import github.com/blang/semver + +v, err := semver.Make("0.0.1-alpha.preview+123.github") +fmt.Printf("Major: %d\n", v.Major) +fmt.Printf("Minor: %d\n", v.Minor) +fmt.Printf("Patch: %d\n", v.Patch) +fmt.Printf("Pre: %s\n", v.Pre) +fmt.Printf("Build: %s\n", v.Build) + +// Prerelease versions array +if len(v.Pre) > 0 { + fmt.Println("Prerelease versions:") + for i, pre := range v.Pre { + fmt.Printf("%d: %q\n", i, pre) + } +} + +// Build meta data array +if len(v.Build) > 0 { + fmt.Println("Build meta data:") + for i, build := range v.Build { + fmt.Printf("%d: %q\n", i, build) + } +} + +v001, err := semver.Make("0.0.1") +// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE +v001.GT(v) == true +v.LT(v001) == true +v.GTE(v) == true +v.LTE(v) == true + +// Or use v.Compare(v2) for comparisons (-1, 0, 1): +v001.Compare(v) == 1 +v.Compare(v001) == -1 +v.Compare(v) == 0 + +// Manipulate Version in place: +v.Pre[0], err = semver.NewPRVersion("beta") +if err != nil { + fmt.Printf("Error parsing pre release version: %q", err) +} + +fmt.Println("\nValidate versions:") +v.Build[0] = "?" + +err = v.Validate() +if err != nil { + fmt.Printf("Validation failed: %s\n", err) +} +``` + + +Benchmarks +----- + + BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op + BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op + BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op + BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op + BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op + BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op + BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op + BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op + BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op + BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op + BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op + BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op + BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op + BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op + BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op + BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op + BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op + BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op + BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op + BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op + +See benchmark cases at [semver_test.go](semver_test.go) + + +Motivation +----- + +I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like. + + +Contribution +----- + +Feel free to make a pull request. For bigger changes create a issue first to discuss about it. + + +License +----- + +See [LICENSE](LICENSE) file. diff --git a/vendor/github.com/blang/semver/examples/main.go b/vendor/github.com/blang/semver/examples/main.go new file mode 100644 index 000000000..f36c983d9 --- /dev/null +++ b/vendor/github.com/blang/semver/examples/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + "github.com/blang/semver" +) + +func main() { + v, err := semver.Parse("0.0.1-alpha.preview.222+123.github") + if err != nil { + fmt.Printf("Error while parsing (not valid): %q", err) + } + fmt.Printf("Version to string: %q\n", v) + + fmt.Printf("Major: %d\n", v.Major) + fmt.Printf("Minor: %d\n", v.Minor) + fmt.Printf("Patch: %d\n", v.Patch) + + // Prerelease versions + if len(v.Pre) > 0 { + fmt.Println("Prerelease versions:") + for i, pre := range v.Pre { + fmt.Printf("%d: %q\n", i, pre) + } + } + + // Build meta data + if len(v.Build) > 0 { + fmt.Println("Build meta data:") + for i, build := range v.Build { + fmt.Printf("%d: %q\n", i, build) + } + } + + // Make == Parse (Value), New for Pointer + v001, err := semver.Make("0.0.1") + + fmt.Println("\nUse Version.Compare for comparisons (-1, 0, 1):") + fmt.Printf("%q is greater than %q: Compare == %d\n", v001, v, v001.Compare(v)) + fmt.Printf("%q is less than %q: Compare == %d\n", v, v001, v.Compare(v001)) + fmt.Printf("%q is equal to %q: Compare == %d\n", v, v, v.Compare(v)) + + fmt.Println("\nUse comparison helpers returning booleans:") + fmt.Printf("%q is greater than %q: %t\n", v001, v, v001.GT(v)) + fmt.Printf("%q is greater than equal %q: %t\n", v001, v, v001.GTE(v)) + fmt.Printf("%q is greater than equal %q: %t\n", v, v, v.GTE(v)) + fmt.Printf("%q is less than %q: %t\n", v, v001, v.LT(v001)) + fmt.Printf("%q is less than equal %q: %t\n", v, v001, v.LTE(v001)) + fmt.Printf("%q is less than equal %q: %t\n", v, v, v.LTE(v)) + + fmt.Println("\nManipulate Version in place:") + v.Pre[0], err = semver.NewPRVersion("beta") + if err != nil { + fmt.Printf("Error parsing pre release version: %q", err) + } + fmt.Printf("Version to string: %q\n", v) + + fmt.Println("\nCompare Prerelease versions:") + pre1, _ := semver.NewPRVersion("123") + pre2, _ := semver.NewPRVersion("alpha") + pre3, _ := semver.NewPRVersion("124") + fmt.Printf("%q is less than %q: Compare == %d\n", pre1, pre2, pre1.Compare(pre2)) + fmt.Printf("%q is greater than %q: Compare == %d\n", pre3, pre1, pre3.Compare(pre1)) + fmt.Printf("%q is equal to %q: Compare == %d\n", pre1, pre1, pre1.Compare(pre1)) + + fmt.Println("\nValidate versions:") + v.Build[0] = "?" + + err = v.Validate() + if err != nil { + fmt.Printf("Validation failed: %s\n", err) + } + + fmt.Println("Create valid build meta data:") + b1, _ := semver.NewBuildVersion("build123") + v.Build[0] = b1 + fmt.Printf("Version with new build version %q\n", v) + + _, err = semver.NewBuildVersion("build?123") + if err != nil { + fmt.Printf("Create build version failed: %s\n", err) + } +} diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go new file mode 100644 index 000000000..a74bf7c44 --- /dev/null +++ b/vendor/github.com/blang/semver/json.go @@ -0,0 +1,23 @@ +package semver + +import ( + "encoding/json" +) + +// MarshalJSON implements the encoding/json.Marshaler interface. +func (v Version) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +// UnmarshalJSON implements the encoding/json.Unmarshaler interface. +func (v *Version) UnmarshalJSON(data []byte) (err error) { + var versionString string + + if err = json.Unmarshal(data, &versionString); err != nil { + return + } + + *v, err = Parse(versionString) + + return +} diff --git a/vendor/github.com/blang/semver/json_test.go b/vendor/github.com/blang/semver/json_test.go new file mode 100644 index 000000000..039117da9 --- /dev/null +++ b/vendor/github.com/blang/semver/json_test.go @@ -0,0 +1,45 @@ +package semver + +import ( + "encoding/json" + "strconv" + "testing" +) + +func TestJSONMarshal(t *testing.T) { + versionString := "3.1.4-alpha.1.5.9+build.2.6.5" + v, err := Parse(versionString) + if err != nil { + t.Fatal(err) + } + + versionJSON, err := json.Marshal(v) + if err != nil { + t.Fatal(err) + } + + quotedVersionString := strconv.Quote(versionString) + + if string(versionJSON) != quotedVersionString { + t.Fatalf("JSON marshaled semantic version not equal: expected %q, got %q", quotedVersionString, string(versionJSON)) + } +} + +func TestJSONUnmarshal(t *testing.T) { + versionString := "3.1.4-alpha.1.5.9+build.2.6.5" + quotedVersionString := strconv.Quote(versionString) + + var v Version + if err := json.Unmarshal([]byte(quotedVersionString), &v); err != nil { + t.Fatal(err) + } + + if v.String() != versionString { + t.Fatalf("JSON unmarshaled semantic version not equal: expected %q, got %q", versionString, v.String()) + } + + badVersionString := strconv.Quote("3.1.4.1.5.9.2.6.5-other-digits-of-pi") + if err := json.Unmarshal([]byte(badVersionString), &v); err == nil { + t.Fatal("expected JSON unmarshal error, got nil") + } +} diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go new file mode 100644 index 000000000..238e1312d --- /dev/null +++ b/vendor/github.com/blang/semver/range.go @@ -0,0 +1,233 @@ +package semver + +import ( + "fmt" + "strings" + "unicode" +) + +type comparator func(Version, Version) bool + +var ( + compEQ comparator = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == 0 + } + compNE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) != 0 + } + compGT = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == 1 + } + compGE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) >= 0 + } + compLT = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) == -1 + } + compLE = func(v1 Version, v2 Version) bool { + return v1.Compare(v2) <= 0 + } +) + +type versionRange struct { + v Version + c comparator +} + +// rangeFunc creates a Range from the given versionRange. +func (vr *versionRange) rangeFunc() Range { + return Range(func(v Version) bool { + return vr.c(v, vr.v) + }) +} + +// Range represents a range of versions. +// A Range can be used to check if a Version satisfies it: +// +// range, err := semver.ParseRange(">1.0.0 <2.0.0") +// range(semver.MustParse("1.1.1") // returns true +type Range func(Version) bool + +// OR combines the existing Range with another Range using logical OR. +func (rf Range) OR(f Range) Range { + return Range(func(v Version) bool { + return rf(v) || f(v) + }) +} + +// AND combines the existing Range with another Range using logical AND. +func (rf Range) AND(f Range) Range { + return Range(func(v Version) bool { + return rf(v) && f(v) + }) +} + +// ParseRange parses a range and returns a Range. +// If the range could not be parsed an error is returned. +// +// Valid ranges are: +// - "<1.0.0" +// - "<=1.0.0" +// - ">1.0.0" +// - ">=1.0.0" +// - "1.0.0", "=1.0.0", "==1.0.0" +// - "!1.0.0", "!=1.0.0" +// +// A Range can consist of multiple ranges separated by space: +// Ranges can be linked by logical AND: +// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0" +// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2 +// +// Ranges can also be linked by logical OR: +// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x" +// +// AND has a higher precedence than OR. It's not possible to use brackets. +// +// Ranges can be combined by both AND and OR +// +// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` +func ParseRange(s string) (Range, error) { + parts := splitAndTrim(s) + orParts, err := splitORParts(parts) + if err != nil { + return nil, err + } + var orFn Range + for _, p := range orParts { + var andFn Range + for _, ap := range p { + opStr, vStr, err := splitComparatorVersion(ap) + if err != nil { + return nil, err + } + vr, err := buildVersionRange(opStr, vStr) + if err != nil { + return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err) + } + rf := vr.rangeFunc() + + // Set function + if andFn == nil { + andFn = rf + } else { // Combine with existing function + andFn = andFn.AND(rf) + } + } + if orFn == nil { + orFn = andFn + } else { + orFn = orFn.OR(andFn) + } + + } + return orFn, nil +} + +// splitORParts splits the already cleaned parts by '||'. +// Checks for invalid positions of the operator and returns an +// error if found. +func splitORParts(parts []string) ([][]string, error) { + var ORparts [][]string + last := 0 + for i, p := range parts { + if p == "||" { + if i == 0 { + return nil, fmt.Errorf("First element in range is '||'") + } + ORparts = append(ORparts, parts[last:i]) + last = i + 1 + } + } + if last == len(parts) { + return nil, fmt.Errorf("Last element in range is '||'") + } + ORparts = append(ORparts, parts[last:]) + return ORparts, nil +} + +// buildVersionRange takes a slice of 2: operator and version +// and builds a versionRange, otherwise an error. +func buildVersionRange(opStr, vStr string) (*versionRange, error) { + c := parseComparator(opStr) + if c == nil { + return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, "")) + } + v, err := Parse(vStr) + if err != nil { + return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err) + } + + return &versionRange{ + v: v, + c: c, + }, nil + +} + +// splitAndTrim splits a range string by spaces and cleans leading and trailing spaces +func splitAndTrim(s string) (result []string) { + last := 0 + for i := 0; i < len(s); i++ { + if s[i] == ' ' { + if last < i-1 { + result = append(result, s[last:i]) + } + last = i + 1 + } + } + if last < len(s)-1 { + result = append(result, s[last:]) + } + // parts := strings.Split(s, " ") + // for _, x := range parts { + // if s := strings.TrimSpace(x); len(s) != 0 { + // result = append(result, s) + // } + // } + return +} + +// splitComparatorVersion splits the comparator from the version. +// Spaces between the comparator and the version are not allowed. +// Input must be free of leading or trailing spaces. +func splitComparatorVersion(s string) (string, string, error) { + i := strings.IndexFunc(s, unicode.IsDigit) + if i == -1 { + return "", "", fmt.Errorf("Could not get version from string: %q", s) + } + return strings.TrimSpace(s[0:i]), s[i:], nil +} + +func parseComparator(s string) comparator { + switch s { + case "==": + fallthrough + case "": + fallthrough + case "=": + return compEQ + case ">": + return compGT + case ">=": + return compGE + case "<": + return compLT + case "<=": + return compLE + case "!": + fallthrough + case "!=": + return compNE + } + + return nil +} + +// MustParseRange is like ParseRange but panics if the range cannot be parsed. +func MustParseRange(s string) Range { + r, err := ParseRange(s) + if err != nil { + panic(`semver: ParseRange(` + s + `): ` + err.Error()) + } + return r +} diff --git a/vendor/github.com/blang/semver/range_test.go b/vendor/github.com/blang/semver/range_test.go new file mode 100644 index 000000000..b895bee5c --- /dev/null +++ b/vendor/github.com/blang/semver/range_test.go @@ -0,0 +1,459 @@ +package semver + +import ( + "reflect" + "strings" + "testing" +) + +type comparatorTest struct { + input string + comparator func(comparator) bool +} + +func TestParseComparator(t *testing.T) { + compatorTests := []comparatorTest{ + {">", testGT}, + {">=", testGE}, + {"<", testLT}, + {"<=", testLE}, + {"", testEQ}, + {"=", testEQ}, + {"==", testEQ}, + {"!=", testNE}, + {"!", testNE}, + {"-", nil}, + {"<==", nil}, + {"<<", nil}, + {">>", nil}, + } + + for _, tc := range compatorTests { + if c := parseComparator(tc.input); c == nil { + if tc.comparator != nil { + t.Errorf("Comparator nil for case %q\n", tc.input) + } + } else if !tc.comparator(c) { + t.Errorf("Invalid comparator for case %q\n", tc.input) + } + } +} + +var ( + v1 = MustParse("1.2.2") + v2 = MustParse("1.2.3") + v3 = MustParse("1.2.4") +) + +func testEQ(f comparator) bool { + return f(v1, v1) && !f(v1, v2) +} + +func testNE(f comparator) bool { + return !f(v1, v1) && f(v1, v2) +} + +func testGT(f comparator) bool { + return f(v2, v1) && f(v3, v2) && !f(v1, v2) && !f(v1, v1) +} + +func testGE(f comparator) bool { + return f(v2, v1) && f(v3, v2) && !f(v1, v2) +} + +func testLT(f comparator) bool { + return f(v1, v2) && f(v2, v3) && !f(v2, v1) && !f(v1, v1) +} + +func testLE(f comparator) bool { + return f(v1, v2) && f(v2, v3) && !f(v2, v1) +} + +func TestSplitAndTrim(t *testing.T) { + tests := []struct { + i string + s []string + }{ + {"1.2.3 1.2.3", []string{"1.2.3", "1.2.3"}}, + {" 1.2.3 1.2.3 ", []string{"1.2.3", "1.2.3"}}, // Spaces + {"1.2.3 || >=1.2.3 <1.2.3", []string{"1.2.3", "||", ">=1.2.3", "<1.2.3"}}, + {" 1.2.3 || >=1.2.3 <1.2.3 ", []string{"1.2.3", "||", ">=1.2.3", "<1.2.3"}}, + } + + for _, tc := range tests { + p := splitAndTrim(tc.i) + if !reflect.DeepEqual(p, tc.s) { + t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.s, p) + } + } +} + +func TestSplitComparatorVersion(t *testing.T) { + tests := []struct { + i string + p []string + }{ + {">1.2.3", []string{">", "1.2.3"}}, + {">=1.2.3", []string{">=", "1.2.3"}}, + {"<1.2.3", []string{"<", "1.2.3"}}, + {"<=1.2.3", []string{"<=", "1.2.3"}}, + {"1.2.3", []string{"", "1.2.3"}}, + {"=1.2.3", []string{"=", "1.2.3"}}, + {"==1.2.3", []string{"==", "1.2.3"}}, + {"!=1.2.3", []string{"!=", "1.2.3"}}, + {"!1.2.3", []string{"!", "1.2.3"}}, + {"error", nil}, + } + for _, tc := range tests { + if op, v, err := splitComparatorVersion(tc.i); err != nil { + if tc.p != nil { + t.Errorf("Invalid for case %q: Expected %q, got error %q", tc.i, tc.p, err) + } + } else if op != tc.p[0] { + t.Errorf("Invalid operator for case %q: Expected %q, got: %q", tc.i, tc.p[0], op) + } else if v != tc.p[1] { + t.Errorf("Invalid version for case %q: Expected %q, got: %q", tc.i, tc.p[1], v) + } + + } +} + +func TestBuildVersionRange(t *testing.T) { + tests := []struct { + opStr string + vStr string + c func(comparator) bool + v string + }{ + {">", "1.2.3", testGT, "1.2.3"}, + {">=", "1.2.3", testGE, "1.2.3"}, + {"<", "1.2.3", testLT, "1.2.3"}, + {"<=", "1.2.3", testLE, "1.2.3"}, + {"", "1.2.3", testEQ, "1.2.3"}, + {"=", "1.2.3", testEQ, "1.2.3"}, + {"==", "1.2.3", testEQ, "1.2.3"}, + {"!=", "1.2.3", testNE, "1.2.3"}, + {"!", "1.2.3", testNE, "1.2.3"}, + {">>", "1.2.3", nil, ""}, // Invalid comparator + {"=", "invalid", nil, ""}, // Invalid version + } + + for _, tc := range tests { + if r, err := buildVersionRange(tc.opStr, tc.vStr); err != nil { + if tc.c != nil { + t.Errorf("Invalid for case %q: Expected %q, got error %q", strings.Join([]string{tc.opStr, tc.vStr}, ""), tc.v, err) + } + } else if r == nil { + t.Errorf("Invalid for case %q: got nil", strings.Join([]string{tc.opStr, tc.vStr}, "")) + } else { + // test version + if tv := MustParse(tc.v); !r.v.EQ(tv) { + t.Errorf("Invalid for case %q: Expected version %q, got: %q", strings.Join([]string{tc.opStr, tc.vStr}, ""), tv, r.v) + } + // test comparator + if r.c == nil { + t.Errorf("Invalid for case %q: got nil comparator", strings.Join([]string{tc.opStr, tc.vStr}, "")) + continue + } + if !tc.c(r.c) { + t.Errorf("Invalid comparator for case %q\n", strings.Join([]string{tc.opStr, tc.vStr}, "")) + } + } + } + +} + +func TestSplitORParts(t *testing.T) { + tests := []struct { + i []string + o [][]string + }{ + {[]string{">1.2.3", "||", "<1.2.3", "||", "=1.2.3"}, [][]string{ + []string{">1.2.3"}, + []string{"<1.2.3"}, + []string{"=1.2.3"}, + }}, + {[]string{">1.2.3", "<1.2.3", "||", "=1.2.3"}, [][]string{ + []string{">1.2.3", "<1.2.3"}, + []string{"=1.2.3"}, + }}, + {[]string{">1.2.3", "||"}, nil}, + {[]string{"||", ">1.2.3"}, nil}, + } + for _, tc := range tests { + o, err := splitORParts(tc.i) + if err != nil && tc.o != nil { + t.Errorf("Unexpected error for case %q: %s", tc.i, err) + } + if !reflect.DeepEqual(tc.o, o) { + t.Errorf("Invalid for case %q: Expected %q, got: %q", tc.i, tc.o, o) + } + } +} + +func TestVersionRangeToRange(t *testing.T) { + vr := versionRange{ + v: MustParse("1.2.3"), + c: compLT, + } + rf := vr.rangeFunc() + if !rf(MustParse("1.2.2")) || rf(MustParse("1.2.3")) { + t.Errorf("Invalid conversion to range func") + } +} + +func TestRangeAND(t *testing.T) { + v := MustParse("1.2.2") + v1 := MustParse("1.2.1") + v2 := MustParse("1.2.3") + rf1 := Range(func(v Version) bool { + return v.GT(v1) + }) + rf2 := Range(func(v Version) bool { + return v.LT(v2) + }) + rf := rf1.AND(rf2) + if rf(v1) { + t.Errorf("Invalid rangefunc, accepted: %s", v1) + } + if rf(v2) { + t.Errorf("Invalid rangefunc, accepted: %s", v2) + } + if !rf(v) { + t.Errorf("Invalid rangefunc, did not accept: %s", v) + } +} + +func TestRangeOR(t *testing.T) { + tests := []struct { + v Version + b bool + }{ + {MustParse("1.2.0"), true}, + {MustParse("1.2.2"), false}, + {MustParse("1.2.4"), true}, + } + v1 := MustParse("1.2.1") + v2 := MustParse("1.2.3") + rf1 := Range(func(v Version) bool { + return v.LT(v1) + }) + rf2 := Range(func(v Version) bool { + return v.GT(v2) + }) + rf := rf1.OR(rf2) + for _, tc := range tests { + if r := rf(tc.v); r != tc.b { + t.Errorf("Invalid for case %q: Expected %t, got %t", tc.v, tc.b, r) + } + } +} + +func TestParseRange(t *testing.T) { + type tv struct { + v string + b bool + } + tests := []struct { + i string + t []tv + }{ + // Simple expressions + {">1.2.3", []tv{ + {"1.2.2", false}, + {"1.2.3", false}, + {"1.2.4", true}, + }}, + {">=1.2.3", []tv{ + {"1.2.3", true}, + {"1.2.4", true}, + {"1.2.2", false}, + }}, + {"<1.2.3", []tv{ + {"1.2.2", true}, + {"1.2.3", false}, + {"1.2.4", false}, + }}, + {"<=1.2.3", []tv{ + {"1.2.2", true}, + {"1.2.3", true}, + {"1.2.4", false}, + }}, + {"1.2.3", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + }}, + {"=1.2.3", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + }}, + {"==1.2.3", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + }}, + {"!=1.2.3", []tv{ + {"1.2.2", true}, + {"1.2.3", false}, + {"1.2.4", true}, + }}, + {"!1.2.3", []tv{ + {"1.2.2", true}, + {"1.2.3", false}, + {"1.2.4", true}, + }}, + // Simple Expression errors + {">>1.2.3", nil}, + {"!1.2.3", nil}, + {"1.0", nil}, + {"string", nil}, + {"", nil}, + + // AND Expressions + {">1.2.2 <1.2.4", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + }}, + {"<1.2.2 <1.2.4", []tv{ + {"1.2.1", true}, + {"1.2.2", false}, + {"1.2.3", false}, + {"1.2.4", false}, + }}, + {">1.2.2 <1.2.5 !=1.2.4", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + {"1.2.5", false}, + }}, + {">1.2.2 <1.2.5 !1.2.4", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + {"1.2.5", false}, + }}, + // OR Expressions + {">1.2.2 || <1.2.4", []tv{ + {"1.2.2", true}, + {"1.2.3", true}, + {"1.2.4", true}, + }}, + {"<1.2.2 || >1.2.4", []tv{ + {"1.2.2", false}, + {"1.2.3", false}, + {"1.2.4", false}, + }}, + // Combined Expressions + {">1.2.2 <1.2.4 || >=2.0.0", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + {"2.0.0", true}, + {"2.0.1", true}, + }}, + {">1.2.2 <1.2.4 || >=2.0.0 <3.0.0", []tv{ + {"1.2.2", false}, + {"1.2.3", true}, + {"1.2.4", false}, + {"2.0.0", true}, + {"2.0.1", true}, + {"2.9.9", true}, + {"3.0.0", false}, + }}, + } + + for _, tc := range tests { + r, err := ParseRange(tc.i) + if err != nil && tc.t != nil { + t.Errorf("Error parsing range %q: %s", tc.i, err) + continue + } + for _, tvc := range tc.t { + v := MustParse(tvc.v) + if res := r(v); res != tvc.b { + t.Errorf("Invalid for case %q matching %q: Expected %t, got: %t", tc.i, tvc.v, tvc.b, res) + } + } + + } +} + +func TestMustParseRange(t *testing.T) { + testCase := ">1.2.2 <1.2.4 || >=2.0.0 <3.0.0" + r := MustParseRange(testCase) + if !r(MustParse("1.2.3")) { + t.Errorf("Unexpected range behavior on MustParseRange") + } +} + +func TestMustParseRange_panic(t *testing.T) { + defer func() { + if recover() == nil { + t.Errorf("Should have panicked") + } + }() + _ = MustParseRange("invalid version") +} + +func BenchmarkRangeParseSimple(b *testing.B) { + const VERSION = ">1.0.0" + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + ParseRange(VERSION) + } +} + +func BenchmarkRangeParseAverage(b *testing.B) { + const VERSION = ">=1.0.0 <2.0.0" + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + ParseRange(VERSION) + } +} + +func BenchmarkRangeParseComplex(b *testing.B) { + const VERSION = ">=1.0.0 <2.0.0 || >=3.0.1 <4.0.0 !=3.0.3 || >=5.0.0" + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + ParseRange(VERSION) + } +} + +func BenchmarkRangeMatchSimple(b *testing.B) { + const VERSION = ">1.0.0" + r, _ := ParseRange(VERSION) + v := MustParse("2.0.0") + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + r(v) + } +} + +func BenchmarkRangeMatchAverage(b *testing.B) { + const VERSION = ">=1.0.0 <2.0.0" + r, _ := ParseRange(VERSION) + v := MustParse("1.2.3") + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + r(v) + } +} + +func BenchmarkRangeMatchComplex(b *testing.B) { + const VERSION = ">=1.0.0 <2.0.0 || >=3.0.1 <4.0.0 !=3.0.3 || >=5.0.0" + r, _ := ParseRange(VERSION) + v := MustParse("5.0.1") + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + r(v) + } +} diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go new file mode 100644 index 000000000..8ee0842e6 --- /dev/null +++ b/vendor/github.com/blang/semver/semver.go @@ -0,0 +1,418 @@ +package semver + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +const ( + numbers string = "0123456789" + alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + alphanum = alphas + numbers +) + +// SpecVersion is the latest fully supported spec version of semver +var SpecVersion = Version{ + Major: 2, + Minor: 0, + Patch: 0, +} + +// Version represents a semver compatible version +type Version struct { + Major uint64 + Minor uint64 + Patch uint64 + Pre []PRVersion + Build []string //No Precendence +} + +// Version to string +func (v Version) String() string { + b := make([]byte, 0, 5) + b = strconv.AppendUint(b, v.Major, 10) + b = append(b, '.') + b = strconv.AppendUint(b, v.Minor, 10) + b = append(b, '.') + b = strconv.AppendUint(b, v.Patch, 10) + + if len(v.Pre) > 0 { + b = append(b, '-') + b = append(b, v.Pre[0].String()...) + + for _, pre := range v.Pre[1:] { + b = append(b, '.') + b = append(b, pre.String()...) + } + } + + if len(v.Build) > 0 { + b = append(b, '+') + b = append(b, v.Build[0]...) + + for _, build := range v.Build[1:] { + b = append(b, '.') + b = append(b, build...) + } + } + + return string(b) +} + +// Equals checks if v is equal to o. +func (v Version) Equals(o Version) bool { + return (v.Compare(o) == 0) +} + +// EQ checks if v is equal to o. +func (v Version) EQ(o Version) bool { + return (v.Compare(o) == 0) +} + +// NE checks if v is not equal to o. +func (v Version) NE(o Version) bool { + return (v.Compare(o) != 0) +} + +// GT checks if v is greater than o. +func (v Version) GT(o Version) bool { + return (v.Compare(o) == 1) +} + +// GTE checks if v is greater than or equal to o. +func (v Version) GTE(o Version) bool { + return (v.Compare(o) >= 0) +} + +// GE checks if v is greater than or equal to o. +func (v Version) GE(o Version) bool { + return (v.Compare(o) >= 0) +} + +// LT checks if v is less than o. +func (v Version) LT(o Version) bool { + return (v.Compare(o) == -1) +} + +// LTE checks if v is less than or equal to o. +func (v Version) LTE(o Version) bool { + return (v.Compare(o) <= 0) +} + +// LE checks if v is less than or equal to o. +func (v Version) LE(o Version) bool { + return (v.Compare(o) <= 0) +} + +// Compare compares Versions v to o: +// -1 == v is less than o +// 0 == v is equal to o +// 1 == v is greater than o +func (v Version) Compare(o Version) int { + if v.Major != o.Major { + if v.Major > o.Major { + return 1 + } + return -1 + } + if v.Minor != o.Minor { + if v.Minor > o.Minor { + return 1 + } + return -1 + } + if v.Patch != o.Patch { + if v.Patch > o.Patch { + return 1 + } + return -1 + } + + // Quick comparison if a version has no prerelease versions + if len(v.Pre) == 0 && len(o.Pre) == 0 { + return 0 + } else if len(v.Pre) == 0 && len(o.Pre) > 0 { + return 1 + } else if len(v.Pre) > 0 && len(o.Pre) == 0 { + return -1 + } + + i := 0 + for ; i < len(v.Pre) && i < len(o.Pre); i++ { + if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 { + continue + } else if comp == 1 { + return 1 + } else { + return -1 + } + } + + // If all pr versions are the equal but one has further prversion, this one greater + if i == len(v.Pre) && i == len(o.Pre) { + return 0 + } else if i == len(v.Pre) && i < len(o.Pre) { + return -1 + } else { + return 1 + } + +} + +// Validate validates v and returns error in case +func (v Version) Validate() error { + // Major, Minor, Patch already validated using uint64 + + for _, pre := range v.Pre { + if !pre.IsNum { //Numeric prerelease versions already uint64 + if len(pre.VersionStr) == 0 { + return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr) + } + if !containsOnly(pre.VersionStr, alphanum) { + return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr) + } + } + } + + for _, build := range v.Build { + if len(build) == 0 { + return fmt.Errorf("Build meta data can not be empty %q", build) + } + if !containsOnly(build, alphanum) { + return fmt.Errorf("Invalid character(s) found in build meta data %q", build) + } + } + + return nil +} + +// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error +func New(s string) (vp *Version, err error) { + v, err := Parse(s) + vp = &v + return +} + +// Make is an alias for Parse, parses version string and returns a validated Version or error +func Make(s string) (Version, error) { + return Parse(s) +} + +// ParseTolerant allows for certain version specifications that do not strictly adhere to semver +// specs to be parsed by this library. It does so by normalizing versions before passing them to +// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions +// with only major and minor components specified +func ParseTolerant(s string) (Version, error) { + s = strings.TrimSpace(s) + s = strings.TrimPrefix(s, "v") + + // Split into major.minor.(patch+pr+meta) + parts := strings.SplitN(s, ".", 3) + if len(parts) < 3 { + if strings.ContainsAny(parts[len(parts)-1], "+-") { + return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data") + } + for len(parts) < 3 { + parts = append(parts, "0") + } + s = strings.Join(parts, ".") + } + + return Parse(s) +} + +// Parse parses version string and returns a validated Version or error +func Parse(s string) (Version, error) { + if len(s) == 0 { + return Version{}, errors.New("Version string empty") + } + + // Split into major.minor.(patch+pr+meta) + parts := strings.SplitN(s, ".", 3) + if len(parts) != 3 { + return Version{}, errors.New("No Major.Minor.Patch elements found") + } + + // Major + if !containsOnly(parts[0], numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0]) + } + if hasLeadingZeroes(parts[0]) { + return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0]) + } + major, err := strconv.ParseUint(parts[0], 10, 64) + if err != nil { + return Version{}, err + } + + // Minor + if !containsOnly(parts[1], numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1]) + } + if hasLeadingZeroes(parts[1]) { + return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1]) + } + minor, err := strconv.ParseUint(parts[1], 10, 64) + if err != nil { + return Version{}, err + } + + v := Version{} + v.Major = major + v.Minor = minor + + var build, prerelease []string + patchStr := parts[2] + + if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 { + build = strings.Split(patchStr[buildIndex+1:], ".") + patchStr = patchStr[:buildIndex] + } + + if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 { + prerelease = strings.Split(patchStr[preIndex+1:], ".") + patchStr = patchStr[:preIndex] + } + + if !containsOnly(patchStr, numbers) { + return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr) + } + if hasLeadingZeroes(patchStr) { + return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr) + } + patch, err := strconv.ParseUint(patchStr, 10, 64) + if err != nil { + return Version{}, err + } + + v.Patch = patch + + // Prerelease + for _, prstr := range prerelease { + parsedPR, err := NewPRVersion(prstr) + if err != nil { + return Version{}, err + } + v.Pre = append(v.Pre, parsedPR) + } + + // Build meta data + for _, str := range build { + if len(str) == 0 { + return Version{}, errors.New("Build meta data is empty") + } + if !containsOnly(str, alphanum) { + return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str) + } + v.Build = append(v.Build, str) + } + + return v, nil +} + +// MustParse is like Parse but panics if the version cannot be parsed. +func MustParse(s string) Version { + v, err := Parse(s) + if err != nil { + panic(`semver: Parse(` + s + `): ` + err.Error()) + } + return v +} + +// PRVersion represents a PreRelease Version +type PRVersion struct { + VersionStr string + VersionNum uint64 + IsNum bool +} + +// NewPRVersion creates a new valid prerelease version +func NewPRVersion(s string) (PRVersion, error) { + if len(s) == 0 { + return PRVersion{}, errors.New("Prerelease is empty") + } + v := PRVersion{} + if containsOnly(s, numbers) { + if hasLeadingZeroes(s) { + return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s) + } + num, err := strconv.ParseUint(s, 10, 64) + + // Might never be hit, but just in case + if err != nil { + return PRVersion{}, err + } + v.VersionNum = num + v.IsNum = true + } else if containsOnly(s, alphanum) { + v.VersionStr = s + v.IsNum = false + } else { + return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s) + } + return v, nil +} + +// IsNumeric checks if prerelease-version is numeric +func (v PRVersion) IsNumeric() bool { + return v.IsNum +} + +// Compare compares two PreRelease Versions v and o: +// -1 == v is less than o +// 0 == v is equal to o +// 1 == v is greater than o +func (v PRVersion) Compare(o PRVersion) int { + if v.IsNum && !o.IsNum { + return -1 + } else if !v.IsNum && o.IsNum { + return 1 + } else if v.IsNum && o.IsNum { + if v.VersionNum == o.VersionNum { + return 0 + } else if v.VersionNum > o.VersionNum { + return 1 + } else { + return -1 + } + } else { // both are Alphas + if v.VersionStr == o.VersionStr { + return 0 + } else if v.VersionStr > o.VersionStr { + return 1 + } else { + return -1 + } + } +} + +// PreRelease version to string +func (v PRVersion) String() string { + if v.IsNum { + return strconv.FormatUint(v.VersionNum, 10) + } + return v.VersionStr +} + +func containsOnly(s string, set string) bool { + return strings.IndexFunc(s, func(r rune) bool { + return !strings.ContainsRune(set, r) + }) == -1 +} + +func hasLeadingZeroes(s string) bool { + return len(s) > 1 && s[0] == '0' +} + +// NewBuildVersion creates a new valid build version +func NewBuildVersion(s string) (string, error) { + if len(s) == 0 { + return "", errors.New("Buildversion is empty") + } + if !containsOnly(s, alphanum) { + return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s) + } + return s, nil +} diff --git a/vendor/github.com/blang/semver/semver_test.go b/vendor/github.com/blang/semver/semver_test.go new file mode 100644 index 000000000..b3e1fd43c --- /dev/null +++ b/vendor/github.com/blang/semver/semver_test.go @@ -0,0 +1,458 @@ +package semver + +import ( + "testing" +) + +func prstr(s string) PRVersion { + return PRVersion{s, 0, false} +} + +func prnum(i uint64) PRVersion { + return PRVersion{"", i, true} +} + +type formatTest struct { + v Version + result string +} + +var formatTests = []formatTest{ + {Version{1, 2, 3, nil, nil}, "1.2.3"}, + {Version{0, 0, 1, nil, nil}, "0.0.1"}, + {Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1-alpha.preview+123.456"}, + {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3-alpha.1+123.456"}, + {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3-alpha.1"}, + {Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3+123.456"}, + // Prereleases and build metadata hyphens + {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3-alpha.b-eta+123.b-uild"}, + {Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3+123.b-uild"}, + {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3-alpha.b-eta"}, +} + +var tolerantFormatTests = []formatTest{ + {Version{1, 2, 3, nil, nil}, "v1.2.3"}, + {Version{1, 2, 3, nil, nil}, " 1.2.3 "}, + {Version{1, 2, 0, nil, nil}, "1.2"}, + {Version{1, 0, 0, nil, nil}, "1"}, +} + +func TestStringer(t *testing.T) { + for _, test := range formatTests { + if res := test.v.String(); res != test.result { + t.Errorf("Stringer, expected %q but got %q", test.result, res) + } + } +} + +func TestParse(t *testing.T) { + for _, test := range formatTests { + if v, err := Parse(test.result); err != nil { + t.Errorf("Error parsing %q: %q", test.result, err) + } else if comp := v.Compare(test.v); comp != 0 { + t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp) + } else if err := v.Validate(); err != nil { + t.Errorf("Error validating parsed version %q: %q", test.v, err) + } + } +} + +func TestParseTolerant(t *testing.T) { + for _, test := range tolerantFormatTests { + if v, err := ParseTolerant(test.result); err != nil { + t.Errorf("Error parsing %q: %q", test.result, err) + } else if comp := v.Compare(test.v); comp != 0 { + t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp) + } else if err := v.Validate(); err != nil { + t.Errorf("Error validating parsed version %q: %q", test.v, err) + } + } +} + +func TestMustParse(t *testing.T) { + _ = MustParse("32.2.1-alpha") +} + +func TestMustParse_panic(t *testing.T) { + defer func() { + if recover() == nil { + t.Errorf("Should have panicked") + } + }() + _ = MustParse("invalid version") +} + +func TestValidate(t *testing.T) { + for _, test := range formatTests { + if err := test.v.Validate(); err != nil { + t.Errorf("Error validating %q: %q", test.v, err) + } + } +} + +type compareTest struct { + v1 Version + v2 Version + result int +} + +var compareTests = []compareTest{ + {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 0}, + {Version{2, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 1}, + {Version{0, 1, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 0}, + {Version{0, 2, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 1}, + {Version{0, 0, 1, nil, nil}, Version{0, 0, 1, nil, nil}, 0}, + {Version{0, 0, 2, nil, nil}, Version{0, 0, 1, nil, nil}, 1}, + {Version{1, 2, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 0}, + {Version{2, 2, 4, nil, nil}, Version{1, 2, 4, nil, nil}, 1}, + {Version{1, 3, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 1}, + {Version{1, 2, 4, nil, nil}, Version{1, 2, 3, nil, nil}, 1}, + + // Spec Examples #11 + {Version{1, 0, 0, nil, nil}, Version{2, 0, 0, nil, nil}, -1}, + {Version{2, 0, 0, nil, nil}, Version{2, 1, 0, nil, nil}, -1}, + {Version{2, 1, 0, nil, nil}, Version{2, 1, 1, nil, nil}, -1}, + + // Spec Examples #9 + {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, 1}, + {Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, -1}, + {Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, Version{1, 0, 0, nil, nil}, -1}, + + // Ignore Build metadata + {Version{1, 0, 0, nil, []string{"1", "2", "3"}}, Version{1, 0, 0, nil, nil}, 0}, +} + +func TestCompare(t *testing.T) { + for _, test := range compareTests { + if res := test.v1.Compare(test.v2); res != test.result { + t.Errorf("Comparing %q : %q, expected %d but got %d", test.v1, test.v2, test.result, res) + } + //Test counterpart + if res := test.v2.Compare(test.v1); res != -test.result { + t.Errorf("Comparing %q : %q, expected %d but got %d", test.v2, test.v1, -test.result, res) + } + } +} + +type wrongformatTest struct { + v *Version + str string +} + +var wrongformatTests = []wrongformatTest{ + {nil, ""}, + {nil, "."}, + {nil, "1."}, + {nil, ".1"}, + {nil, "a.b.c"}, + {nil, "1.a.b"}, + {nil, "1.1.a"}, + {nil, "1.a.1"}, + {nil, "a.1.1"}, + {nil, ".."}, + {nil, "1.."}, + {nil, "1.1."}, + {nil, "1..1"}, + {nil, "1.1.+123"}, + {nil, "1.1.-beta"}, + {nil, "-1.1.1"}, + {nil, "1.-1.1"}, + {nil, "1.1.-1"}, + // giant numbers + {nil, "20000000000000000000.1.1"}, + {nil, "1.20000000000000000000.1"}, + {nil, "1.1.20000000000000000000"}, + {nil, "1.1.1-20000000000000000000"}, + // Leading zeroes + {nil, "01.1.1"}, + {nil, "001.1.1"}, + {nil, "1.01.1"}, + {nil, "1.001.1"}, + {nil, "1.1.01"}, + {nil, "1.1.001"}, + {nil, "1.1.1-01"}, + {nil, "1.1.1-001"}, + {nil, "1.1.1-beta.01"}, + {nil, "1.1.1-beta.001"}, + {&Version{0, 0, 0, []PRVersion{prstr("!")}, nil}, "0.0.0-!"}, + {&Version{0, 0, 0, nil, []string{"!"}}, "0.0.0+!"}, + // empty prversion + {&Version{0, 0, 0, []PRVersion{prstr(""), prstr("alpha")}, nil}, "0.0.0-.alpha"}, + // empty build meta data + {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{""}}, "0.0.0-alpha+"}, + {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{"test", ""}}, "0.0.0-alpha+test."}, +} + +func TestWrongFormat(t *testing.T) { + for _, test := range wrongformatTests { + + if res, err := Parse(test.str); err == nil { + t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res) + } + + if test.v != nil { + if err := test.v.Validate(); err == nil { + t.Errorf("Validating wrong format version %q (%q), expected error", test.v, test.str) + } + } + } +} + +var wrongTolerantFormatTests = []wrongformatTest{ + {nil, "1.0+abc"}, + {nil, "1.0-rc.1"}, +} + +func TestWrongTolerantFormat(t *testing.T) { + for _, test := range wrongTolerantFormatTests { + if res, err := ParseTolerant(test.str); err == nil { + t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res) + } + } +} + +func TestCompareHelper(t *testing.T) { + v := Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil} + v1 := Version{1, 0, 0, nil, nil} + if !v.EQ(v) { + t.Errorf("%q should be equal to %q", v, v) + } + if !v.Equals(v) { + t.Errorf("%q should be equal to %q", v, v) + } + if !v1.NE(v) { + t.Errorf("%q should not be equal to %q", v1, v) + } + if !v.GTE(v) { + t.Errorf("%q should be greater than or equal to %q", v, v) + } + if !v.LTE(v) { + t.Errorf("%q should be less than or equal to %q", v, v) + } + if !v.LT(v1) { + t.Errorf("%q should be less than %q", v, v1) + } + if !v.LTE(v1) { + t.Errorf("%q should be less than or equal %q", v, v1) + } + if !v.LE(v1) { + t.Errorf("%q should be less than or equal %q", v, v1) + } + if !v1.GT(v) { + t.Errorf("%q should be greater than %q", v1, v) + } + if !v1.GTE(v) { + t.Errorf("%q should be greater than or equal %q", v1, v) + } + if !v1.GE(v) { + t.Errorf("%q should be greater than or equal %q", v1, v) + } +} + +func TestPreReleaseVersions(t *testing.T) { + p1, err := NewPRVersion("123") + if !p1.IsNumeric() { + t.Errorf("Expected numeric prversion, got %q", p1) + } + if p1.VersionNum != 123 { + t.Error("Wrong prversion number") + } + if err != nil { + t.Errorf("Not expected error %q", err) + } + p2, err := NewPRVersion("alpha") + if p2.IsNumeric() { + t.Errorf("Expected non-numeric prversion, got %q", p2) + } + if p2.VersionStr != "alpha" { + t.Error("Wrong prversion string") + } + if err != nil { + t.Errorf("Not expected error %q", err) + } +} + +func TestBuildMetaDataVersions(t *testing.T) { + _, err := NewBuildVersion("123") + if err != nil { + t.Errorf("Unexpected error %q", err) + } + + _, err = NewBuildVersion("build") + if err != nil { + t.Errorf("Unexpected error %q", err) + } + + _, err = NewBuildVersion("test?") + if err == nil { + t.Error("Expected error, got none") + } + + _, err = NewBuildVersion("") + if err == nil { + t.Error("Expected error, got none") + } +} + +func TestNewHelper(t *testing.T) { + v, err := New("1.2.3") + if err != nil { + t.Fatalf("Unexpected error %q", err) + } + + // New returns pointer + if v == nil { + t.Fatal("Version is nil") + } + if v.Compare(Version{1, 2, 3, nil, nil}) != 0 { + t.Fatal("Unexpected comparison problem") + } +} + +func TestMakeHelper(t *testing.T) { + v, err := Make("1.2.3") + if err != nil { + t.Fatalf("Unexpected error %q", err) + } + if v.Compare(Version{1, 2, 3, nil, nil}) != 0 { + t.Fatal("Unexpected comparison problem") + } +} + +func BenchmarkParseSimple(b *testing.B) { + const VERSION = "0.0.1" + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + Parse(VERSION) + } +} + +func BenchmarkParseComplex(b *testing.B) { + const VERSION = "0.0.1-alpha.preview+123.456" + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + Parse(VERSION) + } +} + +func BenchmarkParseAverage(b *testing.B) { + l := len(formatTests) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + Parse(formatTests[n%l].result) + } +} + +func BenchmarkParseTolerantAverage(b *testing.B) { + l := len(tolerantFormatTests) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + ParseTolerant(tolerantFormatTests[n%l].result) + } +} + +func BenchmarkStringSimple(b *testing.B) { + const VERSION = "0.0.1" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.String() + } +} + +func BenchmarkStringLarger(b *testing.B) { + const VERSION = "11.15.2012" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.String() + } +} + +func BenchmarkStringComplex(b *testing.B) { + const VERSION = "0.0.1-alpha.preview+123.456" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.String() + } +} + +func BenchmarkStringAverage(b *testing.B) { + l := len(formatTests) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + formatTests[n%l].v.String() + } +} + +func BenchmarkValidateSimple(b *testing.B) { + const VERSION = "0.0.1" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.Validate() + } +} + +func BenchmarkValidateComplex(b *testing.B) { + const VERSION = "0.0.1-alpha.preview+123.456" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.Validate() + } +} + +func BenchmarkValidateAverage(b *testing.B) { + l := len(formatTests) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + formatTests[n%l].v.Validate() + } +} + +func BenchmarkCompareSimple(b *testing.B) { + const VERSION = "0.0.1" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.Compare(v) + } +} + +func BenchmarkCompareComplex(b *testing.B) { + const VERSION = "0.0.1-alpha.preview+123.456" + v, _ := Parse(VERSION) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + v.Compare(v) + } +} + +func BenchmarkCompareAverage(b *testing.B) { + l := len(compareTests) + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + compareTests[n%l].v1.Compare((compareTests[n%l].v2)) + } +} diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go new file mode 100644 index 000000000..e18f88082 --- /dev/null +++ b/vendor/github.com/blang/semver/sort.go @@ -0,0 +1,28 @@ +package semver + +import ( + "sort" +) + +// Versions represents multiple versions. +type Versions []Version + +// Len returns length of version collection +func (s Versions) Len() int { + return len(s) +} + +// Swap swaps two versions inside the collection by its indices +func (s Versions) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Less checks if version at index i is less than version at index j +func (s Versions) Less(i, j int) bool { + return s[i].LT(s[j]) +} + +// Sort sorts a slice of versions +func Sort(versions []Version) { + sort.Sort(Versions(versions)) +} diff --git a/vendor/github.com/blang/semver/sort_test.go b/vendor/github.com/blang/semver/sort_test.go new file mode 100644 index 000000000..68893972a --- /dev/null +++ b/vendor/github.com/blang/semver/sort_test.go @@ -0,0 +1,30 @@ +package semver + +import ( + "reflect" + "testing" +) + +func TestSort(t *testing.T) { + v100, _ := Parse("1.0.0") + v010, _ := Parse("0.1.0") + v001, _ := Parse("0.0.1") + versions := []Version{v010, v100, v001} + Sort(versions) + + correct := []Version{v001, v010, v100} + if !reflect.DeepEqual(versions, correct) { + t.Fatalf("Sort returned wrong order: %s", versions) + } +} + +func BenchmarkSort(b *testing.B) { + v100, _ := Parse("1.0.0") + v010, _ := Parse("0.1.0") + v001, _ := Parse("0.0.1") + b.ReportAllocs() + b.ResetTimer() + for n := 0; n < b.N; n++ { + Sort([]Version{v010, v100, v001}) + } +} diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go new file mode 100644 index 000000000..eb4d80266 --- /dev/null +++ b/vendor/github.com/blang/semver/sql.go @@ -0,0 +1,30 @@ +package semver + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements the database/sql.Scanner interface. +func (v *Version) Scan(src interface{}) (err error) { + var str string + switch src := src.(type) { + case string: + str = src + case []byte: + str = string(src) + default: + return fmt.Errorf("Version.Scan: cannot convert %T to string.", src) + } + + if t, err := Parse(str); err == nil { + *v = t + } + + return +} + +// Value implements the database/sql/driver.Valuer interface. +func (v Version) Value() (driver.Value, error) { + return v.String(), nil +} diff --git a/vendor/github.com/blang/semver/sql_test.go b/vendor/github.com/blang/semver/sql_test.go new file mode 100644 index 000000000..ebf48b584 --- /dev/null +++ b/vendor/github.com/blang/semver/sql_test.go @@ -0,0 +1,38 @@ +package semver + +import ( + "testing" +) + +type scanTest struct { + val interface{} + shouldError bool + expected string +} + +var scanTests = []scanTest{ + {"1.2.3", false, "1.2.3"}, + {[]byte("1.2.3"), false, "1.2.3"}, + {7, true, ""}, + {7e4, true, ""}, + {true, true, ""}, +} + +func TestScanString(t *testing.T) { + for _, tc := range scanTests { + s := &Version{} + err := s.Scan(tc.val) + if tc.shouldError { + if err == nil { + t.Fatalf("Scan did not return an error on %v (%T)", tc.val, tc.val) + } + } else { + if err != nil { + t.Fatalf("Scan returned an unexpected error: %s (%T) on %v (%T)", tc.val, tc.val, tc.val, tc.val) + } + if val, _ := s.Value(); val != tc.expected { + t.Errorf("Wrong Value returned, expected %q, got %q", tc.expected, val) + } + } + } +} diff --git a/vendor/github.com/docker/docker/CHANGELOG.md b/vendor/github.com/docker/docker/CHANGELOG.md index b65ab4023..aca0eec18 100644 --- a/vendor/github.com/docker/docker/CHANGELOG.md +++ b/vendor/github.com/docker/docker/CHANGELOG.md @@ -99,7 +99,6 @@ be found. + Add `Isolation` to the /info endpoint [#26255](https://github.com/docker/docker/pull/26255) + Add `userns` to the /info endpoint [#27840](https://github.com/docker/docker/pull/27840) - Do not allow more than one mode be requested at once in the services endpoint [#26643](https://github.com/docker/docker/pull/26643) -+ Add `--mount` flag to `docker create` and `docker run` [#26825](https://github.com/docker/docker/pull/26825)[#28150](https://github.com/docker/docker/pull/28150) + Add capability to /containers/create API to specify mounts in a more granular and safer way [#22373](https://github.com/docker/docker/pull/22373) + Add `--format` flag to `network ls` and `volume ls` [#23475](https://github.com/docker/docker/pull/23475) * Allow the top-level `docker inspect` command to inspect any kind of resource [#23614](https://github.com/docker/docker/pull/23614) diff --git a/vendor/github.com/docker/docker/Dockerfile.ppc64le b/vendor/github.com/docker/docker/Dockerfile.ppc64le index 3f550d180..bf1e539d1 100644 --- a/vendor/github.com/docker/docker/Dockerfile.ppc64le +++ b/vendor/github.com/docker/docker/Dockerfile.ppc64le @@ -18,6 +18,10 @@ # ppc64le/golang is a debian:jessie based image with golang installed FROM ppc64le/golang:1.6.3 +# allow replacing httpredir or deb mirror +ARG APT_MIRROR=deb.debian.org +RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list + # Packaged dependencies RUN apt-get update && apt-get install -y \ apparmor \ diff --git a/vendor/github.com/docker/docker/Dockerfile.windows b/vendor/github.com/docker/docker/Dockerfile.windows index 75c03fc44..c6e897b7c 100644 --- a/vendor/github.com/docker/docker/Dockerfile.windows +++ b/vendor/github.com/docker/docker/Dockerfile.windows @@ -2,7 +2,7 @@ # ----------------------------------------------------------------------------------------- # This file describes the standard way to build Docker in a container on Windows -# Server 2016. +# Server 2016 or Windows 10. # # Maintainer: @jhowardmsft # ----------------------------------------------------------------------------------------- @@ -11,21 +11,25 @@ # Prerequisites: # -------------- # -# 1. Windows Server 2016 with all Windows updates applied. Pre-release versions -# of Windows are not supported (eg Windows Server 2016 TP5). The build number -# must be at least 14393. This can be confirmed, for example, by running the -# following from an elevated PowerShell prompt - this sample output is from a -# fully up to date machine as at late October 2016: +# 1. Windows Server 2016 or Windows 10 with all Windows updates applied. The major +# build number must be at least 14393. This can be confirmed, for example, by +# running the following from an elevated PowerShell prompt - this sample output +# is from a fully up to date machine as at mid-November 2016: # # >> PS C:\> $(gin).WindowsBuildLabEx -# >> 14393.321.amd64fre.rs1_release_inmarket.161004-2338 +# >> 14393.447.amd64fre.rs1_release_inmarket.161102-0100 # # 2. Git for Windows (or another git client) must be installed. https://git-scm.com/download/win. # # 3. The machine must be configured to run containers. For example, by following # the quick start guidance at https://msdn.microsoft.com/en-us/virtualization/windowscontainers/quick_start/quick_start or # https://github.com/docker/labs/blob/master/windows/windows-containers/Setup.md - +# +# 4. If building in a Hyper-V VM: For Windows Server 2016 using Windows Server +# containers as the default option, it is recommended you have at least 1GB +# of memory assigned; For Windows 10 where Hyper-V Containers are employed, you +# should have at least 4GB of memory assigned. Note also, to run Hyper-V +# containers in a VM, it is necessary to configure the VM for nested virtualization. # ----------------------------------------------------------------------------------------- @@ -63,18 +67,16 @@ # >> docker build -t nativebuildimage -f Dockerfile.windows . # # -# 4. Build the docker executable binaries in a container: +# 4. Build the docker executable binaries: # -# >> docker run --name binaries nativebuildimage sh -c 'cd /c/go/src/github.com/docker/docker; hack/make.sh binary' +# >> docker run --name binaries nativebuildimage hack\make.ps1 -Binary # # -# 5. Copy the binaries out of the above container, replacing HostPath with an appropriate destination +# 5. Copy the binaries out of the container, replacing HostPath with an appropriate destination # folder on the host system where you want the binaries to be located. # -# >> $v=$(Get-Content ".\VERSION" -raw).ToString().Replace("`n","").Trim() -# >> docker cp binaries:C:\go\src\github.com\docker\docker\bundles\$v\binary-client\docker-$v.exe C:\HostPath\docker.exe -# >> docker cp binaries:C:\go\src\github.com\docker\docker\bundles\$v\binary-daemon\dockerd.exe C:\HostPath\dockerd.exe -# >> docker cp binaries:C:\go\src\github.com\docker\docker\bundles\$v\binary-daemon\docker-proxy-$v.exe C:\HostPath\docker-proxy.exe +# >> docker cp binaries:C:\go\src\github.com\docker\docker\bundles\docker.exe C:\HostPath\docker.exe +# >> docker cp binaries:C:\go\src\github.com\docker\docker\bundles\dockerd.exe C:\HostPath\dockerd.exe # # # 6. (Optional) Remove the interim container holding the built executable binaries: @@ -88,6 +90,39 @@ # image which has all the components required to build the binaries already installed. # # >> docker rmi nativebuildimage +# + +# ----------------------------------------------------------------------------------------- + + +# The validation tests can either run in a container, or directly on the host. To run in a +# container, ensure you have created the nativebuildimage above. Then run the following +# from an (elevated) Windows PowerShell prompt: +# +# >> docker run --rm nativebuildimage hack\make.ps1 -DCO -PkgImports -GoFormat + +# To run the validation tests on the host, from the root of the repository, run the +# following from a Windows PowerShell prompt (elevation is not required): (Note Go +# must be installed to run these tests) +# +# >> hack\make.ps1 -DCO -PkgImports -GoFormat + +# ----------------------------------------------------------------------------------------- + + +# To run unit tests, ensure you have created the nativebuildimage above. Then run the +# following from an (elevated) Windows PowerShell prompt: +# +# >> docker run --rm nativebuildimage hack\make.ps1 -TestUnit + + +# ----------------------------------------------------------------------------------------- + + +# To run all tests and binary build, ensure you have created the nativebuildimage above. Then +# run the following from an (elevated) Windows PowerShell prompt: +# +# >> docker run nativebuildimage hack\make.ps1 -All # ----------------------------------------------------------------------------------------- @@ -96,28 +131,26 @@ # Important notes: # --------------- # -# The posix utilities from git aren't usable interactively as at October 2016. This -# is because they require a console window which isn't present in a container in Windows. -# See the example at the top of this file. Do NOT use -it in that docker run. It will not work. +# Don't attempt to use a bind-mount to pass a local directory as the bundles target +# directory. It does not work (golang attempts for follow a mapped folder incorrectly). +# Instead, use docker cp as per the example. # -# Don't attempt to use a volume for passing the source through to the container. The posix utilities will -# balk at reparse points. +# go.zip is not removed from the image as it is used by the Windows CI servers +# to ensure the host and image are running consistent versions of go. # -# The downloaded files are not cleared from the image. go.zip is used by the Windows -# CI servers to ensure the host and image are running consistent versions of go. +# Nanoserver support is a work in progress. Although the image will build if the +# FROM statement is updated, it will not work when running autogen through hack\make.ps1. +# It is suspected that the required GCC utilities (eg gcc, windres, windmc) silently +# quit due to the use of console hooks which are not available. # -# The GIT installer isn't very good at unattended install. We use techniques described -# at the links below to force it to set the path and other options accordingly. -# >> http://superuser.com/questions/944576/git-for-windows-silent-install-silent-arguments -# and follow through to installer at -# >> https://github.com/ferventcoder/chocolatey-packages/blob/master/automatic/git.install/tools/chocolateyInstall.ps1 +# The docker integration tests do not currently run in a container on Windows, predominantly +# due to Windows not supporting privileged mode, so anything using a volume would fail. +# They (along with the rest of the docker CI suite) can be run using +# https://github.com/jhowardmsft/docker-w2wCIScripts/blob/master/runCI/Invoke-DockerCI.ps1. # -# As of October 2016, this does not work on Windows 10 client, just Windows Server 2016, -# and only with the default isolation mode (process). It does not work with isolation mode -# set to Hyper-V containers (hyperv). - # ----------------------------------------------------------------------------------------- + # The number of build steps below are explicitly minimised to improve performance. FROM microsoft/windowsservercore @@ -128,55 +161,102 @@ SHELL ["powershell", "-command"] # - GO_VERSION must be consistent with 'Dockerfile' used by Linux. # - FROM_DOCKERFILE is used for detection of building within a container. ENV GO_VERSION=1.7.3 ` - GIT_LOCATION=https://github.com/git-for-windows/git/releases/download/v2.10.1.windows.1/Git-2.10.1-64-bit.exe ` + GIT_VERSION=2.10.2 ` GOPATH=C:\go ` FROM_DOCKERFILE=1 -WORKDIR C:\ - RUN ` - setx /M Path $($Env:PATH+';C:\gcc\bin;C:\go\bin'); ` - ` $ErrorActionPreference = 'Stop'; ` + $ProgressPreference = 'SilentlyContinue'; ` + ` + Function Test-Nano() { ` + $EditionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID').EditionId; ` + return (($EditionId -eq 'ServerStandardNano') -or ($EditionId -eq 'ServerDataCenterNano') -or ($EditionId -eq 'NanoServer')); ` + }` + ` Function Download-File([string] $source, [string] $target) { ` - $wc = New-Object net.webclient; $wc.Downloadfile($source, $target) ` + if (Test-Nano) { ` + $handler = New-Object System.Net.Http.HttpClientHandler; ` + $client = New-Object System.Net.Http.HttpClient($handler); ` + $client.Timeout = New-Object System.TimeSpan(0, 30, 0); ` + $cancelTokenSource = [System.Threading.CancellationTokenSource]::new(); ` + $responseMsg = $client.GetAsync([System.Uri]::new($source), $cancelTokenSource.Token); ` + $responseMsg.Wait(); ` + if (!$responseMsg.IsCanceled) { ` + $response = $responseMsg.Result; ` + if ($response.IsSuccessStatusCode) { ` + $downloadedFileStream = [System.IO.FileStream]::new($target, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write); ` + $copyStreamOp = $response.Content.CopyToAsync($downloadedFileStream); ` + $copyStreamOp.Wait(); ` + $downloadedFileStream.Close(); ` + if ($copyStreamOp.Exception -ne $null) { throw $copyStreamOp.Exception } ` + } ` + } else { ` + Throw ("Failed to download " + $source) ` + }` + } else { ` + $webClient = New-Object System.Net.WebClient; ` + $webClient.DownloadFile($source, $target); ` + } ` } ` ` + setx /M PATH $('C:\git\bin;C:\git\usr\bin;'+$Env:PATH+';C:\gcc\bin;C:\go\bin'); ` + ` Write-Host INFO: Downloading git...; ` - Download-File $Env:GIT_LOCATION gitsetup.exe; ` + $location='https://github.com/git-for-windows/git/releases/download/v'+$env:GIT_VERSION+'.windows.1/PortableGit-'+$env:GIT_VERSION+'-64-bit.7z.exe'; ` + Download-File $location C:\gitsetup.7z.exe; ` ` Write-Host INFO: Downloading go...; ` - Download-File $('https://golang.org/dl/go'+$Env:GO_VERSION+'.windows-amd64.zip') go.zip; ` + Download-File $('https://golang.org/dl/go'+$Env:GO_VERSION+'.windows-amd64.zip') C:\go.zip; ` ` Write-Host INFO: Downloading compiler 1 of 3...; ` - Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/gcc.zip gcc.zip; ` + Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/gcc.zip C:\gcc.zip; ` ` Write-Host INFO: Downloading compiler 2 of 3...; ` - Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/runtime.zip runtime.zip; ` + Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/runtime.zip C:\runtime.zip; ` ` Write-Host INFO: Downloading compiler 3 of 3...; ` - Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/binutils.zip binutils.zip; ` + Download-File https://raw.githubusercontent.com/jhowardmsft/docker-tdmgcc/master/binutils.zip C:\binutils.zip; ` ` - Write-Host INFO: Installing git...; ` - $installPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'; ` - $installItem = 'Git_is1'; ` - New-Item -Path $installPath -Name $installItem -Force; ` - $installKey = $installPath+'\'+$installItem; ` - New-ItemProperty $installKey -Name 'Inno Setup CodeFile: Path Option' -Value 'CmdTools' -PropertyType 'String' -Force; ` - New-ItemProperty $installKey -Name 'Inno Setup CodeFile: Bash Terminal Option' -Value 'ConHost' -PropertyType 'String' -Force; ` - New-ItemProperty $installKey -Name 'Inno Setup CodeFile: CRLF Option' -Value 'CRLFCommitAsIs' -PropertyType 'String' -Force; ` - Start-Process gitsetup.exe -ArgumentList '/VERYSILENT /SUPPRESSMSGBOXES /CLOSEAPPLICATIONS /DIR=C:\git\' -Wait; ` + Write-Host INFO: Installing PS7Zip package...; ` + Install-Package PS7Zip -Force | Out-Null; ` + Write-Host INFO: Importing PS7Zip...; ` + Import-Module PS7Zip -Force; ` + New-Item C:\git -ItemType Directory | Out-Null ; ` + cd C:\git; ` + Write-Host INFO: Extracting git...; ` + Expand-7Zip C:\gitsetup.7z.exe | Out-Null; ` + cd C:\; ` ` Write-Host INFO: Expanding go...; ` Expand-Archive C:\go.zip -DestinationPath C:\; ` ` - Write-Host INFO: Expanding compiler...; ` + Write-Host INFO: Expanding compiler 1 of 3...; ` Expand-Archive C:\gcc.zip -DestinationPath C:\gcc -Force; ` + Write-Host INFO: Expanding compiler 2 of 3...; ` Expand-Archive C:\runtime.zip -DestinationPath C:\gcc -Force; ` + Write-Host INFO: Expanding compiler 3 of 3...; ` Expand-Archive C:\binutils.zip -DestinationPath C:\gcc -Force; ` ` + Write-Host INFO: Removing downloaded files...; ` + Remove-Item C:\gcc.zip; ` + Remove-Item C:\runtime.zip; ` + Remove-Item C:\binutils.zip; ` + Remove-Item C:\gitsetup.7z.exe; ` + ` + Write-Host INFO: Creating source directory...; ` + New-Item -ItemType Directory -Path C:\go\src\github.com\docker\docker | Out-Null; ` + ` + Write-Host INFO: Configuring git core.autocrlf...; ` + C:\git\bin\git config --global core.autocrlf true; ` + ` Write-Host INFO: Completed -# Prepare for building -COPY . C:\go\src\github.com\docker\docker +# Make PowerShell the default entrypoint +ENTRYPOINT ["powershell.exe"] + +# Set the working directory to the location of the sources +WORKDIR C:\go\src\github.com\docker\docker +# Copy the sources into the container +COPY . . diff --git a/vendor/github.com/docker/docker/Makefile b/vendor/github.com/docker/docker/Makefile index 31d1fa44c..81bde6b4f 100644 --- a/vendor/github.com/docker/docker/Makefile +++ b/vendor/github.com/docker/docker/Makefile @@ -144,4 +144,4 @@ swagger-gen: -w /go/src/github.com/docker/docker \ --entrypoint hack/generate-swagger-api.sh \ -e GOPATH=/go \ - quay.io/goswagger/swagger + quay.io/goswagger/swagger:0.7.4 diff --git a/vendor/github.com/docker/docker/VERSION b/vendor/github.com/docker/docker/VERSION index 042dcfed2..5c71d9db9 100644 --- a/vendor/github.com/docker/docker/VERSION +++ b/vendor/github.com/docker/docker/VERSION @@ -1 +1 @@ -1.13.0-rc2 +1.13.0-rc3 diff --git a/vendor/github.com/docker/docker/api/server/router/container/backend.go b/vendor/github.com/docker/docker/api/server/router/container/backend.go index 0c9f08147..5b4134eba 100644 --- a/vendor/github.com/docker/docker/api/server/router/container/backend.go +++ b/vendor/github.com/docker/docker/api/server/router/container/backend.go @@ -32,17 +32,17 @@ type copyBackend interface { // stateBackend includes functions to implement to provide container state lifecycle functionality. type stateBackend interface { - ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (container.ContainerCreateCreatedBody, error) + ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) ContainerKill(name string, sig uint64) error ContainerPause(name string) error ContainerRename(oldName, newName string) error ContainerResize(name string, height, width int) error ContainerRestart(name string, seconds *int) error ContainerRm(name string, config *types.ContainerRmConfig) error - ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error + ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error ContainerStop(name string, seconds *int) error ContainerUnpause(name string) error - ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) (container.ContainerUpdateOKBody, error) + ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error) ContainerWait(name string, timeout time.Duration) (int, error) } diff --git a/vendor/github.com/docker/docker/api/server/router/container/container_routes.go b/vendor/github.com/docker/docker/api/server/router/container/container_routes.go index b4eacbc81..18bc50bca 100644 --- a/vendor/github.com/docker/docker/api/server/router/container/container_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/container/container_routes.go @@ -156,8 +156,7 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon checkpoint := r.Form.Get("checkpoint") checkpointDir := r.Form.Get("checkpoint-dir") - validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") - if err := s.backend.ContainerStart(vars["name"], hostConfig, validateHostname, checkpoint, checkpointDir); err != nil { + if err := s.backend.ContainerStart(vars["name"], hostConfig, checkpoint, checkpointDir); err != nil { return err } @@ -332,7 +331,6 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon return err } - version := httputils.VersionFromContext(ctx) var updateConfig container.UpdateConfig decoder := json.NewDecoder(r.Body) @@ -346,8 +344,7 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon } name := vars["name"] - validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") - resp, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname) + resp, err := s.backend.ContainerUpdate(name, hostConfig) if err != nil { return err } @@ -372,14 +369,13 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo version := httputils.VersionFromContext(ctx) adjustCPUShares := versions.LessThan(version, "1.19") - validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{ Name: name, Config: config, HostConfig: hostConfig, NetworkingConfig: networkingConfig, AdjustCPUShares: adjustCPUShares, - }, validateHostname) + }) if err != nil { return err } diff --git a/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go b/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go index cb4ae3a7b..fe976434b 100644 --- a/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go @@ -383,6 +383,7 @@ func (sr *swarmRouter) removeSecret(ctx context.Context, w http.ResponseWriter, if err := sr.backend.RemoveSecret(vars["id"]); err != nil { return err } + w.WriteHeader(http.StatusNoContent) return nil } diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index d5e55718b..f3f0f4b66 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -1,3 +1,14 @@ +# A Swagger 2.0 (a.k.a. OpenAPI) definition of the Engine API. +# +# This is used for generating API documentation and the types used by the +# client/server. See api/README.md for more information. +# +# Some style notes: +# - This file is used by ReDoc, which allows GitHub Flavored Markdown in +# descriptions. +# - There is no maximum line length, for ease of editing and pretty diffs. +# - operationIds are in the format "NounVerb", with a singular noun. + swagger: "2.0" schemes: - "http" @@ -45,13 +56,13 @@ info: Docker version | API version | Changes ----------------|-------------|--------- - 1.12.x | [1.24](/engine/api/v1.24/) | [API changes](/engine/api/version-history/#v1-24-api-changes) - 1.11.x | [1.23](/engine/api/v1.23/) | [API changes](/engine/api/version-history/#v1-23-api-changes) - 1.10.x | [1.22](/engine/api/v1.22/) | [API changes](/engine/api/version-history/#v1-22-api-changes) - 1.9.x | [1.21](/engine/api/v1.21/) | [API changes](/engine/api/version-history/#v1-21-api-changes) - 1.8.x | [1.20](/engine/api/v1.20/) | [API changes](/engine/api/version-history/#v1-20-api-changes) - 1.7.x | [1.19](/engine/api/v1.19/) | [API changes](/engine/api/version-history/#v1-19-api-changes) - 1.6.x | [1.18](/engine/api/v1.18/) | [API changes](/engine/api/version-history/#v1-18-api-changes) + 1.12.x | [1.24](https://docs.docker.com/engine/api/v1.24/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-24-api-changes) + 1.11.x | [1.23](https://docs.docker.com/engine/api/v1.23/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-23-api-changes) + 1.10.x | [1.22](https://docs.docker.com/engine/api/v1.22/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-22-api-changes) + 1.9.x | [1.21](https://docs.docker.com/engine/api/v1.21/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-21-api-changes) + 1.8.x | [1.20](https://docs.docker.com/engine/api/v1.20/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-20-api-changes) + 1.7.x | [1.19](https://docs.docker.com/engine/api/v1.19/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-19-api-changes) + 1.6.x | [1.18](https://docs.docker.com/engine/api/v1.18/) | [API changes](https://docs.docker.com/engine/api/version-history/#v1-18-api-changes) # Authentication @@ -68,7 +79,7 @@ info: The `serveraddress` is a domain/IP without a protocol. Throughout this structure, double quotes are required. - If you have already got an identity token from the [`/auth` endpoint](#operation/checkAuthentication), you can just pass this instead of credentials: + If you have already got an identity token from the [`/auth` endpoint](#operation/SystemAuth), you can just pass this instead of credentials: ``` { @@ -76,6 +87,48 @@ info: } ``` +# The tags on paths define the menu sections in the ReDoc documentation, so +# the usage of tags must make sense for that: +# - They should be singular, not plural. +# - There should not be too many tags, or the menu becomes unwieldly. For +# example, it is preferable to add a path to the "System" tag instead of +# creating a tag with a single path in it. +# - The order of tags in this list defines the order in the menu. +tags: + # Primary objects + - name: "Container" + description: | + Create and manage containers. + - name: "Image" + - name: "Network" + description: | + Networks are user-defined networks that containers can be attached to. See the [networking documentation](https://docs.docker.com/engine/userguide/networking/) for more information. + - name: "Volume" + description: | + Create and manage persistent storage that can be attached to containers. + - name: "Exec" + description: | + Run new commands inside running containers. See the [command-line reference](https://docs.docker.com/engine/reference/commandline/exec/) for more information. + + To exec a command in a container, you first need to create an exec instance, then start it. These two API endpoints are wrapped up in a single command-line command, `docker exec`. + - name: "Secret" + # Swarm things + - name: "Swarm" + description: | + Engines can be clustered together in a swarm. See [the swarm mode documentation](https://docs.docker.com/engine/swarm/) for more information. + - name: "Node" + description: | + Nodes are instances of the Engine participating in a swarm. Swarm mode must be enabled for these endpoints to work. + - name: "Service" + description: | + Services are the definitions of tasks to run on a swarm. Swarm mode must be enabled for these endpoints to work. + - name: "Task" + description: | + A task is a container running on a swarm. It is the atomic scheduling unit of swarm. Swarm mode must be enabled for these endpoints to work. + # System things + - name: "Plugin" + - name: "System" + definitions: Port: type: "object" @@ -2387,7 +2440,7 @@ paths: /containers/json: get: summary: "List containers" - operationId: "GetContainerList" + operationId: "ContainerList" produces: - "application/json" parameters: @@ -2565,8 +2618,7 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Container" + tags: ["Container"] /containers/create: post: summary: "Create a container" @@ -2765,13 +2817,12 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Container" + tags: ["Container"] /containers/{id}/json: get: summary: "Inspect a container" description: "Return low-level information about a container." - operationId: "GetContainerInspect" + operationId: "ContainerInspect" produces: - "application/json" responses: @@ -3042,13 +3093,12 @@ paths: type: "boolean" default: false description: "Return the size of container as fields `SizeRw` and `SizeRootFs`" - tags: - - "Container" + tags: ["Container"] /containers/{id}/top: get: summary: "List processes running inside a container" description: "On Unix systems, this is done by running the `ps` command. This endpoint is not supported on Windows." - operationId: "GetContainerTop" + operationId: "ContainerTop" responses: 200: description: "no error" @@ -3119,8 +3169,7 @@ paths: description: "The arguments to pass to `ps`. For example, `aux`" type: "string" default: "-ef" - tags: - - "Container" + tags: ["Container"] /containers/{id}/logs: get: summary: "Get container logs" @@ -3128,7 +3177,7 @@ paths: Get `stdout` and `stderr` logs from a container. Note: This endpoint works only for containers with the `json-file` or `journald` logging driver. - operationId: "GetContainerLogs" + operationId: "ContainerLogs" responses: 101: description: "logs returned as a stream" @@ -3161,7 +3210,7 @@ paths: description: | Return the logs as a stream. - This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/PostContainerAttach). + This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach). type: "boolean" default: false - name: "stdout" @@ -3189,8 +3238,7 @@ paths: description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines." type: "string" default: "all" - tags: - - "Container" + tags: ["Container"] /containers/{id}/changes: get: summary: "Get changes on a container’s filesystem" @@ -3200,7 +3248,7 @@ paths: - `0`: Modified - `1`: Added - `2`: Deleted - operationId: "GetContainerChanges" + operationId: "ContainerChanges" produces: - "application/json" responses: @@ -3246,13 +3294,12 @@ paths: required: true description: "ID or name of the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/export: get: summary: "Export a container" description: "Export the contents of a container as a tarball." - operationId: "GetContainerExport" + operationId: "ContainerExport" produces: - "application/octet-stream" responses: @@ -3275,8 +3322,7 @@ paths: required: true description: "ID or name of the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/stats: get: summary: "Get container stats based on resource usage" @@ -3284,7 +3330,7 @@ paths: This endpoint returns a live stream of a container’s resource usage statistics. The `precpu_stats` is the CPU statistic of last read, which is used for calculating the CPU usage percentage. It is not the same as the `cpu_stats` field. - operationId: "GetContainerStats" + operationId: "ContainerStats" produces: - "application/json" responses: @@ -3404,13 +3450,12 @@ paths: description: "Stream the output. If false, the stats will be output once and then it will disconnect." type: "boolean" default: true - tags: - - "Container" + tags: ["Container"] /containers/{id}/resize: post: summary: "Resize a container TTY" description: "Resize the TTY for a container. You must restart the container for the resize to take effect." - operationId: "PostContainerResize" + operationId: "ContainerResize" consumes: - "application/octet-stream" produces: @@ -3443,12 +3488,11 @@ paths: in: "query" description: "Width of the tty session in characters" type: "integer" - tags: - - "Container" + tags: ["Container"] /containers/{id}/start: post: summary: "Start a container" - operationId: "PostContainerStart" + operationId: "ContainerStart" responses: 204: description: "no error" @@ -3477,12 +3521,11 @@ paths: in: "query" description: "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-` where `` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`." type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/stop: post: summary: "Stop a container" - operationId: "PostContainerStop" + operationId: "ContainerStop" responses: 204: description: "no error" @@ -3511,12 +3554,11 @@ paths: in: "query" description: "Number of seconds to wait before killing the container" type: "integer" - tags: - - "Container" + tags: ["Container"] /containers/{id}/restart: post: summary: "Restart a container" - operationId: "PostContainerRestart" + operationId: "ContainerRestart" responses: 204: description: "no error" @@ -3541,13 +3583,12 @@ paths: in: "query" description: "Number of seconds to wait before killing the container" type: "integer" - tags: - - "Container" + tags: ["Container"] /containers/{id}/kill: post: summary: "Kill a container" description: "Send a POSIX signal to a container, defaulting to killing to the container." - operationId: "PostContainerKill" + operationId: "ContainerKill" responses: 204: description: "no error" @@ -3573,8 +3614,7 @@ paths: description: "Signal to send to the container as an integer or string (e.g. `SIGINT`)" type: "string" default: "SIGKILL" - tags: - - "Container" + tags: ["Container"] /containers/{id}/update: post: summary: "Update a container" @@ -3635,12 +3675,11 @@ paths: RestartPolicy: MaximumRetryCount: 4 Name: "on-failure" - tags: - - "Container" + tags: ["Container"] /containers/{id}/rename: post: summary: "Rename a container" - operationId: "PostContainerRename" + operationId: "ContainerRename" responses: 204: description: "no error" @@ -3670,8 +3709,7 @@ paths: required: true description: "New name for the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/pause: post: summary: "Pause a container" @@ -3679,7 +3717,7 @@ paths: Use the cgroups freezer to suspend all processes in a container. Traditionally, when suspending a process the `SIGSTOP` signal is used, which is observable by the process being suspended. With the cgroups freezer the process is unaware, and unable to capture, that it is being suspended, and subsequently resumed. - operationId: "PostContainerPause" + operationId: "ContainerPause" responses: 204: description: "no error" @@ -3700,13 +3738,12 @@ paths: required: true description: "ID or name of the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/unpause: post: summary: "Unpause a container" description: "Resume a container which has been paused." - operationId: "PostContainerUnpause" + operationId: "ContainerUnpause" responses: 204: description: "no error" @@ -3727,8 +3764,7 @@ paths: required: true description: "ID or name of the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}/attach: post: summary: "Attach to a container" @@ -3737,7 +3773,7 @@ paths: Either the `stream` or `logs` parameter must be `true` for this endpoint to do anything. - See [the documentation for the `docker attach` command](/engine/reference/commandline/attach/) for more details. + See [the documentation for the `docker attach` command](https://docs.docker.com/engine/reference/commandline/attach/) for more details. ### Hijacking @@ -3777,7 +3813,7 @@ paths: ### Stream format - When the TTY setting is disabled in [`POST /containers/create`](#operation/PostContainerCreate), the stream over the hijacked connected is multiplexed to separate out `stdout` and `stderr`. The stream consists of a series of frames, each containing a header and a payload. + When the TTY setting is disabled in [`POST /containers/create`](#operation/ContainerCreate), the stream over the hijacked connected is multiplexed to separate out `stdout` and `stderr`. The stream consists of a series of frames, each containing a header and a payload. The header contains the information which the stream writes (`stdout` or `stderr`). It also contains the size of the associated frame encoded in the last four bytes (`uint32`). @@ -3807,9 +3843,9 @@ paths: ### Stream format when using a TTY - When the TTY setting is enabled in [`POST /containers/create`](#operation/PostContainerCreate), the stream is not multiplexed. The data exchanged over the hijacked connection is simply the raw data from the process PTY and client's `stdin`. + When the TTY setting is enabled in [`POST /containers/create`](#operation/ContainerCreate), the stream is not multiplexed. The data exchanged over the hijacked connection is simply the raw data from the process PTY and client's `stdin`. - operationId: "PostContainerAttach" + operationId: "ContainerAttach" produces: - "application/vnd.docker.raw-stream" responses: @@ -3872,12 +3908,11 @@ paths: description: "Attach to `stderr`" type: "boolean" default: false - tags: - - "Container" + tags: ["Container"] /containers/{id}/attach/ws: get: summary: "Attach to a container via a websocket" - operationId: "PostContainerAttachWebsocket" + operationId: "ContainerAttachWebsocket" responses: 101: description: "no error, hints proxy about hijacking" @@ -3933,8 +3968,7 @@ paths: description: "Attach to `stderr`" type: "boolean" default: false - tags: - - "Container" + tags: ["Container"] /containers/{id}/wait: post: summary: "Wait for a container" @@ -3969,12 +4003,11 @@ paths: required: true description: "ID or name of the container" type: "string" - tags: - - "Container" + tags: ["Container"] /containers/{id}: delete: summary: "Remove a container" - operationId: "DeleteContainer" + operationId: "ContainerDelete" responses: 204: description: "no error" @@ -4009,13 +4042,12 @@ paths: description: "If the container is running, kill it before removing it." type: "boolean" default: false - tags: - - "Container" + tags: ["Container"] /containers/{id}/archive: head: summary: "Get information about files in a container" description: "A response header `X-Docker-Container-Path-Stat` is return containing a base64 - encoded JSON object with some filesystem header information about the path." - operationId: "HeadContainerArchive" + operationId: "ContainerArchiveHead" responses: 200: description: "no error" @@ -4056,12 +4088,11 @@ paths: required: true description: "Resource in the container’s filesystem to archive." type: "string" - tags: - - "Container" + tags: ["Container"] get: summary: "Get an archive of a filesystem resource in a container" description: "Get an tar archive of a resource in the filesystem of container id." - operationId: "GetContainerArchive" + operationId: "ContainerGetArchive" produces: - "application/x-tar" responses: @@ -4100,12 +4131,11 @@ paths: required: true description: "Resource in the container’s filesystem to archive." type: "string" - tags: - - "Container" + tags: ["Container"] put: summary: "Extract an archive of files or folders to a directory in a container" description: "Upload a tar archive to be extracted to a path in the filesystem of container id." - operationId: "PutContainerArchive" + operationId: "ContainerPutArchive" consumes: - "application/x-tar" - "application/octet-stream" @@ -4152,8 +4182,7 @@ paths: description: "The input stream must be a tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz." schema: type: "string" - tags: - - "Container" + tags: ["Container"] /containers/prune: post: summary: "Delete stopped containers" @@ -4181,13 +4210,12 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Container" + tags: ["Container"] /images/json: get: summary: "List Images" description: "Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image." - operationId: "GetImageList" + operationId: "ImageList" produces: - "application/json" responses: @@ -4253,20 +4281,19 @@ paths: description: "Show digest information as a `RepoDigests` field on each image." type: "boolean" default: false - tags: - - "Image" + tags: ["Image"] /build: post: summary: "Build an image" description: | Build an image from a tar archive with a `Dockerfile` in it. - The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive's root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](/engine/reference/builder/). + The `Dockerfile` specifies how the image is built from the tar archive. It is typically in the archive's root, but can be at a different path or have a different name by specifying the `dockerfile` parameter. [See the `Dockerfile` reference for more information](https://docs.docker.com/engine/reference/builder/). The Docker daemon performs a preliminary validation of the `Dockerfile` before starting the build, and returns an error if the syntax is incorrect. After that, each instruction is run one-by-one until the ID of the new image is output. The build is canceled if the client drops the connection by quitting or being killed. - operationId: "PostImageBuild" + operationId: "ImageBuild" consumes: - "application/octet-stream" produces: @@ -4345,7 +4372,7 @@ paths: type: "integer" - name: "buildargs" in: "query" - description: "JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker uses the buildargs as the environment context for commands run via the `Dockerfile` RUN instruction, or for variable expansion in other `Dockerfile` instructions. This is not meant for passing secret values. [Read more about the buildargs instruction.](/engine/reference/builder/#arg)" + description: "JSON map of string pairs for build-time variables. Users pass these values at build-time. Docker uses the buildargs as the environment context for commands run via the `Dockerfile` RUN instruction, or for variable expansion in other `Dockerfile` instructions. This is not meant for passing secret values. [Read more about the buildargs instruction.](https://docs.docker.com/engine/reference/builder/#arg)" type: "integer" - name: "shmsize" in: "query" @@ -4401,13 +4428,12 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Image" + tags: ["Image"] /images/create: post: summary: "Create an image" description: "Create an image by either pulling it from a registry or importing it." - operationId: "PostImageCreate" + operationId: "ImageCreate" consumes: - "text/plain" - "application/octet-stream" @@ -4447,13 +4473,12 @@ paths: in: "header" description: "A base64-encoded auth configuration. [See the authentication section for details.](#section/Authentication)" type: "string" - tags: - - "Image" + tags: ["Image"] /images/{name}/json: get: summary: "Inspect an image" description: "Return low-level information about an image." - operationId: "GetImageInspect" + operationId: "ImageInspect" produces: - "application/json" responses: @@ -4554,13 +4579,12 @@ paths: description: "Image name or id" type: "string" required: true - tags: - - "Image" + tags: ["Image"] /images/{name}/history: get: summary: "Get the history of an image" description: "Return parent layers of an image." - operationId: "GetImageHistory" + operationId: "ImageHistory" produces: - "application/json" responses: @@ -4625,8 +4649,7 @@ paths: description: "Image name or ID" type: "string" required: true - tags: - - "Image" + tags: ["Image"] /images/{name}/push: post: summary: "Push an image" @@ -4636,7 +4659,7 @@ paths: If you wish to push an image on to a private registry, that image must already have a tag which references the registry. For example, `registry.example.com/myimage:latest`. The push is cancelled if the HTTP connection is closed. - operationId: "PostImagePush" + operationId: "ImagePush" consumes: - "application/octet-stream" responses: @@ -4665,13 +4688,12 @@ paths: description: "A base64-encoded auth configuration. [See the authentication section for details.](#section/Authentication)" type: "string" required: true - tags: - - "Image" + tags: ["Image"] /images/{name}/tag: post: summary: "Tag an image" description: "Tag an image so that it becomes part of a repository." - operationId: "PostImageTag" + operationId: "ImageTag" responses: 201: description: "No error" @@ -4705,8 +4727,7 @@ paths: in: "query" description: "The name of the new tag." type: "string" - tags: - - "Image" + tags: ["Image"] /images/{name}: delete: summary: "Remove an image" @@ -4714,7 +4735,7 @@ paths: Remove an image, along with any untagged parent images that were referenced by that image. Images can't be removed if they have descendant images, are being used by a running container or are being used by a build. - operationId: "DeleteImage" + operationId: "ImageDelete" produces: - "application/json" responses: @@ -4757,13 +4778,12 @@ paths: description: "Do not delete untagged parent images" type: "boolean" default: false - tags: - - "Image" + tags: ["Image"] /images/search: get: summary: "Search images" description: "Search for an image on Docker Hub." - operationId: "GetImageSearch" + operationId: "ImageSearch" produces: - "application/json" responses: @@ -4824,8 +4844,7 @@ paths: - `is-automated=(true|false)` - `is-official=(true|false)` type: "string" - tags: - - "Image" + tags: ["Image"] /images/prune: post: summary: "Delete unused images" @@ -4863,13 +4882,12 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Image" + tags: ["Image"] /auth: post: summary: "Check auth configuration" description: "Validate credentials for a registry and, if available, get an identity token for accessing the registry without password." - operationId: "Authenticate" + operationId: "SystemAuth" consumes: ["application/json"] produces: ["application/json"] responses: @@ -4903,11 +4921,11 @@ paths: description: "Authentication to check" schema: $ref: "#/definitions/AuthConfig" - tags: ["Registry"] + tags: ["System"] /info: get: summary: "Get system information" - operationId: "getSystemInformation" + operationId: "SystemInfo" produces: - "application/json" responses: @@ -5115,13 +5133,12 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Misc" + tags: ["System"] /version: get: summary: "Get version" description: "Returns the version of Docker that is running and various information about the system that Docker is running on." - operationId: "getVersion" + operationId: "SystemVersion" produces: - "application/json" responses: @@ -5166,13 +5183,12 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Misc" + tags: ["System"] /_ping: get: summary: "Ping" description: "This is a dummy endpoint you can use to test if the server is accessible." - operationId: "ping" + operationId: "SystemPing" produces: - "text/plain" responses: @@ -5185,12 +5201,11 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Misc" + tags: ["System"] /commit: post: summary: "Create a new image from a container" - operationId: "PostImageCommit" + operationId: "ImageCommit" consumes: - "application/json" produces: @@ -5246,8 +5261,7 @@ paths: in: "query" description: "`Dockerfile` instructions to apply while committing" type: "string" - tags: - - "Image" + tags: ["Image"] /events: get: summary: "Monitor events" @@ -5266,7 +5280,7 @@ paths: The Docker daemon reports these events: `reload` - operationId: "getEvents" + operationId: "SystemEvents" produces: - "application/json" responses: @@ -5337,11 +5351,11 @@ paths: - `network=` network name or ID - `daemon=` daemon name or ID type: "string" - tags: - - "Misc" + tags: ["System"] /system/df: get: summary: "Get data usage information" + operationId: "SystemDataUsage" responses: 200: description: "no error" @@ -5426,8 +5440,7 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Misc" + tags: ["System"] /images/{name}/get: get: summary: "Export an image" @@ -5455,7 +5468,7 @@ paths: } } ``` - operationId: "GetImage" + operationId: "ImageGet" produces: - "application/x-tar" responses: @@ -5474,8 +5487,7 @@ paths: description: "Image name or ID" type: "string" required: true - tags: - - "Image" + tags: ["Image"] /images/get: get: summary: "Export several images" @@ -5484,8 +5496,8 @@ paths: For each value of the `names` parameter: if it is a specific name and tag (e.g. `ubuntu:latest`), then only that image (and its parents) are returned; if it is an image ID, similarly only that image (and its parents) are returned and there would be no names referenced in the 'repositories' file for this image ID. - For details on the format, see [the export image endpoint](#operation/GetImage). - operationId: "GetImageSaveAll" + For details on the format, see [the export image endpoint](#operation/ImageGet). + operationId: "ImageGetAll" produces: - "application/x-tar" responses: @@ -5505,16 +5517,15 @@ paths: type: "array" items: type: "string" - tags: - - "Image" + tags: ["Image"] /images/load: post: summary: "Import images" description: | Load a set of images and tags into a repository. - For details on the format, see [the export image endpoint](#operation/GetImage). - operationId: "PostImageLoad" + For details on the format, see [the export image endpoint](#operation/ImageGet). + operationId: "ImageLoad" consumes: - "application/x-tar" produces: @@ -5538,13 +5549,12 @@ paths: description: "Suppress progress details during load." type: "boolean" default: false - tags: - - "Image" + tags: ["Image"] /containers/{id}/exec: post: summary: "Create an exec instance" description: "Run a command inside a running container." - operationId: "PostContainerExec" + operationId: "ContainerExec" consumes: - "application/json" produces: @@ -5625,13 +5635,12 @@ paths: description: "ID or name of container" type: "string" required: true - tags: - - "Exec" + tags: ["Exec"] /exec/{id}/start: post: summary: "Start an exec instance" description: "Starts a previously set up exec instance. If detach is true, this endpoint returns immediately after starting the command. Otherwise, it sets up an interactive session with the command." - operationId: "PostExecStart" + operationId: "ExecStart" consumes: - "application/json" produces: @@ -5667,13 +5676,12 @@ paths: description: "Exec instance ID" required: true type: "string" - tags: - - "Exec" + tags: ["Exec"] /exec/{id}/resize: post: summary: "Resize an exec instance" description: "Resize the TTY session used by an exec instance. This endpoint only works if `tty` was specified as part of creating and starting the exec instance." - operationId: "PostExecResize" + operationId: "ExecResize" responses: 201: description: "No error" @@ -5695,13 +5703,12 @@ paths: in: "query" description: "Width of the TTY session in characters" type: "integer" - tags: - - "Exec" + tags: ["Exec"] /exec/{id}/json: get: summary: "Inspect an exec instance" description: "Return low-level information about an exec instance." - operationId: "PostExecInspect" + operationId: "ExecInspect" produces: - "application/json" responses: @@ -5763,13 +5770,12 @@ paths: description: "Exec instance ID" required: true type: "string" - tags: - - "Exec" + tags: ["Exec"] /volumes: get: summary: "List volumes" - operationId: "VolumesList" + operationId: "VolumeList" produces: ["application/json"] responses: 200: @@ -5831,7 +5837,7 @@ paths: /volumes/create: post: summary: "Create a volume" - operationId: "VolumesCreate" + operationId: "VolumeCreate" consumes: ["application/json"] produces: ["application/json"] responses: @@ -5881,7 +5887,7 @@ paths: /volumes/{name}: get: summary: "Inspect a volume" - operationId: "VolumesInspect" + operationId: "VolumeInspect" produces: ["application/json"] responses: 200: @@ -5907,7 +5913,7 @@ paths: delete: summary: "Remove a volume" description: "Instruct the driver to remove the volume." - operationId: "VolumesDelete" + operationId: "VolumeDelete" responses: 204: description: "The volume was removed" @@ -5962,12 +5968,11 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Volume" + tags: ["Volume"] /networks: get: summary: "List networks" - operationId: "NetworksList" + operationId: "NetworkList" produces: - "application/json" responses: @@ -6049,7 +6054,7 @@ paths: /networks/{id}: get: summary: "Inspect a network" - operationId: "NetworksInspect" + operationId: "NetworkInspect" produces: - "application/json" responses: @@ -6071,7 +6076,7 @@ paths: delete: summary: "Remove a network" - operationId: "DeleteNetworks" + operationId: "NetworkDelete" responses: 204: description: "No error" @@ -6094,7 +6099,7 @@ paths: /networks/create: post: summary: "Create a network" - operationId: "NetworksCreate" + operationId: "NetworkCreate" consumes: - "application/json" produces: @@ -6190,7 +6195,7 @@ paths: /networks/{id}/connect: post: summary: "Connect a container to a network" - operationId: "NetworksConnect" + operationId: "NetworkConnect" consumes: - "application/octet-stream" responses: @@ -6236,7 +6241,7 @@ paths: /networks/{id}/disconnect: post: summary: "Disconnect a container from a network" - operationId: "NetworksDisconnect" + operationId: "NetworkDisconnect" consumes: - "application/json" responses: @@ -6296,12 +6301,11 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Network" + tags: ["Network"] /plugins: get: summary: "List plugins" - operationId: "PluginsList" + operationId: "PluginList" description: "Returns information about installed plugins." produces: ["application/json"] responses: @@ -6390,14 +6394,14 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: ["Plugins"] + tags: ["Plugin"] /plugins/pull: post: summary: "Install a plugin" - operationId: "PostPluginsPull" + operationId: "PluginPull" description: | - Pulls and installs a plugin. After the plugin is installed, it can be enabled using the [`POST /plugins/{name}/enable` endpoint](#operation/PostPluginsEnable). + Pulls and installs a plugin. After the plugin is installed, it can be enabled using the [`POST /plugins/{name}/enable` endpoint](#operation/PluginEnable). produces: - "application/json" responses: @@ -6447,12 +6451,11 @@ paths: in: "header" description: "A base64-encoded auth configuration to use when pulling a plugin from a registry. [See the authentication section for details.](#section/Authentication)" type: "string" - tags: - - "Plugins" + tags: ["Plugin"] /plugins/{name}: get: summary: "Inspect a plugin" - operationId: "GetPluginsInspect" + operationId: "PluginInspect" responses: 200: description: "no error" @@ -6472,11 +6475,10 @@ paths: description: "The name of the plugin. The `:latest` tag is optional, and is the default if omitted." required: true type: "string" - tags: - - "Plugins" + tags: ["Plugin"] delete: summary: "Remove a plugin" - operationId: "DeletePlugins" + operationId: "PluginDelete" responses: 200: description: "no error" @@ -6501,12 +6503,11 @@ paths: description: "Disable the plugin before removing. This may result in issues if the plugin is in use by a container." type: "boolean" default: false - tags: - - "Plugins" + tags: ["Plugin"] /plugins/{name}/enable: post: summary: "Enable a plugin" - operationId: "PostPluginsEnable" + operationId: "PluginEnable" responses: 200: description: "no error" @@ -6525,12 +6526,11 @@ paths: description: "Set the HTTP client timeout (in seconds)" type: "integer" default: 0 - tags: - - "Plugins" + tags: ["Plugin"] /plugins/{name}/disable: post: summary: "Disable a plugin" - operationId: "PostPluginsDisable" + operationId: "PluginDisable" responses: 200: description: "no error" @@ -6544,12 +6544,11 @@ paths: description: "The name of the plugin. The `:latest` tag is optional, and is the default if omitted." required: true type: "string" - tags: - - "Plugins" + tags: ["Plugin"] /plugins/create: post: summary: "Create a plugin" - operationId: "PostPluginsCreate" + operationId: "PluginCreate" consumes: - "application/x-tar" responses: @@ -6571,8 +6570,7 @@ paths: schema: type: "string" format: "binary" - tags: - - "Plugins" + tags: ["Plugin"] /plugins/{name}/push: post: summary: "Push a plugin" @@ -6596,12 +6594,11 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Plugins" + tags: ["Plugin"] /plugins/{name}/set: post: summary: "Configure a plugin" - operationId: "PostPluginsSet" + operationId: "PluginSet" consumes: - "application/json" parameters: @@ -6628,12 +6625,11 @@ paths: description: "Server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Plugins" + tags: ["Plugin"] /nodes: get: summary: "List nodes" - operationId: "GetNodesList" + operationId: "NodeList" responses: 200: description: "no error" @@ -6658,12 +6654,11 @@ paths: - `name=` - `role=`(`manager`|`worker`)` type: "string" - tags: - - "Nodes" + tags: ["Node"] /nodes/{id}: get: summary: "Inspect a node" - operationId: "GetNodesInspect" + operationId: "NodeInspect" responses: 200: description: "no error" @@ -6683,11 +6678,10 @@ paths: description: "The ID or name of the node" type: "string" required: true - tags: - - "Nodes" + tags: ["Node"] delete: summary: "Delete a node" - operationId: "DeleteNodes" + operationId: "NodeDelete" responses: 200: description: "no error" @@ -6710,12 +6704,11 @@ paths: description: "Force remove a node from the swarm" default: false type: "boolean" - tags: - - "Nodes" + tags: ["Node"] /nodes/{id}/update: post: summary: "Update a node" - operationId: "PostNodesUpdate" + operationId: "NodeUpdate" responses: 200: description: "no error" @@ -6743,12 +6736,11 @@ paths: type: "integer" format: "int64" required: true - tags: - - "Nodes" + tags: ["Node"] /swarm: get: summary: "Inspect swarm" - operationId: "GetSwarmInspect" + operationId: "SwarmInspect" responses: 200: description: "no error" @@ -6796,12 +6788,11 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Swarm" + tags: ["Swarm"] /swarm/init: post: summary: "Initialize a new swarm" - operationId: "PostSwarmInit" + operationId: "SwarmInit" produces: - "application/json" - "text/plain" @@ -6853,12 +6844,11 @@ paths: CAConfig: {} EncryptionConfig: AutoLockManagers: false - tags: - - "Swarm" + tags: ["Swarm"] /swarm/join: post: summary: "Join an existing swarm" - operationId: "PostSwarmJoin" + operationId: "SwarmJoin" responses: 200: description: "no error" @@ -6899,12 +6889,11 @@ paths: RemoteAddrs: - "node1:2377" JoinToken: "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2" - tags: - - "Swarm" + tags: ["Swarm"] /swarm/leave: post: summary: "Leave a swarm" - operationId: "PostSwarmLeave" + operationId: "SwarmLeave" responses: 200: description: "no error" @@ -6922,12 +6911,11 @@ paths: in: "query" type: "boolean" default: false - tags: - - "Swarm" + tags: ["Swarm"] /swarm/update: post: summary: "Update a swarm" - operationId: "PostSwarmUpdate" + operationId: "SwarmUpdate" responses: 200: description: "no error" @@ -6970,8 +6958,7 @@ paths: description: "Rotate the manager unlock key." type: "boolean" default: false - tags: - - "Swarm" + tags: ["Swarm"] /swarm/unlockkey: get: summary: "Get the unlock key" @@ -6993,8 +6980,7 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Swarm" + tags: ["Swarm"] /swarm/unlock: post: summary: "Unlock a locked manager" @@ -7022,12 +7008,11 @@ paths: description: "server error" schema: $ref: "#/definitions/ErrorResponse" - tags: - - "Swarm" + tags: ["Swarm"] /services: get: summary: "List services" - operationId: "GetServicesList" + operationId: "ServiceList" responses: 200: description: "no error" @@ -7049,12 +7034,11 @@ paths: - `id=` - `name=` - `label=` - tags: - - "Services" + tags: ["Service"] /services/create: post: summary: "Create a service" - operationId: "PostServicesCreate" + operationId: "ServiceCreate" consumes: - "application/json" produces: @@ -7147,12 +7131,11 @@ paths: in: "header" description: "A base64-encoded auth configuration for pulling from private registries. [See the authentication section for details.](#section/Authentication)" type: "string" - tags: - - "Services" + tags: ["Service"] /services/{id}: get: summary: "Inspect a service" - operationId: "GetServicesInspect" + operationId: "ServiceInspect" responses: 200: description: "no error" @@ -7172,11 +7155,10 @@ paths: description: "ID or name of service." required: true type: "string" - tags: - - "Services" + tags: ["Service"] delete: summary: "Delete a service" - operationId: "DeleteServices" + operationId: "ServiceDelete" responses: 200: description: "no error" @@ -7194,8 +7176,7 @@ paths: description: "ID or name of service." required: true type: "string" - tags: - - "Services" + tags: ["Service"] /services/{id}/update: post: summary: "Update a service" @@ -7270,7 +7251,7 @@ paths: description: "A base64-encoded auth configuration for pulling from private registries. [See the authentication section for details.](#section/Authentication)" type: "string" - tags: ["Services"] + tags: ["Service"] /services/{id}/logs: get: summary: "Get service logs" @@ -7319,7 +7300,7 @@ paths: description: | Return the logs as a stream. - This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/PostContainerAttach). + This will return a `101` HTTP response with a `Connection: upgrade` header, then hijack the HTTP connection to send raw output. For more information about hijacking and the stream format, [see the documentation for the attach endpoint](#operation/ContainerAttach). type: "boolean" default: false - name: "stdout" @@ -7347,12 +7328,11 @@ paths: description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines." type: "string" default: "all" - tags: - - "Services" + tags: ["Service"] /tasks: get: summary: "List tasks" - operationId: "GetTasksList" + operationId: "TaskList" produces: - "application/json" responses: @@ -7491,12 +7471,11 @@ paths: - `node=` - `label=key` or `label="key=value"` - `desired-state=(running | shutdown | accepted)` - tags: - - "Tasks" + tags: ["Task"] /tasks/{id}: get: summary: "Inspect a task" - operationId: "GetTasksInspect" + operationId: "TaskInspect" produces: - "application/json" responses: @@ -7518,8 +7497,7 @@ paths: description: "ID of the task" required: true type: "string" - tags: - - "Tasks" + tags: ["Task"] /secrets: get: summary: "List secrets" @@ -7553,8 +7531,7 @@ paths: A JSON encoded value of the filters (a `map[string][]string`) to process on the secrets list. Available filters: - `names=` - tags: - - "Secrets" + tags: ["Secret"] /secrets/create: post: summary: "Create a secret" @@ -7598,12 +7575,11 @@ paths: Labels: foo: "bar" Data: "VEhJUyBJUyBOT1QgQSBSRUFMIENFUlRJRklDQVRFCg==" - tags: - - "Secrets" + tags: ["Secret"] /secrets/{id}: get: summary: "Inspect a secret" - operationId: "SecretsInspect" + operationId: "SecretInspect" produces: - "application/json" responses: @@ -7637,11 +7613,10 @@ paths: required: true type: "string" description: "ID of the secret" - tags: - - "Secrets" + tags: ["Secret"] delete: summary: "Delete a secret" - operationId: "SecretsDelete" + operationId: "SecretDelete" produces: - "application/json" responses: @@ -7661,5 +7636,4 @@ paths: required: true type: "string" description: "ID of the secret" - tags: - - "Secrets" + tags: ["Secret"] diff --git a/vendor/github.com/docker/docker/builder/builder.go b/vendor/github.com/docker/docker/builder/builder.go index b25a5cd04..ced19e81e 100644 --- a/vendor/github.com/docker/docker/builder/builder.go +++ b/vendor/github.com/docker/docker/builder/builder.go @@ -116,7 +116,7 @@ type Backend interface { // ContainerAttachRaw attaches to container. ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool) error // ContainerCreate creates a new Docker container and returns potential warnings - ContainerCreate(config types.ContainerCreateConfig, validateHostname bool) (container.ContainerCreateCreatedBody, error) + ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) // ContainerRm removes a container specified by `id`. ContainerRm(name string, config *types.ContainerRmConfig) error // Commit creates a new Docker image from an existing Docker container. @@ -124,7 +124,7 @@ type Backend interface { // ContainerKill stops the container execution abruptly. ContainerKill(containerID string, sig uint64) error // ContainerStart starts a new container - ContainerStart(containerID string, hostConfig *container.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error + ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error // ContainerWait stops processing until the given container is stopped. ContainerWait(containerID string, timeout time.Duration) (int, error) // ContainerUpdateCmdOnBuild updates container.Path and container.Args diff --git a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go index 64f0341d4..cf69fa496 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go @@ -71,14 +71,20 @@ func env(b *Builder, args []string, attributes map[string]bool, original string) if len(args[j]) == 0 { return errBlankCommandNames("ENV") } - newVar := args[j] + "=" + args[j+1] + "" commitStr += " " + newVar gotOne := false for i, envVar := range b.runConfig.Env { envParts := strings.SplitN(envVar, "=", 2) - if envParts[0] == args[j] { + compareFrom := envParts[0] + compareTo := args[j] + if runtime.GOOS == "windows" { + // Case insensitive environment variables on Windows + compareFrom = strings.ToUpper(compareFrom) + compareTo = strings.ToUpper(compareTo) + } + if compareFrom == compareTo { b.runConfig.Env[i] = newVar gotOne = true break @@ -301,7 +307,7 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str return nil } - container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}, true) + container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}) if err != nil { return err } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/envVarTest b/vendor/github.com/docker/docker/builder/dockerfile/envVarTest index 1a7fe975a..067dca9a5 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/envVarTest +++ b/vendor/github.com/docker/docker/builder/dockerfile/envVarTest @@ -1,112 +1,116 @@ -hello | hello -he'll'o | hello -he'llo | hello -he\'llo | he'llo -he\\'llo | he\llo -abc\tdef | abctdef -"abc\tdef" | abc\tdef -'abc\tdef' | abc\tdef -hello\ | hello -hello\\ | hello\ -"hello | hello -"hello\" | hello" -"hel'lo" | hel'lo -'hello | hello -'hello\' | hello\ -"''" | '' -$. | $. -$1 | -he$1x | hex -he$.x | he$.x -he$pwd. | he. -he$PWD | he/home -he\$PWD | he$PWD -he\\$PWD | he\/home -he\${} | he${} -he\${}xx | he${}xx -he${} | he -he${}xx | hexx -he${hi} | he -he${hi}xx | hexx -he${PWD} | he/home -he${.} | error -he${XXX:-000}xx | he000xx -he${PWD:-000}xx | he/homexx -he${XXX:-$PWD}xx | he/homexx -he${XXX:-${PWD:-yyy}}xx | he/homexx -he${XXX:-${YYY:-yyy}}xx | heyyyxx -he${XXX:YYY} | error -he${XXX:+${PWD}}xx | hexx -he${PWD:+${XXX}}xx | hexx -he${PWD:+${SHELL}}xx | hebashxx -he${XXX:+000}xx | hexx -he${PWD:+000}xx | he000xx -'he${XX}' | he${XX} -"he${PWD}" | he/home -"he'$PWD'" | he'/home' -"$PWD" | /home -'$PWD' | $PWD -'\$PWD' | \$PWD -'"hello"' | "hello" -he\$PWD | he$PWD -"he\$PWD" | he$PWD -'he\$PWD' | he\$PWD -he${PWD | error -he${PWD:=000}xx | error -he${PWD:+${PWD}:}xx | he/home:xx -he${XXX:-\$PWD:}xx | he$PWD:xx -he${XXX:-\${PWD}z}xx | he${PWDz}xx -안녕하세요 | 안녕하세요 -안'녕'하세요 | 안녕하세요 -안'녕하세요 | 안녕하세요 -안녕\'하세요 | 안녕'하세요 -안\\'녕하세요 | 안\녕하세요 -안녕\t하세요 | 안녕t하세요 -"안녕\t하세요" | 안녕\t하세요 -'안녕\t하세요 | 안녕\t하세요 -안녕하세요\ | 안녕하세요 -안녕하세요\\ | 안녕하세요\ -"안녕하세요 | 안녕하세요 -"안녕하세요\" | 안녕하세요" -"안녕'하세요" | 안녕'하세요 -'안녕하세요 | 안녕하세요 -'안녕하세요\' | 안녕하세요\ -안녕$1x | 안녕x -안녕$.x | 안녕$.x -안녕$pwd. | 안녕. -안녕$PWD | 안녕/home -안녕\$PWD | 안녕$PWD -안녕\\$PWD | 안녕\/home -안녕\${} | 안녕${} -안녕\${}xx | 안녕${}xx -안녕${} | 안녕 -안녕${}xx | 안녕xx -안녕${hi} | 안녕 -안녕${hi}xx | 안녕xx -안녕${PWD} | 안녕/home -안녕${.} | error -안녕${XXX:-000}xx | 안녕000xx -안녕${PWD:-000}xx | 안녕/homexx -안녕${XXX:-$PWD}xx | 안녕/homexx -안녕${XXX:-${PWD:-yyy}}xx | 안녕/homexx -안녕${XXX:-${YYY:-yyy}}xx | 안녕yyyxx -안녕${XXX:YYY} | error -안녕${XXX:+${PWD}}xx | 안녕xx -안녕${PWD:+${XXX}}xx | 안녕xx -안녕${PWD:+${SHELL}}xx | 안녕bashxx -안녕${XXX:+000}xx | 안녕xx -안녕${PWD:+000}xx | 안녕000xx -'안녕${XX}' | 안녕${XX} -"안녕${PWD}" | 안녕/home -"안녕'$PWD'" | 안녕'/home' -'"안녕"' | "안녕" -안녕\$PWD | 안녕$PWD -"안녕\$PWD" | 안녕$PWD -'안녕\$PWD' | 안녕\$PWD -안녕${PWD | error -안녕${PWD:=000}xx | error -안녕${PWD:+${PWD}:}xx | 안녕/home:xx -안녕${XXX:-\$PWD:}xx | 안녕$PWD:xx -안녕${XXX:-\${PWD}z}xx | 안녕${PWDz}xx -$KOREAN | 한국어 -안녕$KOREAN | 안녕한국어 +A|hello | hello +A|he'll'o | hello +A|he'llo | hello +A|he\'llo | he'llo +A|he\\'llo | he\llo +A|abc\tdef | abctdef +A|"abc\tdef" | abc\tdef +A|'abc\tdef' | abc\tdef +A|hello\ | hello +A|hello\\ | hello\ +A|"hello | hello +A|"hello\" | hello" +A|"hel'lo" | hel'lo +A|'hello | hello +A|'hello\' | hello\ +A|"''" | '' +A|$. | $. +A|$1 | +A|he$1x | hex +A|he$.x | he$.x +# Next one is different on Windows as $pwd==$PWD +U|he$pwd. | he. +W|he$pwd. | he/home. +A|he$PWD | he/home +A|he\$PWD | he$PWD +A|he\\$PWD | he\/home +A|he\${} | he${} +A|he\${}xx | he${}xx +A|he${} | he +A|he${}xx | hexx +A|he${hi} | he +A|he${hi}xx | hexx +A|he${PWD} | he/home +A|he${.} | error +A|he${XXX:-000}xx | he000xx +A|he${PWD:-000}xx | he/homexx +A|he${XXX:-$PWD}xx | he/homexx +A|he${XXX:-${PWD:-yyy}}xx | he/homexx +A|he${XXX:-${YYY:-yyy}}xx | heyyyxx +A|he${XXX:YYY} | error +A|he${XXX:+${PWD}}xx | hexx +A|he${PWD:+${XXX}}xx | hexx +A|he${PWD:+${SHELL}}xx | hebashxx +A|he${XXX:+000}xx | hexx +A|he${PWD:+000}xx | he000xx +A|'he${XX}' | he${XX} +A|"he${PWD}" | he/home +A|"he'$PWD'" | he'/home' +A|"$PWD" | /home +A|'$PWD' | $PWD +A|'\$PWD' | \$PWD +A|'"hello"' | "hello" +A|he\$PWD | he$PWD +A|"he\$PWD" | he$PWD +A|'he\$PWD' | he\$PWD +A|he${PWD | error +A|he${PWD:=000}xx | error +A|he${PWD:+${PWD}:}xx | he/home:xx +A|he${XXX:-\$PWD:}xx | he$PWD:xx +A|he${XXX:-\${PWD}z}xx | he${PWDz}xx +A|안녕하세요 | 안녕하세요 +A|안'녕'하세요 | 안녕하세요 +A|안'녕하세요 | 안녕하세요 +A|안녕\'하세요 | 안녕'하세요 +A|안\\'녕하세요 | 안\녕하세요 +A|안녕\t하세요 | 안녕t하세요 +A|"안녕\t하세요" | 안녕\t하세요 +A|'안녕\t하세요 | 안녕\t하세요 +A|안녕하세요\ | 안녕하세요 +A|안녕하세요\\ | 안녕하세요\ +A|"안녕하세요 | 안녕하세요 +A|"안녕하세요\" | 안녕하세요" +A|"안녕'하세요" | 안녕'하세요 +A|'안녕하세요 | 안녕하세요 +A|'안녕하세요\' | 안녕하세요\ +A|안녕$1x | 안녕x +A|안녕$.x | 안녕$.x +# Next one is different on Windows as $pwd==$PWD +U|안녕$pwd. | 안녕. +W|안녕$pwd. | 안녕/home. +A|안녕$PWD | 안녕/home +A|안녕\$PWD | 안녕$PWD +A|안녕\\$PWD | 안녕\/home +A|안녕\${} | 안녕${} +A|안녕\${}xx | 안녕${}xx +A|안녕${} | 안녕 +A|안녕${}xx | 안녕xx +A|안녕${hi} | 안녕 +A|안녕${hi}xx | 안녕xx +A|안녕${PWD} | 안녕/home +A|안녕${.} | error +A|안녕${XXX:-000}xx | 안녕000xx +A|안녕${PWD:-000}xx | 안녕/homexx +A|안녕${XXX:-$PWD}xx | 안녕/homexx +A|안녕${XXX:-${PWD:-yyy}}xx | 안녕/homexx +A|안녕${XXX:-${YYY:-yyy}}xx | 안녕yyyxx +A|안녕${XXX:YYY} | error +A|안녕${XXX:+${PWD}}xx | 안녕xx +A|안녕${PWD:+${XXX}}xx | 안녕xx +A|안녕${PWD:+${SHELL}}xx | 안녕bashxx +A|안녕${XXX:+000}xx | 안녕xx +A|안녕${PWD:+000}xx | 안녕000xx +A|'안녕${XX}' | 안녕${XX} +A|"안녕${PWD}" | 안녕/home +A|"안녕'$PWD'" | 안녕'/home' +A|'"안녕"' | "안녕" +A|안녕\$PWD | 안녕$PWD +A|"안녕\$PWD" | 안녕$PWD +A|'안녕\$PWD' | 안녕\$PWD +A|안녕${PWD | error +A|안녕${PWD:=000}xx | error +A|안녕${PWD:+${PWD}:}xx | 안녕/home:xx +A|안녕${XXX:-\$PWD:}xx | 안녕$PWD:xx +A|안녕${XXX:-\${PWD}z}xx | 안녕${PWDz}xx +A|$KOREAN | 한국어 +A|안녕$KOREAN | 안녕한국어 diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals.go b/vendor/github.com/docker/docker/builder/dockerfile/internals.go index 0b6c99489..6f0a36784 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/internals.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals.go @@ -180,7 +180,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD return nil } - container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}, true) + container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{Config: b.runConfig}) if err != nil { return err } @@ -496,7 +496,7 @@ func (b *Builder) create() (string, error) { c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{ Config: b.runConfig, HostConfig: hostConfig, - }, true) + }) if err != nil { return "", err } @@ -537,7 +537,7 @@ func (b *Builder) run(cID string) (err error) { } }() - if err := b.docker.ContainerStart(cID, nil, true, "", ""); err != nil { + if err := b.docker.ContainerStart(cID, nil, "", ""); err != nil { close(finished) if cancelErr := <-cancelErrCh; cancelErr != nil { logrus.Debugf("Build cancelled (%v) and got an error from ContainerStart: %v", diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/parser.go b/vendor/github.com/docker/docker/builder/dockerfile/parser/parser.go index b4ce605f4..a156babd0 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/parser.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/parser.go @@ -176,17 +176,10 @@ func Parse(rwc io.Reader, d *Directive) (*Node, error) { newline := scanner.Text() currentLine++ - // If escape followed by a comment line then stop - // Note here that comment line starts with `#` at - // the first pos of the line - if stripComments(newline) == "" { - break + if stripComments(strings.TrimSpace(newline)) == "" { + continue } - // If escape followed by an empty line then stop - if strings.TrimSpace(newline) == "" { - break - } line, child, err = ParseLine(line+newline, d, false) if err != nil { return nil, err diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/parser_test.go b/vendor/github.com/docker/docker/builder/dockerfile/parser/parser_test.go index 7b8f0b233..e8e26961d 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/parser_test.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/parser_test.go @@ -150,8 +150,8 @@ func TestLineInformation(t *testing.T) { t.Fatalf("Error parsing dockerfile %s: %v", testFileLineInfo, err) } - if ast.StartLine != 5 || ast.EndLine != 27 { - fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 27, ast.StartLine, ast.EndLine) + if ast.StartLine != 5 || ast.EndLine != 31 { + fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 31, ast.StartLine, ast.EndLine) t.Fatalf("Root line information doesn't match result.") } if len(ast.Children) != 3 { @@ -161,7 +161,7 @@ func TestLineInformation(t *testing.T) { expected := [][]int{ {5, 5}, {11, 12}, - {17, 27}, + {17, 31}, } for i, child := range ast.Children { if child.StartLine != expected[i][0] || child.EndLine != expected[i][1] { diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfile-line/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfile-line/Dockerfile index 19a26b237..c7601c9f6 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfile-line/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfile-line/Dockerfile @@ -16,11 +16,15 @@ ENV GOPATH \ # Install the packages we need, clean up after them and us RUN apt-get update \ && dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.clean \ + + && apt-get install -y --no-install-recommends git golang ca-certificates \ && apt-get clean \ && rm -rf /var/lib/apt/lists \ + && go get -v github.com/brimstone/consuldock \ && mv $GOPATH/bin/consuldock /usr/local/bin/consuldock \ + && dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \ && apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \ && rm /tmp/dpkg.* \ diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-consuldock/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-consuldock/Dockerfile index 7827da41c..0364ef9d9 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-consuldock/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-consuldock/Dockerfile @@ -16,8 +16,10 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends git golang ca-certificates \ && apt-get clean \ && rm -rf /var/lib/apt/lists \ + && go get -v github.com/brimstone/consuldock \ && mv $GOPATH/bin/consuldock /usr/local/bin/consuldock \ + && dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \ && apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \ && rm /tmp/dpkg.* \ diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-docker-consul/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-docker-consul/Dockerfile index 3f7bcca3c..25ae35216 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-docker-consul/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/brimstone-docker-consul/Dockerfile @@ -23,12 +23,14 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends unzip wget \ && apt-get clean \ && rm -rf /var/lib/apt/lists \ + && cd /tmp \ && wget https://dl.bintray.com/mitchellh/consul/0.3.1_web_ui.zip \ -O web_ui.zip \ && unzip web_ui.zip \ && mv dist /webui \ && rm web_ui.zip \ + && dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \ && apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \ && rm /tmp/dpkg.* @@ -40,8 +42,10 @@ RUN apt-get update \ && apt-get install -y --no-install-recommends git golang ca-certificates build-essential \ && apt-get clean \ && rm -rf /var/lib/apt/lists \ + && go get -v github.com/hashicorp/consul \ && mv $GOPATH/bin/consul /usr/bin/consul \ + && dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \ && apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \ && rm /tmp/dpkg.* \ diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/Dockerfile index d6ed07592..97f915f16 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/Dockerfile @@ -27,5 +27,8 @@ bye\ frog RUN echo hello \ -# this is a comment that breaks escape continuation -RUN echo this is some more useful stuff +# this is a comment + +# this is a comment with a blank line surrounding it + +this is some more useful stuff diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/result b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/result index 85e31160b..76a1cb6f2 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/result +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/continueIndent/result @@ -6,5 +6,4 @@ (run "echo hi world goodnight") (run "echo goodbyefrog") (run "echo goodbyefrog") -(run "echo hello") -(run "echo this is some more useful stuff") +(run "echo hello this is some more useful stuff") diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/Dockerfile deleted file mode 100644 index 2157f51f0..000000000 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM busybox - -# The following will create two instructions -# `Run foo` -# `bar` -# because empty line will break the escape. -# The parser will generate the following: -# (from "busybox") -# (run "foo") -# (bar "") -# And `bar` will return an error instruction later -# Note: Parse() will not immediately error out. -RUN foo \ - -bar diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/result b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/result deleted file mode 100644 index 29305cc3b..000000000 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/empty-line-after-escape/result +++ /dev/null @@ -1,3 +0,0 @@ -(from "busybox") -(run "foo") -(bar "") diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/escapes/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/escapes/Dockerfile index 05c5d9790..1ffb17ef0 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/escapes/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/escapes/Dockerfile @@ -6,7 +6,9 @@ RUN apt-get \update && \ ADD \conf\\" /.znc RUN foo \ + bar \ + baz CMD [ "\/usr\\\"/bin/znc", "-f", "-r" ] diff --git a/vendor/github.com/docker/docker/builder/dockerfile/shell_parser.go b/vendor/github.com/docker/docker/builder/dockerfile/shell_parser.go index 3a095299a..189afd1fd 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/shell_parser.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/shell_parser.go @@ -8,6 +8,7 @@ package dockerfile import ( "fmt" + "runtime" "strings" "text/scanner" "unicode" @@ -298,9 +299,16 @@ func (sw *shellWord) processName() string { } func (sw *shellWord) getEnv(name string) string { + if runtime.GOOS == "windows" { + // Case-insensitive environment variables on Windows + name = strings.ToUpper(name) + } for _, env := range sw.envs { i := strings.Index(env, "=") if i < 0 { + if runtime.GOOS == "windows" { + env = strings.ToUpper(env) + } if name == env { // Should probably never get here, but just in case treat // it like "var" and "var=" are the same @@ -308,7 +316,11 @@ func (sw *shellWord) getEnv(name string) string { } continue } - if name != env[:i] { + compareName := env[:i] + if runtime.GOOS == "windows" { + compareName = strings.ToUpper(compareName) + } + if name != compareName { continue } return env[i+1:] diff --git a/vendor/github.com/docker/docker/builder/dockerfile/shell_parser_test.go b/vendor/github.com/docker/docker/builder/dockerfile/shell_parser_test.go index 35dea63fb..6cf691c07 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/shell_parser_test.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/shell_parser_test.go @@ -3,12 +3,14 @@ package dockerfile import ( "bufio" "os" + "runtime" "strings" "testing" ) func TestShellParser4EnvVars(t *testing.T) { fn := "envVarTest" + lineCount := 0 file, err := os.Open(fn) if err != nil { @@ -20,6 +22,7 @@ func TestShellParser4EnvVars(t *testing.T) { envs := []string{"PWD=/home", "SHELL=bash", "KOREAN=한국어"} for scanner.Scan() { line := scanner.Text() + lineCount++ // Trim comments and blank lines i := strings.Index(line, "#") @@ -33,21 +36,30 @@ func TestShellParser4EnvVars(t *testing.T) { } words := strings.Split(line, "|") - if len(words) != 2 { + if len(words) != 3 { t.Fatalf("Error in '%s' - should be exactly one | in:%q", fn, line) } words[0] = strings.TrimSpace(words[0]) words[1] = strings.TrimSpace(words[1]) + words[2] = strings.TrimSpace(words[2]) - newWord, err := ProcessWord(words[0], envs, '\\') - - if err != nil { - newWord = "error" + // Key W=Windows; A=All; U=Unix + if (words[0] != "W") && (words[0] != "A") && (words[0] != "U") { + t.Fatalf("Invalid tag %s at line %d of %s. Must be W, A or U", words[0], lineCount, fn) } - if newWord != words[1] { - t.Fatalf("Error. Src: %s Calc: %s Expected: %s", words[0], newWord, words[1]) + if ((words[0] == "W" || words[0] == "A") && runtime.GOOS == "windows") || + ((words[0] == "U" || words[0] == "A") && runtime.GOOS != "windows") { + newWord, err := ProcessWord(words[1], envs, '\\') + + if err != nil { + newWord = "error" + } + + if newWord != words[2] { + t.Fatalf("Error. Src: %s Calc: %s Expected: %s at line %d", words[1], newWord, words[2], lineCount) + } } } } diff --git a/vendor/github.com/docker/docker/cli/command/node/ps.go b/vendor/github.com/docker/docker/cli/command/node/ps.go index 8591f0466..a034721d2 100644 --- a/vendor/github.com/docker/docker/cli/command/node/ps.go +++ b/vendor/github.com/docker/docker/cli/command/node/ps.go @@ -17,7 +17,6 @@ import ( type psOptions struct { nodeIDs []string - all bool noResolve bool noTrunc bool filter opts.FilterOpt @@ -44,7 +43,6 @@ func newPsCommand(dockerCli *command.DockerCli) *cobra.Command { 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") - flags.BoolVarP(&opts.all, "all", "a", false, "Show all tasks (default shows tasks that are or will be running)") return cmd } @@ -74,11 +72,6 @@ func runPs(dockerCli *command.DockerCli, opts psOptions) error { filter := opts.filter.Value() filter.Add("node", node.ID) - if !opts.all && !filter.Include("desired-state") { - filter.Add("desired-state", string(swarm.TaskStateRunning)) - filter.Add("desired-state", string(swarm.TaskStateAccepted)) - } - nodeTasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) if err != nil { errs = append(errs, err.Error()) diff --git a/vendor/github.com/docker/docker/cli/command/plugin/inspect.go b/vendor/github.com/docker/docker/cli/command/plugin/inspect.go index 13c7fa72d..46ec7b229 100644 --- a/vendor/github.com/docker/docker/cli/command/plugin/inspect.go +++ b/vendor/github.com/docker/docker/cli/command/plugin/inspect.go @@ -1,12 +1,9 @@ package plugin import ( - "fmt" - "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command/inspect" - "github.com/docker/docker/reference" "github.com/spf13/cobra" "golang.org/x/net/context" ) @@ -20,7 +17,7 @@ func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { var opts inspectOptions cmd := &cobra.Command{ - Use: "inspect [OPTIONS] PLUGIN [PLUGIN...]", + Use: "inspect [OPTIONS] PLUGIN|ID [PLUGIN|ID...]", Short: "Display detailed information on one or more plugins", Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { @@ -37,20 +34,8 @@ func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { client := dockerCli.Client() ctx := context.Background() - getRef := func(name string) (interface{}, []byte, error) { - named, err := reference.ParseNamed(name) // FIXME: validate - if err != nil { - return nil, nil, err - } - if reference.IsNameOnly(named) { - named = reference.WithDefaultTag(named) - } - ref, ok := named.(reference.NamedTagged) - if !ok { - return nil, nil, fmt.Errorf("invalid name: %s", named.String()) - } - - return client.PluginInspectWithRaw(ctx, ref.String()) + getRef := func(ref string) (interface{}, []byte, error) { + return client.PluginInspectWithRaw(ctx, ref) } return inspect.Inspect(dockerCli.Out(), opts.pluginNames, opts.format, getRef) diff --git a/vendor/github.com/docker/docker/cli/command/plugin/list.go b/vendor/github.com/docker/docker/cli/command/plugin/list.go index e402d44b3..4f800d7ec 100644 --- a/vendor/github.com/docker/docker/cli/command/plugin/list.go +++ b/vendor/github.com/docker/docker/cli/command/plugin/list.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/pkg/stringutils" "github.com/spf13/cobra" "golang.org/x/net/context" @@ -43,17 +44,19 @@ func runList(dockerCli *command.DockerCli, opts listOptions) error { } w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) - fmt.Fprintf(w, "NAME \tTAG \tDESCRIPTION\tENABLED") + fmt.Fprintf(w, "ID \tNAME \tTAG \tDESCRIPTION\tENABLED") fmt.Fprintf(w, "\n") for _, p := range plugins { + id := p.ID desc := strings.Replace(p.Config.Description, "\n", " ", -1) desc = strings.Replace(desc, "\r", " ", -1) if !opts.noTrunc { + id = stringid.TruncateID(p.ID) desc = stringutils.Ellipsis(desc, 45) } - fmt.Fprintf(w, "%s\t%s\t%s\t%v\n", p.Name, p.Tag, desc, p.Enabled) + fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%v\n", id, p.Name, p.Tag, desc, p.Enabled) } w.Flush() return nil diff --git a/vendor/github.com/docker/docker/cli/command/secret/create.go b/vendor/github.com/docker/docker/cli/command/secret/create.go index faef32ef8..381a93141 100644 --- a/vendor/github.com/docker/docker/cli/command/secret/create.go +++ b/vendor/github.com/docker/docker/cli/command/secret/create.go @@ -25,9 +25,9 @@ func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command { } cmd := &cobra.Command{ - Use: "create [OPTIONS] SECRET [SECRET...]", + Use: "create [OPTIONS] SECRET", Short: "Create a secret using stdin as content", - Args: cli.RequiresMinArgs(1), + Args: cli.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { createOpts.name = args[0] return runSecretCreate(dockerCli, createOpts) diff --git a/vendor/github.com/docker/docker/cli/command/secret/inspect.go b/vendor/github.com/docker/docker/cli/command/secret/inspect.go index 1dda6f783..0a8bd4a23 100644 --- a/vendor/github.com/docker/docker/cli/command/secret/inspect.go +++ b/vendor/github.com/docker/docker/cli/command/secret/inspect.go @@ -25,7 +25,7 @@ func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command { }, } - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template") + cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") return cmd } diff --git a/vendor/github.com/docker/docker/cli/command/secret/ls.go b/vendor/github.com/docker/docker/cli/command/secret/ls.go index d96b37786..faeab314b 100644 --- a/vendor/github.com/docker/docker/cli/command/secret/ls.go +++ b/vendor/github.com/docker/docker/cli/command/secret/ls.go @@ -21,9 +21,10 @@ func newSecretListCommand(dockerCli *command.DockerCli) *cobra.Command { opts := listOptions{} cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Short: "List secrets", - Args: cli.NoArgs, + Use: "ls [OPTIONS]", + Aliases: []string{"list"}, + Short: "List secrets", + Args: cli.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return runSecretList(dockerCli, opts) }, diff --git a/vendor/github.com/docker/docker/cli/command/secret/remove.go b/vendor/github.com/docker/docker/cli/command/secret/remove.go index 97d1f445c..f45a619f6 100644 --- a/vendor/github.com/docker/docker/cli/command/secret/remove.go +++ b/vendor/github.com/docker/docker/cli/command/secret/remove.go @@ -16,9 +16,10 @@ type removeOptions struct { func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { return &cobra.Command{ - Use: "rm SECRET [SECRET...]", - Short: "Remove one or more secrets", - Args: cli.RequiresMinArgs(1), + Use: "rm SECRET [SECRET...]", + Aliases: []string{"remove"}, + Short: "Remove one or more secrets", + Args: cli.RequiresMinArgs(1), RunE: func(cmd *cobra.Command, args []string) error { opts := removeOptions{ names: args, diff --git a/vendor/github.com/docker/docker/cli/command/service/ps.go b/vendor/github.com/docker/docker/cli/command/service/ps.go index 0028507c2..cf94ad737 100644 --- a/vendor/github.com/docker/docker/cli/command/service/ps.go +++ b/vendor/github.com/docker/docker/cli/command/service/ps.go @@ -2,7 +2,6 @@ package service import ( "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" @@ -15,7 +14,6 @@ import ( type psOptions struct { serviceID string - all bool quiet bool noResolve bool noTrunc bool @@ -39,7 +37,6 @@ func newPsCommand(dockerCli *command.DockerCli) *cobra.Command { 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") - flags.BoolVarP(&opts.all, "all", "a", false, "Show all tasks (default shows tasks that are or will be running)") return cmd } @@ -67,11 +64,6 @@ func runPS(dockerCli *command.DockerCli, opts psOptions) error { } } - 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 { return err diff --git a/vendor/github.com/docker/docker/cli/command/stack/common.go b/vendor/github.com/docker/docker/cli/command/stack/common.go index b94c10866..920a1af0c 100644 --- a/vendor/github.com/docker/docker/cli/command/stack/common.go +++ b/vendor/github.com/docker/docker/cli/command/stack/common.go @@ -37,7 +37,7 @@ func getServices( types.ServiceListOptions{Filters: getStackFilter(namespace)}) } -func getNetworks( +func getStackNetworks( ctx context.Context, apiclient client.APIClient, namespace string, diff --git a/vendor/github.com/docker/docker/cli/command/stack/deploy.go b/vendor/github.com/docker/docker/cli/command/stack/deploy.go index 9161c0965..e7764f3b8 100644 --- a/vendor/github.com/docker/docker/cli/command/stack/deploy.go +++ b/vendor/github.com/docker/docker/cli/command/stack/deploy.go @@ -22,6 +22,7 @@ import ( "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" servicecmd "github.com/docker/docker/cli/command/service" + dockerclient "github.com/docker/docker/client" "github.com/docker/docker/opts" runconfigopts "github.com/docker/docker/runconfig/opts" "github.com/docker/go-connections/nat" @@ -123,7 +124,10 @@ func deployCompose(ctx context.Context, dockerCli *command.DockerCli, opts deplo namespace := namespace{name: opts.namespace} - networks := convertNetworks(namespace, config.Networks) + networks, externalNetworks := convertNetworks(namespace, config.Networks) + if err := validateExternalNetworks(ctx, dockerCli, externalNetworks); err != nil { + return err + } if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { return err } @@ -179,7 +183,7 @@ func getConfigFile(filename string) (*composetypes.ConfigFile, error) { func convertNetworks( namespace namespace, networks map[string]composetypes.NetworkConfig, -) map[string]types.NetworkCreate { +) (map[string]types.NetworkCreate, []string) { if networks == nil { networks = make(map[string]composetypes.NetworkConfig) } @@ -187,10 +191,12 @@ func convertNetworks( // TODO: only add default network if it's used networks["default"] = composetypes.NetworkConfig{} + externalNetworks := []string{} result := make(map[string]types.NetworkCreate) for internalName, network := range networks { - if network.External.Name != "" { + if network.External.External { + externalNetworks = append(externalNetworks, network.External.Name) continue } @@ -216,7 +222,29 @@ func convertNetworks( result[internalName] = createOpts } - return result + return result, externalNetworks +} + +func validateExternalNetworks( + ctx context.Context, + dockerCli *command.DockerCli, + externalNetworks []string) error { + client := dockerCli.Client() + + for _, networkName := range externalNetworks { + network, err := client.NetworkInspect(ctx, networkName) + if err != nil { + if dockerclient.IsErrNetworkNotFound(err) { + return fmt.Errorf("network %q is declared as external, but could not be found. You need to create the network before the stack is deployed (with overlay driver)", networkName) + } + return err + } + if network.Scope != "swarm" { + return fmt.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of %q", networkName, network.Scope, "swarm") + } + } + + return nil } func createNetworks( @@ -227,7 +255,7 @@ func createNetworks( ) error { client := dockerCli.Client() - existingNetworks, err := getNetworks(ctx, client, namespace.name) + existingNetworks, err := getStackNetworks(ctx, client, namespace.name) if err != nil { return err } @@ -258,30 +286,39 @@ func createNetworks( func convertServiceNetworks( networks map[string]*composetypes.ServiceNetworkConfig, + networkConfigs map[string]composetypes.NetworkConfig, namespace namespace, name string, -) []swarm.NetworkAttachmentConfig { +) ([]swarm.NetworkAttachmentConfig, error) { if len(networks) == 0 { return []swarm.NetworkAttachmentConfig{ { Target: namespace.scope("default"), Aliases: []string{name}, }, - } + }, nil } nets := []swarm.NetworkAttachmentConfig{} for networkName, network := range networks { + networkConfig, ok := networkConfigs[networkName] + if !ok { + return []swarm.NetworkAttachmentConfig{}, fmt.Errorf("invalid network: %s", networkName) + } var aliases []string if network != nil { aliases = network.Aliases } + target := namespace.scope(networkName) + if networkConfig.External.External { + target = networkName + } nets = append(nets, swarm.NetworkAttachmentConfig{ - Target: namespace.scope(networkName), + Target: target, Aliases: append(aliases, name), }) } - return nets + return nets, nil } func convertVolumes( @@ -472,9 +509,10 @@ func convertServices( services := config.Services volumes := config.Volumes + networks := config.Networks for _, service := range services { - serviceSpec, err := convertService(namespace, service, volumes) + serviceSpec, err := convertService(namespace, service, networks, volumes) if err != nil { return nil, err } @@ -487,6 +525,7 @@ func convertServices( func convertService( namespace namespace, service composetypes.ServiceConfig, + networkConfigs map[string]composetypes.NetworkConfig, volumes map[string]composetypes.VolumeConfig, ) (swarm.ServiceSpec, error) { name := namespace.scope(service.Name) @@ -523,6 +562,11 @@ func convertService( return swarm.ServiceSpec{}, err } + networks, err := convertServiceNetworks(service.Networks, networkConfigs, namespace, service.Name) + if err != nil { + return swarm.ServiceSpec{}, err + } + serviceSpec := swarm.ServiceSpec{ Annotations: swarm.Annotations{ Name: name, @@ -553,7 +597,7 @@ func convertService( }, EndpointSpec: endpoint, Mode: mode, - Networks: convertServiceNetworks(service.Networks, namespace, service.Name), + Networks: networks, UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig), } diff --git a/vendor/github.com/docker/docker/cli/command/stack/remove.go b/vendor/github.com/docker/docker/cli/command/stack/remove.go index 8137903d4..734ff92a5 100644 --- a/vendor/github.com/docker/docker/cli/command/stack/remove.go +++ b/vendor/github.com/docker/docker/cli/command/stack/remove.go @@ -49,7 +49,7 @@ func runRemove(dockerCli *command.DockerCli, opts removeOptions) error { } } - networks, err := getNetworks(ctx, client, namespace) + networks, err := getStackNetworks(ctx, client, namespace) if err != nil { return err } diff --git a/vendor/github.com/docker/docker/cli/command/system/inspect.go b/vendor/github.com/docker/docker/cli/command/system/inspect.go index a403685ee..dee4efcfe 100644 --- a/vendor/github.com/docker/docker/cli/command/system/inspect.go +++ b/vendor/github.com/docker/docker/cli/command/system/inspect.go @@ -45,7 +45,7 @@ func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command { func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { var elementSearcher inspect.GetRefFunc switch opts.inspectType { - case "", "container", "image", "node", "network", "service", "volume", "task": + case "", "container", "image", "node", "network", "service", "volume", "task", "plugin": elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType) default: return fmt.Errorf("%q is not a valid value for --type", opts.inspectType) @@ -95,6 +95,12 @@ func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.Ge } } +func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { + return func(ref string) (interface{}, []byte, error) { + return dockerCli.Client().PluginInspectWithRaw(ctx, ref) + } +} + func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc { var inspectAutodetect = []struct { ObjectType string @@ -108,6 +114,7 @@ func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, {"service", false, inspectService(ctx, dockerCli)}, {"task", false, inspectTasks(ctx, dockerCli)}, {"node", false, inspectNode(ctx, dockerCli)}, + {"plugin", false, inspectPlugin(ctx, dockerCli)}, } isErrNotSwarmManager := func(err error) bool { diff --git a/vendor/github.com/docker/docker/client/errors.go b/vendor/github.com/docker/docker/client/errors.go index 854516669..bf6923f13 100644 --- a/vendor/github.com/docker/docker/client/errors.go +++ b/vendor/github.com/docker/docker/client/errors.go @@ -255,3 +255,24 @@ func IsErrSecretNotFound(err error) bool { _, ok := err.(secretNotFoundError) return ok } + +// pluginNotFoundError implements an error returned when a plugin is not in the docker host. +type pluginNotFoundError struct { + name string +} + +// NotFound indicates that this error type is of NotFound +func (e pluginNotFoundError) NotFound() bool { + return true +} + +// Error returns a string representation of a pluginNotFoundError +func (e pluginNotFoundError) Error() string { + return fmt.Sprintf("Error: No such plugin: %s", e.name) +} + +// IsErrPluginNotFound returns true if the error is caused +// when a plugin is not found in the docker host. +func IsErrPluginNotFound(err error) bool { + return IsErrNotFound(err) +} diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go index e9474b5a9..72900a131 100644 --- a/vendor/github.com/docker/docker/client/plugin_inspect.go +++ b/vendor/github.com/docker/docker/client/plugin_inspect.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "io/ioutil" + "net/http" "github.com/docker/docker/api/types" "golang.org/x/net/context" @@ -13,6 +14,9 @@ import ( func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { resp, err := cli.get(ctx, "/plugins/"+name, nil, nil) if err != nil { + if resp.statusCode == http.StatusNotFound { + return nil, nil, pluginNotFoundError{name} + } return nil, nil, err } diff --git a/vendor/github.com/docker/docker/container/stream/streams.go b/vendor/github.com/docker/docker/container/stream/streams.go index a45e31f21..79f366afd 100644 --- a/vendor/github.com/docker/docker/container/stream/streams.go +++ b/vendor/github.com/docker/docker/container/stream/streams.go @@ -135,7 +135,7 @@ func (c *Config) CopyToPipe(iop libcontainerd.IOPipe) { go func() { pools.Copy(iop.Stdin, stdin) if err := iop.Stdin.Close(); err != nil { - logrus.Errorf("failed to close stdin: %+v", err) + logrus.Warnf("failed to close stdin: %+v", err) } }() } diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-23/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-23/Dockerfile index c2e5bf078..7d9353d2c 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-23/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-23/Dockerfile @@ -4,6 +4,7 @@ FROM fedora:23 +RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile index 0d79914eb..07e373325 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile @@ -4,6 +4,7 @@ FROM fedora:24 +RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile index c80a4deb1..266383260 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile @@ -4,6 +4,7 @@ FROM fedora:25 +RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/generate.sh b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/generate.sh index 895837e3c..58a5381fc 100755 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/generate.sh +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/generate.sh @@ -53,6 +53,9 @@ for version in "${versions[@]}"; do echo "RUN yum install -y kernel-uek-devel-4.1.12-32.el6uek" >> "$version/Dockerfile" echo >> "$version/Dockerfile" ;; + fedora:*) + echo "RUN ${installer} -y upgrade" >> "$version/Dockerfile" + ;; *) ;; esac diff --git a/vendor/github.com/docker/docker/contrib/completion/bash/docker b/vendor/github.com/docker/docker/contrib/completion/bash/docker index 5f1a398aa..63b1b2e65 100644 --- a/vendor/github.com/docker/docker/contrib/completion/bash/docker +++ b/vendor/github.com/docker/docker/contrib/completion/bash/docker @@ -123,7 +123,7 @@ __docker_complete_container_ids() { COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") ) } -__docker_complete_images() { +__docker_images() { local images_args="" case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in @@ -152,8 +152,11 @@ __docker_complete_images() { ;; esac - local images=$(__docker_q images $images_args | awk "$awk_script") - COMPREPLY=( $(compgen -W "$images" -- "$cur") ) + __docker_q images $images_args | awk "$awk_script" | grep -v '$' +} + +__docker_complete_images() { + COMPREPLY=( $(compgen -W "$(__docker_images)" -- "$cur") ) __ltrim_colon_completions "$cur" } @@ -168,13 +171,6 @@ __docker_complete_image_repos_and_tags() { __ltrim_colon_completions "$cur" } -__docker_complete_containers_and_images() { - __docker_complete_containers_all - local containers=( "${COMPREPLY[@]}" ) - __docker_complete_images - COMPREPLY+=( "${containers[@]}" ) -} - # __docker_networks returns a list of all networks. Additional options to # `docker network ls` may be specified in order to filter the list, e.g. # `__docker_networks --filter type=custom` @@ -315,6 +311,22 @@ __docker_complete_runtimes() { COMPREPLY=( $(compgen -W "$(__docker_runtimes)" -- "$cur") ) } +# __docker_stacks returns a list of all stacks. +__docker_stacks() { + __docker_q stack ls | awk 'NR>1 {print $1}' +} + +# __docker_complete_stacks applies completion of stacks based on the current value +# of `$cur` or the value of the optional first option `--cur`, if given. +__docker_complete_stacks() { + local current="$cur" + if [ "$1" = "--cur" ] ; then + current="$2" + shift 2 + fi + COMPREPLY=( $(compgen -W "$(__docker_stacks "$@")" -- "$current") ) +} + # __docker_nodes returns a list of all nodes. Additional options to # `docker node ls` may be specified in order to filter the list, e.g. # `__docker_nodes --filter role=manager` @@ -397,6 +409,13 @@ __docker_append_to_completions() { COMPREPLY=( ${COMPREPLY[@]/%/"$1"} ) } +# __docker_is_experimental tests whether the currently configured Docker daemon +# runs in experimental mode. If so, the function exits with 0 (true). +# Otherwise, or if the result cannot be determined, the exit value is 1 (false). +__docker_is_experimental() { + [ "$(__docker_q version -f '{{.Server.Experimental}}')" = "true" ] +} + # __docker_pos_first_nonflag finds the position of the first word that is neither # option nor an option's argument. If there are options that require arguments, # you should pass a glob describing those options, e.g. "--option1|-o|--option2" @@ -839,6 +858,7 @@ _docker_docker() { *) local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) if [ $cword -eq $counter ]; then + __docker_is_experimental && commands+=(${experimental_commands[*]}) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) fi ;; @@ -1297,7 +1317,6 @@ _docker_container_run() { --memory-swap --memory-swappiness --memory-reservation - --mount --name --network --network-alias @@ -1863,6 +1882,10 @@ _docker_daemon() { esac } +_docker_deploy() { + __docker_is_experimental && _docker_stack_deploy +} + _docker_diff() { _docker_container_diff } @@ -2253,7 +2276,7 @@ _docker_inspect() { ;; --type) if [ -z "$preselected_type" ] ; then - COMPREPLY=( $( compgen -W "image container" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "container image network node service volume" -- "$cur" ) ) return fi ;; @@ -2270,7 +2293,14 @@ _docker_inspect() { *) case "$type" in '') - __docker_complete_containers_and_images + COMPREPLY=( $( compgen -W " + $(__docker_containers --all) + $(__docker_images) + $(__docker_networks) + $(__docker_nodes) + $(__docker_services) + $(__docker_volumes) + " -- "$cur" ) ) ;; container) __docker_complete_containers_all @@ -2278,6 +2308,18 @@ _docker_inspect() { image) __docker_complete_images ;; + network) + __docker_complete_networks + ;; + node) + __docker_complete_nodes + ;; + service) + __docker_complete_services + ;; + volume) + __docker_complete_volumes + ;; esac esac } @@ -2623,7 +2665,7 @@ _docker_service_ps() { case "$cur" in -*) - COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) ) + COMPREPLY=( $( compgen -W "--filter -f --help --no-resolve --no-trunc --quiet -q" -- "$cur" ) ) ;; *) local counter=$(__docker_pos_first_nonflag '--filter|-f') @@ -3318,6 +3360,166 @@ _docker_search() { esac } + +_docker_stack() { + local subcommands=" + deploy + ls + ps + rm + services + " + local aliases=" + down + list + remove + up + " + __docker_subcommands "$subcommands $aliases" && return + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) ) + ;; + esac +} + +_docker_stack_deploy() { + case "$prev" in + --bundle-file) + _filedir dab + return + ;; + --compose-file|-c) + _filedir yml + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--bundle-file --compose-file -c --help --with-registry-auth" -- "$cur" ) ) + ;; + esac +} + +_docker_stack_down() { + _docker_stack_rm +} + +_docker_stack_list() { + _docker_stack_ls +} + +_docker_stack_ls() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + esac +} + +_docker_stack_ps() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + desired-state) + COMPREPLY=( $( compgen -W "accepted running" -- "${cur##*=}" ) ) + return + ;; + id) + __docker_complete_stacks --cur "${cur##*=}" --id + return + ;; + name) + __docker_complete_stacks --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "id name desired-state" -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--all -a --filter -f --help --no-resolve --no-trunc" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_stacks + fi + ;; + esac +} + +_docker_stack_remove() { + _docker_stack_rm +} + +_docker_stack_rm() { + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--help" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag) + if [ $cword -eq $counter ]; then + __docker_complete_stacks + fi + ;; + esac +} + +_docker_stack_services() { + local key=$(__docker_map_key_of_current_option '--filter|-f') + case "$key" in + id) + __docker_complete_services --cur "${cur##*=}" --id + return + ;; + label) + return + ;; + name) + __docker_complete_services --cur "${cur##*=}" --name + return + ;; + esac + + case "$prev" in + --filter|-f) + COMPREPLY=( $( compgen -S = -W "id label name" -- "$cur" ) ) + __docker_nospace + return + ;; + esac + + case "$cur" in + -*) + COMPREPLY=( $( compgen -W "--filter -f --help --quiet -q" -- "$cur" ) ) + ;; + *) + local counter=$(__docker_pos_first_nonflag '--filter|-f') + if [ $cword -eq $counter ]; then + __docker_complete_stacks + fi + ;; + esac +} + +_docker_stack_up() { + _docker_stack_deploy +} + + _docker_start() { _docker_container_start } @@ -3651,6 +3853,7 @@ _docker() { save search service + stack start stats stop @@ -3665,6 +3868,10 @@ _docker() { wait ) + local experimental_commands=( + deploy + ) + # These options are valid as global options for all client commands # and valid as command options for `docker daemon` local global_boolean_options=" diff --git a/vendor/github.com/docker/docker/contrib/completion/fish/docker.fish b/vendor/github.com/docker/docker/contrib/completion/fish/docker.fish index 6630331b7..2715cb1aa 100644 --- a/vendor/github.com/docker/docker/contrib/completion/fish/docker.fish +++ b/vendor/github.com/docker/docker/contrib/completion/fish/docker.fish @@ -137,7 +137,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s m -l memory -d 'Memory limit (format: [], where unit = b, k, m or g)' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: [], where unit = b, k, m or g)" -complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l mount -d 'Attach a filesystem mount to the container' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l name -d 'Assign a name to the container' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l net -d 'Set the Network mode for the container' complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s P -l publish-all -d 'Publish all exposed ports to random ports on the host interfaces' @@ -329,7 +328,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l link -d 'Add li complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s m -l memory -d 'Memory limit (format: [], where unit = b, k, m or g)' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: [], where unit = b, k, m or g)" -complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l mount -d 'Attach a filesystem mount to the container' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l name -d 'Assign a name to the container' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l net -d 'Set the Network mode for the container' complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s P -l publish-all -d 'Publish all exposed ports to random ports on the host interfaces' diff --git a/vendor/github.com/docker/docker/contrib/completion/zsh/_docker b/vendor/github.com/docker/docker/contrib/completion/zsh/_docker index a65b7d9ff..5dfd1ef64 100644 --- a/vendor/github.com/docker/docker/contrib/completion/zsh/_docker +++ b/vendor/github.com/docker/docker/contrib/completion/zsh/_docker @@ -551,7 +551,6 @@ __docker_container_subcommand() { "($help)--log-driver=[Default driver for container logs]:logging driver:__docker_complete_log_drivers" "($help)*--log-opt=[Log driver specific options]:log driver options:__docker_complete_log_options" "($help)--mac-address=[Container MAC address]:MAC address: " - "($help)*--mount=[Attach a filesystem mount to the container]:mount: " "($help)--name=[Container name]:name: " "($help)--network=[Connect a container to a network]:network mode:(bridge none container host)" "($help)*--network-alias=[Add network-scoped alias for the container]:alias: " @@ -1883,6 +1882,147 @@ __docker_service_subcommand() { # EO service +# BO stack + +__docker_stack_complete_ps_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + (desired-state) + state_opts=('accepted' 'running') + _describe -t state-opts "desired state options" state_opts && ret=0 + ;; + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('desired-state' 'id' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_stack_complete_services_filters() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + + if compset -P '*='; then + case "${${words[-1]%=*}#*=}" in + *) + _message 'value' && ret=0 + ;; + esac + else + opts=('id' 'label' 'name') + _describe -t filter-opts "filter options" opts -qS "=" && ret=0 + fi + + return ret +} + +__docker_stacks() { + [[ $PREFIX = -* ]] && return 1 + integer ret=1 + local line s + declare -a lines stacks + + lines=(${(f)${:-"$(_call_program commands docker $docker_options stack ls)"$'\n'}}) + + # Parse header line to find columns + local i=1 j=1 k header=${lines[1]} + declare -A begin end + while (( j < ${#header} - 1 )); do + i=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 1 )) + j=$(( i + ${${header[$i,-1]}[(i) ]} - 1 )) + k=$(( j + ${${header[$j,-1]}[(i)[^ ]]} - 2 )) + begin[${header[$i,$((j-1))]}]=$i + end[${header[$i,$((j-1))]}]=$k + done + end[${header[$i,$((j-1))]}]=-1 + lines=(${lines[2,-1]}) + + # Service ID + for line in $lines; do + s="${line[${begin[ID]},${end[ID]}]%% ##}" + stacks=($stacks $s) + done + + _describe -t stacks-list "stacks" stacks "$@" && ret=0 + return ret +} + +__docker_complete_stacks() { + [[ $PREFIX = -* ]] && return 1 + __docker_stacks "$@" +} + +__docker_stack_commands() { + local -a _docker_stack_subcommands + _docker_stack_subcommands=( + "deploy:Deploy a new stack or update an existing stack" + "ls:List stacks" + "ps:List the tasks in the stack" + "rm:Remove the stack" + "services:List the services in the stack" + ) + _describe -t docker-stack-commands "docker stack command" _docker_stack_subcommands +} + +__docker_stack_subcommand() { + local -a _command_args opts_help + local expl help="--help" + integer ret=1 + + opts_help=("(: -)--help[Print usage]") + + case "$words[1]" in + (deploy|up) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)--bundle-file=[Path to a Distributed Application Bundle file]:dab:_files -g \"*.dab\"" \ + "($help -c --compose-file)"{-c=,--compose-file=}"[Path to a Compose file]:compose file:_files -g \"*.(yml|yaml)\"" \ + "($help)--with-registry-auth[Send registry authentication details to Swarm agents]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (ls|list) + _arguments $(__docker_arguments) \ + $opts_help && ret=0 + ;; + (ps) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -a --all)"{-a,--all}"[Display all tasks]" \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_stack_complete_ps_filters" \ + "($help)--no-resolve[Do not map IDs to Names]" \ + "($help)--no-trunc[Do not truncate output]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (rm|remove|down) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (services) + _arguments $(__docker_arguments) \ + $opts_help \ + "($help)*"{-f=,--filter=}"[Filter output based on conditions provided]:filter:__docker_stack_complete_services_filters" \ + "($help -q --quiet)"{-q,--quiet}"[Only display IDs]" \ + "($help -):stack:__docker_complete_stacks" && ret=0 + ;; + (help) + _arguments $(__docker_arguments) ":subcommand:__docker_stack_commands" && ret=0 + ;; + esac + + return ret +} + +# EO stack + # BO swarm __docker_swarm_commands() { @@ -2451,6 +2591,23 @@ __docker_subcommand() { ;; esac ;; + (stack) + local curcontext="$curcontext" state + _arguments $(__docker_arguments) \ + $opts_help \ + "($help -): :->command" \ + "($help -)*:: :->option-or-argument" && ret=0 + + case $state in + (command) + __docker_stack_commands && ret=0 + ;; + (option-or-argument) + curcontext=${curcontext%:*:*}:docker-${words[-1]}: + __docker_stack_subcommand && ret=0 + ;; + esac + ;; (swarm) local curcontext="$curcontext" state _arguments $(__docker_arguments) \ diff --git a/vendor/github.com/docker/docker/daemon/cluster/cluster.go b/vendor/github.com/docker/docker/daemon/cluster/cluster.go index 8bb46a699..b2afe15ee 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/cluster.go +++ b/vendor/github.com/docker/docker/daemon/cluster/cluster.go @@ -16,6 +16,7 @@ import ( "time" "github.com/Sirupsen/logrus" + "github.com/docker/distribution/digest" distreference "github.com/docker/distribution/reference" apierrors "github.com/docker/docker/api/errors" apitypes "github.com/docker/docker/api/types" @@ -1024,6 +1025,9 @@ func (c *Cluster) GetServices(options apitypes.ServiceListOptions) ([]types.Serv // TODO(nishanttotla): After the packages converge, the function must // convert distreference.Named -> distreference.Canonical, and the logic simplified. func (c *Cluster) imageWithDigestString(ctx context.Context, image string, authConfig *apitypes.AuthConfig) (string, error) { + if _, err := digest.ParseDigest(image); err == nil { + return "", errors.New("image reference is an image ID") + } ref, err := distreference.ParseNamed(image) if err != nil { return "", err diff --git a/vendor/github.com/docker/docker/daemon/cluster/convert/container.go b/vendor/github.com/docker/docker/daemon/cluster/convert/container.go index 8eb56b6eb..10383f749 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/convert/container.go +++ b/vendor/github.com/docker/docker/daemon/cluster/convert/container.go @@ -64,6 +64,13 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec { } } } + + if m.TmpfsOptions != nil { + mount.TmpfsOptions = &mounttypes.TmpfsOptions{ + SizeBytes: m.TmpfsOptions.SizeBytes, + Mode: m.TmpfsOptions.Mode, + } + } containerSpec.Mounts = append(containerSpec.Mounts, mount) } @@ -174,9 +181,7 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) { mount.BindOptions = &swarmapi.Mount_BindOptions{Propagation: swarmapi.Mount_BindOptions_MountPropagation(mountPropagation)} } else if string(m.BindOptions.Propagation) != "" { return nil, fmt.Errorf("invalid MountPropagation: %q", m.BindOptions.Propagation) - } - } if m.VolumeOptions != nil { @@ -192,6 +197,13 @@ func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) { } } + if m.TmpfsOptions != nil { + mount.TmpfsOptions = &swarmapi.Mount_TmpfsOptions{ + SizeBytes: m.TmpfsOptions.SizeBytes, + Mode: m.TmpfsOptions.Mode, + } + } + containerSpec.Mounts = append(containerSpec.Mounts, mount) } diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go b/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go index db7991b4d..5cbbf4da1 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go @@ -28,8 +28,8 @@ type Backend interface { FindNetwork(idName string) (libnetwork.Network, error) SetupIngress(req clustertypes.NetworkCreateRequest, nodeIP string) error PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error - CreateManagedContainer(config types.ContainerCreateConfig, validateHostname bool) (container.ContainerCreateCreatedBody, error) - ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error + CreateManagedContainer(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) + ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error ContainerStop(name string, seconds *int) error ContainerLogs(context.Context, string, *backend.ContainerLogsConfig, chan struct{}) error ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go b/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go index 010c18c5b..09325be25 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go @@ -10,12 +10,11 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/docker/docker/api/server/httputils" + "github.com/docker/distribution/digest" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/backend" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/versions" "github.com/docker/docker/daemon/cluster/convert" executorpkg "github.com/docker/docker/daemon/cluster/executor" "github.com/docker/docker/reference" @@ -53,6 +52,11 @@ func newContainerAdapter(b executorpkg.Backend, task *api.Task, secrets exec.Sec func (c *containerAdapter) pullImage(ctx context.Context) error { spec := c.container.spec() + // Skip pulling if the image is referenced by image ID. + if _, err := digest.ParseDigest(spec.Image); err == nil { + return nil + } + // Skip pulling if the image is referenced by digest and already // exists locally. named, err := reference.ParseNamed(spec.Image) @@ -209,8 +213,6 @@ func (c *containerAdapter) waitForDetach(ctx context.Context) error { func (c *containerAdapter) create(ctx context.Context) error { var cr containertypes.ContainerCreateCreatedBody var err error - version := httputils.VersionFromContext(ctx) - validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{ Name: c.container.name(), @@ -218,7 +220,7 @@ func (c *containerAdapter) create(ctx context.Context) error { HostConfig: c.container.hostConfig(), // Use the first network in container create NetworkingConfig: c.container.createNetworkingConfig(), - }, validateHostname); err != nil { + }); err != nil { return err } @@ -257,9 +259,7 @@ func (c *containerAdapter) create(ctx context.Context) error { } func (c *containerAdapter) start(ctx context.Context) error { - version := httputils.VersionFromContext(ctx) - validateHostname := versions.GreaterThanOrEqualTo(version, "1.24") - return c.backend.ContainerStart(c.container.name(), nil, validateHostname, "", "") + return c.backend.ContainerStart(c.container.name(), nil, "", "") } func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) { diff --git a/vendor/github.com/docker/docker/daemon/commit.go b/vendor/github.com/docker/docker/daemon/commit.go index ae6f51be3..333f7f2f9 100644 --- a/vendor/github.com/docker/docker/daemon/commit.go +++ b/vendor/github.com/docker/docker/daemon/commit.go @@ -46,6 +46,11 @@ func merge(userConf, imageConf *containertypes.Config) error { imageEnvKey := strings.Split(imageEnv, "=")[0] for _, userEnv := range userConf.Env { userEnvKey := strings.Split(userEnv, "=")[0] + if runtime.GOOS == "windows" { + // Case insensitive environment variables on Windows + imageEnvKey = strings.ToUpper(imageEnvKey) + userEnvKey = strings.ToUpper(userEnvKey) + } if imageEnvKey == userEnvKey { found = true break diff --git a/vendor/github.com/docker/docker/daemon/container.go b/vendor/github.com/docker/docker/daemon/container.go index d27ed27db..dd4a5d6c1 100644 --- a/vendor/github.com/docker/docker/daemon/container.go +++ b/vendor/github.com/docker/docker/daemon/container.go @@ -3,7 +3,6 @@ package daemon import ( "fmt" "path/filepath" - "regexp" "time" "github.com/docker/docker/api/errors" @@ -204,7 +203,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig * // verifyContainerSettings performs validation of the hostconfig and config // structures. -func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool, validateHostname bool) ([]string, error) { +func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) { // First perform verification of settings common across all platforms. if config != nil { @@ -222,18 +221,6 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon } } - // Validate if the given hostname is RFC 1123 (https://tools.ietf.org/html/rfc1123) compliant. - if validateHostname && len(config.Hostname) > 0 { - // RFC1123 specifies that 63 bytes is the maximium length - // Windows has the limitation of 63 bytes in length - // Linux hostname is limited to HOST_NAME_MAX=64, not including the terminating null byte. - // We limit the length to 63 bytes here to match RFC1035 and RFC1123. - matched, _ := regexp.MatchString("^(([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])\\.)*([[:alnum:]]|[[:alnum:]][[:alnum:]\\-]*[[:alnum:]])$", config.Hostname) - if len(config.Hostname) > 63 || !matched { - return nil, fmt.Errorf("invalid hostname format: %s", config.Hostname) - } - } - // Validate if Env contains empty variable or not (e.g., ``, `=foo`) for _, env := range config.Env { if _, err := opts.ValidateEnv(env); err != nil { @@ -268,11 +255,11 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon switch p.Name { case "always", "unless-stopped", "no": if p.MaximumRetryCount != 0 { - return nil, fmt.Errorf("maximum restart count not valid with restart policy of '%s'", p.Name) + return nil, fmt.Errorf("maximum retry count cannot be used with restart policy '%s'", p.Name) } case "on-failure": - if p.MaximumRetryCount < 1 { - return nil, fmt.Errorf("maximum restart count must be a positive integer") + if p.MaximumRetryCount < 0 { + return nil, fmt.Errorf("maximum retry count cannot be negative") } case "": // do nothing diff --git a/vendor/github.com/docker/docker/daemon/create.go b/vendor/github.com/docker/docker/daemon/create.go index 88133a159..85d3779eb 100644 --- a/vendor/github.com/docker/docker/daemon/create.go +++ b/vendor/github.com/docker/docker/daemon/create.go @@ -25,22 +25,22 @@ import ( ) // CreateManagedContainer creates a container that is managed by a Service -func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig, validateHostname bool) (containertypes.ContainerCreateCreatedBody, error) { - return daemon.containerCreate(params, true, validateHostname) +func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (containertypes.ContainerCreateCreatedBody, error) { + return daemon.containerCreate(params, true) } // ContainerCreate creates a regular container -func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig, validateHostname bool) (containertypes.ContainerCreateCreatedBody, error) { - return daemon.containerCreate(params, false, validateHostname) +func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (containertypes.ContainerCreateCreatedBody, error) { + return daemon.containerCreate(params, false) } -func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool, validateHostname bool) (containertypes.ContainerCreateCreatedBody, error) { +func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (containertypes.ContainerCreateCreatedBody, error) { start := time.Now() if params.Config == nil { return containertypes.ContainerCreateCreatedBody{}, fmt.Errorf("Config cannot be empty in order to create a container") } - warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false, validateHostname) + warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config, false) if err != nil { return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, err } diff --git a/vendor/github.com/docker/docker/daemon/daemon.go b/vendor/github.com/docker/docker/daemon/daemon.go index 9de1411d5..7c2ce5055 100644 --- a/vendor/github.com/docker/docker/daemon/daemon.go +++ b/vendor/github.com/docker/docker/daemon/daemon.go @@ -40,7 +40,6 @@ import ( "github.com/docker/docker/libcontainerd" "github.com/docker/docker/migrate/v1" "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/graphdb" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/progress" @@ -158,7 +157,6 @@ func (daemon *Daemon) restore() error { } } - var migrateLegacyLinks bool removeContainers := make(map[string]*container.Container) restartContainers := make(map[*container.Container]chan struct{}) activeSandboxes := make(map[string]interface{}) @@ -190,6 +188,8 @@ func (daemon *Daemon) restore() error { } } } + + var migrateLegacyLinks bool // Not relevant on Windows var wg sync.WaitGroup var mapLock sync.Mutex for _, c := range containers { @@ -265,24 +265,15 @@ func (daemon *Daemon) restore() error { return fmt.Errorf("Error initializing network controller: %v", err) } - // migrate any legacy links from sqlite - linkdbFile := filepath.Join(daemon.root, "linkgraph.db") - var legacyLinkDB *graphdb.Database + // Perform migration of legacy sqlite links (no-op on Windows) if migrateLegacyLinks { - legacyLinkDB, err = graphdb.NewSqliteConn(linkdbFile) - if err != nil { - return fmt.Errorf("error connecting to legacy link graph DB %s, container links may be lost: %v", linkdbFile, err) + if err := daemon.sqliteMigration(containers); err != nil { + return err } - defer legacyLinkDB.Close() } // Now that all the containers are registered, register the links for _, c := range containers { - if migrateLegacyLinks { - if err := daemon.migrateLegacySqliteLinks(legacyLinkDB, c); err != nil { - return err - } - } if err := daemon.registerLinks(c, c.HostConfig); err != nil { logrus.Errorf("failed to register link for container %s: %v", c.ID, err) } @@ -692,7 +683,11 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event // on Windows to dump Go routine stacks - d.setupDumpStackTrap(config.Root) + stackDumpDir := config.Root + if execRoot := config.GetExecRoot(); execRoot != "" { + stackDumpDir = execRoot + } + d.setupDumpStackTrap(stackDumpDir) return d, nil } @@ -792,7 +787,13 @@ func (daemon *Daemon) Shutdown() error { }) } - // Shutdown plugins after containers. Dont change the order. + if daemon.layerStore != nil { + if err := daemon.layerStore.Cleanup(); err != nil { + logrus.Errorf("Error during layer Store.Cleanup(): %v", err) + } + } + + // Shutdown plugins after containers and layerstore. Don't change the order. daemon.pluginShutdown() // trigger libnetwork Stop only if it's initialized @@ -800,12 +801,6 @@ func (daemon *Daemon) Shutdown() error { daemon.netController.Stop() } - if daemon.layerStore != nil { - if err := daemon.layerStore.Cleanup(); err != nil { - logrus.Errorf("Error during layer Store.Cleanup(): %v", err) - } - } - if err := daemon.cleanupMounts(); err != nil { return err } diff --git a/vendor/github.com/docker/docker/daemon/links.go b/vendor/github.com/docker/docker/daemon/links.go index aaf1917d7..7f691d4f1 100644 --- a/vendor/github.com/docker/docker/daemon/links.go +++ b/vendor/github.com/docker/docker/daemon/links.go @@ -1,12 +1,9 @@ package daemon import ( - "strings" "sync" - "github.com/Sirupsen/logrus" "github.com/docker/docker/container" - "github.com/docker/docker/pkg/graphdb" ) // linkIndex stores link relationships between containers, including their specified alias @@ -88,41 +85,3 @@ func (l *linkIndex) delete(container *container.Container) { delete(l.childIdx, container) l.mu.Unlock() } - -// migrateLegacySqliteLinks migrates sqlite links to use links from HostConfig -// when sqlite links were used, hostConfig.Links was set to nil -func (daemon *Daemon) migrateLegacySqliteLinks(db *graphdb.Database, container *container.Container) error { - // if links is populated (or an empty slice), then this isn't using sqlite links and can be skipped - if container.HostConfig == nil || container.HostConfig.Links != nil { - return nil - } - - logrus.Debugf("migrating legacy sqlite link info for container: %s", container.ID) - - fullName := container.Name - if fullName[0] != '/' { - fullName = "/" + fullName - } - - // don't use a nil slice, this ensures that the check above will skip once the migration has completed - links := []string{} - children, err := db.Children(fullName, 0) - if err != nil { - if !strings.Contains(err.Error(), "Cannot find child for") { - return err - } - // else continue... it's ok if we didn't find any children, it'll just be nil and we can continue the migration - } - - for _, child := range children { - c, err := daemon.GetContainer(child.Entity.ID()) - if err != nil { - return err - } - - links = append(links, c.Name+":"+child.Edge.Name) - } - - container.HostConfig.Links = links - return container.WriteHostConfig() -} diff --git a/vendor/github.com/docker/docker/daemon/links_linux.go b/vendor/github.com/docker/docker/daemon/links_linux.go new file mode 100644 index 000000000..2ea40d9e5 --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/links_linux.go @@ -0,0 +1,72 @@ +package daemon + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/Sirupsen/logrus" + "github.com/docker/docker/container" + "github.com/docker/docker/pkg/graphdb" +) + +// migrateLegacySqliteLinks migrates sqlite links to use links from HostConfig +// when sqlite links were used, hostConfig.Links was set to nil +func (daemon *Daemon) migrateLegacySqliteLinks(db *graphdb.Database, container *container.Container) error { + // if links is populated (or an empty slice), then this isn't using sqlite links and can be skipped + if container.HostConfig == nil || container.HostConfig.Links != nil { + return nil + } + + logrus.Debugf("migrating legacy sqlite link info for container: %s", container.ID) + + fullName := container.Name + if fullName[0] != '/' { + fullName = "/" + fullName + } + + // don't use a nil slice, this ensures that the check above will skip once the migration has completed + links := []string{} + children, err := db.Children(fullName, 0) + if err != nil { + if !strings.Contains(err.Error(), "Cannot find child for") { + return err + } + // else continue... it's ok if we didn't find any children, it'll just be nil and we can continue the migration + } + + for _, child := range children { + c, err := daemon.GetContainer(child.Entity.ID()) + if err != nil { + return err + } + + links = append(links, c.Name+":"+child.Edge.Name) + } + + container.HostConfig.Links = links + return container.WriteHostConfig() +} + +// sqliteMigration performs the link graph DB migration. +func (daemon *Daemon) sqliteMigration(containers map[string]*container.Container) error { + // migrate any legacy links from sqlite + linkdbFile := filepath.Join(daemon.root, "linkgraph.db") + var ( + legacyLinkDB *graphdb.Database + err error + ) + + legacyLinkDB, err = graphdb.NewSqliteConn(linkdbFile) + if err != nil { + return fmt.Errorf("error connecting to legacy link graph DB %s, container links may be lost: %v", linkdbFile, err) + } + defer legacyLinkDB.Close() + + for _, c := range containers { + if err := daemon.migrateLegacySqliteLinks(legacyLinkDB, c); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/links_test.go b/vendor/github.com/docker/docker/daemon/links_linux_test.go similarity index 100% rename from vendor/github.com/docker/docker/daemon/links_test.go rename to vendor/github.com/docker/docker/daemon/links_linux_test.go diff --git a/vendor/github.com/docker/docker/daemon/links_notlinux.go b/vendor/github.com/docker/docker/daemon/links_notlinux.go new file mode 100644 index 000000000..12c226cfa --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/links_notlinux.go @@ -0,0 +1,10 @@ +// +build !linux + +package daemon + +import "github.com/docker/docker/container" + +// sqliteMigration performs the link graph DB migration. No-op on platforms other than Linux +func (daemon *Daemon) sqliteMigration(_ map[string]*container.Container) error { + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/logger/logger.go b/vendor/github.com/docker/docker/daemon/logger/logger.go index 1ce7ed595..d09199735 100644 --- a/vendor/github.com/docker/docker/daemon/logger/logger.go +++ b/vendor/github.com/docker/docker/daemon/logger/logger.go @@ -49,7 +49,7 @@ func CopyMessage(msg *Message) *Message { m.Timestamp = msg.Timestamp m.Partial = msg.Partial m.Attrs = make(LogAttributes) - for k, v := range m.Attrs { + for k, v := range msg.Attrs { m.Attrs[k] = v } return m diff --git a/vendor/github.com/docker/docker/daemon/logger/logger_test.go b/vendor/github.com/docker/docker/daemon/logger/logger_test.go new file mode 100644 index 000000000..16e1514d2 --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/logger/logger_test.go @@ -0,0 +1,26 @@ +package logger + +import ( + "reflect" + "testing" + "time" +) + +func TestCopyMessage(t *testing.T) { + msg := &Message{ + Line: []byte("test line."), + Source: "stdout", + Timestamp: time.Now(), + Attrs: LogAttributes{ + "key1": "val1", + "key2": "val2", + "key3": "val3", + }, + Partial: true, + } + + m := CopyMessage(msg) + if !reflect.DeepEqual(m, msg) { + t.Fatalf("CopyMessage failed to copy message") + } +} diff --git a/vendor/github.com/docker/docker/daemon/start.go b/vendor/github.com/docker/docker/daemon/start.go index 807fe569d..1a5b0e755 100644 --- a/vendor/github.com/docker/docker/daemon/start.go +++ b/vendor/github.com/docker/docker/daemon/start.go @@ -19,7 +19,7 @@ import ( ) // ContainerStart starts a container. -func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error { +func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error { if checkpoint != "" && !daemon.HasExperimental() { return apierrors.NewBadRequestError(fmt.Errorf("checkpoint is only supported in experimental mode")) } @@ -73,7 +73,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos // check if hostConfig is in line with the current system settings. // It may happen cgroups are umounted or the like. - if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false, validateHostname); err != nil { + if _, err = daemon.verifyContainerSettings(container.HostConfig, nil, false); err != nil { return err } // Adapt for old containers in case we have updates in this function and diff --git a/vendor/github.com/docker/docker/daemon/update.go b/vendor/github.com/docker/docker/daemon/update.go index 3e05047ae..67c0e59bf 100644 --- a/vendor/github.com/docker/docker/daemon/update.go +++ b/vendor/github.com/docker/docker/daemon/update.go @@ -7,10 +7,10 @@ import ( ) // ContainerUpdate updates configuration of the container -func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) (container.ContainerUpdateOKBody, error) { +func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error) { var warnings []string - warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true, validateHostname) + warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true) if err != nil { return container.ContainerUpdateOKBody{Warnings: warnings}, err } diff --git a/vendor/github.com/docker/docker/distribution/errors.go b/vendor/github.com/docker/docker/distribution/errors.go index ed8c3c053..7f9e20f27 100644 --- a/vendor/github.com/docker/docker/distribution/errors.go +++ b/vendor/github.com/docker/docker/distribution/errors.go @@ -6,6 +6,7 @@ import ( "syscall" "github.com/Sirupsen/logrus" + "github.com/docker/distribution" "github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/v2" "github.com/docker/distribution/registry/client" @@ -139,6 +140,9 @@ func retryOnError(err error) error { case *client.UnexpectedHTTPResponseError: return xfer.DoNotRetry{Err: err} case error: + if err == distribution.ErrBlobUnknown { + return xfer.DoNotRetry{Err: err} + } if strings.Contains(err.Error(), strings.ToLower(syscall.ENOSPC.Error())) { return xfer.DoNotRetry{Err: err} } diff --git a/vendor/github.com/docker/docker/distribution/pull_v2.go b/vendor/github.com/docker/docker/distribution/pull_v2.go index d62200dda..5bfb328a1 100644 --- a/vendor/github.com/docker/docker/distribution/pull_v2.go +++ b/vendor/github.com/docker/docker/distribution/pull_v2.go @@ -189,9 +189,6 @@ func (ld *v2LayerDescriptor) Download(ctx context.Context, progressOutput progre layerDownload, err := ld.open(ctx) if err != nil { logrus.Errorf("Error initiating layer download: %v", err) - if err == distribution.ErrBlobUnknown { - return nil, 0, xfer.DoNotRetry{Err: err} - } return nil, 0, retryOnError(err) } diff --git a/vendor/github.com/docker/docker/distribution/push_v2.go b/vendor/github.com/docker/docker/distribution/push_v2.go index f2a1f0271..d72882b0d 100644 --- a/vendor/github.com/docker/docker/distribution/push_v2.go +++ b/vendor/github.com/docker/docker/distribution/push_v2.go @@ -523,6 +523,7 @@ func (pd *v2PushDescriptor) layerAlreadyExists( layerDigests = append(layerDigests, meta.Digest) } +attempts: for _, dgst := range layerDigests { meta := digestToMetadata[dgst] logrus.Debugf("Checking for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.FullName()) @@ -541,15 +542,14 @@ func (pd *v2PushDescriptor) layerAlreadyExists( } desc.MediaType = schema2.MediaTypeLayer exists = true - break + break attempts case distribution.ErrBlobUnknown: if meta.SourceRepository == pd.repoInfo.FullName() { // remove the mapping to the target repository pd.v2MetadataService.Remove(*meta) } default: - progress.Update(progressOutput, pd.ID(), "Image push failed") - return desc, false, retryOnError(err) + logrus.WithError(err).Debugf("Failed to check for presence of layer %s (%s) in %s", diffID, dgst, pd.repoInfo.FullName()) } } diff --git a/vendor/github.com/docker/docker/distribution/push_v2_test.go b/vendor/github.com/docker/docker/distribution/push_v2_test.go index b76e1a373..c56f50bda 100644 --- a/vendor/github.com/docker/docker/distribution/push_v2_test.go +++ b/vendor/github.com/docker/docker/distribution/push_v2_test.go @@ -180,7 +180,7 @@ func TestLayerAlreadyExists(t *testing.T) { maxExistenceChecks: 1, metadata: []metadata.V2Metadata{{Digest: digest.Digest("apple"), SourceRepository: "docker.io/library/busybox"}}, remoteErrors: map[digest.Digest]error{digest.Digest("apple"): distribution.ErrAccessDenied}, - expectedError: distribution.ErrAccessDenied, + expectedError: nil, expectedRequests: []string{"apple"}, }, { @@ -310,7 +310,7 @@ func TestLayerAlreadyExists(t *testing.T) { expectedRemovals: []metadata.V2Metadata{taggedMetadata("key3", "apple", "docker.io/library/busybox")}, }, { - name: "stop on first error", + name: "don't stop on first error", targetRepo: "user/app", hmacKey: "key", metadata: []metadata.V2Metadata{ @@ -321,9 +321,12 @@ func TestLayerAlreadyExists(t *testing.T) { maxExistenceChecks: 3, remoteErrors: map[digest.Digest]error{"orange": distribution.ErrAccessDenied}, remoteBlobs: map[digest.Digest]distribution.Descriptor{digest.Digest("apple"): {}}, - expectedError: distribution.ErrAccessDenied, - expectedRequests: []string{"plum", "orange"}, - expectedRemovals: []metadata.V2Metadata{taggedMetadata("key", "plum", "docker.io/user/app")}, + expectedError: nil, + expectedRequests: []string{"plum", "orange", "banana"}, + expectedRemovals: []metadata.V2Metadata{ + taggedMetadata("key", "plum", "docker.io/user/app"), + taggedMetadata("key", "banana", "docker.io/user/app"), + }, }, { name: "remove outdated metadata", diff --git a/vendor/github.com/docker/docker/docs/api/v1.18.md b/vendor/github.com/docker/docker/docs/api/v1.18.md index bfffc9e0a..df063c20b 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.18.md +++ b/vendor/github.com/docker/docker/docs/api/v1.18.md @@ -16,9 +16,7 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.18 - -# 1. Brief introduction +## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can [Bind Docker to another host/port or a Unix socket](../commandline/dockerd.md#bind-docker-to-another-host-port-or-a-unix-socket). @@ -26,11 +24,11 @@ redirect_from: or `pull`, the HTTP connection is hijacked to transport `STDOUT`, `STDIN` and `STDERR`. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -123,7 +121,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -310,7 +308,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -443,7 +441,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -507,7 +505,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -547,7 +545,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -589,7 +587,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -614,7 +612,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -702,7 +700,7 @@ This endpoint returns a live stream of a container's resource usage statistics. - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize?h=&w=` @@ -729,7 +727,7 @@ Resize the TTY for container with `id`. You must restart the container for the - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -754,7 +752,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -779,7 +777,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -803,7 +801,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -828,7 +826,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -853,7 +851,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -873,7 +871,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -893,7 +891,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -978,7 +976,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1015,7 +1013,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1038,7 +1036,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1067,7 +1065,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1097,9 +1095,9 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1185,7 +1183,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1256,7 +1254,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1300,7 +1298,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1351,7 +1349,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1385,7 +1383,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -1428,7 +1426,7 @@ then be used in the URL. This duplicates the command line's flow. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -1456,7 +1454,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -1489,7 +1487,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -1542,9 +1540,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -1572,7 +1570,7 @@ Get the default username and email - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -1637,7 +1635,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -1667,7 +1665,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -1689,7 +1687,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -1751,7 +1749,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -1793,7 +1791,7 @@ Docker images report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -1823,7 +1821,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -1852,7 +1850,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -1875,7 +1873,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -1896,7 +1894,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -1939,7 +1937,7 @@ Sets up an exec instance in a running container `id` - **201** – no error - **404** – no such container -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -1980,7 +1978,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2007,7 +2005,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2112,9 +2110,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -2132,7 +2130,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -2148,7 +2146,7 @@ from **200 OK** to **101 UPGRADED** and resends the same headers. This might change in the future. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.19.md b/vendor/github.com/docker/docker/docs/api/v1.19.md index b20f1d7b8..d22c158d8 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.19.md +++ b/vendor/github.com/docker/docker/docs/api/v1.19.md @@ -16,8 +16,6 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.19 - ## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can @@ -28,11 +26,11 @@ redirect_from: - When the client API version is newer than the daemon's, these calls return an HTTP `400 Bad Request` error message. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -125,7 +123,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -322,7 +320,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -459,7 +457,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -523,7 +521,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -565,7 +563,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -607,7 +605,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -632,7 +630,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -741,7 +739,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize?h=&w=` @@ -768,7 +766,7 @@ Resize the TTY for container with `id`. You must restart the container for the - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -793,7 +791,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -818,7 +816,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -842,7 +840,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -867,7 +865,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -892,7 +890,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -912,7 +910,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -932,7 +930,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1017,7 +1015,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1054,7 +1052,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1077,7 +1075,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1106,7 +1104,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1136,9 +1134,9 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1229,7 +1227,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1302,7 +1300,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1346,7 +1344,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1397,7 +1395,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1451,7 +1449,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -1494,7 +1492,7 @@ then be used in the URL. This duplicates the command line's flow. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -1522,7 +1520,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -1555,7 +1553,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -1614,9 +1612,9 @@ be deprecated and replaced by the `is_automated` property. - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -1644,7 +1642,7 @@ Get the default username and email - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -1713,7 +1711,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -1743,7 +1741,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -1765,7 +1763,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -1831,7 +1829,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -1873,7 +1871,7 @@ Docker images report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -1903,7 +1901,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -1932,7 +1930,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -1955,7 +1953,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -1976,7 +1974,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2022,7 +2020,7 @@ Sets up an exec instance in a running container `id` - **201** – no error - **404** – no such container -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2063,7 +2061,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2090,7 +2088,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2195,9 +2193,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -2215,7 +2213,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -2230,7 +2228,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.20.md b/vendor/github.com/docker/docker/docs/api/v1.20.md index 1f093f3cc..ab83b3eca 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.20.md +++ b/vendor/github.com/docker/docker/docs/api/v1.20.md @@ -16,9 +16,7 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.20 - -# 1. Brief introduction +## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can [Bind Docker to another host/port or a Unix socket](../commandline/dockerd.md#bind-docker-to-another-host-port-or-a-unix-socket). @@ -26,11 +24,11 @@ redirect_from: or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -123,7 +121,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -324,7 +322,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -466,7 +464,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -530,7 +528,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -572,7 +570,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -614,7 +612,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -639,7 +637,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -748,7 +746,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize?h=&w=` @@ -775,7 +773,7 @@ Resize the TTY for container with `id`. You must restart the container for the - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -800,7 +798,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -825,7 +823,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -849,7 +847,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -874,7 +872,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -899,7 +897,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -919,7 +917,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -939,7 +937,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1024,7 +1022,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1061,7 +1059,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1084,7 +1082,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1113,7 +1111,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1145,14 +1143,14 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -### Retrieving information about files and folders in a container +#### Retrieving information about files and folders in a container `HEAD /containers/(id or name)/archive` See the description of the `X-Docker-Container-Path-Stat` header in the following section. -### Get an archive of a filesystem resource in a container +#### Get an archive of a filesystem resource in a container `GET /containers/(id or name)/archive` @@ -1217,7 +1215,7 @@ desired. - no such file or directory (**path** does not exist) - **500** - server error -### Extract an archive of files or folders to a directory in a container +#### Extract an archive of files or folders to a directory in a container `PUT /containers/(id or name)/archive` @@ -1265,9 +1263,9 @@ Upload a tar archive to be extracted to a path in the filesystem of container - no such file or directory (**path** resource does not exist) - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1358,7 +1356,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1456,7 +1454,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1500,7 +1498,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1551,7 +1549,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1605,7 +1603,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -1648,7 +1646,7 @@ then be used in the URL. This duplicates the command line's flow. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -1676,7 +1674,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -1709,7 +1707,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -1762,9 +1760,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -1792,7 +1790,7 @@ Get the default username and email - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -1861,7 +1859,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -1892,7 +1890,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -1914,7 +1912,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -1986,7 +1984,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -2028,7 +2026,7 @@ Docker images report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -2058,7 +2056,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -2087,7 +2085,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -2110,7 +2108,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -2131,7 +2129,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2177,7 +2175,7 @@ Sets up an exec instance in a running container `id` - **201** – no error - **404** – no such container -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2218,7 +2216,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2245,7 +2243,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2348,9 +2346,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -2368,7 +2366,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -2383,7 +2381,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.21.md b/vendor/github.com/docker/docker/docs/api/v1.21.md index 7d2c65d6b..3ab8ac0c9 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.21.md +++ b/vendor/github.com/docker/docker/docs/api/v1.21.md @@ -16,8 +16,6 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.21 - ## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can @@ -28,11 +26,11 @@ redirect_from: - When the client API version is newer than the daemon's, these calls return an HTTP `400 Bad Request` error message. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -129,7 +127,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -347,7 +345,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -537,7 +535,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -601,7 +599,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -643,7 +641,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -685,7 +683,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -710,7 +708,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -831,7 +829,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize` @@ -858,7 +856,7 @@ Resize the TTY for container with `id`. The unit is number of characters. You m - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -883,7 +881,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -908,7 +906,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -932,7 +930,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -957,7 +955,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -982,7 +980,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -1002,7 +1000,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -1022,7 +1020,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1107,7 +1105,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1144,7 +1142,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1167,7 +1165,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1196,7 +1194,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1228,14 +1226,14 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -### Retrieving information about files and folders in a container +#### Retrieving information about files and folders in a container `HEAD /containers/(id or name)/archive` See the description of the `X-Docker-Container-Path-Stat` header in the following section. -### Get an archive of a filesystem resource in a container +#### Get an archive of a filesystem resource in a container `GET /containers/(id or name)/archive` @@ -1300,7 +1298,7 @@ desired. - no such file or directory (**path** does not exist) - **500** - server error -### Extract an archive of files or folders to a directory in a container +#### Extract an archive of files or folders to a directory in a container `PUT /containers/(id or name)/archive` @@ -1348,9 +1346,9 @@ Upload a tar archive to be extracted to a path in the filesystem of container - no such file or directory (**path** resource does not exist) - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1441,7 +1439,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1545,7 +1543,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1593,7 +1591,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1704,7 +1702,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1758,7 +1756,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -1801,7 +1799,7 @@ then be used in the URL. This duplicates the command line's flow. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -1829,7 +1827,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -1862,7 +1860,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -1915,9 +1913,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -1945,7 +1943,7 @@ Get the default username and email - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -2016,7 +2014,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -2047,7 +2045,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -2069,7 +2067,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -2141,7 +2139,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -2184,7 +2182,7 @@ Docker images report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -2214,7 +2212,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -2243,7 +2241,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -2266,7 +2264,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -2287,7 +2285,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2337,7 +2335,7 @@ Sets up an exec instance in a running container `id` - **409** - container is paused - **500** - server error -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2379,7 +2377,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2406,7 +2404,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2532,9 +2530,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -## 2.4 Volumes +### 2.4 Volumes -### List volumes +#### List volumes `GET /volumes` @@ -2566,7 +2564,7 @@ Return low-level information about the `exec` command `id`. - **200** - no error - **500** - server error -### Create a volume +#### Create a volume `POST /volumes/create` @@ -2604,7 +2602,7 @@ Create a volume - **DriverOpts** - A mapping of driver options and values. These options are passed directly to the driver and are driver specific. -### Inspect a volume +#### Inspect a volume `GET /volumes/(name)` @@ -2631,7 +2629,7 @@ Return low-level information on the volume `name` - **404** - no such volume - **500** - server error -### Remove a volume +#### Remove a volume `DELETE /volumes/(name)` @@ -2652,9 +2650,9 @@ Instruct the driver to remove the volume (`name`). - **409** - volume is in use and cannot be removed - **500** - server error -## 2.5 Networks +### 2.5 Networks -### List networks +#### List networks `GET /networks` @@ -2735,7 +2733,7 @@ Content-Type: application/json - **200** - no error - **500** - server error -### Inspect network +#### Inspect network `GET /networks/` @@ -2786,7 +2784,7 @@ Content-Type: application/json - **200** - no error - **404** - network not found -### Create a network +#### Create a network `POST /networks/create` @@ -2844,7 +2842,7 @@ Content-Type: application/json `{"Subnet": , "IPRange": , "Gateway": , "AuxAddress": }` - **Options** - Network specific options to be used by the drivers -### Connect a container to a network +#### Connect a container to a network `POST /networks/(id)/connect` @@ -2875,7 +2873,7 @@ Content-Type: application/json - **container** - container-id/name to be connected to the network -### Disconnect a container from a network +#### Disconnect a container from a network `POST /networks/(id)/disconnect` @@ -2906,7 +2904,7 @@ Content-Type: application/json - **Container** - container-id/name to be disconnected from a network -### Remove a network +#### Remove a network `DELETE /networks/(id)` @@ -2926,9 +2924,9 @@ Instruct the driver to remove the network (`id`). - **404** - no such network - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -2946,7 +2944,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -2961,7 +2959,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.22.md b/vendor/github.com/docker/docker/docs/api/v1.22.md index 66391eafa..943224cab 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.22.md +++ b/vendor/github.com/docker/docker/docs/api/v1.22.md @@ -16,9 +16,7 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.22 - -# 1. Brief introduction +## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can [Bind Docker to another host/port or a Unix socket](../commandline/dockerd.md#bind-docker-to-another-host-port-or-a-unix-socket). @@ -26,11 +24,11 @@ redirect_from: or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -212,7 +210,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -460,7 +458,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -663,7 +661,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -727,7 +725,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -769,7 +767,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -811,7 +809,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -836,7 +834,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -957,7 +955,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize` @@ -984,7 +982,7 @@ Resize the TTY for container with `id`. The unit is number of characters. You m - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -1015,7 +1013,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -1040,7 +1038,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -1064,7 +1062,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -1089,7 +1087,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Update a container +#### Update a container `POST /containers/(id or name)/update` @@ -1129,7 +1127,7 @@ Update resource configs of one or more containers. - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -1154,7 +1152,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -1174,7 +1172,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -1194,7 +1192,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1283,7 +1281,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1323,7 +1321,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1346,7 +1344,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1375,7 +1373,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1407,14 +1405,14 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -### Retrieving information about files and folders in a container +#### Retrieving information about files and folders in a container `HEAD /containers/(id or name)/archive` See the description of the `X-Docker-Container-Path-Stat` header in the following section. -### Get an archive of a filesystem resource in a container +#### Get an archive of a filesystem resource in a container `GET /containers/(id or name)/archive` @@ -1479,7 +1477,7 @@ desired. - no such file or directory (**path** does not exist) - **500** - server error -### Extract an archive of files or folders to a directory in a container +#### Extract an archive of files or folders to a directory in a container `PUT /containers/(id or name)/archive` @@ -1527,9 +1525,9 @@ Upload a tar archive to be extracted to a path in the filesystem of container - no such file or directory (**path** resource does not exist) - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1620,7 +1618,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1725,7 +1723,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1791,7 +1789,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1902,7 +1900,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1956,7 +1954,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -2018,7 +2016,7 @@ The push is cancelled if the HTTP connection is closed. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -2046,7 +2044,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -2079,7 +2077,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -2132,9 +2130,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -2162,7 +2160,7 @@ Get the default username and email - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -2249,7 +2247,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -2281,7 +2279,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -2303,7 +2301,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -2375,7 +2373,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -2575,7 +2573,7 @@ Docker networks report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -2605,7 +2603,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -2634,7 +2632,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -2657,7 +2655,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -2678,7 +2676,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2732,7 +2730,7 @@ Sets up an exec instance in a running container `id` - **409** - container is paused - **500** - server error -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2774,7 +2772,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2801,7 +2799,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2844,9 +2842,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -## 2.4 Volumes +### 2.4 Volumes -### List volumes +#### List volumes `GET /volumes` @@ -2879,7 +2877,7 @@ Return low-level information about the `exec` command `id`. - **200** - no error - **500** - server error -### Create a volume +#### Create a volume `POST /volumes/create` @@ -2917,7 +2915,7 @@ Create a volume - **DriverOpts** - A mapping of driver options and values. These options are passed directly to the driver and are driver specific. -### Inspect a volume +#### Inspect a volume `GET /volumes/(name)` @@ -2944,7 +2942,7 @@ Return low-level information on the volume `name` - **404** - no such volume - **500** - server error -### Remove a volume +#### Remove a volume `DELETE /volumes/(name)` @@ -2965,9 +2963,9 @@ Instruct the driver to remove the volume (`name`). - **409** - volume is in use and cannot be removed - **500** - server error -## 2.5 Networks +### 2.5 Networks -### List networks +#### List networks `GET /networks` @@ -3051,7 +3049,7 @@ Content-Type: application/json - **200** - no error - **500** - server error -### Inspect network +#### Inspect network `GET /networks/` @@ -3107,7 +3105,7 @@ Content-Type: application/json - **200** - no error - **404** - network not found -### Create a network +#### Create a network `POST /networks/create` @@ -3174,7 +3172,7 @@ Content-Type: application/json - **Options** - Driver-specific options, specified as a map: `{"option":"value" [,"option2":"value2"]}` - **Options** - Network specific options to be used by the drivers -### Connect a container to a network +#### Connect a container to a network `POST /networks/(id)/connect` @@ -3211,7 +3209,7 @@ Content-Type: application/json - **container** - container-id/name to be connected to the network -### Disconnect a container from a network +#### Disconnect a container from a network `POST /networks/(id)/disconnect` @@ -3244,7 +3242,7 @@ Content-Type: application/json - **Container** - container-id/name to be disconnected from a network - **Force** - Force the container to disconnect from a network -### Remove a network +#### Remove a network `DELETE /networks/(id)` @@ -3264,9 +3262,9 @@ Instruct the driver to remove the network (`id`). - **404** - no such network - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -3284,7 +3282,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -3299,7 +3297,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.23.md b/vendor/github.com/docker/docker/docs/api/v1.23.md index f0a560c77..d8c39b39e 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.23.md +++ b/vendor/github.com/docker/docker/docs/api/v1.23.md @@ -16,8 +16,6 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.23 - ## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can @@ -28,11 +26,11 @@ redirect_from: - When the client API version is newer than the daemon's, these calls return an HTTP `400 Bad Request` error message. -# 2. Endpoints +## 2. Endpoints -## 2.1 Containers +### 2.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -236,7 +234,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -488,7 +486,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -691,7 +689,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -755,7 +753,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -797,7 +795,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -839,7 +837,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -864,7 +862,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -988,7 +986,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize` @@ -1015,7 +1013,7 @@ Resize the TTY for container with `id`. The unit is number of characters. You m - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -1046,7 +1044,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -1071,7 +1069,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -1095,7 +1093,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -1120,7 +1118,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Update a container +#### Update a container `POST /containers/(id or name)/update` @@ -1164,7 +1162,7 @@ Update configuration of one or more containers. - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -1189,7 +1187,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -1209,7 +1207,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -1229,7 +1227,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1318,7 +1316,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1358,7 +1356,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1381,7 +1379,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1410,7 +1408,7 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Copy files or folders from a container +#### Copy files or folders from a container `POST /containers/(id or name)/copy` @@ -1442,14 +1440,14 @@ Copy files or folders of container `id` - **404** – no such container - **500** – server error -### Retrieving information about files and folders in a container +#### Retrieving information about files and folders in a container `HEAD /containers/(id or name)/archive` See the description of the `X-Docker-Container-Path-Stat` header in the following section. -### Get an archive of a filesystem resource in a container +#### Get an archive of a filesystem resource in a container `GET /containers/(id or name)/archive` @@ -1514,7 +1512,7 @@ desired. - no such file or directory (**path** does not exist) - **500** - server error -### Extract an archive of files or folders to a directory in a container +#### Extract an archive of files or folders to a directory in a container `PUT /containers/(id or name)/archive` @@ -1562,9 +1560,9 @@ Upload a tar archive to be extracted to a path in the filesystem of container - no such file or directory (**path** resource does not exist) - **500** – server error -## 2.2 Images +### 2.2 Images -### List Images +#### List Images `GET /images/json` @@ -1655,7 +1653,7 @@ references on the command line. - `label=key` or `label="key=value"` of an image label - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1761,7 +1759,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1827,7 +1825,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1945,7 +1943,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1999,7 +1997,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -2061,7 +2059,7 @@ The push is cancelled if the HTTP connection is closed. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -2089,7 +2087,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -2122,7 +2120,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -2175,9 +2173,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 2.3 Misc +### 2.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -2210,7 +2208,7 @@ if available, for accessing the registry without password. - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -2299,7 +2297,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -2331,7 +2329,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -2353,7 +2351,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -2425,7 +2423,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -2625,7 +2623,7 @@ Docker networks report the following events: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -2655,7 +2653,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -2684,7 +2682,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -2733,7 +2731,7 @@ action completes. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -2754,7 +2752,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2808,7 +2806,7 @@ Sets up an exec instance in a running container `id` - **409** - container is paused - **500** - server error -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2850,7 +2848,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2877,7 +2875,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2920,9 +2918,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -## 2.4 Volumes +### 2.4 Volumes -### List volumes +#### List volumes `GET /volumes` @@ -2955,7 +2953,7 @@ Return low-level information about the `exec` command `id`. - **200** - no error - **500** - server error -### Create a volume +#### Create a volume `POST /volumes/create` @@ -3002,7 +3000,7 @@ Create a volume passed directly to the driver and are driver specific. - **Labels** - Labels to set on the volume, specified as a map: `{"key":"value","key2":"value2"}` -### Inspect a volume +#### Inspect a volume `GET /volumes/(name)` @@ -3033,7 +3031,7 @@ Return low-level information on the volume `name` - **404** - no such volume - **500** - server error -### Remove a volume +#### Remove a volume `DELETE /volumes/(name)` @@ -3054,9 +3052,9 @@ Instruct the driver to remove the volume (`name`). - **409** - volume is in use and cannot be removed - **500** - server error -## 3.5 Networks +### 3.5 Networks -### List networks +#### List networks `GET /networks` @@ -3146,7 +3144,7 @@ Content-Type: application/json - **200** - no error - **500** - server error -### Inspect network +#### Inspect network `GET /networks/` @@ -3208,7 +3206,7 @@ Content-Type: application/json - **200** - no error - **404** - network not found -### Create a network +#### Create a network `POST /networks/create` @@ -3291,7 +3289,7 @@ Content-Type: application/json - **Options** - Network specific options to be used by the drivers - **Labels** - Labels to set on the network, specified as a map: `{"key":"value" [,"key2":"value2"]}` -### Connect a container to a network +#### Connect a container to a network `POST /networks/(id)/connect` @@ -3328,7 +3326,7 @@ Content-Type: application/json - **container** - container-id/name to be connected to the network -### Disconnect a container from a network +#### Disconnect a container from a network `POST /networks/(id)/disconnect` @@ -3361,7 +3359,7 @@ Content-Type: application/json - **Container** - container-id/name to be disconnected from a network - **Force** - Force the container to disconnect from a network -### Remove a network +#### Remove a network `DELETE /networks/(id)` @@ -3381,9 +3379,9 @@ Instruct the driver to remove the network (`id`). - **404** - no such network - **500** - server error -# 3. Going further +## 3. Going further -## 3.1 Inside `docker run` +### 3.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -3401,7 +3399,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 3.2 Hijacking +### 3.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -3416,7 +3414,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 3.3 CORS Requests +### 3.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/v1.24.md b/vendor/github.com/docker/docker/docs/api/v1.24.md index 475fb7d33..d05ee7a2d 100644 --- a/vendor/github.com/docker/docker/docs/api/v1.24.md +++ b/vendor/github.com/docker/docker/docs/api/v1.24.md @@ -16,9 +16,7 @@ redirect_from: will be rejected. --> -# Docker Engine API v1.24 - -# 1. Brief introduction +## 1. Brief introduction - The daemon listens on `unix:///var/run/docker.sock` but you can [Bind Docker to another host/port or a Unix socket](../commandline/dockerd.md#bind-docker-to-another-host-port-or-a-unix-socket). @@ -26,7 +24,7 @@ redirect_from: or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. -# 2. Errors +## 2. Errors The Engine API uses standard HTTP status codes to indicate the success or failure of the API call. The body of the response will be JSON in the following format: @@ -36,11 +34,11 @@ The Engine API uses standard HTTP status codes to indicate the success or failur The status codes that are returned for each endpoint are specified in the endpoint documentation below. -# 3. Endpoints +## 3. Endpoints -## 3.1 Containers +### 3.1 Containers -### List containers +#### List containers `GET /containers/json` @@ -245,7 +243,7 @@ List containers - **400** – bad parameter - **500** – server error -### Create a container +#### Create a container `POST /containers/create` @@ -511,7 +509,7 @@ Create a container - **409** – conflict - **500** – server error -### Inspect a container +#### Inspect a container `GET /containers/(id or name)/json` @@ -721,7 +719,7 @@ Return low-level information on the container `id` - **404** – no such container - **500** – server error -### List processes running inside a container +#### List processes running inside a container `GET /containers/(id or name)/top` @@ -785,7 +783,7 @@ supported on Windows. - **404** – no such container - **500** – server error -### Get container logs +#### Get container logs `GET /containers/(id or name)/logs` @@ -828,7 +826,7 @@ Get `stdout` and `stderr` logs from the container ``id`` - **404** – no such container - **500** – server error -### Inspect changes on a container's filesystem +#### Inspect changes on a container's filesystem `GET /containers/(id or name)/changes` @@ -870,7 +868,7 @@ Values for `Kind`: - **404** – no such container - **500** – server error -### Export a container +#### Export a container `GET /containers/(id or name)/export` @@ -895,7 +893,7 @@ Export the contents of container `id` - **404** – no such container - **500** – server error -### Get container stats based on resource usage +#### Get container stats based on resource usage `GET /containers/(id or name)/stats` @@ -1019,7 +1017,7 @@ The precpu_stats is the cpu statistic of last read, which is used for calculatin - **404** – no such container - **500** – server error -### Resize a container TTY +#### Resize a container TTY `POST /containers/(id or name)/resize` @@ -1046,7 +1044,7 @@ Resize the TTY for container with `id`. The unit is number of characters. You m - **404** – No such container - **500** – Cannot resize container -### Start a container +#### Start a container `POST /containers/(id or name)/start` @@ -1073,7 +1071,7 @@ Start the container `id` - **404** – no such container - **500** – server error -### Stop a container +#### Stop a container `POST /containers/(id or name)/stop` @@ -1098,7 +1096,7 @@ Stop the container `id` - **404** – no such container - **500** – server error -### Restart a container +#### Restart a container `POST /containers/(id or name)/restart` @@ -1122,7 +1120,7 @@ Restart the container `id` - **404** – no such container - **500** – server error -### Kill a container +#### Kill a container `POST /containers/(id or name)/kill` @@ -1147,7 +1145,7 @@ Kill the container `id` - **404** – no such container - **500** – server error -### Update a container +#### Update a container `POST /containers/(id or name)/update` @@ -1191,7 +1189,7 @@ Update configuration of one or more containers. - **404** – no such container - **500** – server error -### Rename a container +#### Rename a container `POST /containers/(id or name)/rename` @@ -1216,7 +1214,7 @@ Rename the container `id` to a `new_name` - **409** - conflict name already assigned - **500** – server error -### Pause a container +#### Pause a container `POST /containers/(id or name)/pause` @@ -1236,7 +1234,7 @@ Pause the container `id` - **404** – no such container - **500** – server error -### Unpause a container +#### Unpause a container `POST /containers/(id or name)/unpause` @@ -1256,7 +1254,7 @@ Unpause the container `id` - **404** – no such container - **500** – server error -### Attach to a container +#### Attach to a container `POST /containers/(id or name)/attach` @@ -1345,7 +1343,7 @@ The simplest way to implement the Attach protocol is the following: 4. Read the extracted size and output it on the correct output. 5. Goto 1. -### Attach to a container (websocket) +#### Attach to a container (websocket) `GET /containers/(id or name)/attach/ws` @@ -1385,7 +1383,7 @@ Implements websocket protocol handshake according to [RFC 6455](http://tools.iet - **404** – no such container - **500** – server error -### Wait a container +#### Wait a container `POST /containers/(id or name)/wait` @@ -1408,7 +1406,7 @@ Block until container `id` stops, then returns the exit code - **404** – no such container - **500** – server error -### Remove a container +#### Remove a container `DELETE /containers/(id or name)` @@ -1437,14 +1435,14 @@ Remove the container `id` from the filesystem - **409** – conflict - **500** – server error -### Retrieving information about files and folders in a container +#### Retrieving information about files and folders in a container `HEAD /containers/(id or name)/archive` See the description of the `X-Docker-Container-Path-Stat` header in the following section. -### Get an archive of a filesystem resource in a container +#### Get an archive of a filesystem resource in a container `GET /containers/(id or name)/archive` @@ -1509,7 +1507,7 @@ desired. - no such file or directory (**path** does not exist) - **500** - server error -### Extract an archive of files or folders to a directory in a container +#### Extract an archive of files or folders to a directory in a container `PUT /containers/(id or name)/archive` @@ -1557,9 +1555,9 @@ Upload a tar archive to be extracted to a path in the filesystem of container - no such file or directory (**path** resource does not exist) - **500** – server error -## 3.2 Images +### 3.2 Images -### List Images +#### List Images `GET /images/json` @@ -1652,7 +1650,7 @@ references on the command line. - `since`=(`[:]`, `` or ``) - **filter** - only return images with the specified name -### Build image from a Dockerfile +#### Build image from a Dockerfile `POST /build` @@ -1758,7 +1756,7 @@ or being killed. - **200** – no error - **500** – server error -### Create an image +#### Create an image `POST /images/create` @@ -1824,7 +1822,7 @@ a base64-encoded AuthConfig object. -### Inspect an image +#### Inspect an image `GET /images/(name)/json` @@ -1942,7 +1940,7 @@ Return low-level information on the image `name` - **404** – no such image - **500** – server error -### Get the history of an image +#### Get the history of an image `GET /images/(name)/history` @@ -1996,7 +1994,7 @@ Return the history of the image `name` - **404** – no such image - **500** – server error -### Push an image on the registry +#### Push an image on the registry `POST /images/(name)/push` @@ -2058,7 +2056,7 @@ The push is cancelled if the HTTP connection is closed. - **404** – no such image - **500** – server error -### Tag an image into a repository +#### Tag an image into a repository `POST /images/(name)/tag` @@ -2085,7 +2083,7 @@ Tag the image `name` into a repository - **409** – conflict - **500** – server error -### Remove an image +#### Remove an image `DELETE /images/(name)` @@ -2118,7 +2116,7 @@ Remove the image `name` from the filesystem - **409** – conflict - **500** – server error -### Search images +#### Search images `GET /images/search` @@ -2176,9 +2174,9 @@ Search for an image on [Docker Hub](https://hub.docker.com). - **200** – no error - **500** – server error -## 3.3 Misc +### 3.3 Misc -### Check auth configuration +#### Check auth configuration `POST /auth` @@ -2211,7 +2209,7 @@ if available, for accessing the registry without password. - **204** – no error - **500** – server error -### Display system-wide information +#### Display system-wide information `GET /info` @@ -2304,7 +2302,7 @@ Display system-wide information - **200** – no error - **500** – server error -### Show the docker version information +#### Show the docker version information `GET /version` @@ -2336,7 +2334,7 @@ Show the docker version information - **200** – no error - **500** – server error -### Ping the docker server +#### Ping the docker server `GET /_ping` @@ -2358,7 +2356,7 @@ Ping the docker server - **200** - no error - **500** - server error -### Create a new image from a container's changes +#### Create a new image from a container's changes `POST /commit` @@ -2430,7 +2428,7 @@ Create a new image from a container's changes - **404** – no such container - **500** – server error -### Monitor Docker's events +#### Monitor Docker's events `GET /events` @@ -2635,7 +2633,7 @@ Docker daemon report the following event: - **200** – no error - **500** – server error -### Get a tarball containing all images in a repository +#### Get a tarball containing all images in a repository `GET /images/(name)/get` @@ -2665,7 +2663,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Get a tarball containing all images +#### Get a tarball containing all images `GET /images/get` @@ -2694,7 +2692,7 @@ See the [image tarball format](#image-tarball-format) for more details. - **200** – no error - **500** – server error -### Load a tarball with a set of images and tags into docker +#### Load a tarball with a set of images and tags into docker `POST /images/load` @@ -2743,7 +2741,7 @@ action completes. - **200** – no error - **500** – server error -### Image tarball format +#### Image tarball format An image tarball contains one directory per image layer (named using its long ID), each containing these files: @@ -2764,7 +2762,7 @@ the root that contains a list of repository and tag names mapped to layer IDs. } ``` -### Exec Create +#### Exec Create `POST /containers/(id or name)/exec` @@ -2818,7 +2816,7 @@ Sets up an exec instance in a running container `id` - **409** - container is paused - **500** - server error -### Exec Start +#### Exec Start `POST /exec/(id)/start` @@ -2860,7 +2858,7 @@ interactive session with the `exec` command. Similar to the stream behavior of `POST /containers/(id or name)/attach` API -### Exec Resize +#### Exec Resize `POST /exec/(id)/resize` @@ -2887,7 +2885,7 @@ This API is valid only if `tty` was specified as part of creating and starting t - **201** – no error - **404** – no such exec instance -### Exec Inspect +#### Exec Inspect `GET /exec/(id)/json` @@ -2930,9 +2928,9 @@ Return low-level information about the `exec` command `id`. - **404** – no such exec instance - **500** - server error -## 3.4 Volumes +### 3.4 Volumes -### List volumes +#### List volumes `GET /volumes` @@ -2970,7 +2968,7 @@ Return low-level information about the `exec` command `id`. - **200** - no error - **500** - server error -### Create a volume +#### Create a volume `POST /volumes/create` @@ -3027,7 +3025,7 @@ Create a volume Refer to the [inspect a volume](#inspect-a-volume) section or details about the JSON fields returned in the response. -### Inspect a volume +#### Inspect a volume `GET /volumes/(name)` @@ -3079,7 +3077,7 @@ response. - **Scope** - Scope describes the level at which the volume exists, can be one of `global` for cluster-wide or `local` for machine level. The default is `local`. -### Remove a volume +#### Remove a volume `DELETE /volumes/(name)` @@ -3100,9 +3098,9 @@ Instruct the driver to remove the volume (`name`). - **409** - volume is in use and cannot be removed - **500** - server error -## 3.5 Networks +### 3.5 Networks -### List networks +#### List networks `GET /networks` @@ -3194,7 +3192,7 @@ Content-Type: application/json - **200** - no error - **500** - server error -### Inspect network +#### Inspect network `GET /networks/` @@ -3256,7 +3254,7 @@ Content-Type: application/json - **200** - no error - **404** - network not found -### Create a network +#### Create a network `POST /networks/create` @@ -3339,7 +3337,7 @@ Content-Type: application/json - **Options** - Network specific options to be used by the drivers - **Labels** - Labels to set on the network, specified as a map: `{"key":"value" [,"key2":"value2"]}` -### Connect a container to a network +#### Connect a container to a network `POST /networks/(id)/connect` @@ -3377,7 +3375,7 @@ Content-Type: application/json - **container** - container-id/name to be connected to the network -### Disconnect a container from a network +#### Disconnect a container from a network `POST /networks/(id)/disconnect` @@ -3411,7 +3409,7 @@ Content-Type: application/json - **Container** - container-id/name to be disconnected from a network - **Force** - Force the container to disconnect from a network -### Remove a network +#### Remove a network `DELETE /networks/(id)` @@ -3431,9 +3429,9 @@ Instruct the driver to remove the network (`id`). - **404** - no such network - **500** - server error -## 3.6 Plugins (experimental) +### 3.6 Plugins (experimental) -### List plugins +#### List plugins `GET /plugins` @@ -3563,7 +3561,7 @@ Content-Type: application/json - **200** - no error - **500** - server error -### Install a plugin +#### Install a plugin `POST /plugins/pull?name=` @@ -3625,7 +3623,7 @@ Content-Length: 175 name must have at least one component - **500** - plugin already exists -### Inspect a plugin +#### Inspect a plugin `GET /plugins/(plugin name)` @@ -3758,7 +3756,7 @@ Content-Type: application/json - **200** - no error - **404** - plugin not installed -### Enable a plugin +#### Enable a plugin `POST /plugins/(plugin name)/enable` @@ -3786,7 +3784,7 @@ Content-Type: text/plain; charset=utf-8 - **200** - no error - **500** - plugin is already enabled -### Disable a plugin +#### Disable a plugin `POST /plugins/(plugin name)/disable` @@ -3814,7 +3812,7 @@ Content-Type: text/plain; charset=utf-8 - **200** - no error - **500** - plugin is already disabled -### Remove a plugin +#### Remove a plugin `DELETE /plugins/(plugin name)` @@ -3844,7 +3842,7 @@ Content-Type: text/plain; charset=utf-8 -## 3.7 Nodes +### 3.7 Nodes **Note**: Node operations require the engine to be part of a swarm. -### List nodes +#### List nodes `GET /nodes` @@ -3964,10 +3962,11 @@ List nodes **Status codes**: -- **200** – no error -- **500** – server error +- **200** – no error +- **406** - node is not part of a swarm +- **500** – server error -### Inspect a node +#### Inspect a node `GET /nodes/(id or name)` @@ -4047,9 +4046,10 @@ Return low-level information on the node `id` - **200** – no error - **404** – no such node +- **406** – node is not part of a swarm - **500** – server error -### Remove a node +#### Remove a node `DELETE /nodes/(id or name)` @@ -4075,9 +4075,10 @@ Remove a node from the swarm. - **200** – no error - **404** – no such node +- **406** – node is not part of a swarm - **500** – server error -### Update a node +#### Update a node `POST /nodes/(id)/update` @@ -4130,11 +4131,12 @@ JSON Parameters: - **200** – no error - **404** – no such node +- **406** – node is not part of a swarm - **500** – server error -## 3.8 Swarm +### 3.8 Swarm -### Inspect swarm +#### Inspect swarm `GET /swarm` @@ -4180,9 +4182,11 @@ Inspect swarm **Status codes**: -- **200** - no error +- **200** - no error +- **406** – node is not part of a swarm +- **500** - sever error -### Initialize a new swarm +#### Initialize a new swarm `POST /swarm/init` @@ -4218,9 +4222,10 @@ Initialize a new swarm. The body of the HTTP response includes the node ID. **Status codes**: -- **200** – no error -- **400** – bad parameter -- **406** – node is already part of a swarm +- **200** – no error +- **400** – bad parameter +- **406** – node is already part of a swarm +- **500** - server error JSON Parameters: @@ -4258,7 +4263,7 @@ JSON Parameters: - **Options** - An object with key/value pairs that are interpreted as protocol-specific options for the external CA driver. -### Join an existing swarm +#### Join an existing swarm `POST /swarm/join` @@ -4284,9 +4289,10 @@ Join an existing swarm **Status codes**: -- **200** – no error -- **400** – bad parameter -- **406** – node is already part of a swarm +- **200** – no error +- **400** – bad parameter +- **406** – node is already part of a swarm +- **500** - server error JSON Parameters: @@ -4300,7 +4306,7 @@ JSON Parameters: - **RemoteAddr** – Address of any manager node already participating in the swarm. - **JoinToken** – Secret token for joining this swarm. -### Leave a swarm +#### Leave a swarm `POST /swarm/leave` @@ -4323,10 +4329,11 @@ Leave a swarm **Status codes**: -- **200** – no error -- **406** – node is not part of a swarm +- **200** – no error +- **406** – node is not part of a swarm +- **500** - server error -### Update a swarm +#### Update a swarm `POST /swarm/update` @@ -4376,9 +4383,10 @@ Update a swarm **Status codes**: -- **200** – no error -- **400** – bad parameter -- **406** – node is not part of a swarm +- **200** – no error +- **400** – bad parameter +- **406** – node is not part of a swarm +- **500** - server error JSON Parameters: @@ -4407,11 +4415,11 @@ JSON Parameters: - **Worker** - Token to use for joining as a worker. - **Manager** - Token to use for joining as a manager. -## 3.9 Services +### 3.9 Services **Note**: Service operations require to first be part of a swarm. -### List services +#### List services `GET /services` @@ -4513,10 +4521,11 @@ List services **Status codes**: -- **200** – no error -- **500** – server error +- **200** – no error +- **406** – node is not part of a swarm +- **500** – server error -### Create a service +#### Create a service `POST /services/create` @@ -4608,9 +4617,10 @@ image](#create-an-image) section for more details. **Status codes**: -- **201** – no error -- **406** – server error or node is not part of a swarm -- **409** – name conflicts with an existing object +- **201** – no error +- **406** – node is not part of a swarm +- **409** – name conflicts with an existing object +- **500** - server error **JSON Parameters**: @@ -4689,7 +4699,7 @@ image](#create-an-image) section for more details. section for more details. -### Remove a service +#### Remove a service `DELETE /services/(id or name)` @@ -4710,9 +4720,10 @@ Stop and remove the service `id` - **200** – no error - **404** – no such service +- **406** - node is not part of a swarm - **500** – server error -### Inspect one or more services +#### Inspect one or more services `GET /services/(id or name)` @@ -4799,9 +4810,10 @@ Return information on the service `id`. - **200** – no error - **404** – no such service +- **406** - node is not part of a swarm - **500** – server error -### Update a service +#### Update a service `POST /services/(id or name)/update` @@ -4932,13 +4944,14 @@ image](#create-an-image) section for more details. - **200** – no error - **404** – no such service +- **406** - node is not part of a swarm - **500** – server error -## 3.10 Tasks +### 3.10 Tasks **Note**: Task operations require the engine to be part of a swarm. -### List tasks +#### List tasks `GET /tasks` @@ -5133,15 +5146,16 @@ List tasks **Status codes**: -- **200** – no error -- **500** – server error +- **200** – no error +- **406** - node is not part of a swarm +- **500** – server error -### Inspect a task +#### Inspect a task -`GET /tasks/(task id)` +`GET /tasks/(id)` -Get details on a task +Get details on the task `id` **Example request**: @@ -5235,13 +5249,14 @@ Get details on a task **Status codes**: -- **200** – no error -- **404** – unknown task -- **500** – server error +- **200** – no error +- **404** – unknown task +- **406** - node is not part of a swarm +- **500** – server error -# 4. Going further +## 4. Going further -## 4.1 Inside `docker run` +### 4.1 Inside `docker run` As an example, the `docker run` command line makes the following API calls: @@ -5259,7 +5274,7 @@ As an example, the `docker run` command line makes the following API calls: - If in detached mode or only `stdin` is attached, display the container's id. -## 4.2 Hijacking +### 4.2 Hijacking In this version of the API, `/attach`, uses hijacking to transport `stdin`, `stdout`, and `stderr` on the same socket. @@ -5274,7 +5289,7 @@ When Docker daemon detects the `Upgrade` header, it switches its status code from **200 OK** to **101 UPGRADED** and resends the same headers. -## 4.3 CORS Requests +### 4.3 CORS Requests To set cross origin requests to the Engine API please give values to `--api-cors-header` when running Docker in daemon mode. Set * (asterisk) allows all, diff --git a/vendor/github.com/docker/docker/docs/api/version-history.md b/vendor/github.com/docker/docker/docs/api/version-history.md index 3e4871dec..4e3de96e9 100644 --- a/vendor/github.com/docker/docker/docs/api/version-history.md +++ b/vendor/github.com/docker/docker/docs/api/version-history.md @@ -72,7 +72,11 @@ keywords: "API, Docker, rcli, REST, documentation" * `DELETE /plugins/(plugin name)` delete a plugin. * `POST /node/(id or name)/update` now accepts both `id` or `name` to identify the node to update. * `GET /images/json` now support a `reference` filter. - +* `GET /secrets` returns information on the secrets. +* `POST /secrets/create` creates a secret. +* `DELETE /secrets/{id}` removes the secret `id`. +* `GET /secrets/{id}` returns information on the secret `id`. +* `POST /secrets/{id}/update` updates the secret `id`. ## v1.24 API changes diff --git a/vendor/github.com/docker/docker/docs/deprecated.md b/vendor/github.com/docker/docker/docs/deprecated.md index 553a90257..d6cfef5d0 100644 --- a/vendor/github.com/docker/docker/docs/deprecated.md +++ b/vendor/github.com/docker/docker/docs/deprecated.md @@ -32,7 +32,7 @@ The `filter` param to filter the list of image by reference (name or name:tag) i **Target For Removal In Release: v1.16** -`repository:shortid` syntax for referencing images is very little used, collides with with tag references can be confused with digest references. +`repository:shortid` syntax for referencing images is very little used, collides with tag references can be confused with digest references. ### `docker daemon` subcommand **Deprecated In Release: [v1.13](https://github.com/docker/docker/releases/tag/v1.13.0)** diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/create.md b/vendor/github.com/docker/docker/docs/reference/commandline/create.md index 9fdfd4c20..0218af3a7 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/create.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/create.md @@ -82,7 +82,6 @@ Options: --memory-reservation string Memory soft limit --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1) - --mount value Attach a filesytem mount to the container (default []) --name string Assign a name to the container --network-alias value Add network-scoped alias for the container (default []) --network string Connect a container to a network (default "default") diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/logs.md b/vendor/github.com/docker/docker/docs/reference/commandline/logs.md index 989460f16..891e10b55 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/logs.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/logs.md @@ -34,7 +34,7 @@ The `docker logs` command batch-retrieves logs present at the time of execution. > **Note**: this command is only functional for containers that are started with > the `json-file` or `journald` logging driver. -For more information about selecting and configuring login-drivers, refer to +For more information about selecting and configuring logging drivers, refer to [Configure logging drivers](https://docs.docker.com/engine/admin/logging/overview/). The `docker logs --follow` command will continue streaming the new output from diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/node_ps.md b/vendor/github.com/docker/docker/docs/reference/commandline/node_ps.md index 7a4054beb..0c54c9cfb 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/node_ps.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/node_ps.md @@ -22,7 +22,7 @@ Usage: docker node ps [OPTIONS] [NODE...] List tasks running on one or more nodes, defaults to current node. Options: - -a, --all Show all tasks (default shows tasks that are or will be running) + -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 diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/plugin_inspect.md b/vendor/github.com/docker/docker/docs/reference/commandline/plugin_inspect.md index 80b8e8c88..9e09e0c58 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/plugin_inspect.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/plugin_inspect.md @@ -16,13 +16,13 @@ keywords: "plugin, inspect" # plugin inspect ```markdown -Usage: docker plugin inspect [OPTIONS] PLUGIN [PLUGIN...] +Usage: docker plugin inspect [OPTIONS] PLUGIN|ID [PLUGIN|ID...] Display detailed information on one or more plugins Options: - -f, --format string Format the output using the given Go template - --help Print usage + -f, --format string Format the output using the given Go template + --help Print usage ``` Returns information about a plugin. By default, this command renders all results diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/plugin_ls.md b/vendor/github.com/docker/docker/docs/reference/commandline/plugin_ls.md index 3ea4c2585..b727b5334 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/plugin_ls.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/plugin_ls.md @@ -36,8 +36,8 @@ Example output: ```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/vendor/github.com/docker/docker/docs/reference/commandline/run.md b/vendor/github.com/docker/docker/docs/reference/commandline/run.md index 6c845e40a..619564701 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/run.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/run.md @@ -92,7 +92,6 @@ Options: --memory-reservation string Memory soft limit --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1) - --mount value Attach a filesystem mount to the container (default []) --name string Assign a name to the container --network-alias value Add network-scoped alias for the container (default []) --network string Connect a container to a network @@ -284,21 +283,6 @@ of a bind mount must be a local directory, not a file. For in-depth information about volumes, refer to [manage data in containers](https://docs.docker.com/engine/tutorials/dockervolumes/) -### Add bin-mounts or volumes using the --mount flag - -The `--mount` flag allows you to mount volumes, host-directories and `tmpfs` -mounts in a container. - -The `--mount` flag supports most options that are supported by the `-v` or the -`--volume` flag, but uses a different syntax. For in-depth information on the -`--mount` flag, and a comparison between `--volume` and `--mount`, refer to -the [service create command reference](service_create.md#add-bind-mounts-or-volumes). - -Examples: - - $ docker run --read-only --mount type=volume,target=/icanwrite busybox touch /icanwrite/here - $ docker run -t -i --mount type=bind,src=/data,dst=/data busybox sh - ### Publish or expose port (-p, --expose) $ docker run -p 127.0.0.1:80:8080 ubuntu bash @@ -678,7 +662,7 @@ The `credentialspec` must be in the format `file://spec.txt` or `registry://keyn ### Stop container with timeout (--stop-timeout) -The `--stop-timeout` flag sets the the timeout (in seconds) that a pre-defined (see `--stop-signal`) system call +The `--stop-timeout` flag sets the timeout (in seconds) that a pre-defined (see `--stop-signal`) system call signal that will be sent to the container to exit. After timeout elapses the container will be killed with SIGKILL. ### Specify isolation technology for container (--isolation) diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/secret_ls.md b/vendor/github.com/docker/docker/docs/reference/commandline/secret_ls.md index 31659e72e..6b34fc214 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/secret_ls.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/secret_ls.md @@ -27,9 +27,9 @@ Options: -q, --quiet Only display IDs ``` -Run this command from a manager to list the secrets in the Swarm. +Run this command on a manager node to list the secrets in the Swarm. -On a manager node: +## Examples ```bash $ docker secret ls diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/service_logs.md b/vendor/github.com/docker/docker/docs/reference/commandline/service_logs.md index eb319141e..e10018636 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/service_logs.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/service_logs.md @@ -35,7 +35,7 @@ The `docker service logs` command batch-retrieves logs present at the time of ex > **Note**: this command is only functional for services that are started with > the `json-file` or `journald` logging driver. -For more information about selecting and configuring login-drivers, refer to +For more information about selecting and configuring logging drivers, refer to [Configure logging drivers](https://docs.docker.com/engine/admin/logging/overview/). The `docker service logs --follow` command will continue streaming the new output from diff --git a/vendor/github.com/docker/docker/docs/reference/commandline/service_ps.md b/vendor/github.com/docker/docker/docs/reference/commandline/service_ps.md index 2554267f3..b824f53da 100644 --- a/vendor/github.com/docker/docker/docs/reference/commandline/service_ps.md +++ b/vendor/github.com/docker/docker/docs/reference/commandline/service_ps.md @@ -22,7 +22,6 @@ Usage: docker service ps [OPTIONS] SERVICE List the tasks of a service Options: - -a, --all Show all tasks (default shows tasks that are or will be running) -f, --filter filter Filter output based on conditions provided --help Print usage --no-resolve Do not map IDs to Names diff --git a/vendor/github.com/docker/docker/docs/reference/glossary.md b/vendor/github.com/docker/docker/docs/reference/glossary.md index 94bd1ceec..0bc39a202 100644 --- a/vendor/github.com/docker/docker/docs/reference/glossary.md +++ b/vendor/github.com/docker/docker/docs/reference/glossary.md @@ -280,7 +280,7 @@ A virtual machine is a program that emulates a complete computer and imitates de It shares physical hardware resources with other users but isolates the operating system. The end user has the same experience on a Virtual Machine as they would have on dedicated hardware. -Compared to to containers, a virtual machine is heavier to run, provides more isolation, +Compared to containers, a virtual machine is heavier to run, provides more isolation, gets its own set of resources and does minimal sharing. *Also known as : VM* diff --git a/vendor/github.com/docker/docker/hack/make.ps1 b/vendor/github.com/docker/docker/hack/make.ps1 new file mode 100644 index 000000000..6084b3492 --- /dev/null +++ b/vendor/github.com/docker/docker/hack/make.ps1 @@ -0,0 +1,401 @@ +<# +.NOTES + Author: @jhowardmsft + + Summary: Windows native build script. This is similar to functionality provided + by hack\make.sh, but uses native Windows PowerShell semantics. It does + not support the full set of options provided by the Linux counterpart. + For example: + + - You can't cross-build Linux docker binaries on Windows + - Hashes aren't generated on binaries + - 'Releasing' isn't supported. + - Integration tests. This is because they currently cannot run inside a container, + and require significant external setup. + + It does however provided the minimum necessary to support parts of local Windows + development and Windows to Windows CI. + + Usage Examples (run from repo root): + "hack\make.ps1 -Binary" to build the binaries + "hack\make.ps1 -Client" to build just the client 64-bit binary + "hack\make.ps1 -TestUnit" to run unit tests + "hack\make.ps1 -Binary -TestUnit" to build the binaries and run unit tests + "hack\make.ps1 -All" to run everything this script knows about + +.PARAMETER Client + Builds the client binaries. + +.PARAMETER Daemon + Builds the daemon binary. + +.PARAMETER Binary + Builds the client binaries and the daemon binary. A convenient shortcut to `make.ps1 -Client -Daemon`. + +.PARAMETER Race + Use -race in go build and go test. + +.PARAMETER Noisy + Use -v in go build. + +.PARAMETER ForceBuildAll + Use -a in go build. + +.PARAMETER NoOpt + Use -gcflags -N -l in go build to disable optimisation (can aide debugging). + +.PARAMETER CommitSuffix + Adds a custom string to be appended to the commit ID (spaces are stripped). + +.PARAMETER DCO + Runs the DCO (Developer Certificate Of Origin) test. + +.PARAMETER PkgImports + Runs the pkg\ directory imports test. + +.PARAMETER GoFormat + Runs the Go formatting test. + +.PARAMETER TestUnit + Runs unit tests. + +.PARAMETER All + Runs everything this script knows about. + + +TODO +- Unify the head commit +- Sort out the GITCOMMIT environment variable in the absense of a .git (longer term) +- Add golint and other checks (swagger maybe?) + +#> + + +param( + [Parameter(Mandatory=$False)][switch]$Client, + [Parameter(Mandatory=$False)][switch]$Daemon, + [Parameter(Mandatory=$False)][switch]$Binary, + [Parameter(Mandatory=$False)][switch]$Race, + [Parameter(Mandatory=$False)][switch]$Noisy, + [Parameter(Mandatory=$False)][switch]$ForceBuildAll, + [Parameter(Mandatory=$False)][switch]$NoOpt, + [Parameter(Mandatory=$False)][string]$CommitSuffix="", + [Parameter(Mandatory=$False)][switch]$DCO, + [Parameter(Mandatory=$False)][switch]$PkgImports, + [Parameter(Mandatory=$False)][switch]$GoFormat, + [Parameter(Mandatory=$False)][switch]$TestUnit, + [Parameter(Mandatory=$False)][switch]$All +) + +$ErrorActionPreference = "Stop" +$pushed=$False # To restore the directory if we have temporarily pushed to one. + +# Utility function to get the commit ID of the repository +Function Get-GitCommit() { + if (-not (Test-Path ".\.git")) { + # If we don't have a .git directory, but we do have the environment + # variable DOCKER_GITCOMMIT set, that can override it. + if ($env:DOCKER_GITCOMMIT.Length -eq 0) { + Throw ".git directory missing and DOCKER_GITCOMMIT environment variable not specified." + } + Write-Host "INFO: Git commit assumed from DOCKER_GITCOMMIT environment variable" + return $env:DOCKER_GITCOMMIT + } + $gitCommit=$(git rev-parse --short HEAD) + if ($(git status --porcelain --untracked-files=no).Length -ne 0) { + $gitCommit="$gitCommit-unsupported" + Write-Host "" + Write-Warning "This version is unsupported because there are uncommitted file(s)." + Write-Warning "Either commit these changes, or add them to .gitignore." + git status --porcelain --untracked-files=no | Write-Warning + Write-Host "" + } + return $gitCommit +} + +# Utility function to get get the current build version of docker +Function Get-DockerVersion() { + if (-not (Test-Path ".\VERSION")) { Throw "VERSION file not found. Is this running from the root of a docker repository?" } + return $(Get-Content ".\VERSION" -raw).ToString().Replace("`n","").Trim() +} + +# Utility function to determine if we are running in a container or not. +# In Windows, we get this through an environment variable set in `Dockerfile.Windows` +Function Check-InContainer() { + if ($env:FROM_DOCKERFILE.Length -eq 0) { + Write-Host "" + Write-Warning "Not running in a container. The result might be an incorrect build." + Write-Host "" + } +} + +# Utility function to get the commit for HEAD +Function Get-HeadCommit() { + $head = Invoke-Expression "git rev-parse --verify HEAD" + if ($LASTEXITCODE -ne 0) { Throw "Failed getting HEAD commit" } + + return $head +} + +# Utility function to get the commit for upstream +Function Get-UpstreamCommit() { + Invoke-Expression "git fetch -q https://github.com/docker/docker.git refs/heads/master" + if ($LASTEXITCODE -ne 0) { Throw "Failed fetching" } + + $upstream = Invoke-Expression "git rev-parse --verify FETCH_HEAD" + if ($LASTEXITCODE -ne 0) { Throw "Failed getting upstream commit" } + + return $upstream +} + +# Build a binary (client or daemon) +Function Execute-Build($type, $additionalBuildTags, $directory) { + # Generate the build flags + $buildTags = "autogen" + if ($Noisy) { $verboseParm=" -v" } + if ($Race) { Write-Warning "Using race detector"; $raceParm=" -race"} + if ($ForceBuildAll) { $allParm=" -a" } + if ($NoOpt) { $optParm=" -gcflags "+""""+"-N -l"+"""" } + if ($addtionalBuildTags -ne "") { $buildTags += $(" " + $additionalBuildTags) } + + # Do the go build in the appropriate directory + # Note -linkmode=internal is required to be able to debug on Windows. + # https://github.com/golang/go/issues/14319#issuecomment-189576638 + Write-Host "INFO: Building $type..." + Push-Location $root\cmd\$directory; $global:pushed=$True + $buildCommand = "go build" + ` + $raceParm + ` + $verboseParm + ` + $allParm + ` + $optParm + ` + " -tags """ + $buildTags + """" + ` + " -ldflags """ + "-linkmode=internal" + """" + ` + " -o $root\bundles\"+$directory+".exe" + Invoke-Expression $buildCommand + if ($LASTEXITCODE -ne 0) { Throw "Failed to compile $type" } + Pop-Location; $global:pushed=$False +} + +# Validates the DCO marker is present on each commit +Function Validate-DCO($headCommit, $upstreamCommit) { + Write-Host "INFO: Validating Developer Certificate of Origin..." + # Username may only contain alphanumeric characters or dashes and cannot begin with a dash + $usernameRegex='[a-zA-Z0-9][a-zA-Z0-9-]+' + + $dcoPrefix="Signed-off-by:" + $dcoRegex="^(Docker-DCO-1.1-)?$dcoPrefix ([^<]+) <([^<>@]+@[^<>]+)>( \\(github: ($githubUsernameRegex)\\))?$" + + $counts = Invoke-Expression "git diff --numstat $upstreamCommit...$headCommit" + if ($LASTEXITCODE -ne 0) { Throw "Failed git diff --numstat" } + + # Counts of adds and deletes after removing multiple white spaces. AWK anyone? :( + $adds=0; $dels=0; $($counts -replace '\s+', ' ') | %{ $a=$_.Split(" "); $adds+=[int]$a[0]; $dels+=[int]$a[1] } + if (($adds -eq 0) -and ($dels -eq 0)) { + Write-Warning "DCO validation - nothing to validate!" + return + } + + $commits = Invoke-Expression "git log $upstreamCommit..$headCommit --format=format:%H%n" + if ($LASTEXITCODE -ne 0) { Throw "Failed git log --format" } + $commits = $($commits -split '\s+' -match '\S') + $badCommits=@() + $commits | %{ + # Skip commits with no content such as merge commits etc + if ($(git log -1 --format=format: --name-status $_).Length -gt 0) { + # Ignore exit code on next call - always process regardless + $commitMessage = Invoke-Expression "git log -1 --format=format:%B --name-status $_" + if (($commitMessage -match $dcoRegex).Length -eq 0) { $badCommits+=$_ } + } + } + if ($badCommits.Length -eq 0) { + Write-Host "Congratulations! All commits are properly signed with the DCO!" + } else { + $e = "`nThese commits do not have a proper '$dcoPrefix' marker:`n" + $badCommits | %{ $e+=" - $_`n"} + $e += "`nPlease amend each commit to include a properly formatted DCO marker.`n`n" + $e += "Visit the following URL for information about the Docker DCO:`n" + $e += "https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work`n" + Throw $e + } +} + +# Validates that .\pkg\... is safely isolated from internal code +Function Validate-PkgImports($headCommit, $upstreamCommit) { + Write-Host "INFO: Validating pkg import isolation..." + + # Get a list of go source-code files which have changed under pkg\. Ignore exit code on next call - always process regardless + $files=@(); $files = Invoke-Expression "git diff $upstreamCommit...$headCommit --diff-filter=ACMR --name-only -- `'pkg\*.go`'" + $badFiles=@(); $files | %{ + $file=$_ + # For the current changed file, get its list of dependencies, sorted and uniqued. + $imports = Invoke-Expression "go list -e -f `'{{ .Deps }}`' $file" + if ($LASTEXITCODE -ne 0) { Throw "Failed go list for dependencies on $file" } + $imports = $imports -Replace "\[" -Replace "\]", "" -Split(" ") | Sort-Object | Get-Unique + # Filter out what we are looking for + $imports = $imports -NotMatch "^github.com/docker/docker/pkg/" ` + -NotMatch "^github.com/docker/docker/vendor" ` + -Match "^github.com/docker/docker" ` + -Replace "`n", "" + $imports | % { $badFiles+="$file imports $_`n" } + } + if ($badFiles.Length -eq 0) { + Write-Host 'Congratulations! ".\pkg\*.go" is safely isolated from internal code.' + } else { + $e = "`nThese files import internal code: (either directly or indirectly)`n" + $badFiles | %{ $e+=" - $_"} + Throw $e + } +} + +# Validates that changed files are correctly go-formatted +Function Validate-GoFormat($headCommit, $upstreamCommit) { + Write-Host "INFO: Validating go formatting on changed files..." + + # Verify gofmt is installed + if ($(Get-Command gofmt -ErrorAction SilentlyContinue) -eq $nil) { Throw "gofmt does not appear to be installed" } + + # Get a list of all go source-code files which have changed. Ignore exit code on next call - always process regardless + $files=@(); $files = Invoke-Expression "git diff $upstreamCommit...$headCommit --diff-filter=ACMR --name-only -- `'*.go`'" + $files = $files | Select-String -NotMatch "^vendor/" + $badFiles=@(); $files | %{ + # Deliberately ignore error on next line - treat as failed + $content=Invoke-Expression "git show $headCommit`:$_" + + # Next set of hoops are to ensure we have LF not CRLF semantics as otherwise gofmt on Windows will not succeed. + # Also note that gofmt on Windows does not appear to support stdin piping correctly. Hence go through a temporary file. + $content=$content -join "`n" + $content+="`n" + $outputFile=[System.IO.Path]::GetTempFileName() + if (Test-Path $outputFile) { Remove-Item $outputFile } + [System.IO.File]::WriteAllText($outputFile, $content, (New-Object System.Text.UTF8Encoding($False))) + $valid=Invoke-Expression "gofmt -s -l $outputFile" + Write-Host "Checking $outputFile" + if ($valid.Length -ne 0) { $badFiles+=$_ } + if (Test-Path $outputFile) { Remove-Item $outputFile } + } + if ($badFiles.Length -eq 0) { + Write-Host 'Congratulations! All Go source files are properly formatted.' + } else { + $e = "`nThese files are not properly gofmt`'d:`n" + $badFiles | %{ $e+=" - $_`n"} + $e+= "`nPlease reformat the above files using `"gofmt -s -w`" and commit the result." + Throw $e + } +} + +# Run the unit tests +Function Run-UnitTests() { + Write-Host "INFO: Running unit tests..." + $testPath="./..." + $goListCommand = "go list -e -f '{{if ne .Name """ + '\"github.com/docker/docker\"' + """}}{{.ImportPath}}{{end}}' $testPath" + $pkgList = $(Invoke-Expression $goListCommand) + if ($LASTEXITCODE -ne 0) { Throw "go list for unit tests failed" } + $pkgList = $pkgList | Select-String -Pattern "github.com/docker/docker" + $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/vendor" + $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/man" + $pkgList = $pkgList | Select-String -NotMatch "github.com/docker/docker/integration-cli" + $pkgList = $pkgList -replace "`r`n", " " + $goTestCommand = "go test" + $raceParm + " -cover -ldflags -w -tags """ + "autogen daemon" + """ -a """ + "-test.timeout=10m" + """ $pkgList" + Invoke-Expression $goTestCommand + if ($LASTEXITCODE -ne 0) { Throw "Unit tests failed" } +} + +# Start of main code. +Try { + Write-Host -ForegroundColor Cyan "INFO: make.ps1 starting at $(Get-Date)" + $root=$(pwd) + + # Handle the "-All" shortcut to turn on all things we can handle. + if ($All) { $Client=$True; $Daemon=$True; $DCO=$True; $PkgImports=$True; $GoFormat=$True; $TestUnit=$True } + + # Handle the "-Binary" shortcut to build both client and daemon. + if ($Binary) { $Client = $True; $Daemon = $True } + + # Make sure we have something to do + if (-not($Client) -and -not($Daemon) -and -not($DCO) -and -not($PkgImports) -and -not($GoFormat) -and -not($TestUnit)) { Throw 'Nothing to do. Try adding "-All" for everything I can do' } + + # Verify git is installed + if ($(Get-Command git -ErrorAction SilentlyContinue) -eq $nil) { Throw "Git does not appear to be installed" } + + # Verify go is installed + if ($(Get-Command go -ErrorAction SilentlyContinue) -eq $nil) { Throw "GoLang does not appear to be installed" } + + # Get the git commit. This will also verify if we are in a repo or not. Then add a custom string if supplied. + $gitCommit=Get-GitCommit + if ($CommitSuffix -ne "") { $gitCommit += "-"+$CommitSuffix -Replace ' ', '' } + + # Get the version of docker (eg 1.14.0-dev) + $dockerVersion=Get-DockerVersion + + # Give a warning if we are not running in a container and are building binaries or running unit tests. + # Not relevant for validation tests as these are fine to run outside of a container. + if ($Client -or $Daemon -or $TestUnit) { Check-InContainer } + + # Verify GOPATH is set + if ($env:GOPATH.Length -eq 0) { Throw "Missing GOPATH environment variable. See https://golang.org/doc/code.html#GOPATH" } + + # Run autogen if building binaries or running unit tests. + if ($Client -or $Daemon -or $TestUnit) { + Write-Host "INFO: Invoking autogen..." + Try { .\hack\make\.go-autogen.ps1 -CommitString $gitCommit -DockerVersion $dockerVersion } + Catch [Exception] { Throw $_ } + } + + # DCO, Package import and Go formatting tests. + if ($DCO -or $PkgImports -or $GoFormat) { + # We need the head and upstream commits for these + $headCommit=Get-HeadCommit + $upstreamCommit=Get-UpstreamCommit + + # Run DCO validation + if ($DCO) { Validate-DCO $headCommit $upstreamCommit } + + # Run `gofmt` validation + if ($GoFormat) { Validate-GoFormat $headCommit $upstreamCommit } + + # Run pkg isolation validation + if ($PkgImports) { Validate-PkgImports $headCommit $upstreamCommit } + } + + # Build the binaries + if ($Client -or $Daemon) { + # Create the bundles directory if it doesn't exist + if (-not (Test-Path ".\bundles")) { New-Item ".\bundles" -ItemType Directory | Out-Null } + + # Perform the actual build + if ($Daemon) { Execute-Build "daemon" "daemon" "dockerd" } + if ($Client) { Execute-Build "client" "" "docker" } + } + + # Run unit tests + if ($TestUnit) { Run-UnitTests } + + # Gratuitous ASCII art. + if ($Daemon -or $Client) { + Write-Host + Write-Host -ForegroundColor Green " ________ ____ __." + Write-Host -ForegroundColor Green " \_____ \ `| `|/ _`|" + Write-Host -ForegroundColor Green " / `| \`| `<" + Write-Host -ForegroundColor Green " / `| \ `| \" + Write-Host -ForegroundColor Green " \_______ /____`|__ \" + Write-Host -ForegroundColor Green " \/ \/" + Write-Host + } +} +Catch [Exception] { + Write-Host -ForegroundColor Red ("`nERROR: make.ps1 failed:`n$_") + + # More gratuitous ASCII art. + Write-Host + Write-Host -ForegroundColor Red "___________ .__.__ .___" + Write-Host -ForegroundColor Red "\_ _____/____ `|__`| `| ____ __`| _/" + Write-Host -ForegroundColor Red " `| __) \__ \ `| `| `| _/ __ \ / __ `| " + Write-Host -ForegroundColor Red " `| \ / __ \`| `| `|_\ ___// /_/ `| " + Write-Host -ForegroundColor Red " \___ / (____ /__`|____/\___ `>____ `| " + Write-Host -ForegroundColor Red " \/ \/ \/ \/ " + Write-Host +} +Finally { + if ($global:pushed) { Pop-Location } + Write-Host -ForegroundColor Cyan "INFO: make.ps1 ended at $(Get-Date)" +} diff --git a/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 b/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 index 3fb616152..3adc4c3e9 100644 --- a/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 +++ b/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 @@ -10,16 +10,11 @@ .PARAMETER DockerVersion The version such as 1.14.0-dev. This is calculated externally to this script. - -.PARAMETER StaticSQLite - A string indicating if the daemon binary is compiled with the SQLite - sources compiled in. This is calculated externally to this script. #> param( [Parameter(Mandatory=$true)][string]$CommitString, - [Parameter(Mandatory=$true)][string]$DockerVersion, - [Parameter(Mandatory=$true)][string]$StaticSQLiteString + [Parameter(Mandatory=$true)][string]$DockerVersion ) $ErrorActionPreference = "Stop" @@ -48,7 +43,6 @@ const ( GitCommit string = "'+$CommitString+'" Version string = "'+$DockerVersion+'" BuildTime string = "'+$buildDateTime+'" - StaticSQLite string = "'+$StaticSQLiteString+'" ) // AUTOGENERATED FILE; see hack\make\.go-autogen.ps1 diff --git a/vendor/github.com/docker/docker/hack/validate/swagger-gen b/vendor/github.com/docker/docker/hack/validate/swagger-gen index 37ced76e8..42c974936 100755 --- a/vendor/github.com/docker/docker/hack/validate/swagger-gen +++ b/vendor/github.com/docker/docker/hack/validate/swagger-gen @@ -4,7 +4,7 @@ export SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "${SCRIPTDIR}/.validate" IFS=$'\n' -files=( $(validate_diff --diff-filter=ACMR --name-only -- 'api/types/' || true) ) +files=( $(validate_diff --diff-filter=ACMR --name-only -- 'api/types/' 'api/swagger.yaml' || true) ) unset IFS if [ ${#files[@]} -gt 0 ]; then @@ -26,5 +26,5 @@ if [ ${#files[@]} -gt 0 ]; then echo 'Congratulations! All api changes are done the right way.' fi else - echo 'No api/types/ changes in diff.' + echo 'No api/types/ or api/swagger.yaml changes in diff.' fi diff --git a/vendor/github.com/docker/docker/image/tarexport/save.go b/vendor/github.com/docker/docker/image/tarexport/save.go index cd5c82dc1..6e3a5bc58 100644 --- a/vendor/github.com/docker/docker/image/tarexport/save.go +++ b/vendor/github.com/docker/docker/image/tarexport/save.go @@ -234,7 +234,9 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Desc var layers []string var foreignSrcs map[layer.DiffID]distribution.Descriptor for i := range img.RootFS.DiffIDs { - v1Img := image.V1Image{} + v1Img := image.V1Image{ + Created: img.Created, + } if i == len(img.RootFS.DiffIDs)-1 { v1Img = img.V1Image } diff --git a/vendor/github.com/docker/docker/integration-cli/daemon_swarm.go b/vendor/github.com/docker/docker/integration-cli/daemon_swarm.go index cb364f044..a5039971a 100644 --- a/vendor/github.com/docker/docker/integration-cli/daemon_swarm.go +++ b/vendor/github.com/docker/docker/integration-cli/daemon_swarm.go @@ -317,7 +317,7 @@ func (d *SwarmDaemon) getSecret(c *check.C, id string) *swarm.Secret { func (d *SwarmDaemon) deleteSecret(c *check.C, id string) { status, out, err := d.SockRequest("DELETE", "/secrets/"+id, nil) c.Assert(err, checker.IsNil, check.Commentf(string(out))) - c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out))) + c.Assert(status, checker.Equals, http.StatusNoContent, check.Commentf("output: %q", string(out))) } func (d *SwarmDaemon) getSwarm(c *check.C) swarm.Swarm { diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go index cd3dd30a0..d046ec068 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go @@ -728,7 +728,7 @@ func (s *DockerSuite) TestContainerAPIInvalidPortSyntax(c *check.C) { c.Assert(string(b[:]), checker.Contains, "invalid port") } -func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyName(c *check.C) { +func (s *DockerSuite) TestContainerAPIRestartPolicyInvalidPolicyName(c *check.C) { config := `{ "Image": "busybox", "HostConfig": { @@ -748,7 +748,7 @@ func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyName(c *check.C) { c.Assert(string(b[:]), checker.Contains, "invalid restart policy") } -func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyRetryMismatch(c *check.C) { +func (s *DockerSuite) TestContainerAPIRestartPolicyRetryMismatch(c *check.C) { config := `{ "Image": "busybox", "HostConfig": { @@ -765,10 +765,10 @@ func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyRetryMismatch(c *check b, err := readBody(body) c.Assert(err, checker.IsNil) - c.Assert(string(b[:]), checker.Contains, "maximum restart count not valid with restart policy") + c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be used with restart policy") } -func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyPositiveRetryCount(c *check.C) { +func (s *DockerSuite) TestContainerAPIRestartPolicyNegativeRetryCount(c *check.C) { config := `{ "Image": "busybox", "HostConfig": { @@ -785,7 +785,23 @@ func (s *DockerSuite) TestContainerAPIInvalidRestartPolicyPositiveRetryCount(c * b, err := readBody(body) c.Assert(err, checker.IsNil) - c.Assert(string(b[:]), checker.Contains, "maximum restart count must be a positive integer") + c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be negative") +} + +func (s *DockerSuite) TestContainerAPIRestartPolicyDefaultRetryCount(c *check.C) { + config := `{ + "Image": "busybox", + "HostConfig": { + "RestartPolicy": { + "Name": "on-failure", + "MaximumRetryCount": 0 + } + } + }` + + res, _, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json") + c.Assert(err, checker.IsNil) + c.Assert(res.StatusCode, checker.Equals, http.StatusCreated) } // Issue 7941 - test to make sure a "null" in JSON is just ignored. diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go index eea4712fe..e3524c7bd 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go @@ -3610,8 +3610,8 @@ RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/do # Switch back to root and double check that worked exactly as we might expect it to USER root -# Add a "supplementary" group for our dockerio user RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ] && \ + # Add a "supplementary" group for our dockerio user echo 'supplementary:x:1002:dockerio' >> /etc/group # ... and then go verify that we get it like we expect @@ -7141,41 +7141,6 @@ func (s *DockerSuite) TestBuildNetContainer(c *check.C) { c.Assert(strings.TrimSpace(host), check.Equals, "foobar") } -// Test case for #24693 -func (s *DockerSuite) TestBuildRunEmptyLineAfterEscape(c *check.C) { - name := "testbuildemptylineafterescape" - _, out, err := buildImageWithOut(name, - ` -FROM busybox -RUN echo x \ - -RUN echo y -RUN echo z -# Comment requires the '#' to start from position 1 -# RUN echo w -`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/4 : FROM busybox") - c.Assert(out, checker.Contains, "Step 2/4 : RUN echo x") - c.Assert(out, checker.Contains, "Step 3/4 : RUN echo y") - c.Assert(out, checker.Contains, "Step 4/4 : RUN echo z") - - // With comment, see #24693 - name = "testbuildcommentandemptylineafterescape" - _, out, err = buildImageWithOut(name, - ` -FROM busybox -RUN echo grafana && \ - echo raintank \ -#echo env-load -RUN echo vegeta -`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/3 : FROM busybox") - c.Assert(out, checker.Contains, "Step 2/3 : RUN echo grafana && echo raintank") - c.Assert(out, checker.Contains, "Step 3/3 : RUN echo vegeta") -} - func (s *DockerSuite) TestBuildSquashParent(c *check.C) { testRequires(c, ExperimentalDaemon) dockerFile := ` @@ -7311,3 +7276,19 @@ RUN ["cat", "/foo/file"] c.Fatal(err) } } + +// Case-insensitive environment variables on Windows +func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) { + testRequires(c, DaemonIsWindows) + name := "testbuildwindowsenvcaseinsensitive" + if _, err := buildImage(name, ` + FROM `+WindowsBaseImage+` + ENV FOO=bar foo=bar + `, true); err != nil { + c.Fatal(err) + } + res := inspectFieldJSON(c, name, "Config.Env") + if res != `["foo=bar"]` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped. + c.Fatalf("Case insensitive environment variables on Windows failed. Got %s", res) + } +} diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go index 2abd36389..7673d6c11 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go @@ -568,8 +568,36 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverOutOfBandDelete(c *c // simulate out of band volume deletion on plugin level delete(p.vols, "test") + // test re-create with same driver + out, err = s.d.Cmd("volume", "create", "-d", driverName, "--opt", "foo=bar", "--name", "test") + c.Assert(err, checker.IsNil, check.Commentf(out)) + out, err = s.d.Cmd("volume", "inspect", "test") + c.Assert(err, checker.IsNil, check.Commentf(out)) + + var vs []types.Volume + err = json.Unmarshal([]byte(out), &vs) + c.Assert(err, checker.IsNil) + c.Assert(vs, checker.HasLen, 1) + c.Assert(vs[0].Driver, checker.Equals, driverName) + c.Assert(vs[0].Options, checker.NotNil) + c.Assert(vs[0].Options["foo"], checker.Equals, "bar") + c.Assert(vs[0].Driver, checker.Equals, driverName) + + // simulate out of band volume deletion on plugin level + delete(p.vols, "test") + + // test create with different driver out, err = s.d.Cmd("volume", "create", "-d", "local", "--name", "test") c.Assert(err, checker.IsNil, check.Commentf(out)) + + out, err = s.d.Cmd("volume", "inspect", "test") + c.Assert(err, checker.IsNil, check.Commentf(out)) + vs = nil + err = json.Unmarshal([]byte(out), &vs) + c.Assert(err, checker.IsNil) + c.Assert(vs, checker.HasLen, 1) + c.Assert(vs[0].Options, checker.HasLen, 0) + c.Assert(vs[0].Driver, checker.Equals, "local") } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnmountOnMountFail(c *check.C) { diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go index d99ae6d09..5d79ad1d8 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go @@ -417,3 +417,33 @@ func (s *DockerSuite) TestInspectAmpersand(c *check.C) { out, _ = dockerCmd(c, "inspect", name) c.Assert(out, checker.Contains, `soanni&rtr`) } + +func (s *DockerSuite) TestInspectPlugin(c *check.C) { + testRequires(c, DaemonIsLinux, Network) + _, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag) + c.Assert(err, checker.IsNil) + + out, _, err := dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pNameWithTag) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, pName) + + out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pNameWithTag) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, pName) + + // Even without tag the inspect still work + out, _, err = dockerCmdWithError("inspect", "--type", "plugin", "--format", "{{.Name}}", pName) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, pName) + + out, _, err = dockerCmdWithError("inspect", "--format", "{{.Name}}", pName) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, pName) + + _, _, err = dockerCmdWithError("plugin", "disable", pNameWithTag) + c.Assert(err, checker.IsNil) + + out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag) + c.Assert(err, checker.IsNil) + c.Assert(out, checker.Contains, pNameWithTag) +} diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go index f6d2f28b5..730580e56 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go @@ -201,3 +201,52 @@ func (s *DockerSuite) TestPluginCreate(c *check.C) { // The output will consists of one HEADER line and one line of foo/bar-driver c.Assert(len(strings.Split(strings.TrimSpace(out), "\n")), checker.Equals, 2) } + +func (s *DockerSuite) TestPluginInspect(c *check.C) { + testRequires(c, DaemonIsLinux, Network) + _, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", pNameWithTag) + c.Assert(err, checker.IsNil) + + out, _, err := dockerCmdWithError("plugin", "ls") + c.Assert(err, checker.IsNil) + c.Assert(out, checker.Contains, pName) + c.Assert(out, checker.Contains, pTag) + c.Assert(out, checker.Contains, "true") + + // Find the ID first + out, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", pNameWithTag) + c.Assert(err, checker.IsNil) + id := strings.TrimSpace(out) + c.Assert(id, checker.Not(checker.Equals), "") + + // Long form + out, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", id) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, id) + + // Short form + out, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", id[:5]) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, id) + + // Name with tag form + out, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", pNameWithTag) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, id) + + // Name without tag form + out, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", pName) + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, id) + + _, _, err = dockerCmdWithError("plugin", "disable", pNameWithTag) + c.Assert(err, checker.IsNil) + + out, _, err = dockerCmdWithError("plugin", "remove", pNameWithTag) + c.Assert(err, checker.IsNil) + c.Assert(out, checker.Contains, pNameWithTag) + + // After remove nothing should be found + _, _, err = dockerCmdWithError("plugin", "inspect", "-f", "{{.Id}}", id[:5]) + c.Assert(err, checker.NotNil) +} diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go index 9094e7d69..373d614b5 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go @@ -62,10 +62,10 @@ func (s *DockerSuite) TestRenameCheckNames(c *check.C) { name := inspectField(c, newName, "Name") c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name)) - result := dockerCmdWithResult("inspect", "-f={{.Name}}", "first_name") + result := dockerCmdWithResult("inspect", "-f={{.Name}}", "--type=container", "first_name") c.Assert(result, icmd.Matches, icmd.Expected{ ExitCode: 1, - Err: "No such object: first_name", + Err: "No such container: first_name", }) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go index ca71aaa14..7d585289e 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go @@ -74,7 +74,7 @@ func (s *DockerSuite) TestRestartWithVolumes(c *check.C) { } func (s *DockerSuite) TestRestartPolicyNO(c *check.C) { - out, _ := dockerCmd(c, "run", "-d", "--restart=no", "busybox", "false") + out, _ := dockerCmd(c, "create", "--restart=no", "busybox") id := strings.TrimSpace(string(out)) name := inspectField(c, id, "HostConfig.RestartPolicy.Name") @@ -82,7 +82,7 @@ func (s *DockerSuite) TestRestartPolicyNO(c *check.C) { } func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) { - out, _ := dockerCmd(c, "run", "-d", "--restart=always", "busybox", "false") + out, _ := dockerCmd(c, "create", "--restart=always", "busybox") id := strings.TrimSpace(string(out)) name := inspectField(c, id, "HostConfig.RestartPolicy.Name") @@ -95,12 +95,36 @@ func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) { } func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) { - out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:1", "busybox", "false") + out, _, err := dockerCmdWithError("create", "--restart=on-failure:-1", "busybox") + c.Assert(err, check.NotNil, check.Commentf(out)) + c.Assert(out, checker.Contains, "maximum retry count cannot be negative") + + out, _ = dockerCmd(c, "create", "--restart=on-failure:1", "busybox") id := strings.TrimSpace(string(out)) name := inspectField(c, id, "HostConfig.RestartPolicy.Name") + maxRetry := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") + c.Assert(name, checker.Equals, "on-failure") + c.Assert(maxRetry, checker.Equals, "1") + + out, _ = dockerCmd(c, "create", "--restart=on-failure:0", "busybox") + id = strings.TrimSpace(string(out)) + name = inspectField(c, id, "HostConfig.RestartPolicy.Name") + maxRetry = inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") + + c.Assert(name, checker.Equals, "on-failure") + c.Assert(maxRetry, checker.Equals, "0") + + out, _ = dockerCmd(c, "create", "--restart=on-failure", "busybox") + + id = strings.TrimSpace(string(out)) + name = inspectField(c, id, "HostConfig.RestartPolicy.Name") + maxRetry = inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") + + c.Assert(name, checker.Equals, "on-failure") + c.Assert(maxRetry, checker.Equals, "0") } // a good container with --restart=on-failure:3 diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go index dd3f4cef3..62b3a8d37 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go @@ -4372,42 +4372,6 @@ func (s *DockerSuite) TestRunVolumeCopyFlag(c *check.C) { c.Assert(err, checker.NotNil, check.Commentf(out)) } -func (s *DockerSuite) TestRunTooLongHostname(c *check.C) { - // Test case in #21445 - hostname1 := "this-is-a-way-too-long-hostname-but-it-should-give-a-nice-error.local" - out, _, err := dockerCmdWithError("run", "--hostname", hostname1, "busybox", "echo", "test") - c.Assert(err, checker.NotNil, check.Commentf("Expected docker run to fail!")) - c.Assert(out, checker.Contains, "invalid hostname format:", check.Commentf("Expected to have 'invalid hostname format:' in the output, get: %s!", out)) - - // Additional test cases - validHostnames := map[string]string{ - "hostname": "hostname", - "host-name": "host-name", - "hostname123": "hostname123", - "123hostname": "123hostname", - "hostname-of-63-bytes-long-should-be-valid-and-without-any-error": "hostname-of-63-bytes-long-should-be-valid-and-without-any-error", - } - for hostname := range validHostnames { - dockerCmd(c, "run", "--hostname", hostname, "busybox", "echo", "test") - } - - invalidHostnames := map[string]string{ - "^hostname": "invalid hostname format: ^hostname", - "hostname%": "invalid hostname format: hostname%", - "host&name": "invalid hostname format: host&name", - "-hostname": "invalid hostname format: -hostname", - "host_name": "invalid hostname format: host_name", - "hostname-of-64-bytes-long-should-be-invalid-and-be-with-an-error": "invalid hostname format: hostname-of-64-bytes-long-should-be-invalid-and-be-with-an-error", - } - - for hostname, expectedError := range invalidHostnames { - out, _, err = dockerCmdWithError("run", "--hostname", hostname, "busybox", "echo", "test") - c.Assert(err, checker.NotNil, check.Commentf("Expected docker run to fail!")) - c.Assert(out, checker.Contains, expectedError, check.Commentf("Expected to have '%s' in the output, get: %s!", expectedError, out)) - - } -} - // Test case for #21976 func (s *DockerSuite) TestRunDNSInHostMode(c *check.C) { testRequires(c, DaemonIsLinux, NotUserNamespace) @@ -4590,184 +4554,6 @@ func (s *DockerSuite) TestRunDuplicateMount(c *check.C) { c.Assert(out, checker.Contains, "null") } -func (s *DockerSuite) TestRunMount(c *check.C) { - testRequires(c, DaemonIsLinux, SameHostDaemon, NotUserNamespace) - - // mnt1, mnt2, and testCatFooBar are commonly used in multiple test cases - tmpDir, err := ioutil.TempDir("", "mount") - if err != nil { - c.Fatal(err) - } - defer os.RemoveAll(tmpDir) - mnt1, mnt2 := path.Join(tmpDir, "mnt1"), path.Join(tmpDir, "mnt2") - if err := os.Mkdir(mnt1, 0755); err != nil { - c.Fatal(err) - } - if err := os.Mkdir(mnt2, 0755); err != nil { - c.Fatal(err) - } - if err := ioutil.WriteFile(path.Join(mnt1, "test1"), []byte("test1"), 0644); err != nil { - c.Fatal(err) - } - if err := ioutil.WriteFile(path.Join(mnt2, "test2"), []byte("test2"), 0644); err != nil { - c.Fatal(err) - } - testCatFooBar := func(cName string) error { - out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1") - if out != "test1" { - return fmt.Errorf("%s not mounted on /foo", mnt1) - } - out, _ = dockerCmd(c, "exec", cName, "cat", "/bar/test2") - if out != "test2" { - return fmt.Errorf("%s not mounted on /bar", mnt2) - } - return nil - } - - type testCase struct { - equivalents [][]string - valid bool - // fn should be nil if valid==false - fn func(cName string) error - } - cases := []testCase{ - { - equivalents: [][]string{ - { - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/bar", mnt2), - }, - { - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2), - }, - { - "--volume", fmt.Sprintf("%s:/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,target=/bar", mnt2), - }, - }, - valid: true, - fn: testCatFooBar, - }, - { - equivalents: [][]string{ - { - "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2), - }, - { - "--mount", fmt.Sprintf("type=volume,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2), - }, - }, - valid: false, - }, - { - equivalents: [][]string{ - { - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=volume,src=%s,dst=/bar", mnt2), - }, - { - "--volume", fmt.Sprintf("%s:/foo", mnt1), - "--mount", fmt.Sprintf("type=volume,src=%s,target=/bar", mnt2), - }, - }, - valid: false, - fn: testCatFooBar, - }, - { - equivalents: [][]string{ - { - "--read-only", - "--mount", "type=volume,dst=/bar", - }, - }, - valid: true, - fn: func(cName string) error { - _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere") - return err - }, - }, - { - equivalents: [][]string{ - { - "--read-only", - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", "type=volume,dst=/bar", - }, - { - "--read-only", - "--volume", fmt.Sprintf("%s:/foo", mnt1), - "--mount", "type=volume,dst=/bar", - }, - }, - valid: true, - fn: func(cName string) error { - out, _ := dockerCmd(c, "exec", cName, "cat", "/foo/test1") - if out != "test1" { - return fmt.Errorf("%s not mounted on /foo", mnt1) - } - _, _, err := dockerCmdWithError("exec", cName, "touch", "/bar/icanwritehere") - return err - }, - }, - { - equivalents: [][]string{ - { - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt2), - }, - { - "--mount", fmt.Sprintf("type=bind,src=%s,dst=/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2), - }, - { - "--volume", fmt.Sprintf("%s:/foo", mnt1), - "--mount", fmt.Sprintf("type=bind,src=%s,target=/foo", mnt2), - }, - }, - valid: false, - }, - { - equivalents: [][]string{ - { - "--volume", fmt.Sprintf("%s:/foo", mnt1), - "--mount", fmt.Sprintf("type=volume,src=%s,target=/foo", mnt2), - }, - }, - valid: false, - }, - { - equivalents: [][]string{ - { - "--mount", "type=volume,target=/foo", - "--mount", "type=volume,target=/foo", - }, - }, - valid: false, - }, - } - - for i, testCase := range cases { - for j, opts := range testCase.equivalents { - cName := fmt.Sprintf("mount-%d-%d", i, j) - _, _, err := dockerCmdWithError(append([]string{"run", "-i", "-d", "--name", cName}, - append(opts, []string{"busybox", "top"}...)...)...) - if testCase.valid { - c.Assert(err, check.IsNil, - check.Commentf("got error while creating a container with %v (%s)", opts, cName)) - c.Assert(testCase.fn(cName), check.IsNil, - check.Commentf("got error while executing test for %v (%s)", opts, cName)) - dockerCmd(c, "rm", "-f", cName) - } else { - c.Assert(err, checker.NotNil, - check.Commentf("got nil while creating a container with %v (%s)", opts, cName)) - } - } - } -} - func (s *DockerSuite) TestRunWindowsWithCPUCount(c *check.C) { testRequires(c, DaemonIsWindows) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_service_create_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_service_create_test.go index 8b838b5aa..9e8b1e995 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_service_create_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_service_create_test.go @@ -123,7 +123,7 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTarget(c *check.C) { func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) { d := s.AddDaemon(c, true, true) - out, err := d.Cmd("service", "create", "--mount", "type=tmpfs,target=/foo", "busybox", "sh", "-c", "mount | grep foo; tail -f /dev/null") + out, err := d.Cmd("service", "create", "--mount", "type=tmpfs,target=/foo,tmpfs-size=1MB", "busybox", "sh", "-c", "mount | grep foo; tail -f /dev/null") c.Assert(err, checker.IsNil, check.Commentf(out)) id := strings.TrimSpace(out) @@ -152,6 +152,8 @@ func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) { c.Assert(mountConfig[0].Source, checker.Equals, "") c.Assert(mountConfig[0].Target, checker.Equals, "/foo") c.Assert(mountConfig[0].Type, checker.Equals, mount.TypeTmpfs) + c.Assert(mountConfig[0].TmpfsOptions, checker.NotNil) + c.Assert(mountConfig[0].TmpfsOptions.SizeBytes, checker.Equals, int64(1048576)) // check container mounts actual out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .Mounts}}", task.Status.ContainerStatus.ContainerID) @@ -169,4 +171,5 @@ func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *check.C) { out, err = s.nodeCmd(c, task.NodeID, "logs", task.Status.ContainerStatus.ContainerID) c.Assert(err, checker.IsNil, check.Commentf(out)) c.Assert(strings.TrimSpace(out), checker.HasPrefix, "tmpfs on /foo type tmpfs") + c.Assert(strings.TrimSpace(out), checker.Contains, "size=1024k") } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go index fc343a1c1..b9a2ca765 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go @@ -226,88 +226,6 @@ func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *check.C) { c.Assert(out, checker.Not(checker.Contains), name+".1") c.Assert(out, checker.Not(checker.Contains), name+".2") c.Assert(out, checker.Not(checker.Contains), name+".3") - - out, err = d.Cmd("node", "ps", "--filter", "desired-state=running", "self") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name+".1") - c.Assert(out, checker.Contains, name+".2") - c.Assert(out, checker.Contains, name+".3") - - out, err = d.Cmd("node", "ps", "--filter", "desired-state=shutdown", "self") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Not(checker.Contains), name+".1") - c.Assert(out, checker.Not(checker.Contains), name+".2") - c.Assert(out, checker.Not(checker.Contains), name+".3") -} - -func (s *DockerSwarmSuite) TestSwarmServiceTaskListAll(c *check.C) { - d := s.AddDaemon(c, true, true) - - name := "service-task-list-1" - out, err := d.Cmd("service", "create", "--name", name, "--replicas=3", "busybox", "top") - c.Assert(err, checker.IsNil) - c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") - - // make sure task has been deployed. - waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 3) - - out, err = d.Cmd("service", "ps", name) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name+".1") - c.Assert(out, checker.Contains, name+".2") - c.Assert(out, checker.Contains, name+".3") - - // Get the last container id so we can restart it to cause a task error in the history - containerID, err := d.Cmd("ps", "-q", "-l") - c.Assert(err, checker.IsNil) - - _, err = d.Cmd("stop", strings.TrimSpace(containerID)) - c.Assert(err, checker.IsNil) - - waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 3) - - out, err = d.Cmd("service", "ps", name) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Count, name, 3) - - out, err = d.Cmd("service", "ps", name, "-a") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Count, name, 4) -} - -func (s *DockerSwarmSuite) TestSwarmNodeTaskListAll(c *check.C) { - d := s.AddDaemon(c, true, true) - - name := "node-task-list" - out, err := d.Cmd("service", "create", "--name", name, "--replicas=3", "busybox", "top") - c.Assert(err, checker.IsNil) - c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "") - - // make sure task has been deployed. - waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 3) - - out, err = d.Cmd("service", "ps", name) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, name+".1") - c.Assert(out, checker.Contains, name+".2") - c.Assert(out, checker.Contains, name+".3") - - // Get the last container id so we can restart it to cause a task error in the history - containerID, err := d.Cmd("ps", "-q", "-l") - c.Assert(err, checker.IsNil) - - _, err = d.Cmd("stop", strings.TrimSpace(containerID)) - c.Assert(err, checker.IsNil) - - waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 3) - - out, err = d.Cmd("node", "ps", "self") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Count, name, 3) - - out, err = d.Cmd("node", "ps", "self", "-a") - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Count, name, 4) } // Test case for #25375 diff --git a/vendor/github.com/docker/docker/libcontainerd/client_linux.go b/vendor/github.com/docker/docker/libcontainerd/client_linux.go index b67690b12..657eda2c0 100644 --- a/vendor/github.com/docker/docker/libcontainerd/client_linux.go +++ b/vendor/github.com/docker/docker/libcontainerd/client_linux.go @@ -405,13 +405,8 @@ func (clnt *client) getContainerLastEventSinceTime(id string, tsp *timestamp.Tim logrus.Errorf("libcontainerd: failed to get container event for %s: %q", id, err) return nil, err } - - logrus.Debugf("libcontainerd: received past event %#v", e) - - switch e.Type { - case StateExit, StatePause, StateResume: - ev = e - } + ev = e + logrus.Debugf("libcontainerd: received past event %#v", ev) } return ev, nil @@ -456,30 +451,36 @@ func (clnt *client) Restore(containerID string, attachStdio StdioCallback, optio // Get its last event ev, eerr := clnt.getContainerLastEvent(containerID) if err != nil || cont.Status == "Stopped" { - if err != nil && !strings.Contains(err.Error(), "container not found") { - // Legitimate error - return err + if err != nil { + logrus.Warnf("libcontainerd: failed to retrieve container %s state: %v", containerID, err) } - - if ev == nil { - if _, err := clnt.getContainer(containerID); err == nil { - // If ev is nil and the container is running in containerd, - // we already consumed all the event of the - // container, included the "exit" one. - // Thus we return to avoid overriding the Exit Code. - logrus.Warnf("libcontainerd: restore was called on a fully synced container (%s)", containerID) - return nil - } - // the container is not running so we need to fix the state within docker - ev = &containerd.Event{ - Type: StateExit, - Status: 1, + if ev != nil && (ev.Pid != InitFriendlyName || ev.Type != StateExit) { + // Wait a while for the exit event + timeout := time.NewTimer(10 * time.Second) + tick := time.NewTicker(100 * time.Millisecond) + stop: + for { + select { + case <-timeout.C: + break stop + case <-tick.C: + ev, eerr = clnt.getContainerLastEvent(containerID) + if eerr != nil { + break stop + } + if ev != nil && ev.Pid == InitFriendlyName && ev.Type == StateExit { + break stop + } + } } + timeout.Stop() + tick.Stop() } - // get the exit status for this container - ec := uint32(0) - if eerr == nil && ev.Type == StateExit { + // get the exit status for this container, if we don't have + // one, indicate an error + ec := uint32(255) + if eerr == nil && ev != nil && ev.Pid == InitFriendlyName && ev.Type == StateExit { ec = ev.Status } clnt.setExited(containerID, ec) diff --git a/vendor/github.com/docker/docker/libcontainerd/process_unix.go b/vendor/github.com/docker/docker/libcontainerd/process_unix.go index e3d8c5f34..514ebf643 100644 --- a/vendor/github.com/docker/docker/libcontainerd/process_unix.go +++ b/vendor/github.com/docker/docker/libcontainerd/process_unix.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" goruntime "runtime" + "strings" "time" containerd "github.com/docker/containerd/api/grpc/types" @@ -86,6 +87,9 @@ func (p *process) sendCloseStdin() error { Pid: p.friendlyName, CloseStdin: true, }) + if err != nil && (strings.Contains(err.Error(), "container not found") || strings.Contains(err.Error(), "process not found")) { + return nil + } return err } diff --git a/vendor/github.com/docker/docker/man/docker-build.1.md b/vendor/github.com/docker/docker/man/docker-build.1.md index 32caaafc7..aef341487 100644 --- a/vendor/github.com/docker/docker/man/docker-build.1.md +++ b/vendor/github.com/docker/docker/man/docker-build.1.md @@ -83,7 +83,7 @@ set as the **URL**, the repository is cloned locally and then sent as the contex Users pass these values at build-time. Docker uses the `buildargs` as the environment context for command(s) run via the Dockerfile's `RUN` instruction or for variable expansion in other Dockerfile instructions. This is not meant - for passing secret values. [Read more about the buildargs instruction](/reference/builder/#arg) + for passing secret values. [Read more about the buildargs instruction](https://docs.docker.com/engine/reference/builder/#arg) **--force-rm**=*true*|*false* Always remove intermediate containers, even after unsuccessful builds. The default is *false*. diff --git a/vendor/github.com/docker/docker/man/docker-create.1.md b/vendor/github.com/docker/docker/man/docker-create.1.md index 8bb162c2c..a819904ef 100644 --- a/vendor/github.com/docker/docker/man/docker-create.1.md +++ b/vendor/github.com/docker/docker/man/docker-create.1.md @@ -56,7 +56,6 @@ docker-create - Create a new container [**--memory-reservation**[=*MEMORY-RESERVATION*]] [**--memory-swap**[=*LIMIT*]] [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]] -[**--mount**[=*MOUNT*]] [**--name**[=*NAME*]] [**--network-alias**[=*[]*]] [**--network**[=*"bridge"*]] diff --git a/vendor/github.com/docker/docker/man/docker-login.1.md b/vendor/github.com/docker/docker/man/docker-login.1.md index 6bb035594..c0d4f795d 100644 --- a/vendor/github.com/docker/docker/man/docker-login.1.md +++ b/vendor/github.com/docker/docker/man/docker-login.1.md @@ -20,7 +20,7 @@ do not specify a `SERVER`, the command uses Docker's public registry located at `docker login` requires user to use `sudo` or be `root`, except when: 1. connecting to a remote daemon, such as a `docker-machine` provisioned `docker engine`. -2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/articles/security/#docker-daemon-attack-surface) for details. +2. user is added to the `docker` group. This will impact the security of your system; the `docker` group is `root` equivalent. See [Docker Daemon Attack Surface](https://docs.docker.com/engine/articles/security/#docker-daemon-attack-surface) for details. You can log into any public or private repository for which you have credentials. When you log in, the command stores encoded credentials in diff --git a/vendor/github.com/docker/docker/man/docker-pause.1.md b/vendor/github.com/docker/docker/man/docker-pause.1.md index ffc3b35ca..1f7d81e74 100644 --- a/vendor/github.com/docker/docker/man/docker-pause.1.md +++ b/vendor/github.com/docker/docker/man/docker-pause.1.md @@ -18,7 +18,7 @@ that it is being suspended, and subsequently resumed. On Windows, only Hyper-V containers can be paused. See the [cgroups freezer documentation] -(https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt) for +(https://www.kernel.org/doc/Documentation/cgroup-v1/freezer-subsystem.txt) for further details. # OPTIONS diff --git a/vendor/github.com/docker/docker/man/docker-run.1.md b/vendor/github.com/docker/docker/man/docker-run.1.md index 061f509c2..a0cbd2ba6 100644 --- a/vendor/github.com/docker/docker/man/docker-run.1.md +++ b/vendor/github.com/docker/docker/man/docker-run.1.md @@ -58,7 +58,6 @@ docker-run - Run a command in a new container [**--memory-reservation**[=*MEMORY-RESERVATION*]] [**--memory-swap**[=*LIMIT*]] [**--memory-swappiness**[=*MEMORY-SWAPPINESS*]] -[**--mount**[=*MOUNT*]] [**--name**[=*NAME*]] [**--network-alias**[=*[]*]] [**--network**[=*"bridge"*]] diff --git a/vendor/github.com/docker/docker/man/docker-unpause.1.md b/vendor/github.com/docker/docker/man/docker-unpause.1.md index 8c64e68de..f1ea14bbe 100644 --- a/vendor/github.com/docker/docker/man/docker-unpause.1.md +++ b/vendor/github.com/docker/docker/man/docker-unpause.1.md @@ -14,7 +14,7 @@ The `docker unpause` command un-suspends all processes in a container. On Linux, it does this using the cgroups freezer. See the [cgroups freezer documentation] -(https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt) for +(https://www.kernel.org/doc/Documentation/cgroup-v1/freezer-subsystem.txt) for further details. # OPTIONS diff --git a/vendor/github.com/docker/docker/man/docker-version.1.md b/vendor/github.com/docker/docker/man/docker-version.1.md index bb521c4ee..1838f8205 100644 --- a/vendor/github.com/docker/docker/man/docker-version.1.md +++ b/vendor/github.com/docker/docker/man/docker-version.1.md @@ -59,4 +59,4 @@ To view all available fields, you can use the format `{{json .}}`. # HISTORY June 2014, updated by Sven Dowideit June 2015, updated by John Howard -June 2015, updated by Patrick Hemmer diff --git a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3.go b/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_linux.go similarity index 75% rename from vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3.go rename to vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_linux.go index dbcf44c25..8e61ff3b4 100644 --- a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3.go +++ b/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_linux.go @@ -2,7 +2,11 @@ package graphdb -import "database/sql" +import ( + "database/sql" + + _ "github.com/mattn/go-sqlite3" // registers sqlite +) // NewSqliteConn opens a connection to a sqlite // database. diff --git a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_unix.go b/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_unix.go deleted file mode 100644 index f932fff28..000000000 --- a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_unix.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build cgo,!windows - -package graphdb - -import ( - _ "github.com/mattn/go-sqlite3" // registers sqlite -) diff --git a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_windows.go b/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_windows.go deleted file mode 100644 index 52590303d..000000000 --- a/vendor/github.com/docker/docker/pkg/graphdb/conn_sqlite3_windows.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build cgo,windows - -package graphdb - -import ( - _ "github.com/mattn/go-sqlite3" // registers sqlite -) diff --git a/vendor/github.com/docker/docker/pkg/graphdb/conn_unsupported.go b/vendor/github.com/docker/docker/pkg/graphdb/conn_unsupported.go deleted file mode 100644 index cf977050d..000000000 --- a/vendor/github.com/docker/docker/pkg/graphdb/conn_unsupported.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !cgo - -package graphdb - -// NewSqliteConn return a new sqlite connection. -func NewSqliteConn(root string) (*Database, error) { - panic("Not implemented") -} diff --git a/vendor/github.com/docker/docker/pkg/graphdb/graphdb.go b/vendor/github.com/docker/docker/pkg/graphdb/graphdb_linux.go similarity index 100% rename from vendor/github.com/docker/docker/pkg/graphdb/graphdb.go rename to vendor/github.com/docker/docker/pkg/graphdb/graphdb_linux.go diff --git a/vendor/github.com/docker/docker/pkg/graphdb/graphdb_test.go b/vendor/github.com/docker/docker/pkg/graphdb/graphdb_linux_test.go similarity index 100% rename from vendor/github.com/docker/docker/pkg/graphdb/graphdb_test.go rename to vendor/github.com/docker/docker/pkg/graphdb/graphdb_linux_test.go diff --git a/vendor/github.com/docker/docker/pkg/graphdb/sort.go b/vendor/github.com/docker/docker/pkg/graphdb/sort_linux.go similarity index 100% rename from vendor/github.com/docker/docker/pkg/graphdb/sort.go rename to vendor/github.com/docker/docker/pkg/graphdb/sort_linux.go diff --git a/vendor/github.com/docker/docker/pkg/graphdb/sort_test.go b/vendor/github.com/docker/docker/pkg/graphdb/sort_linux_test.go similarity index 100% rename from vendor/github.com/docker/docker/pkg/graphdb/sort_test.go rename to vendor/github.com/docker/docker/pkg/graphdb/sort_linux_test.go diff --git a/vendor/github.com/docker/docker/pkg/graphdb/unsupported.go b/vendor/github.com/docker/docker/pkg/graphdb/unsupported.go new file mode 100644 index 000000000..2b8ba7172 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/graphdb/unsupported.go @@ -0,0 +1,3 @@ +// +build !cgo !linux + +package graphdb diff --git a/vendor/github.com/docker/docker/pkg/graphdb/utils.go b/vendor/github.com/docker/docker/pkg/graphdb/utils_linux.go similarity index 100% rename from vendor/github.com/docker/docker/pkg/graphdb/utils.go rename to vendor/github.com/docker/docker/pkg/graphdb/utils_linux.go diff --git a/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go b/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go index 57e48c4f8..cfb8157d6 100644 --- a/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go +++ b/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go @@ -15,68 +15,91 @@ var ( "amazing", "angry", "awesome", - "backstabbing", - "berserk", - "big", + "blissful", "boring", + "brave", "clever", "cocky", "compassionate", + "competent", "condescending", + "confident", "cranky", - "desperate", + "dazzling", "determined", "distracted", "dreamy", - "drunk", "eager", "ecstatic", "elastic", "elated", "elegant", - "evil", + "eloquent", + "epic", "fervent", + "festive", + "flamboyant", "focused", - "furious", - "gigantic", - "gloomy", + "friendly", + "frosty", + "gallant", + "gifted", "goofy", - "grave", + "gracious", "happy", - "high", + "hardcore", + "heuristic", "hopeful", "hungry", "infallible", + "inspiring", "jolly", "jovial", + "keen", "kickass", - "lonely", + "kind", + "laughing", "loving", - "mad", + "lucid", + "mystifying", "modest", + "musing", "naughty", - "nauseous", + "nervous", + "nifty", "nostalgic", + "objective", + "optimistic", "peaceful", "pedantic", "pensive", - "prickly", + "practical", + "priceless", + "quirky", + "quizzical", + "relaxed", "reverent", "romantic", "sad", "serene", "sharp", - "sick", "silly", "sleepy", - "small", "stoic", "stupefied", "suspicious", "tender", "thirsty", - "tiny", "trusting", + "unruffled", + "upbeat", + "vibrant", + "vigilant", + "wizardly", + "wonderful", + "xenodochial", + "youthful", + "zealous", "zen", } diff --git a/vendor/github.com/docker/docker/pkg/signal/trap.go b/vendor/github.com/docker/docker/pkg/signal/trap.go index 44c578aef..638a1ab66 100644 --- a/vendor/github.com/docker/docker/pkg/signal/trap.go +++ b/vendor/github.com/docker/docker/pkg/signal/trap.go @@ -83,15 +83,21 @@ func DumpStacks(dir string) (string, error) { bufferLen *= 2 } buf = buf[:stackSize] - path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1))) - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return "", errors.Wrap(err, "failed to open file to write the goroutine stacks") + var f *os.File + if dir != "" { + path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1))) + var err error + f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + return "", errors.Wrap(err, "failed to open file to write the goroutine stacks") + } + defer f.Close() + defer f.Sync() + } else { + f = os.Stderr } - defer f.Close() if _, err := f.Write(buf); err != nil { return "", errors.Wrap(err, "failed to write goroutine stacks") } - f.Sync() - return path, nil + return f.Name(), nil } diff --git a/vendor/github.com/docker/docker/plugin/backend_linux.go b/vendor/github.com/docker/docker/plugin/backend_linux.go index d40dd83e0..5ab9b4d6a 100644 --- a/vendor/github.com/docker/docker/plugin/backend_linux.go +++ b/vendor/github.com/docker/docker/plugin/backend_linux.go @@ -11,6 +11,7 @@ import ( "net/http" "os" "path/filepath" + "regexp" "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" @@ -23,6 +24,11 @@ import ( "golang.org/x/net/context" ) +var ( + validFullID = regexp.MustCompile(`^([a-f0-9]{64})$`) + validPartialID = regexp.MustCompile(`^([a-f0-9]{1,64})$`) +) + // Disable deactivates a plugin, which implies that they cannot be used by containers. func (pm *Manager) Disable(name string) error { p, err := pm.pluginStore.GetByName(name) @@ -53,12 +59,32 @@ func (pm *Manager) Enable(name string, config *types.PluginEnableConfig) error { } // Inspect examines a plugin config -func (pm *Manager) Inspect(name string) (tp types.Plugin, err error) { - p, err := pm.pluginStore.GetByName(name) - if err != nil { +func (pm *Manager) Inspect(refOrID string) (tp types.Plugin, err error) { + // Match on full ID + if validFullID.MatchString(refOrID) { + p, err := pm.pluginStore.GetByID(refOrID) + if err == nil { + return p.PluginObj, nil + } + } + + // Match on full name + if pluginName, err := getPluginName(refOrID); err == nil { + if p, err := pm.pluginStore.GetByName(pluginName); err == nil { + return p.PluginObj, nil + } + } + + // Match on partial ID + if validPartialID.MatchString(refOrID) { + p, err := pm.pluginStore.Search(refOrID) + if err == nil { + return p.PluginObj, nil + } return tp, err } - return p.PluginObj, nil + + return tp, fmt.Errorf("no such plugin name or ID associated with %q", refOrID) } func (pm *Manager) pull(ref reference.Named, metaHeader http.Header, authConfig *types.AuthConfig, pluginID string) (types.PluginPrivileges, error) { @@ -244,3 +270,18 @@ func (pm *Manager) createFromContext(ctx context.Context, pluginID, pluginDir st return nil } + +func getPluginName(name string) (string, error) { + named, err := reference.ParseNamed(name) // FIXME: validate + if err != nil { + return "", err + } + if reference.IsNameOnly(named) { + named = reference.WithDefaultTag(named) + } + ref, ok := named.(reference.NamedTagged) + if !ok { + return "", fmt.Errorf("invalid name: %s", named.String()) + } + return ref.String(), nil +} diff --git a/vendor/github.com/docker/docker/plugin/store/store.go b/vendor/github.com/docker/docker/plugin/store/store.go index fe834dc4d..0517f8f2c 100644 --- a/vendor/github.com/docker/docker/plugin/store/store.go +++ b/vendor/github.com/docker/docker/plugin/store/store.go @@ -30,6 +30,13 @@ type ErrNotFound string func (name ErrNotFound) Error() string { return fmt.Sprintf("plugin %q not found", string(name)) } +// ErrAmbiguous indicates that a plugin was not found locally. +type ErrAmbiguous string + +func (name ErrAmbiguous) Error() string { + return fmt.Sprintf("multiple plugins found for %q", string(name)) +} + // GetByName retreives a plugin by name. func (ps *Store) GetByName(name string) (*v2.Plugin, error) { ps.RLock() @@ -253,3 +260,25 @@ func (ps *Store) CallHandler(p *v2.Plugin) { } } } + +// Search retreives a plugin by ID Prefix +// If no plugin is found, then ErrNotFound is returned +// If multiple plugins are found, then ErrAmbiguous is returned +func (ps *Store) Search(partialID string) (*v2.Plugin, error) { + ps.RLock() + defer ps.RUnlock() + + var found *v2.Plugin + for id, p := range ps.plugins { + if strings.HasPrefix(id, partialID) { + if found != nil { + return nil, ErrAmbiguous(partialID) + } + found = p + } + } + if found == nil { + return nil, ErrNotFound(partialID) + } + return found, nil +} diff --git a/vendor/github.com/docker/docker/runconfig/opts/parse.go b/vendor/github.com/docker/docker/runconfig/opts/parse.go index b9631f1a3..c3aa6e98b 100644 --- a/vendor/github.com/docker/docker/runconfig/opts/parse.go +++ b/vendor/github.com/docker/docker/runconfig/opts/parse.go @@ -25,7 +25,6 @@ type ContainerOptions struct { attach opts.ListOpts volumes opts.ListOpts tmpfs opts.ListOpts - mounts opts.MountOpt blkioWeightDevice WeightdeviceOpt deviceReadBps ThrottledeviceOpt deviceWriteBps ThrottledeviceOpt @@ -217,7 +216,6 @@ func AddFlags(flags *pflag.FlagSet) *ContainerOptions { flags.Var(&copts.tmpfs, "tmpfs", "Mount a tmpfs directory") flags.Var(&copts.volumesFrom, "volumes-from", "Mount volumes from the specified container(s)") flags.VarP(&copts.volumes, "volume", "v", "Bind mount a volume") - flags.Var(&copts.mounts, "mount", "Attach a filesystem mount to the container") // Health-checking flags.StringVar(&copts.healthCmd, "health-cmd", "", "Command to run to check health") @@ -357,8 +355,6 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c } } - mounts := copts.mounts.Value() - var binds []string volumes := copts.volumes.GetMap() // add any bind targets to the list of container volumes @@ -623,7 +619,6 @@ func Parse(flags *pflag.FlagSet, copts *ContainerOptions) (*container.Config, *c Tmpfs: tmpfs, Sysctls: copts.sysctls.GetAll(), Runtime: copts.runtime, - Mounts: mounts, } // only set this value if the user provided the flag, else it should default to nil diff --git a/vendor/github.com/docker/docker/vendor.conf b/vendor/github.com/docker/docker/vendor.conf index e7510b3d0..5d272a83e 100644 --- a/vendor/github.com/docker/docker/vendor.conf +++ b/vendor/github.com/docker/docker/vendor.conf @@ -23,7 +23,7 @@ github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 github.com/imdario/mergo 0.2.1 #get libnetwork packages -github.com/docker/libnetwork dd0ddde6749fdffe310087e1c3616142d8c3ef9e +github.com/docker/libnetwork fd27f22aaa35e3d57f88688f919d05b744f431fd github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec @@ -100,7 +100,7 @@ github.com/docker/containerd 03e5862ec0d8d3b3f750e19fca3ee367e13c090e github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 # cluster -github.com/docker/swarmkit 1109c363ce9d6400d42908ead944df4f7f788860 +github.com/docker/swarmkit 522d951f733c821cdc33cccca6127c15a2b6de38 github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 github.com/gogo/protobuf v0.3 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/agent.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/agent.go index c4f18ba9a..540aa79cf 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/agent.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/agent.go @@ -7,6 +7,7 @@ import ( "net" "os" "sort" + "sync" "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/stringid" @@ -39,6 +40,7 @@ type agent struct { advertiseAddr string epTblCancel func() driverCancelFuncs map[string][]func() + sync.Mutex } func getBindAddr(ifaceName string) (string, error) { @@ -86,9 +88,16 @@ func resolveAddr(addrOrInterface string) (string, error) { func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error { drvEnc := discoverapi.DriverEncryptionUpdate{} - a := c.agent + a := c.getAgent() + if a == nil { + logrus.Debug("Skipping key change as agent is nil") + return nil + } + // Find the deleted key. If the deleted key was the primary key, // a new primary key should be set before removing if from keyring. + c.Lock() + added := []byte{} deleted := []byte{} j := len(c.keys) for i := 0; i < j; { @@ -127,7 +136,7 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error { if !same { c.keys = append(c.keys, key) if key.Subsystem == subsysGossip { - a.networkDB.SetKey(key.Key) + added = key.Key } if key.Subsystem == subsysIPSec { @@ -136,6 +145,11 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error { } } } + c.Unlock() + + if len(added) > 0 { + a.networkDB.SetKey(added) + } key, tag, err := c.getPrimaryKeyTag(subsysGossip) if err != nil { @@ -166,8 +180,10 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error { } func (c *controller) agentSetup() error { + c.Lock() clusterProvider := c.cfg.Daemon.ClusterProvider - + agent := c.agent + c.Unlock() bindAddr := clusterProvider.GetLocalAddress() advAddr := clusterProvider.GetAdvertiseAddress() remote := clusterProvider.GetRemoteAddress() @@ -176,7 +192,7 @@ func (c *controller) agentSetup() error { listenAddr, _, _ := net.SplitHostPort(listen) logrus.Infof("Initializing Libnetwork Agent Listen-Addr=%s Local-addr=%s Adv-addr=%s Remote-addr =%s", listenAddr, bindAddr, advAddr, remoteAddr) - if advAddr != "" && c.agent == nil { + if advAddr != "" && agent == nil { if err := c.agentInit(listenAddr, bindAddr, advAddr); err != nil { logrus.Errorf("Error in agentInit : %v", err) } else { @@ -208,6 +224,9 @@ func (c *controller) agentSetup() error { // For a given subsystem getKeys sorts the keys by lamport time and returns // slice of keys and lamport time which can used as a unique tag for the keys func (c *controller) getKeys(subsys string) ([][]byte, []uint64) { + c.Lock() + defer c.Unlock() + sort.Sort(ByTime(c.keys)) keys := [][]byte{} @@ -227,6 +246,8 @@ func (c *controller) getKeys(subsys string) ([][]byte, []uint64) { // getPrimaryKeyTag returns the primary key for a given subsystem from the // list of sorted key and the associated tag func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64, error) { + c.Lock() + defer c.Unlock() sort.Sort(ByTime(c.keys)) keys := []*types.EncryptionKey{} for _, key := range c.keys { @@ -265,6 +286,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st ch, cancel := nDB.Watch("endpoint_table", "", "") + c.Lock() c.agent = &agent{ networkDB: nDB, bindAddr: bindAddr, @@ -272,6 +294,7 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st epTblCancel: cancel, driverCancelFuncs: make(map[string][]func()), } + c.Unlock() go c.handleTableEvents(ch, c.handleEpTableEvent) @@ -294,21 +317,22 @@ func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr st } func (c *controller) agentJoin(remote string) error { - if c.agent == nil { + agent := c.getAgent() + if agent == nil { return nil } - - return c.agent.networkDB.Join([]string{remote}) + return agent.networkDB.Join([]string{remote}) } func (c *controller) agentDriverNotify(d driverapi.Driver) { - if c.agent == nil { + agent := c.getAgent() + if agent == nil { return } d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{ - Address: c.agent.advertiseAddr, - BindAddress: c.agent.bindAddr, + Address: agent.advertiseAddr, + BindAddress: agent.bindAddr, Self: true, }) @@ -339,11 +363,19 @@ func (c *controller) agentClose() { return } + var cancelList []func() + + agent.Lock() for _, cancelFuncs := range agent.driverCancelFuncs { for _, cancel := range cancelFuncs { - cancel() + cancelList = append(cancelList, cancel) } } + agent.Unlock() + + for _, cancel := range cancelList { + cancel() + } agent.epTblCancel() @@ -354,13 +386,7 @@ func (n *network) isClusterEligible() bool { if n.driverScope() != datastore.GlobalScope { return false } - - c := n.getController() - if c.agent == nil { - return false - } - - return true + return n.getController().getAgent() != nil } func (n *network) joinCluster() error { @@ -368,8 +394,12 @@ func (n *network) joinCluster() error { return nil } - c := n.getController() - return c.agent.networkDB.JoinNetwork(n.ID()) + agent := n.getController().getAgent() + if agent == nil { + return nil + } + + return agent.networkDB.JoinNetwork(n.ID()) } func (n *network) leaveCluster() error { @@ -377,8 +407,12 @@ func (n *network) leaveCluster() error { return nil } - c := n.getController() - return c.agent.networkDB.LeaveNetwork(n.ID()) + agent := n.getController().getAgent() + if agent == nil { + return nil + } + + return agent.networkDB.LeaveNetwork(n.ID()) } func (ep *endpoint) addDriverInfoToCluster() error { @@ -390,10 +424,7 @@ func (ep *endpoint) addDriverInfoToCluster() error { return nil } - ctrlr := n.ctrlr - ctrlr.Lock() - agent := ctrlr.agent - ctrlr.Unlock() + agent := n.getController().getAgent() if agent == nil { return nil } @@ -415,10 +446,7 @@ func (ep *endpoint) deleteDriverInfoFromCluster() error { return nil } - ctrlr := n.ctrlr - ctrlr.Lock() - agent := ctrlr.agent - ctrlr.Unlock() + agent := n.getController().getAgent() if agent == nil { return nil } @@ -438,6 +466,7 @@ func (ep *endpoint) addServiceInfoToCluster() error { } c := n.getController() + agent := c.getAgent() if !ep.isAnonymous() && ep.Iface().Address() != nil { var ingressPorts []*PortConfig if ep.svcID != "" { @@ -466,8 +495,10 @@ func (ep *endpoint) addServiceInfoToCluster() error { return err } - if err := c.agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil { - return err + if agent != nil { + if err := agent.networkDB.CreateEntry("endpoint_table", n.ID(), ep.ID(), buf); err != nil { + return err + } } } @@ -481,6 +512,8 @@ func (ep *endpoint) deleteServiceInfoFromCluster() error { } c := n.getController() + agent := c.getAgent() + if !ep.isAnonymous() { if ep.svcID != "" && ep.Iface().Address() != nil { var ingressPorts []*PortConfig @@ -492,9 +525,10 @@ func (ep *endpoint) deleteServiceInfoFromCluster() error { return err } } - - if err := c.agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil { - return err + if agent != nil { + if err := agent.networkDB.DeleteEntry("endpoint_table", n.ID(), ep.ID()); err != nil { + return err + } } } return nil @@ -506,16 +540,15 @@ func (n *network) addDriverWatches() { } c := n.getController() + agent := c.getAgent() + if agent == nil { + return + } for _, tableName := range n.driverTables { - c.Lock() - if c.agent == nil { - c.Unlock() - return - } - ch, cancel := c.agent.networkDB.Watch(tableName, n.ID(), "") - c.agent.driverCancelFuncs[n.ID()] = append(c.agent.driverCancelFuncs[n.ID()], cancel) - c.Unlock() - + ch, cancel := agent.networkDB.Watch(tableName, n.ID(), "") + agent.Lock() + agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel) + agent.Unlock() go c.handleTableEvents(ch, n.handleDriverTableEvent) d, err := n.driver(false) if err != nil { @@ -523,7 +556,7 @@ func (n *network) addDriverWatches() { return } - c.agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool { + agent.networkDB.WalkTable(tableName, func(nid, key string, value []byte) bool { if nid == n.ID() { d.EventNotify(driverapi.Create, nid, tableName, key, value) } @@ -538,11 +571,15 @@ func (n *network) cancelDriverWatches() { return } - c := n.getController() - c.Lock() - cancelFuncs := c.agent.driverCancelFuncs[n.ID()] - delete(c.agent.driverCancelFuncs, n.ID()) - c.Unlock() + agent := n.getController().getAgent() + if agent == nil { + return + } + + agent.Lock() + cancelFuncs := agent.driverCancelFuncs[n.ID()] + delete(agent.driverCancelFuncs, n.ID()) + agent.Unlock() for _, cancel := range cancelFuncs { cancel() diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/controller.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/controller.go index 6eaa1c663..68bccf074 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/controller.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/controller.go @@ -237,12 +237,13 @@ func New(cfgOptions ...config.Option) (NetworkController, error) { func (c *controller) SetClusterProvider(provider cluster.Provider) { c.Lock() - defer c.Unlock() c.cfg.Daemon.ClusterProvider = provider + disableProviderCh := c.cfg.Daemon.DisableProvider + c.Unlock() if provider != nil { go c.clusterAgentInit() } else { - c.cfg.Daemon.DisableProvider <- struct{}{} + disableProviderCh <- struct{}{} } } @@ -295,6 +296,12 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error { return c.handleKeyChange(keys) } +func (c *controller) getAgent() *agent { + c.Lock() + defer c.Unlock() + return c.agent +} + func (c *controller) clusterAgentInit() { clusterProvider := c.cfg.Daemon.ClusterProvider for { diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go index 2f69083f2..aaf94e586 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go @@ -57,7 +57,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error { config: config, } - d.vxlanIdm, err = idm.New(nil, "vxlan-id", 1, vxlanIDEnd) + d.vxlanIdm, err = idm.New(nil, "vxlan-id", 0, vxlanIDEnd) if err != nil { return fmt.Errorf("failed to initialize vxlan id manager: %v", err) } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/idm/idm.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/idm/idm.go index 84839c1c9..20be113c8 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/idm/idm.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/idm/idm.go @@ -15,7 +15,7 @@ type Idm struct { handle *bitseq.Handle } -// New returns an instance of id manager for a set of [start-end] numerical ids +// New returns an instance of id manager for a [start,end] set of numerical ids func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { if id == "" { return nil, fmt.Errorf("Invalid id") @@ -54,7 +54,7 @@ func (i *Idm) GetSpecificID(id uint64) error { return i.handle.Set(id - i.start) } -// GetIDInRange returns the first available id in the set within a range +// GetIDInRange returns the first available id in the set within a [start,end] range func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) { if i.handle == nil { return 0, fmt.Errorf("ID set is not initialized") @@ -64,7 +64,9 @@ func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) { return 0, fmt.Errorf("Requested range does not belong to the set") } - return i.handle.SetAnyInRange(start, end-start) + ordinal, err := i.handle.SetAnyInRange(start-i.start, end-i.start) + + return i.start + ordinal, err } // Release releases the specified id diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/iptables/iptables.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/iptables/iptables.go index 388425736..e3a41b556 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/iptables/iptables.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/iptables/iptables.go @@ -45,6 +45,7 @@ var ( iptablesPath string supportsXlock = false supportsCOpt = false + xLockWaitMsg = "Another app is currently holding the xtables lock; waiting" // used to lock iptables commands if xtables lock is not supported bestEffortLock sync.Mutex // ErrIptablesNotFound is returned when the rule is not found. @@ -402,7 +403,7 @@ func raw(args ...string) ([]byte, error) { } // ignore iptables' message about xtables lock - if strings.Contains(string(output), "waiting for it to exit") { + if strings.Contains(string(output), xLockWaitMsg) { output = []byte("") } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/network.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/network.go index ef40ea2bc..79e7e49a9 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/network.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/network.go @@ -1485,17 +1485,12 @@ func (n *network) Peers() []networkdb.PeerInfo { return []networkdb.PeerInfo{} } - var nDB *networkdb.NetworkDB - n.ctrlr.Lock() - if n.ctrlr.agentInitDone == nil && n.ctrlr.agent != nil { - nDB = n.ctrlr.agent.networkDB + agent := n.getController().getAgent() + if agent == nil { + return []networkdb.PeerInfo{} } - n.ctrlr.Unlock() - if nDB != nil { - return n.ctrlr.agent.networkDB.Peers(n.id) - } - return []networkdb.PeerInfo{} + return agent.networkDB.Peers(n.ID()) } func (n *network) DriverOptions() map[string]string { diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/networkdb/cluster.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/networkdb/cluster.go index c871d92f4..2c1a438c5 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/networkdb/cluster.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/networkdb/cluster.go @@ -45,6 +45,8 @@ func (l *logWriter) Write(p []byte) (int, error) { // SetKey adds a new key to the key ring func (nDB *NetworkDB) SetKey(key []byte) { logrus.Debugf("Adding key %s", hex.EncodeToString(key)[0:5]) + nDB.Lock() + defer nDB.Unlock() for _, dbKey := range nDB.config.Keys { if bytes.Equal(key, dbKey) { return @@ -60,6 +62,8 @@ func (nDB *NetworkDB) SetKey(key []byte) { // been added apriori through SetKey func (nDB *NetworkDB) SetPrimaryKey(key []byte) { logrus.Debugf("Primary Key %s", hex.EncodeToString(key)[0:5]) + nDB.RLock() + defer nDB.RUnlock() for _, dbKey := range nDB.config.Keys { if bytes.Equal(key, dbKey) { if nDB.keyring != nil { @@ -74,6 +78,8 @@ func (nDB *NetworkDB) SetPrimaryKey(key []byte) { // can't be the primary key func (nDB *NetworkDB) RemoveKey(key []byte) { logrus.Debugf("Remove Key %s", hex.EncodeToString(key)[0:5]) + nDB.Lock() + defer nDB.Unlock() for i, dbKey := range nDB.config.Keys { if bytes.Equal(key, dbKey) { nDB.config.Keys = append(nDB.config.Keys[:i], nDB.config.Keys[i+1:]...) diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/resolver.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/resolver.go index 68e4831d5..ca3850c58 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/resolver.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/resolver.go @@ -418,8 +418,12 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) { } execErr := r.backend.ExecFunc(extConnect) - if execErr != nil || err != nil { - logrus.Debugf("Connect failed, %s", err) + if execErr != nil { + logrus.Warn(execErr) + continue + } + if err != nil { + logrus.Warnf("Connect failed: %s", err) continue } logrus.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype, diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_common.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_common.go index a0172f594..b43c6403f 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_common.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_common.go @@ -156,11 +156,10 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in c.Lock() s, ok := c.serviceBindings[skey] + c.Unlock() if !ok { - c.Unlock() return nil } - c.Unlock() s.Lock() lb, ok := s.loadBalancers[nid] @@ -188,7 +187,9 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in if len(s.loadBalancers) == 0 { // All loadbalancers for the service removed. Time to // remove the service itself. + c.Lock() delete(c.serviceBindings, skey) + c.Unlock() } // Remove loadbalancer service(if needed) and backend in all diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_linux.go b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_linux.go index be8dc84d3..fbcc89d22 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_linux.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/libnetwork/service_linux.go @@ -34,8 +34,8 @@ func init() { func (n *network) connectedLoadbalancers() []*loadBalancer { c := n.getController() - serviceBindings := make([]*service, 0, len(c.serviceBindings)) c.Lock() + serviceBindings := make([]*service, 0, len(c.serviceBindings)) for _, s := range c.serviceBindings { serviceBindings = append(serviceBindings, s) } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/exec/controller_test.mock.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/exec/controller_test.mock.go index 4e6c8897d..42b5a2be4 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/exec/controller_test.mock.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/exec/controller_test.mock.go @@ -193,11 +193,12 @@ func (_m *MockLogPublisherProvider) EXPECT() *_MockLogPublisherProviderRecorder return _m.recorder } -func (_m *MockLogPublisherProvider) Publisher(ctx context.Context, subscriptionID string) (LogPublisher, error) { +func (_m *MockLogPublisherProvider) Publisher(ctx context.Context, subscriptionID string) (LogPublisher, func(), error) { ret := _m.ctrl.Call(_m, "Publisher", ctx, subscriptionID) ret0, _ := ret[0].(LogPublisher) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(func()) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } func (_mr *_MockLogPublisherProviderRecorder) Publisher(arg0, arg1 interface{}) *gomock.Call { diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/session.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/session.go index 277944591..a8f657ffa 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/session.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/session.go @@ -226,16 +226,6 @@ func (s *session) logSubscriptions(ctx context.Context) error { client := api.NewLogBrokerClient(s.conn) subscriptions, err := client.ListenSubscriptions(ctx, &api.ListenSubscriptionsRequest{}) - if grpc.Code(err) == codes.Unimplemented { - log.Warning("manager does not support log subscriptions") - // Don't return, because returning would bounce the session - select { - case <-s.closed: - return errSessionClosed - case <-ctx.Done(): - return ctx.Err() - } - } if err != nil { return err } @@ -243,6 +233,16 @@ func (s *session) logSubscriptions(ctx context.Context) error { for { resp, err := subscriptions.Recv() + if grpc.Code(err) == codes.Unimplemented { + log.Warning("manager does not support log subscriptions") + // Don't return, because returning would bounce the session + select { + case <-s.closed: + return errSessionClosed + case <-ctx.Done(): + return ctx.Err() + } + } if err != nil { return err } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/worker.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/worker.go index 55e747771..c3684f496 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/worker.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/agent/worker.go @@ -441,10 +441,10 @@ func (w *worker) Subscribe(ctx context.Context, subscription *api.SubscriptionMe for _, tm := range w.taskManagers { if match(tm.task) { wg.Add(1) - go func() { + go func(tm *taskManager) { defer wg.Done() tm.Logs(ctx, *subscription.Options, publisher) - }() + }(tm) } } w.mu.Unlock() diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.pb.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.pb.go index 19d103e84..437558bb6 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.pb.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.pb.go @@ -43,8 +43,9 @@ func (*NodeCertificateStatusRequest) ProtoMessage() {} func (*NodeCertificateStatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorCa, []int{0} } type NodeCertificateStatusResponse struct { - Status *IssuanceStatus `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` - Certificate *Certificate `protobuf:"bytes,2,opt,name=certificate" json:"certificate,omitempty"` + Status *IssuanceStatus `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` + Certificate *Certificate `protobuf:"bytes,2,opt,name=certificate" json:"certificate,omitempty"` + RootCABundle []byte `protobuf:"bytes,3,opt,name=root_ca_bundle,json=rootCaBundle,proto3" json:"root_ca_bundle,omitempty"` } func (m *NodeCertificateStatusResponse) Reset() { *m = NodeCertificateStatusResponse{} } @@ -181,8 +182,9 @@ func (m *NodeCertificateStatusResponse) Copy() *NodeCertificateStatusResponse { } o := &NodeCertificateStatusResponse{ - Status: m.Status.Copy(), - Certificate: m.Certificate.Copy(), + Status: m.Status.Copy(), + Certificate: m.Certificate.Copy(), + RootCABundle: m.RootCABundle, } return o @@ -274,7 +276,7 @@ func (this *NodeCertificateStatusResponse) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 6) + s := make([]string, 0, 7) s = append(s, "&api.NodeCertificateStatusResponse{") if this.Status != nil { s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n") @@ -282,6 +284,7 @@ func (this *NodeCertificateStatusResponse) GoString() string { if this.Certificate != nil { s = append(s, "Certificate: "+fmt.Sprintf("%#v", this.Certificate)+",\n") } + s = append(s, "RootCABundle: "+fmt.Sprintf("%#v", this.RootCABundle)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -639,6 +642,12 @@ func (m *NodeCertificateStatusResponse) MarshalTo(data []byte) (int, error) { } i += n2 } + if len(m.RootCABundle) > 0 { + data[i] = 0x1a + i++ + i = encodeVarintCa(data, i, uint64(len(m.RootCABundle))) + i += copy(data[i:], m.RootCABundle) + } return i, nil } @@ -1103,6 +1112,10 @@ func (m *NodeCertificateStatusResponse) Size() (n int) { l = m.Certificate.Size() n += 1 + l + sovCa(uint64(l)) } + l = len(m.RootCABundle) + if l > 0 { + n += 1 + l + sovCa(uint64(l)) + } return n } @@ -1200,6 +1213,7 @@ func (this *NodeCertificateStatusResponse) String() string { s := strings.Join([]string{`&NodeCertificateStatusResponse{`, `Status:` + strings.Replace(fmt.Sprintf("%v", this.Status), "IssuanceStatus", "IssuanceStatus", 1) + `,`, `Certificate:` + strings.Replace(fmt.Sprintf("%v", this.Certificate), "Certificate", "Certificate", 1) + `,`, + `RootCABundle:` + fmt.Sprintf("%v", this.RootCABundle) + `,`, `}`, }, "") return s @@ -1448,6 +1462,37 @@ func (m *NodeCertificateStatusResponse) Unmarshal(data []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RootCABundle", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCa + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := data[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCa + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RootCABundle = append(m.RootCABundle[:0], data[iNdEx:postIndex]...) + if m.RootCABundle == nil { + m.RootCABundle = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipCa(data[iNdEx:]) @@ -2096,42 +2141,44 @@ var ( func init() { proto.RegisterFile("ca.proto", fileDescriptorCa) } var fileDescriptorCa = []byte{ - // 586 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0xcb, 0x6e, 0xd3, 0x40, - 0x14, 0xcd, 0x38, 0x25, 0x69, 0x6f, 0x42, 0x8a, 0xa6, 0x89, 0x14, 0xf2, 0x70, 0x2a, 0xb3, 0x68, - 0x37, 0x38, 0x6d, 0x60, 0x05, 0x1b, 0x92, 0x20, 0x55, 0x11, 0x02, 0x21, 0x47, 0xb0, 0xad, 0x5c, - 0x67, 0x08, 0x56, 0x12, 0x8f, 0xf1, 0x8c, 0x0b, 0xd9, 0x21, 0x51, 0xf1, 0x07, 0x08, 0x56, 0x7c, - 0x02, 0xdf, 0x11, 0xb1, 0x62, 0xc9, 0x2a, 0x22, 0xfe, 0x00, 0xc4, 0x27, 0x20, 0x8f, 0x6d, 0x9a, - 0x87, 0x13, 0xda, 0x55, 0x3c, 0xd7, 0xe7, 0x9c, 0x7b, 0xee, 0xc9, 0xf5, 0xc0, 0xb6, 0xa1, 0xab, - 0xb6, 0x43, 0x39, 0xc5, 0xb8, 0x47, 0x8d, 0x01, 0x71, 0x54, 0xf6, 0x56, 0x77, 0x46, 0x03, 0x93, - 0xab, 0xe7, 0xc7, 0xa5, 0x0c, 0x1f, 0xdb, 0x84, 0x05, 0x80, 0x52, 0x86, 0xd9, 0xc4, 0x88, 0x0e, - 0xf9, 0x3e, 0xed, 0x53, 0xf1, 0x58, 0xf7, 0x9f, 0xc2, 0xea, 0x9e, 0x3d, 0x74, 0xfb, 0xa6, 0x55, - 0x0f, 0x7e, 0x82, 0xa2, 0xd2, 0x86, 0xca, 0x33, 0xda, 0x23, 0x6d, 0xe2, 0x70, 0xf3, 0x95, 0x69, - 0xe8, 0x9c, 0x74, 0xb9, 0xce, 0x5d, 0xa6, 0x91, 0x37, 0x2e, 0x61, 0x1c, 0xdf, 0x81, 0xb4, 0x45, - 0x7b, 0xe4, 0xd4, 0xec, 0x15, 0xd1, 0x3e, 0x3a, 0xdc, 0x69, 0x81, 0x37, 0xad, 0xa5, 0x7c, 0x4a, - 0xe7, 0xb1, 0x96, 0xf2, 0x5f, 0x75, 0x7a, 0xca, 0x57, 0x04, 0xd5, 0x35, 0x2a, 0xcc, 0xa6, 0x16, - 0x23, 0xf8, 0x01, 0xa4, 0x98, 0xa8, 0x08, 0x95, 0x4c, 0x43, 0x51, 0x57, 0x07, 0x52, 0x3b, 0x8c, - 0xb9, 0xba, 0x65, 0x44, 0xdc, 0x90, 0x81, 0x9b, 0x90, 0x31, 0x2e, 0x85, 0x8b, 0x92, 0x10, 0xa8, - 0xc5, 0x09, 0xcc, 0xf5, 0xd7, 0xe6, 0x39, 0xca, 0x05, 0x82, 0xb2, 0xaf, 0x4e, 0x96, 0x5c, 0x46, - 0x53, 0xde, 0x87, 0x2d, 0x87, 0x0e, 0x89, 0x30, 0x97, 0x6b, 0x54, 0xe2, 0xb4, 0x7d, 0xa6, 0x46, - 0x87, 0xa4, 0x25, 0x15, 0x91, 0x26, 0xd0, 0xf8, 0x36, 0x24, 0x0d, 0xe6, 0x08, 0x43, 0xd9, 0x56, - 0xda, 0x9b, 0xd6, 0x92, 0xed, 0xae, 0xa6, 0xf9, 0x35, 0x9c, 0x87, 0x1b, 0x9c, 0x0e, 0x88, 0x55, - 0x4c, 0xfa, 0xa1, 0x69, 0xc1, 0x41, 0xf9, 0x84, 0xa0, 0x12, 0x6f, 0x23, 0x8c, 0xe9, 0x2a, 0x69, - 0xe3, 0xe7, 0xb0, 0x2b, 0x40, 0x23, 0x32, 0x3a, 0x23, 0x0e, 0x7b, 0x6d, 0xda, 0xc2, 0x42, 0xae, - 0x71, 0xb0, 0xce, 0x77, 0xd7, 0x26, 0x86, 0xfa, 0xf4, 0x1f, 0x5c, 0xcb, 0xf9, 0xfc, 0xcb, 0xb3, - 0x52, 0x85, 0xf2, 0x09, 0xe1, 0x1a, 0xa5, 0xbc, 0xdd, 0x5c, 0x4d, 0x47, 0x79, 0x04, 0x95, 0xf8, - 0xd7, 0xa1, 0xeb, 0xfd, 0xc5, 0x3f, 0xc8, 0x77, 0x9e, 0x5d, 0xcc, 0xbf, 0x00, 0x7b, 0x27, 0x84, - 0xbf, 0xb0, 0x86, 0xd4, 0x18, 0x3c, 0x21, 0xe3, 0x48, 0xd8, 0x81, 0xfc, 0x62, 0x39, 0x14, 0xac, - 0x02, 0xb8, 0xa2, 0x78, 0x3a, 0x20, 0xe3, 0x50, 0x6f, 0xc7, 0x8d, 0x60, 0xf8, 0x21, 0xa4, 0xcf, - 0x89, 0xc3, 0x4c, 0x6a, 0x85, 0xcb, 0x50, 0x8e, 0x1b, 0xfc, 0x65, 0x00, 0x69, 0x6d, 0x4d, 0xa6, - 0xb5, 0x84, 0x16, 0x31, 0x1a, 0x17, 0x12, 0x48, 0xed, 0x26, 0xfe, 0x80, 0x44, 0xef, 0x95, 0xa1, - 0x70, 0x3d, 0x4e, 0x6b, 0x43, 0x3a, 0xa5, 0xa3, 0xab, 0x13, 0x82, 0xf1, 0x94, 0xed, 0xef, 0xdf, - 0x7e, 0x7f, 0x91, 0xa4, 0x5b, 0x08, 0xbf, 0x83, 0xec, 0x7c, 0x00, 0xf8, 0x60, 0x8d, 0xd6, 0x72, - 0x72, 0xa5, 0xc3, 0xff, 0x03, 0xc3, 0x66, 0x05, 0xd1, 0x6c, 0x17, 0x6e, 0x0a, 0xe4, 0xdd, 0x91, - 0x6e, 0xe9, 0x7d, 0xe2, 0x34, 0x3e, 0x4b, 0x20, 0xf6, 0x2a, 0x8c, 0x22, 0x6e, 0x2b, 0xe3, 0xa3, - 0xd8, 0xf0, 0x19, 0xc5, 0x47, 0xb1, 0x69, 0xe1, 0xe7, 0xa2, 0xf8, 0x88, 0xa0, 0x10, 0x7b, 0x87, - 0xe0, 0xa3, 0x75, 0x6b, 0xbd, 0xee, 0xd2, 0x2a, 0x1d, 0x5f, 0x83, 0xb1, 0x6c, 0xa4, 0x55, 0x99, - 0xcc, 0xe4, 0xc4, 0xcf, 0x99, 0x9c, 0xf8, 0x33, 0x93, 0xd1, 0x7b, 0x4f, 0x46, 0x13, 0x4f, 0x46, - 0x3f, 0x3c, 0x19, 0xfd, 0xf2, 0x64, 0x74, 0x96, 0x12, 0xd7, 0xe6, 0xbd, 0xbf, 0x01, 0x00, 0x00, - 0xff, 0xff, 0xe7, 0x80, 0x3b, 0x00, 0x9b, 0x05, 0x00, 0x00, + // 624 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0xc1, 0x6e, 0xd3, 0x4a, + 0x14, 0xed, 0xb8, 0x7d, 0x69, 0x7b, 0x93, 0x97, 0x56, 0xd3, 0x56, 0x0a, 0x69, 0xea, 0x54, 0x66, + 0xd1, 0x6e, 0x48, 0xdb, 0x80, 0x58, 0xc0, 0x86, 0xda, 0x48, 0x55, 0x85, 0x40, 0x68, 0x2a, 0xd8, + 0x46, 0xae, 0x7d, 0x09, 0x56, 0x12, 0x8f, 0xf1, 0x8c, 0x0b, 0xdd, 0x21, 0x51, 0xf1, 0x07, 0x08, + 0xbe, 0x82, 0xef, 0xa8, 0x58, 0xb1, 0x42, 0xac, 0x22, 0xea, 0x0f, 0x40, 0x7c, 0x02, 0xf2, 0xd8, + 0xa6, 0x69, 0xeb, 0x84, 0xb2, 0x8a, 0xe7, 0xce, 0x39, 0x67, 0xce, 0x3d, 0x73, 0x33, 0x30, 0xe7, + 0xd8, 0xad, 0x20, 0xe4, 0x92, 0x53, 0xea, 0x72, 0xa7, 0x87, 0x61, 0x4b, 0xbc, 0xb6, 0xc3, 0x41, + 0xcf, 0x93, 0xad, 0xa3, 0x9d, 0x7a, 0x59, 0x1e, 0x07, 0x28, 0x52, 0x40, 0xbd, 0x2c, 0x02, 0x74, + 0xf2, 0xc5, 0x72, 0x97, 0x77, 0xb9, 0xfa, 0xdc, 0x4a, 0xbe, 0xb2, 0xea, 0x52, 0xd0, 0x8f, 0xba, + 0x9e, 0xbf, 0x95, 0xfe, 0xa4, 0x45, 0xc3, 0x82, 0xc6, 0x13, 0xee, 0xa2, 0x85, 0xa1, 0xf4, 0x5e, + 0x78, 0x8e, 0x2d, 0xf1, 0x40, 0xda, 0x32, 0x12, 0x0c, 0x5f, 0x45, 0x28, 0x24, 0xbd, 0x09, 0xb3, + 0x3e, 0x77, 0xb1, 0xe3, 0xb9, 0x35, 0xb2, 0x4e, 0x36, 0xe7, 0x4d, 0x88, 0x87, 0xcd, 0x52, 0x42, + 0xd9, 0x7f, 0xc8, 0x4a, 0xc9, 0xd6, 0xbe, 0x6b, 0x7c, 0x23, 0xb0, 0x36, 0x46, 0x45, 0x04, 0xdc, + 0x17, 0x48, 0xef, 0x41, 0x49, 0xa8, 0x8a, 0x52, 0x29, 0xb7, 0x8d, 0xd6, 0xd5, 0x86, 0x5a, 0xfb, + 0x42, 0x44, 0xb6, 0xef, 0xe4, 0xdc, 0x8c, 0x41, 0x77, 0xa1, 0xec, 0x9c, 0x0b, 0xd7, 0x34, 0x25, + 0xd0, 0x2c, 0x12, 0x18, 0x39, 0x9f, 0x8d, 0x72, 0xe8, 0x5d, 0xa8, 0x86, 0x9c, 0xcb, 0x8e, 0x63, + 0x77, 0x0e, 0x23, 0xdf, 0xed, 0x63, 0x6d, 0x7a, 0x9d, 0x6c, 0x56, 0xcc, 0xc5, 0x78, 0xd8, 0xac, + 0x30, 0xce, 0xa5, 0xb5, 0x6b, 0xaa, 0x3a, 0xab, 0x24, 0x38, 0xcb, 0x4e, 0x57, 0xc6, 0x09, 0x81, + 0xd5, 0xc4, 0x15, 0x5e, 0xea, 0x2e, 0x4f, 0xe7, 0x0e, 0xcc, 0x84, 0xbc, 0x8f, 0xaa, 0xa9, 0x6a, + 0xbb, 0x51, 0xe4, 0x29, 0x61, 0x32, 0xde, 0x47, 0x53, 0xab, 0x11, 0xa6, 0xd0, 0xf4, 0x06, 0x4c, + 0x3b, 0x22, 0x54, 0x8d, 0x54, 0xcc, 0xd9, 0x78, 0xd8, 0x9c, 0xb6, 0x0e, 0x18, 0x4b, 0x6a, 0x74, + 0x19, 0xfe, 0x93, 0xbc, 0x87, 0xbe, 0xf2, 0x37, 0xcf, 0xd2, 0x85, 0xf1, 0x81, 0x40, 0xa3, 0xd8, + 0x46, 0x16, 0xef, 0x75, 0x6e, 0x89, 0x3e, 0x85, 0x05, 0x05, 0x1a, 0xe0, 0xe0, 0x10, 0x43, 0xf1, + 0xd2, 0x0b, 0x94, 0x85, 0x6a, 0x7b, 0x63, 0x9c, 0xef, 0x83, 0x00, 0x9d, 0xd6, 0xe3, 0x3f, 0x70, + 0x56, 0x4d, 0xf8, 0xe7, 0x6b, 0x63, 0x0d, 0x56, 0xf7, 0x50, 0xa6, 0xf9, 0x5d, 0x4d, 0xc7, 0x78, + 0x00, 0x8d, 0xe2, 0xed, 0xcc, 0xf5, 0xfa, 0xc5, 0x8b, 0x4d, 0x9c, 0x57, 0x2e, 0xdc, 0x9b, 0xb1, + 0x02, 0x4b, 0x7b, 0x28, 0x9f, 0xf9, 0x7d, 0xee, 0xf4, 0x1e, 0xe1, 0x71, 0x2e, 0x1c, 0xc2, 0xf2, + 0xc5, 0x72, 0x26, 0xb8, 0x06, 0x10, 0xa9, 0x62, 0xa7, 0x87, 0xc7, 0x99, 0xde, 0x7c, 0x94, 0xc3, + 0xe8, 0x7d, 0x98, 0x3d, 0xc2, 0x50, 0x78, 0xdc, 0xcf, 0x86, 0x68, 0xb5, 0xa8, 0xf1, 0xe7, 0x29, + 0xc4, 0x9c, 0x39, 0x1d, 0x36, 0xa7, 0x58, 0xce, 0x68, 0x9f, 0x68, 0xa0, 0x59, 0xbb, 0xf4, 0x1d, + 0x51, 0x67, 0x5f, 0x69, 0x8a, 0x6e, 0x15, 0x69, 0x4d, 0x48, 0xa7, 0xbe, 0x7d, 0x7d, 0x42, 0xda, + 0x9e, 0x31, 0xf7, 0xe5, 0xf3, 0xcf, 0x4f, 0x9a, 0xb6, 0x48, 0xe8, 0x1b, 0xa8, 0x8c, 0x06, 0x40, + 0x37, 0xc6, 0x68, 0x5d, 0x4e, 0xae, 0xbe, 0xf9, 0x77, 0x60, 0x76, 0xd8, 0x8a, 0x3a, 0x6c, 0x01, + 0xfe, 0x57, 0xc8, 0x5b, 0x03, 0xdb, 0xb7, 0xbb, 0x18, 0xb6, 0x3f, 0x6a, 0xa0, 0xe6, 0x2a, 0x8b, + 0xa2, 0x68, 0x2a, 0x8b, 0xa3, 0x98, 0xf0, 0x37, 0x2a, 0x8e, 0x62, 0xd2, 0xc0, 0x8f, 0x44, 0xf1, + 0x9e, 0xc0, 0x4a, 0xe1, 0xdb, 0x43, 0xb7, 0xc7, 0x8d, 0xf5, 0xb8, 0xc7, 0xae, 0xbe, 0xf3, 0x0f, + 0x8c, 0xcb, 0x46, 0xcc, 0xc6, 0xe9, 0x99, 0x3e, 0xf5, 0xfd, 0x4c, 0x9f, 0xfa, 0x75, 0xa6, 0x93, + 0xb7, 0xb1, 0x4e, 0x4e, 0x63, 0x9d, 0x7c, 0x8d, 0x75, 0xf2, 0x23, 0xd6, 0xc9, 0x61, 0x49, 0x3d, + 0xb7, 0xb7, 0x7f, 0x07, 0x00, 0x00, 0xff, 0xff, 0x34, 0x4d, 0x5b, 0xfa, 0xd3, 0x05, 0x00, 0x00, } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.proto b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.proto index 5aa1f673e..c3b1f1e65 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.proto +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/api/ca.proto @@ -36,6 +36,7 @@ message NodeCertificateStatusRequest { message NodeCertificateStatusResponse { IssuanceStatus status = 1; Certificate certificate = 2; + bytes root_ca_bundle = 3 [(gogoproto.customname) = "RootCABundle"]; } message IssueNodeCertificateRequest { diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/certificates.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/certificates.go index dc5dbc8f1..1477de257 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/certificates.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/certificates.go @@ -102,13 +102,15 @@ type RootCA struct { // Key will only be used by the original manager to put the private // key-material in raft, no signing operations depend on it. Key []byte - // Cert includes the PEM encoded Certificate for the Root CA + // Cert includes the PEM encoded Certificate bundle for the Root CA Cert []byte Pool *x509.CertPool // Digest of the serialized bytes of the certificate Digest digest.Digest // This signer will be nil if the node doesn't have the appropriate key material Signer cfsigner.Signer + // Path stores the location on disk where the RootCA lives + Path CertPaths } // CanSign ensures that the signer has all three necessary elements needed to operate @@ -163,9 +165,9 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit // Get the remote manager to issue a CA signed certificate for this node // Retry up to 5 times in case the manager we first try to contact isn't // responding properly (for example, it may have just been demoted). - var signedCert []byte + var response *api.NodeCertificateStatusResponse for i := 0; i != 5; i++ { - signedCert, err = GetRemoteSignedCertificate(ctx, csr, token, rca.Pool, r, transport, nodeInfo) + response, err = GetRemoteSignedCertificate(ctx, csr, token, rca.Pool, r, transport, nodeInfo) if err == nil { break } @@ -177,7 +179,7 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit // Доверяй, но проверяй. // Before we overwrite our local key + certificate, let's make sure the server gave us one that is valid // Create an X509Cert so we can .Verify() - certBlock, _ := pem.Decode(signedCert) + certBlock, _ := pem.Decode(response.Certificate.Certificate) if certBlock == nil { return nil, errors.New("failed to parse certificate PEM") } @@ -185,17 +187,34 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit if err != nil { return nil, err } - // Include our current root pool + // We retrieve the certificate with the current root pool, so we know this was issued by a legitimate manager. + // However, there might have been a server-side root rotation, so we verify this cert with a new pool. + // If we got a valid response.RootCABundle, turn it into a Pool, and verify the newly minted certificate using it. + var ( + newRootErr error + newRootCA RootCA + ) + rootCAPool := rca.Pool + if response.RootCABundle != nil { + newRootCA, newRootErr = NewRootCA(response.RootCABundle, nil, rca.Path, time.Minute) + if newRootErr == nil { + // The response.RootCABundle we got from the remote server seems to be good, use it + rootCAPool = newRootCA.Pool + } + } + + // Create VerifyOptions with either the new certificate bundle, or the old pool opts := x509.VerifyOptions{ - Roots: rca.Pool, + Roots: rootCAPool, } - // Check to see if this certificate was signed by our CA, and isn't expired + + // Check to see if this certificate was signed by one of the CAs, and isn't expired if _, err := X509Cert.Verify(opts); err != nil { return nil, err } // Create a valid TLSKeyPair out of the PEM encoded private key and certificate - tlsKeyPair, err := tls.X509KeyPair(signedCert, key) + tlsKeyPair, err := tls.X509KeyPair(response.Certificate.Certificate, key) if err != nil { return nil, err } @@ -211,7 +230,16 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWrit return nil, err } - if err := kw.Write(signedCert, key, kekUpdate); err != nil { + // If a CA certificate bundle exists it has been validated before. If it's different, let's write it to disk. + // Root rotation should always happen by appending a new CA cert, and later removing the old one, + // so it's safer to do it in this order of operations (write root, write certificate) + if newRootErr == nil && !bytes.Equal(rca.Cert, response.RootCABundle) { + if err := newRootCA.saveCertificate(); err != nil { + return nil, err + } + } + + if err := kw.Write(response.Certificate.Certificate, key, kekUpdate); err != nil { return nil, err } @@ -316,10 +344,28 @@ func (rca *RootCA) AppendFirstRootPEM(cert []byte) ([]byte, error) { return certChain, nil } +func (rca *RootCA) saveCertificate() error { + if rca.Cert == nil { + return errors.New("no valid certificate bundle found") + + } + if rca.Path.Cert == "" { + return errors.New("no path found for this root CA") + } + + // Make sure the necessary dirs exist and they are writable + err := os.MkdirAll(filepath.Dir(rca.Path.Cert), 0755) + if err != nil { + return err + } + + return ioutils.AtomicWriteFile(rca.Path.Cert, rca.Cert, 0644) +} + // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte // slices. key may be nil, and in this case NewRootCA will return a RootCA // without a signer. -func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, error) { +func NewRootCA(certBytes, keyBytes []byte, paths CertPaths, certExpiry time.Duration) (RootCA, error) { // Parse all the certificates in the cert bundle parsedCerts, err := helpers.ParseCertificatesPEM(certBytes) if err != nil { @@ -345,7 +391,7 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er if len(keyBytes) == 0 { // This RootCA does not have a valid signer. - return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil + return RootCA{Cert: certBytes, Digest: digest, Pool: pool, Path: paths}, nil } var ( @@ -387,7 +433,7 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er keyBlock, _ := pem.Decode(keyBytes) if keyBlock == nil { // This RootCA does not have a valid signer. - return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil + return RootCA{Cert: certBytes, Digest: digest, Pool: pool, Path: paths}, nil } if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) { keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr) @@ -396,7 +442,7 @@ func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, er } } - return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool}, nil + return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool, Path: paths}, nil } func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error { @@ -414,8 +460,7 @@ func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error { return errors.New("certificate key mismatch") } -// GetLocalRootCA validates if the contents of the file are a valid self-signed -// CA certificate, and returns the PEM-encoded Certificate if so +// GetLocalRootCA returns the PEM-encoded root CA Certificate if it exists func GetLocalRootCA(paths CertPaths) (RootCA, error) { // Check if we have a Certificate file cert, err := ioutil.ReadFile(paths.Cert) @@ -427,17 +472,7 @@ func GetLocalRootCA(paths CertPaths) (RootCA, error) { return RootCA{}, err } - key, err := ioutil.ReadFile(paths.Key) - if err != nil { - if !os.IsNotExist(err) { - return RootCA{}, err - } - // There may not be a local key. It's okay to pass in a nil - // key. We'll get a root CA without a signer. - key = nil - } - - return NewRootCA(cert, key, DefaultNodeCertExpiration) + return NewRootCA(cert, nil, paths, DefaultNodeCertExpiration) } func getGRPCConnection(creds credentials.TransportCredentials, r remotes.Remotes) (*grpc.ClientConn, api.Peer, error) { @@ -530,13 +565,13 @@ func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) { return RootCA{}, err } - rootCA, err := NewRootCA(cert, key, DefaultNodeCertExpiration) + rootCA, err := NewRootCA(cert, key, paths, DefaultNodeCertExpiration) if err != nil { return RootCA{}, err } // save the cert to disk - if err := saveRootCA(rootCA, paths); err != nil { + if err := rootCA.saveCertificate(); err != nil { return RootCA{}, err } @@ -545,7 +580,7 @@ func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) { // GetRemoteSignedCertificate submits a CSR to a remote CA server address, // and that is part of a CA identified by a specific certificate pool. -func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, r remotes.Remotes, creds credentials.TransportCredentials, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) { +func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, r remotes.Remotes, creds credentials.TransportCredentials, nodeInfo chan<- api.IssueNodeCertificateResponse) (*api.NodeCertificateStatusResponse, error) { if rootCAPool == nil { return nil, errors.New("valid root CA pool required") } @@ -597,7 +632,7 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r } // If the certificate was issued, return - if statusResponse.Status.State == api.IssuanceStateIssued { + if statusResponse.Status != nil && statusResponse.Status.State == api.IssuanceStateIssued { if statusResponse.Certificate == nil { return nil, errors.New("no certificate in CertificateStatus response") } @@ -609,7 +644,7 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, r // current request. if bytes.Equal(statusResponse.Certificate.CSR, csr) { r.Observe(peer, remotes.DefaultObservationWeight) - return statusResponse.Certificate.Certificate, nil + return statusResponse, nil } } @@ -643,17 +678,6 @@ func readCertValidity(kr KeyReader) (time.Time, time.Time, error) { } -func saveRootCA(rootCA RootCA, paths CertPaths) error { - // Make sure the necessary dirs exist and they are writable - err := os.MkdirAll(filepath.Dir(paths.Cert), 0755) - if err != nil { - return err - } - - // If the root certificate got returned successfully, save the rootCA to disk. - return ioutils.AtomicWriteFile(paths.Cert, rootCA.Cert, 0644) -} - // GenerateNewCSR returns a newly generated key and CSR signed with said key func GenerateNewCSR() (csr, key []byte, err error) { req := &cfcsr.CertificateRequest{ diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/config.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/config.go index 96ef82061..bde2d8f71 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/config.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/config.go @@ -119,8 +119,15 @@ func (s *SecurityConfig) UpdateRootCA(cert, key []byte, certExpiry time.Duration s.mu.Lock() defer s.mu.Unlock() - rootCA, err := NewRootCA(cert, key, certExpiry) + // Create a new RootCA, keeping the path of the old RootCA + rootCA, err := NewRootCA(cert, key, s.rootCA.Path, certExpiry) + if err != nil { + return err + } + // Attempt to write the new certificate to disk + err = rootCA.saveCertificate() if err == nil { + // No errors, save the current rootCA s.rootCA = &rootCA } @@ -231,7 +238,8 @@ func DownloadRootCA(ctx context.Context, paths CertPaths, token string, r remote } // Save root CA certificate to disk - if err = saveRootCA(rootCA, paths); err != nil { + rootCA.Path = paths + if err = rootCA.saveCertificate(); err != nil { return RootCA{}, err } @@ -402,7 +410,6 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, remotes remotes.Remo // Since the expiration of the certificate is managed remotely we should update our // retry timer on every iteration of this loop. - // Retrieve the current certificate expiration information. validFrom, validUntil, err := readCertValidity(s.KeyReader()) if err != nil { // We failed to read the expiration, let's stick with the starting default diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/server.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/server.go index 5e074b53d..68e7d4567 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/server.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/ca/server.go @@ -142,8 +142,9 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer // If this certificate has a final state, return it immediately (both pending and renew are transition states) if isFinalState(node.Certificate.Status) { return &api.NodeCertificateStatusResponse{ - Status: &node.Certificate.Status, - Certificate: &node.Certificate, + Status: &node.Certificate.Status, + Certificate: &node.Certificate, + RootCABundle: s.securityConfig.RootCA().Cert, }, nil } @@ -164,8 +165,9 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer if isFinalState(v.Node.Certificate.Status) { cert := v.Node.Certificate.Copy() return &api.NodeCertificateStatusResponse{ - Status: &cert.Status, - Certificate: cert, + Status: &cert.Status, + Certificate: cert, + RootCABundle: s.securityConfig.RootCA().Cert, }, nil } } diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go index f741a21fe..ab258a484 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/allocator/networkallocator/networkallocator.go @@ -573,9 +573,18 @@ func (na *NetworkAllocator) allocateDriverState(n *api.Network) error { return err } - var options map[string]string + options := make(map[string]string) + // reconcile the driver specific options from the network spec + // and from the operational state retrieved from the store if n.Spec.DriverConfig != nil { - options = n.Spec.DriverConfig.Options + for k, v := range n.Spec.DriverConfig.Options { + options[k] = v + } + } + if n.DriverState != nil { + for k, v := range n.DriverState.Options { + options[k] = v + } } // Construct IPAM data for driver consumption. diff --git a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go index 923dddf3e..9ae9293ff 100644 --- a/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go +++ b/vendor/github.com/docker/docker/vendor/github.com/docker/swarmkit/manager/state/raft/raft.go @@ -896,18 +896,39 @@ func (n *Node) RemoveMember(ctx context.Context, id uint64) error { return n.removeMember(ctx, id) } +// processRaftMessageLogger is used to lazily create a logger for +// ProcessRaftMessage. Usually nothing will be logged, so it is useful to avoid +// formatting strings and allocating a logger when it won't be used. +func (n *Node) processRaftMessageLogger(ctx context.Context, msg *api.ProcessRaftMessageRequest) *logrus.Entry { + fields := logrus.Fields{ + "method": "(*Node).ProcessRaftMessage", + } + + if n.IsMember() { + fields["raft_id"] = fmt.Sprintf("%x", n.Config.ID) + } + + if msg != nil && msg.Message != nil { + fields["from"] = fmt.Sprintf("%x", msg.Message.From) + } + + return log.G(ctx).WithFields(fields) +} + // ProcessRaftMessage calls 'Step' which advances the // raft state machine with the provided message on the // receiving node func (n *Node) ProcessRaftMessage(ctx context.Context, msg *api.ProcessRaftMessageRequest) (*api.ProcessRaftMessageResponse, error) { if msg == nil || msg.Message == nil { - return nil, grpc.Errorf(codes.InvalidArgument, "no message provided") + n.processRaftMessageLogger(ctx, msg).Debug("received empty message") + return &api.ProcessRaftMessageResponse{}, nil } // Don't process the message if this comes from // a node in the remove set if n.cluster.IsIDRemoved(msg.Message.From) { - return nil, ErrMemberRemoved + n.processRaftMessageLogger(ctx, msg).Debug("received message from removed member") + return nil, grpc.Errorf(codes.NotFound, "%s", ErrMemberRemoved.Error()) } var sourceHost string @@ -925,16 +946,16 @@ func (n *Node) ProcessRaftMessage(ctx context.Context, msg *api.ProcessRaftMessa if msg.Message.Type == raftpb.MsgVote { member := n.cluster.GetMember(msg.Message.From) if member == nil || member.Conn == nil { - log.G(ctx).Errorf("received vote request from unknown member %x", msg.Message.From) - return nil, ErrMemberUnknown + n.processRaftMessageLogger(ctx, msg).Debug("received message from unknown member") + return &api.ProcessRaftMessageResponse{}, nil } healthCtx, cancel := context.WithTimeout(ctx, time.Duration(n.Config.ElectionTick)*n.opts.TickInterval) defer cancel() if err := member.HealthCheck(healthCtx); err != nil { - log.G(ctx).WithError(err).Warningf("member %x which sent vote request failed health check", msg.Message.From) - return nil, errors.Wrap(err, "member unreachable") + n.processRaftMessageLogger(ctx, msg).Debug("member which sent vote request failed health check") + return &api.ProcessRaftMessageResponse{}, nil } } @@ -943,19 +964,18 @@ func (n *Node) ProcessRaftMessage(ctx context.Context, msg *api.ProcessRaftMessa // current architecture depends on only the leader // making proposals, so in-flight proposals can be // guaranteed not to conflict. - return nil, grpc.Errorf(codes.InvalidArgument, "proposals not accepted") + n.processRaftMessageLogger(ctx, msg).Debug("dropped forwarded proposal") + return &api.ProcessRaftMessageResponse{}, nil } // can't stop the raft node while an async RPC is in progress n.stopMu.RLock() defer n.stopMu.RUnlock() - if !n.IsMember() { - return nil, ErrNoRaftMember - } - - if err := n.raftNode.Step(ctx, *msg.Message); err != nil { - return nil, err + if n.IsMember() { + if err := n.raftNode.Step(ctx, *msg.Message); err != nil { + n.processRaftMessageLogger(ctx, msg).WithError(err).Debug("raft Step failed") + } } return &api.ProcessRaftMessageResponse{}, nil @@ -1341,7 +1361,7 @@ func (n *Node) sendToMember(ctx context.Context, members map[uint64]*membership. _, err := api.NewRaftClient(conn.Conn).ProcessRaftMessage(ctx, &api.ProcessRaftMessageRequest{Message: &m}) if err != nil { - if grpc.ErrorDesc(err) == ErrMemberRemoved.Error() { + if grpc.Code(err) == codes.NotFound && grpc.ErrorDesc(err) == ErrMemberRemoved.Error() { n.removeRaftFunc() } if m.Type == raftpb.MsgSnap { diff --git a/vendor/github.com/docker/docker/volume/store/store.go b/vendor/github.com/docker/docker/volume/store/store.go index 40ae6ad6f..06c026030 100644 --- a/vendor/github.com/docker/docker/volume/store/store.go +++ b/vendor/github.com/docker/docker/volume/store/store.go @@ -284,56 +284,64 @@ func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]st func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, error) { // check the local cache v, _ := s.getNamed(name) - if v != nil { - vDriverName := v.DriverName() - if driverName != "" && vDriverName != driverName { - // we have what looks like a conflict - // let's see if there are existing refs to this volume, if so we don't need - // to go any further since we can assume the volume is legit. - if len(s.getRefs(name)) > 0 { - return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name) - } + if v == nil { + return nil, nil + } - // looks like there is a conflict, but nothing is referencing it... - // let's check if the found volume ref - // is stale by checking with the driver if it still exists - vd, err := volumedrivers.GetDriver(vDriverName) - if err != nil { - // play it safe and return the error - // TODO(cpuguy83): maybe when when v2 plugins are ubiquitous, we should - // just purge this from the cache - return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err) - } + vDriverName := v.DriverName() + var conflict bool + if driverName != "" && vDriverName != driverName { + conflict = true + } - // now check if it still exists in the driver - v2, err := vd.Get(name) - err = errors.Cause(err) - if err != nil { - if _, ok := err.(net.Error); ok { - // got some error related to the driver connectivity - // play it safe and return the error - // TODO(cpuguy83): When when v2 plugins are ubiquitous, maybe we should - // just purge this from the cache - return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err) - } - - // a driver can return whatever it wants, so let's make sure this is nil - if v2 == nil { - // purge this reference from the cache - s.Purge(name) - return nil, nil - } - } - if v2 != nil { - return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name) - } + // let's check if the found volume ref + // is stale by checking with the driver if it still exists + exists, err := volumeExists(v) + if err != nil { + return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err) + } + + if exists { + if conflict { + return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name) } return v, nil } + if len(s.getRefs(v.Name())) > 0 { + // Containers are referencing this volume but it doesn't seem to exist anywhere. + // Return a conflict error here, the user can fix this with `docker volume rm -f` + return nil, errors.Wrapf(errNameConflict, "found references to volume '%s' in driver '%s' but the volume was not found in the driver -- you may need to remove containers referencing this volume or force remove the volume to re-create it", name, vDriverName) + } + + // doesn't exist, so purge it from the cache + s.Purge(name) return nil, nil } +// volumeExists returns if the volume is still present in the driver. +// An error is returned if there was an issue communicating with the driver. +func volumeExists(v volume.Volume) (bool, error) { + vd, err := volumedrivers.GetDriver(v.DriverName()) + if err != nil { + return false, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName()) + } + exists, err := vd.Get(v.Name()) + if err != nil { + err = errors.Cause(err) + if _, ok := err.(net.Error); ok { + return false, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName()) + } + + // At this point, the error could be anything from the driver, such as "no such volume" + // Let's not check an error here, and instead check if the driver returned a volume + } + if exists == nil { + return false, nil + } + return true, nil +} + // create asks the given driver to create a volume with the name/opts. // If a volume with the name is already known, it will ask the stored driver for the volume. // If the passed in driver name does not match the driver name which is stored @@ -354,6 +362,7 @@ func (s *VolumeStore) create(name, driverName string, opts, labels map[string]st if err != nil { return nil, err } + if v != nil { return v, nil }