vendor: update docker cadvisor winterm

This vendor change was purely for the changes in docker to allow for
setting the Masked and Read-only paths.

See: moby/moby#36644

But because of the docker dep update it also needed cadvisor to be
updated and winterm due to changes in pkg/tlsconfig in docker

See: google/cadvisor#1967

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
pull/8/head
Jess Frazelle 2018-08-20 08:05:52 -04:00
parent dbf7186bee
commit 31ffd9f881
No known key found for this signature in database
GPG Key ID: 18F3685C0022BFF3
291 changed files with 4231 additions and 9465 deletions

282
Godeps/Godeps.json generated
View File

@ -66,11 +66,11 @@
}, },
{ {
"ImportPath": "github.com/Azure/go-ansiterm", "ImportPath": "github.com/Azure/go-ansiterm",
"Rev": "19f72df4d05d31cbe1c56bfc8045c96babff6c7e" "Rev": "d6e3b3328b783f23731bc4d058875b0371ff8109"
}, },
{ {
"ImportPath": "github.com/Azure/go-ansiterm/winterm", "ImportPath": "github.com/Azure/go-ansiterm/winterm",
"Rev": "19f72df4d05d31cbe1c56bfc8045c96babff6c7e" "Rev": "d6e3b3328b783f23731bc4d058875b0371ff8109"
}, },
{ {
"ImportPath": "github.com/Azure/go-autorest/autorest", "ImportPath": "github.com/Azure/go-autorest/autorest",
@ -1310,153 +1310,133 @@
}, },
{ {
"ImportPath": "github.com/docker/docker/api", "ImportPath": "github.com/docker/docker/api",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types", "ImportPath": "github.com/docker/docker/api/types",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/blkiodev", "ImportPath": "github.com/docker/docker/api/types/blkiodev",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/container", "ImportPath": "github.com/docker/docker/api/types/container",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/events", "ImportPath": "github.com/docker/docker/api/types/events",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/filters", "ImportPath": "github.com/docker/docker/api/types/filters",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/image", "ImportPath": "github.com/docker/docker/api/types/image",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/mount", "ImportPath": "github.com/docker/docker/api/types/mount",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/network", "ImportPath": "github.com/docker/docker/api/types/network",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/registry", "ImportPath": "github.com/docker/docker/api/types/registry",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/strslice", "ImportPath": "github.com/docker/docker/api/types/strslice",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/swarm", "ImportPath": "github.com/docker/docker/api/types/swarm",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/swarm/runtime", "ImportPath": "github.com/docker/docker/api/types/swarm/runtime",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/time", "ImportPath": "github.com/docker/docker/api/types/time",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/versions", "ImportPath": "github.com/docker/docker/api/types/versions",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/api/types/volume", "ImportPath": "github.com/docker/docker/api/types/volume",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/client", "ImportPath": "github.com/docker/docker/client",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/ioutils", "ImportPath": "github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
},
{
"ImportPath": "github.com/docker/docker/pkg/jsonlog",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/jsonmessage", "ImportPath": "github.com/docker/docker/pkg/jsonmessage",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
},
{
"ImportPath": "github.com/docker/docker/pkg/longpath",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/mount", "ImportPath": "github.com/docker/docker/pkg/mount",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/parsers", "ImportPath": "github.com/docker/docker/pkg/parsers",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem", "ImportPath": "github.com/docker/docker/pkg/parsers/operatingsystem",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/stdcopy", "ImportPath": "github.com/docker/docker/pkg/stdcopy",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/sysinfo", "ImportPath": "github.com/docker/docker/pkg/sysinfo",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
},
{
"ImportPath": "github.com/docker/docker/pkg/system",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/term", "ImportPath": "github.com/docker/docker/pkg/term",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
}, },
{ {
"ImportPath": "github.com/docker/docker/pkg/term/windows", "ImportPath": "github.com/docker/docker/pkg/term/windows",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1", "Comment": "docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8d",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756" "Rev": "a9fbbdc8dd8794b20af358382ab780559bca589d"
},
{
"ImportPath": "github.com/docker/docker/pkg/tlsconfig",
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756"
}, },
{ {
"ImportPath": "github.com/docker/go-connections/nat", "ImportPath": "github.com/docker/go-connections/nat",
@ -1483,10 +1463,6 @@
"Comment": "v0.8.0-dev.2-910-gba46b928", "Comment": "v0.8.0-dev.2-910-gba46b928",
"Rev": "ba46b928444931e6865d8618dc03622cac79aa6f" "Rev": "ba46b928444931e6865d8618dc03622cac79aa6f"
}, },
{
"ImportPath": "github.com/docker/libtrust",
"Rev": "9cbd2a1374f46905c68a4eb3694a130610adc62a"
},
{ {
"ImportPath": "github.com/docker/spdystream", "ImportPath": "github.com/docker/spdystream",
"Rev": "449fdfce4d962303d702fec724ef0ad181c92528" "Rev": "449fdfce4d962303d702fec724ef0ad181c92528"
@ -1794,183 +1770,183 @@
}, },
{ {
"ImportPath": "github.com/google/cadvisor/accelerators", "ImportPath": "github.com/google/cadvisor/accelerators",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/cache/memory", "ImportPath": "github.com/google/cadvisor/cache/memory",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/client/v2", "ImportPath": "github.com/google/cadvisor/client/v2",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/collector", "ImportPath": "github.com/google/cadvisor/collector",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container", "ImportPath": "github.com/google/cadvisor/container",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/common", "ImportPath": "github.com/google/cadvisor/container/common",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/containerd", "ImportPath": "github.com/google/cadvisor/container/containerd",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/crio", "ImportPath": "github.com/google/cadvisor/container/crio",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/docker", "ImportPath": "github.com/google/cadvisor/container/docker",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/libcontainer", "ImportPath": "github.com/google/cadvisor/container/libcontainer",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/raw", "ImportPath": "github.com/google/cadvisor/container/raw",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/rkt", "ImportPath": "github.com/google/cadvisor/container/rkt",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/systemd", "ImportPath": "github.com/google/cadvisor/container/systemd",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/devicemapper", "ImportPath": "github.com/google/cadvisor/devicemapper",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/events", "ImportPath": "github.com/google/cadvisor/events",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/fs", "ImportPath": "github.com/google/cadvisor/fs",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v1", "ImportPath": "github.com/google/cadvisor/info/v1",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v2", "ImportPath": "github.com/google/cadvisor/info/v2",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/machine", "ImportPath": "github.com/google/cadvisor/machine",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager", "ImportPath": "github.com/google/cadvisor/manager",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher", "ImportPath": "github.com/google/cadvisor/manager/watcher",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw", "ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt", "ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/metrics", "ImportPath": "github.com/google/cadvisor/metrics",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/storage", "ImportPath": "github.com/google/cadvisor/storage",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/summary", "ImportPath": "github.com/google/cadvisor/summary",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils", "ImportPath": "github.com/google/cadvisor/utils",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo", "ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload", "ImportPath": "github.com/google/cadvisor/utils/cpuload",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink", "ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/docker", "ImportPath": "github.com/google/cadvisor/utils/docker",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/oomparser", "ImportPath": "github.com/google/cadvisor/utils/oomparser",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysfs", "ImportPath": "github.com/google/cadvisor/utils/sysfs",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysinfo", "ImportPath": "github.com/google/cadvisor/utils/sysinfo",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/version", "ImportPath": "github.com/google/cadvisor/version",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/zfs", "ImportPath": "github.com/google/cadvisor/zfs",
"Comment": "v0.30.2", "Comment": "v0.30.0-12-gf834c0f4",
"Rev": "de723a090f4dd5390dc7c2acee37ba9c62f0cc09" "Rev": "f834c0f4c100ae524db33139dce953e0003f23ad"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency-go", "ImportPath": "github.com/google/certificate-transparency-go",
@ -3313,6 +3289,10 @@
"ImportPath": "golang.org/x/sys/windows", "ImportPath": "golang.org/x/sys/windows",
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce" "Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
}, },
{
"ImportPath": "golang.org/x/sys/windows/registry",
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{ {
"ImportPath": "golang.org/x/sys/windows/svc", "ImportPath": "golang.org/x/sys/windows/svc",
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce" "Rev": "95c6576299259db960f6c5b9b69ea52422860fce"

1032
Godeps/LICENSES generated

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ go_library(
"//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library",
"//pkg/util/tail:go_default_library", "//pkg/util/tail:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//vendor/github.com/docker/docker/pkg/jsonlog:go_default_library", "//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:go_default_library",
"//vendor/github.com/fsnotify/fsnotify:go_default_library", "//vendor/github.com/fsnotify/fsnotify:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
], ],

7
vendor/BUILD vendored
View File

@ -168,23 +168,18 @@ filegroup(
"//vendor/github.com/docker/distribution/reference:all-srcs", "//vendor/github.com/docker/distribution/reference:all-srcs",
"//vendor/github.com/docker/docker/api:all-srcs", "//vendor/github.com/docker/docker/api:all-srcs",
"//vendor/github.com/docker/docker/client:all-srcs", "//vendor/github.com/docker/docker/client:all-srcs",
"//vendor/github.com/docker/docker/pkg/ioutils:all-srcs", "//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:all-srcs",
"//vendor/github.com/docker/docker/pkg/jsonlog:all-srcs",
"//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs", "//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs",
"//vendor/github.com/docker/docker/pkg/longpath:all-srcs",
"//vendor/github.com/docker/docker/pkg/mount:all-srcs", "//vendor/github.com/docker/docker/pkg/mount:all-srcs",
"//vendor/github.com/docker/docker/pkg/parsers:all-srcs", "//vendor/github.com/docker/docker/pkg/parsers:all-srcs",
"//vendor/github.com/docker/docker/pkg/stdcopy:all-srcs", "//vendor/github.com/docker/docker/pkg/stdcopy:all-srcs",
"//vendor/github.com/docker/docker/pkg/sysinfo:all-srcs", "//vendor/github.com/docker/docker/pkg/sysinfo:all-srcs",
"//vendor/github.com/docker/docker/pkg/system:all-srcs",
"//vendor/github.com/docker/docker/pkg/term:all-srcs", "//vendor/github.com/docker/docker/pkg/term:all-srcs",
"//vendor/github.com/docker/docker/pkg/tlsconfig:all-srcs",
"//vendor/github.com/docker/go-connections/nat:all-srcs", "//vendor/github.com/docker/go-connections/nat:all-srcs",
"//vendor/github.com/docker/go-connections/sockets:all-srcs", "//vendor/github.com/docker/go-connections/sockets:all-srcs",
"//vendor/github.com/docker/go-connections/tlsconfig:all-srcs", "//vendor/github.com/docker/go-connections/tlsconfig:all-srcs",
"//vendor/github.com/docker/go-units:all-srcs", "//vendor/github.com/docker/go-units:all-srcs",
"//vendor/github.com/docker/libnetwork/ipvs:all-srcs", "//vendor/github.com/docker/libnetwork/ipvs:all-srcs",
"//vendor/github.com/docker/libtrust:all-srcs",
"//vendor/github.com/docker/spdystream:all-srcs", "//vendor/github.com/docker/spdystream:all-srcs",
"//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs", "//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs",
"//vendor/github.com/elazarl/goproxy:all-srcs", "//vendor/github.com/elazarl/goproxy:all-srcs",

View File

@ -21,7 +21,6 @@ go_library(
importmap = "k8s.io/kubernetes/vendor/github.com/Azure/go-ansiterm", importmap = "k8s.io/kubernetes/vendor/github.com/Azure/go-ansiterm",
importpath = "github.com/Azure/go-ansiterm", importpath = "github.com/Azure/go-ansiterm",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/github.com/sirupsen/logrus:go_default_library"],
) )
filegroup( filegroup(

View File

@ -5,7 +5,7 @@ type csiEntryState struct {
} }
func (csiState csiEntryState) Handle(b byte) (s state, e error) { func (csiState csiEntryState) Handle(b byte) (s state, e error) {
logger.Infof("CsiEntry::Handle %#x", b) csiState.parser.logf("CsiEntry::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b) nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
@ -25,7 +25,7 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
} }
func (csiState csiEntryState) Transition(s state) error { func (csiState csiEntryState) Transition(s state) error {
logger.Infof("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s) csiState.baseState.Transition(s)
switch s { switch s {

View File

@ -5,7 +5,7 @@ type csiParamState struct {
} }
func (csiState csiParamState) Handle(b byte) (s state, e error) { func (csiState csiParamState) Handle(b byte) (s state, e error) {
logger.Infof("CsiParam::Handle %#x", b) csiState.parser.logf("CsiParam::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b) nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
@ -26,7 +26,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
} }
func (csiState csiParamState) Transition(s state) error { func (csiState csiParamState) Transition(s state) error {
logger.Infof("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s) csiState.baseState.Transition(s)
switch s { switch s {

View File

@ -5,7 +5,7 @@ type escapeIntermediateState struct {
} }
func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
logger.Infof("escapeIntermediateState::Handle %#x", b) escState.parser.logf("escapeIntermediateState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b) nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err
@ -24,7 +24,7 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
} }
func (escState escapeIntermediateState) Transition(s state) error { func (escState escapeIntermediateState) Transition(s state) error {
logger.Infof("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s) escState.baseState.Transition(s)
switch s { switch s {

View File

@ -5,7 +5,7 @@ type escapeState struct {
} }
func (escState escapeState) Handle(b byte) (s state, e error) { func (escState escapeState) Handle(b byte) (s state, e error) {
logger.Infof("escapeState::Handle %#x", b) escState.parser.logf("escapeState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b) nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err
@ -28,7 +28,7 @@ func (escState escapeState) Handle(b byte) (s state, e error) {
} }
func (escState escapeState) Transition(s state) error { func (escState escapeState) Transition(s state) error {
logger.Infof("Escape::Transition %s --> %s", escState.Name(), s.Name()) escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s) escState.baseState.Transition(s)
switch s { switch s {

View File

@ -5,7 +5,7 @@ type oscStringState struct {
} }
func (oscState oscStringState) Handle(b byte) (s state, e error) { func (oscState oscStringState) Handle(b byte) (s state, e error) {
logger.Infof("OscString::Handle %#x", b) oscState.parser.logf("OscString::Handle %#x", b)
nextState, err := oscState.baseState.Handle(b) nextState, err := oscState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err

View File

@ -2,14 +2,10 @@ package ansiterm
import ( import (
"errors" "errors"
"io/ioutil" "log"
"os" "os"
"github.com/sirupsen/logrus"
) )
var logger *logrus.Logger
type AnsiParser struct { type AnsiParser struct {
currState state currState state
eventHandler AnsiEventHandler eventHandler AnsiEventHandler
@ -23,50 +19,69 @@ type AnsiParser struct {
ground state ground state
oscString state oscString state
stateMap []state stateMap []state
logf func(string, ...interface{})
} }
func CreateParser(initialState string, evtHandler AnsiEventHandler) *AnsiParser { type Option func(*AnsiParser)
logFile := ioutil.Discard
if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { func WithLogf(f func(string, ...interface{})) Option {
logFile, _ = os.Create("ansiParser.log") return func(ap *AnsiParser) {
ap.logf = f
} }
}
logger = &logrus.Logger{ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser {
Out: logFile, ap := &AnsiParser{
Formatter: new(logrus.TextFormatter),
Level: logrus.InfoLevel,
}
parser := &AnsiParser{
eventHandler: evtHandler, eventHandler: evtHandler,
context: &ansiContext{}, context: &ansiContext{},
} }
for _, o := range opts {
parser.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: parser}} o(ap)
parser.csiParam = csiParamState{baseState{name: "CsiParam", parser: parser}}
parser.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: parser}}
parser.escape = escapeState{baseState{name: "Escape", parser: parser}}
parser.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: parser}}
parser.error = errorState{baseState{name: "Error", parser: parser}}
parser.ground = groundState{baseState{name: "Ground", parser: parser}}
parser.oscString = oscStringState{baseState{name: "OscString", parser: parser}}
parser.stateMap = []state{
parser.csiEntry,
parser.csiParam,
parser.dcsEntry,
parser.escape,
parser.escapeIntermediate,
parser.error,
parser.ground,
parser.oscString,
} }
parser.currState = getState(initialState, parser.stateMap) if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
logFile, _ := os.Create("ansiParser.log")
logger := log.New(logFile, "", log.LstdFlags)
if ap.logf != nil {
l := ap.logf
ap.logf = func(s string, v ...interface{}) {
l(s, v...)
logger.Printf(s, v...)
}
} else {
ap.logf = logger.Printf
}
}
logger.Infof("CreateParser: parser %p", parser) if ap.logf == nil {
return parser ap.logf = func(string, ...interface{}) {}
}
ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}}
ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}}
ap.escape = escapeState{baseState{name: "Escape", parser: ap}}
ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}}
ap.error = errorState{baseState{name: "Error", parser: ap}}
ap.ground = groundState{baseState{name: "Ground", parser: ap}}
ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}}
ap.stateMap = []state{
ap.csiEntry,
ap.csiParam,
ap.dcsEntry,
ap.escape,
ap.escapeIntermediate,
ap.error,
ap.ground,
ap.oscString,
}
ap.currState = getState(initialState, ap.stateMap)
ap.logf("CreateParser: parser %p", ap)
return ap
} }
func getState(name string, states []state) state { func getState(name string, states []state) state {
@ -97,7 +112,7 @@ func (ap *AnsiParser) handle(b byte) error {
} }
if newState == nil { if newState == nil {
logger.Warning("newState is nil") ap.logf("WARNING: newState is nil")
return errors.New("New state of 'nil' is invalid.") return errors.New("New state of 'nil' is invalid.")
} }
@ -111,23 +126,23 @@ func (ap *AnsiParser) handle(b byte) error {
} }
func (ap *AnsiParser) changeState(newState state) error { func (ap *AnsiParser) changeState(newState state) error {
logger.Infof("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
// Exit old state // Exit old state
if err := ap.currState.Exit(); err != nil { if err := ap.currState.Exit(); err != nil {
logger.Infof("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
return err return err
} }
// Perform transition action // Perform transition action
if err := ap.currState.Transition(newState); err != nil { if err := ap.currState.Transition(newState); err != nil {
logger.Infof("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
return err return err
} }
// Enter new state // Enter new state
if err := newState.Enter(); err != nil { if err := newState.Enter(); err != nil {
logger.Infof("Enter state '%s' failed with: '%v'", newState.Name(), err) ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err)
return err return err
} }

View File

@ -27,7 +27,6 @@ func parseParams(bytes []byte) ([]string, error) {
params = append(params, s) params = append(params, s)
} }
logger.Infof("Parsed params: %v with length: %d", params, len(params))
return params, nil return params, nil
} }
@ -37,7 +36,6 @@ func parseCmd(context ansiContext) (string, error) {
func getInt(params []string, dflt int) int { func getInt(params []string, dflt int) int {
i := getInts(params, 1, dflt)[0] i := getInts(params, 1, dflt)[0]
logger.Infof("getInt: %v", i)
return i return i
} }
@ -60,8 +58,6 @@ func getInts(params []string, minCount int, dflt int) []int {
} }
} }
logger.Infof("getInts: %v", ints)
return ints return ints
} }

View File

@ -1,19 +1,15 @@
package ansiterm package ansiterm
import (
"fmt"
)
func (ap *AnsiParser) collectParam() error { func (ap *AnsiParser) collectParam() error {
currChar := ap.context.currentChar currChar := ap.context.currentChar
logger.Infof("collectParam %#x", currChar) ap.logf("collectParam %#x", currChar)
ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) ap.context.paramBuffer = append(ap.context.paramBuffer, currChar)
return nil return nil
} }
func (ap *AnsiParser) collectInter() error { func (ap *AnsiParser) collectInter() error {
currChar := ap.context.currentChar currChar := ap.context.currentChar
logger.Infof("collectInter %#x", currChar) ap.logf("collectInter %#x", currChar)
ap.context.paramBuffer = append(ap.context.interBuffer, currChar) ap.context.paramBuffer = append(ap.context.interBuffer, currChar)
return nil return nil
} }
@ -21,8 +17,8 @@ func (ap *AnsiParser) collectInter() error {
func (ap *AnsiParser) escDispatch() error { func (ap *AnsiParser) escDispatch() error {
cmd, _ := parseCmd(*ap.context) cmd, _ := parseCmd(*ap.context)
intermeds := ap.context.interBuffer intermeds := ap.context.interBuffer
logger.Infof("escDispatch currentChar: %#x", ap.context.currentChar) ap.logf("escDispatch currentChar: %#x", ap.context.currentChar)
logger.Infof("escDispatch: %v(%v)", cmd, intermeds) ap.logf("escDispatch: %v(%v)", cmd, intermeds)
switch cmd { switch cmd {
case "D": // IND case "D": // IND
@ -43,8 +39,9 @@ func (ap *AnsiParser) escDispatch() error {
func (ap *AnsiParser) csiDispatch() error { func (ap *AnsiParser) csiDispatch() error {
cmd, _ := parseCmd(*ap.context) cmd, _ := parseCmd(*ap.context)
params, _ := parseParams(ap.context.paramBuffer) params, _ := parseParams(ap.context.paramBuffer)
ap.logf("Parsed params: %v with length: %d", params, len(params))
logger.Infof("csiDispatch: %v(%v)", cmd, params) ap.logf("csiDispatch: %v(%v)", cmd, params)
switch cmd { switch cmd {
case "@": case "@":
@ -102,7 +99,7 @@ func (ap *AnsiParser) csiDispatch() error {
top, bottom := ints[0], ints[1] top, bottom := ints[0], ints[1]
return ap.eventHandler.DECSTBM(top, bottom) return ap.eventHandler.DECSTBM(top, bottom)
default: default:
logger.Errorf(fmt.Sprintf("Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)) ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)
return nil return nil
} }

View File

@ -18,7 +18,6 @@ go_library(
deps = select({ deps = select({
"@io_bazel_rules_go//go/platform:windows": [ "@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/Azure/go-ansiterm:go_default_library", "//vendor/github.com/Azure/go-ansiterm:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
], ],
"//conditions:default": [], "//conditions:default": [],
}), }),

View File

@ -175,7 +175,7 @@ func GetStdFile(nFile int) (*os.File, uintptr) {
fd, err := syscall.GetStdHandle(nFile) fd, err := syscall.GetStdHandle(nFile)
if err != nil { if err != nil {
panic(fmt.Errorf("Invalid standard handle indentifier: %v -- %v", nFile, err)) panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err))
} }
return file, uintptr(fd) return file, uintptr(fd)

View File

@ -57,9 +57,14 @@ const (
ENABLE_INSERT_MODE = 0x0020 ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040 ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080 ENABLE_EXTENDED_FLAGS = 0x0080
ENABLE_AUTO_POSITION = 0x0100
ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
ENABLE_PROCESSED_OUTPUT = 0x0001 ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
DISABLE_NEWLINE_AUTO_RETURN = 0x0008
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
// Character attributes // Character attributes
// Note: // Note:

View File

@ -34,7 +34,7 @@ func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL
if err != nil { if err != nil {
return err return err
} }
logger.Infof("Cursor position set: (%d, %d)", position.X, position.Y) h.logf("Cursor position set: (%d, %d)", position.X, position.Y)
return err return err
} }

View File

@ -50,8 +50,8 @@ func (h *windowsAnsiEventHandler) insertLines(param int) error {
// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. // scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates.
func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error {
logger.Infof("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
logger.Infof("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
// Copy from and clip to the scroll region (full buffer width) // Copy from and clip to the scroll region (full buffer width)
scrollRect := SMALL_RECT{ scrollRect := SMALL_RECT{

View File

@ -4,16 +4,13 @@ package winterm
import ( import (
"bytes" "bytes"
"io/ioutil" "log"
"os" "os"
"strconv" "strconv"
"github.com/Azure/go-ansiterm" "github.com/Azure/go-ansiterm"
"github.com/sirupsen/logrus"
) )
var logger *logrus.Logger
type windowsAnsiEventHandler struct { type windowsAnsiEventHandler struct {
fd uintptr fd uintptr
file *os.File file *os.File
@ -28,32 +25,52 @@ type windowsAnsiEventHandler struct {
marginByte byte marginByte byte
curInfo *CONSOLE_SCREEN_BUFFER_INFO curInfo *CONSOLE_SCREEN_BUFFER_INFO
curPos COORD curPos COORD
logf func(string, ...interface{})
} }
func CreateWinEventHandler(fd uintptr, file *os.File) ansiterm.AnsiEventHandler { type Option func(*windowsAnsiEventHandler)
logFile := ioutil.Discard
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { func WithLogf(f func(string, ...interface{})) Option {
logFile, _ = os.Create("winEventHandler.log") return func(w *windowsAnsiEventHandler) {
} w.logf = f
logger = &logrus.Logger{
Out: logFile,
Formatter: new(logrus.TextFormatter),
Level: logrus.DebugLevel,
} }
}
func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler {
infoReset, err := GetConsoleScreenBufferInfo(fd) infoReset, err := GetConsoleScreenBufferInfo(fd)
if err != nil { if err != nil {
return nil return nil
} }
return &windowsAnsiEventHandler{ h := &windowsAnsiEventHandler{
fd: fd, fd: fd,
file: file, file: file,
infoReset: infoReset, infoReset: infoReset,
attributes: infoReset.Attributes, attributes: infoReset.Attributes,
} }
for _, o := range opts {
o(h)
}
if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" {
logFile, _ := os.Create("winEventHandler.log")
logger := log.New(logFile, "", log.LstdFlags)
if h.logf != nil {
l := h.logf
h.logf = func(s string, v ...interface{}) {
l(s, v...)
logger.Printf(s, v...)
}
} else {
h.logf = logger.Printf
}
}
if h.logf == nil {
h.logf = func(string, ...interface{}) {}
}
return h
} }
type scrollRegion struct { type scrollRegion struct {
@ -96,7 +113,7 @@ func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return false, err return false, err
} }
logger.Info("Simulating LF inside scroll region") h.logf("Simulating LF inside scroll region")
if err := h.scrollUp(1); err != nil { if err := h.scrollUp(1); err != nil {
return false, err return false, err
} }
@ -119,7 +136,7 @@ func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) {
} else { } else {
// The cursor is at the bottom of the screen but outside the scroll // The cursor is at the bottom of the screen but outside the scroll
// region. Skip the LF. // region. Skip the LF.
logger.Info("Simulating LF outside scroll region") h.logf("Simulating LF outside scroll region")
if includeCR { if includeCR {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return false, err return false, err
@ -151,7 +168,7 @@ func (h *windowsAnsiEventHandler) executeLF() error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Info("Resetting cursor position for LF without CR") h.logf("Resetting cursor position for LF without CR")
if err := SetConsoleCursorPosition(h.fd, pos); err != nil { if err := SetConsoleCursorPosition(h.fd, pos); err != nil {
return err return err
} }
@ -186,7 +203,7 @@ func (h *windowsAnsiEventHandler) Print(b byte) error {
func (h *windowsAnsiEventHandler) Execute(b byte) error { func (h *windowsAnsiEventHandler) Execute(b byte) error {
switch b { switch b {
case ansiterm.ANSI_TAB: case ansiterm.ANSI_TAB:
logger.Info("Execute(TAB)") h.logf("Execute(TAB)")
// Move to the next tab stop, but preserve auto-wrap if already set. // Move to the next tab stop, but preserve auto-wrap if already set.
if !h.wrapNext { if !h.wrapNext {
pos, info, err := h.getCurrentInfo() pos, info, err := h.getCurrentInfo()
@ -269,7 +286,7 @@ func (h *windowsAnsiEventHandler) CUU(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CUU: [%v]", []string{strconv.Itoa(param)}) h.logf("CUU: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorVertical(-param) return h.moveCursorVertical(-param)
} }
@ -278,7 +295,7 @@ func (h *windowsAnsiEventHandler) CUD(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CUD: [%v]", []string{strconv.Itoa(param)}) h.logf("CUD: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorVertical(param) return h.moveCursorVertical(param)
} }
@ -287,7 +304,7 @@ func (h *windowsAnsiEventHandler) CUF(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CUF: [%v]", []string{strconv.Itoa(param)}) h.logf("CUF: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorHorizontal(param) return h.moveCursorHorizontal(param)
} }
@ -296,7 +313,7 @@ func (h *windowsAnsiEventHandler) CUB(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CUB: [%v]", []string{strconv.Itoa(param)}) h.logf("CUB: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorHorizontal(-param) return h.moveCursorHorizontal(-param)
} }
@ -305,7 +322,7 @@ func (h *windowsAnsiEventHandler) CNL(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CNL: [%v]", []string{strconv.Itoa(param)}) h.logf("CNL: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorLine(param) return h.moveCursorLine(param)
} }
@ -314,7 +331,7 @@ func (h *windowsAnsiEventHandler) CPL(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CPL: [%v]", []string{strconv.Itoa(param)}) h.logf("CPL: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorLine(-param) return h.moveCursorLine(-param)
} }
@ -323,7 +340,7 @@ func (h *windowsAnsiEventHandler) CHA(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CHA: [%v]", []string{strconv.Itoa(param)}) h.logf("CHA: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.moveCursorColumn(param) return h.moveCursorColumn(param)
} }
@ -332,7 +349,7 @@ func (h *windowsAnsiEventHandler) VPA(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("VPA: [[%d]]", param) h.logf("VPA: [[%d]]", param)
h.clearWrap() h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd) info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil { if err != nil {
@ -348,7 +365,7 @@ func (h *windowsAnsiEventHandler) CUP(row int, col int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("CUP: [[%d %d]]", row, col) h.logf("CUP: [[%d %d]]", row, col)
h.clearWrap() h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd) info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil { if err != nil {
@ -364,7 +381,7 @@ func (h *windowsAnsiEventHandler) HVP(row int, col int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("HVP: [[%d %d]]", row, col) h.logf("HVP: [[%d %d]]", row, col)
h.clearWrap() h.clearWrap()
return h.CUP(row, col) return h.CUP(row, col)
} }
@ -373,7 +390,7 @@ func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DECTCEM: [%v]", []string{strconv.FormatBool(visible)}) h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)})
h.clearWrap() h.clearWrap()
return nil return nil
} }
@ -382,7 +399,7 @@ func (h *windowsAnsiEventHandler) DECOM(enable bool) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DECOM: [%v]", []string{strconv.FormatBool(enable)}) h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)})
h.clearWrap() h.clearWrap()
h.originMode = enable h.originMode = enable
return h.CUP(1, 1) return h.CUP(1, 1)
@ -392,7 +409,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DECCOLM: [%v]", []string{strconv.FormatBool(use132)}) h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)})
h.clearWrap() h.clearWrap()
if err := h.ED(2); err != nil { if err := h.ED(2); err != nil {
return err return err
@ -407,7 +424,7 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
} }
if info.Size.X < targetWidth { if info.Size.X < targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
logger.Info("set buffer failed:", err) h.logf("set buffer failed: %v", err)
return err return err
} }
} }
@ -415,12 +432,12 @@ func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error {
window.Left = 0 window.Left = 0
window.Right = targetWidth - 1 window.Right = targetWidth - 1
if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { if err := SetConsoleWindowInfo(h.fd, true, window); err != nil {
logger.Info("set window failed:", err) h.logf("set window failed: %v", err)
return err return err
} }
if info.Size.X > targetWidth { if info.Size.X > targetWidth {
if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil {
logger.Info("set buffer failed:", err) h.logf("set buffer failed: %v", err)
return err return err
} }
} }
@ -431,7 +448,7 @@ func (h *windowsAnsiEventHandler) ED(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("ED: [%v]", []string{strconv.Itoa(param)}) h.logf("ED: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
// [J -- Erases from the cursor to the end of the screen, including the cursor position. // [J -- Erases from the cursor to the end of the screen, including the cursor position.
@ -490,7 +507,7 @@ func (h *windowsAnsiEventHandler) EL(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("EL: [%v]", strconv.Itoa(param)) h.logf("EL: [%v]", strconv.Itoa(param))
h.clearWrap() h.clearWrap()
// [K -- Erases from the cursor to the end of the line, including the cursor position. // [K -- Erases from the cursor to the end of the line, including the cursor position.
@ -531,7 +548,7 @@ func (h *windowsAnsiEventHandler) IL(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("IL: [%v]", strconv.Itoa(param)) h.logf("IL: [%v]", strconv.Itoa(param))
h.clearWrap() h.clearWrap()
return h.insertLines(param) return h.insertLines(param)
} }
@ -540,7 +557,7 @@ func (h *windowsAnsiEventHandler) DL(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DL: [%v]", strconv.Itoa(param)) h.logf("DL: [%v]", strconv.Itoa(param))
h.clearWrap() h.clearWrap()
return h.deleteLines(param) return h.deleteLines(param)
} }
@ -549,7 +566,7 @@ func (h *windowsAnsiEventHandler) ICH(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("ICH: [%v]", strconv.Itoa(param)) h.logf("ICH: [%v]", strconv.Itoa(param))
h.clearWrap() h.clearWrap()
return h.insertCharacters(param) return h.insertCharacters(param)
} }
@ -558,7 +575,7 @@ func (h *windowsAnsiEventHandler) DCH(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DCH: [%v]", strconv.Itoa(param)) h.logf("DCH: [%v]", strconv.Itoa(param))
h.clearWrap() h.clearWrap()
return h.deleteCharacters(param) return h.deleteCharacters(param)
} }
@ -572,7 +589,7 @@ func (h *windowsAnsiEventHandler) SGR(params []int) error {
strings = append(strings, strconv.Itoa(v)) strings = append(strings, strconv.Itoa(v))
} }
logger.Infof("SGR: [%v]", strings) h.logf("SGR: [%v]", strings)
if len(params) <= 0 { if len(params) <= 0 {
h.attributes = h.infoReset.Attributes h.attributes = h.infoReset.Attributes
@ -606,7 +623,7 @@ func (h *windowsAnsiEventHandler) SU(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("SU: [%v]", []string{strconv.Itoa(param)}) h.logf("SU: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.scrollUp(param) return h.scrollUp(param)
} }
@ -615,13 +632,13 @@ func (h *windowsAnsiEventHandler) SD(param int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("SD: [%v]", []string{strconv.Itoa(param)}) h.logf("SD: [%v]", []string{strconv.Itoa(param)})
h.clearWrap() h.clearWrap()
return h.scrollDown(param) return h.scrollDown(param)
} }
func (h *windowsAnsiEventHandler) DA(params []string) error { func (h *windowsAnsiEventHandler) DA(params []string) error {
logger.Infof("DA: [%v]", params) h.logf("DA: [%v]", params)
// DA cannot be implemented because it must send data on the VT100 input stream, // DA cannot be implemented because it must send data on the VT100 input stream,
// which is not available to go-ansiterm. // which is not available to go-ansiterm.
return nil return nil
@ -631,7 +648,7 @@ func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Infof("DECSTBM: [%d, %d]", top, bottom) h.logf("DECSTBM: [%d, %d]", top, bottom)
// Windows is 0 indexed, Linux is 1 indexed // Windows is 0 indexed, Linux is 1 indexed
h.sr.top = int16(top - 1) h.sr.top = int16(top - 1)
@ -646,7 +663,7 @@ func (h *windowsAnsiEventHandler) RI() error {
if err := h.Flush(); err != nil { if err := h.Flush(); err != nil {
return err return err
} }
logger.Info("RI: []") h.logf("RI: []")
h.clearWrap() h.clearWrap()
info, err := GetConsoleScreenBufferInfo(h.fd) info, err := GetConsoleScreenBufferInfo(h.fd)
@ -663,21 +680,21 @@ func (h *windowsAnsiEventHandler) RI() error {
} }
func (h *windowsAnsiEventHandler) IND() error { func (h *windowsAnsiEventHandler) IND() error {
logger.Info("IND: []") h.logf("IND: []")
return h.executeLF() return h.executeLF()
} }
func (h *windowsAnsiEventHandler) Flush() error { func (h *windowsAnsiEventHandler) Flush() error {
h.curInfo = nil h.curInfo = nil
if h.buffer.Len() > 0 { if h.buffer.Len() > 0 {
logger.Infof("Flush: [%s]", h.buffer.Bytes()) h.logf("Flush: [%s]", h.buffer.Bytes())
if _, err := h.buffer.WriteTo(h.file); err != nil { if _, err := h.buffer.WriteTo(h.file); err != nil {
return err return err
} }
} }
if h.wrapNext && !h.drewMarginByte { if h.wrapNext && !h.drewMarginByte {
logger.Infof("Flush: drawing margin byte '%c'", h.marginByte) h.logf("Flush: drawing margin byte '%c'", h.marginByte)
info, err := GetConsoleScreenBufferInfo(h.fd) info, err := GetConsoleScreenBufferInfo(h.fd)
if err != nil { if err != nil {

File diff suppressed because it is too large Load Diff

View File

@ -6,16 +6,10 @@ go_library(
"common.go", "common.go",
"common_unix.go", "common_unix.go",
"common_windows.go", "common_windows.go",
"names.go",
], ],
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api",
importpath = "github.com/docker/docker/api", importpath = "github.com/docker/docker/api",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/docker/pkg/ioutils:go_default_library",
"//vendor/github.com/docker/docker/pkg/system:go_default_library",
"//vendor/github.com/docker/libtrust:go_default_library",
],
) )
filegroup( filegroup(

View File

@ -10,7 +10,7 @@ It consists of various components in this repository:
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs. - `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
- `daemon/` The daemon, which serves the API. - `daemon/` The daemon, which serves the API.
## Swagger definition ## Swagger definition
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to: The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
@ -20,7 +20,7 @@ The API is defined by the [Swagger](http://swagger.io/specification/) definition
## Updating the API documentation ## Updating the API documentation
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, you'll need to edit this file to represent the change in the documentation. The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation.
The file is split into two main sections: The file is split into two main sections:
@ -29,9 +29,9 @@ The file is split into two main sections:
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section. To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919) There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919).
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful for when you are making edits to ensure you are doing the right thing. `swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing.
## Viewing the API documentation ## Viewing the API documentation

View File

@ -1,65 +1,11 @@
package api package api
import (
"encoding/json"
"encoding/pem"
"fmt"
"os"
"path/filepath"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/system"
"github.com/docker/libtrust"
)
// Common constants for daemon and client. // Common constants for daemon and client.
const ( const (
// DefaultVersion of Current REST API // DefaultVersion of Current REST API
DefaultVersion string = "1.31" DefaultVersion = "1.38"
// NoBaseImageSpecifier is the symbol used by the FROM // NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used. // command to specify that no base image is to be used.
NoBaseImageSpecifier string = "scratch" NoBaseImageSpecifier = "scratch"
) )
// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
// otherwise generates a new one
func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700, "")
if err != nil {
return nil, err
}
trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
if err == libtrust.ErrKeyFileDoesNotExist {
trustKey, err = libtrust.GenerateECP256PrivateKey()
if err != nil {
return nil, fmt.Errorf("Error generating key: %s", err)
}
encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath))
if err != nil {
return nil, fmt.Errorf("Error serializing key: %s", err)
}
if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil {
return nil, fmt.Errorf("Error saving key file: %s", err)
}
} else if err != nil {
return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
}
return trustKey, nil
}
func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) {
if ext == ".json" || ext == ".jwk" {
encoded, err = json.Marshal(key)
if err != nil {
return nil, fmt.Errorf("unable to encode private key JWK: %s", err)
}
} else {
pemBlock, err := key.PEMBlock()
if err != nil {
return nil, fmt.Errorf("unable to encode private key PEM: %s", err)
}
encoded = pem.EncodeToMemory(pemBlock)
}
return
}

View File

@ -3,4 +3,4 @@
package api package api
// MinVersion represents Minimum REST API version supported // MinVersion represents Minimum REST API version supported
const MinVersion string = "1.12" const MinVersion = "1.12"

View File

@ -1,9 +0,0 @@
package api
import "regexp"
// RestrictedNameChars collects the characters allowed to represent a name, normally used to validate container and volume names.
const RestrictedNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
// RestrictedNamePattern is a regular expression to validate names against the collection of restricted characters.
var RestrictedNamePattern = regexp.MustCompile(`^` + RestrictedNameChars + `+$`)

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
units "github.com/docker/go-units" "github.com/docker/go-units"
) )
// CheckpointCreateOptions holds parameters to create a checkpoint from a container // CheckpointCreateOptions holds parameters to create a checkpoint from a container
@ -74,6 +74,7 @@ type ContainerLogsOptions struct {
ShowStdout bool ShowStdout bool
ShowStderr bool ShowStderr bool
Since string Since string
Until string
Timestamps bool Timestamps bool
Follow bool Follow bool
Tail string Tail string
@ -179,10 +180,7 @@ type ImageBuildOptions struct {
ExtraHosts []string // List of extra hosts ExtraHosts []string // List of extra hosts
Target string Target string
SessionID string SessionID string
Platform string
// TODO @jhowardmsft LCOW Support: This will require extending to include
// `Platform string`, but is ommited for now as it's hard-coded temporarily
// to avoid API changes.
} }
// ImageBuildResponse holds information // ImageBuildResponse holds information
@ -195,7 +193,8 @@ type ImageBuildResponse struct {
// ImageCreateOptions holds information to create images. // ImageCreateOptions holds information to create images.
type ImageCreateOptions struct { type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
} }
// ImageImportSource holds source information for ImageImport // ImageImportSource holds source information for ImageImport
@ -209,6 +208,7 @@ type ImageImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated. Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
} }
// ImageListOptions holds parameters to filter the list of images with. // ImageListOptions holds parameters to filter the list of images with.
@ -229,6 +229,7 @@ type ImagePullOptions struct {
All bool All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
PrivilegeFunc RequestPrivilegeFunc PrivilegeFunc RequestPrivilegeFunc
Platform string
} }
// RequestPrivilegeFunc is a function interface that // RequestPrivilegeFunc is a function interface that

View File

@ -16,7 +16,6 @@ type ContainerCreateConfig struct {
HostConfig *container.HostConfig HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig NetworkingConfig *network.NetworkingConfig
AdjustCPUShares bool AdjustCPUShares bool
Platform string
} }
// ContainerRmConfig holds arguments for the container remove // ContainerRmConfig holds arguments for the container remove
@ -26,19 +25,6 @@ type ContainerRmConfig struct {
ForceRemove, RemoveVolume, RemoveLink bool ForceRemove, RemoveVolume, RemoveLink bool
} }
// ContainerCommitConfig contains build configs for commit operation,
// and is used when making a commit with the current state of the container.
type ContainerCommitConfig struct {
Pause bool
Repo string
Tag string
Author string
Comment string
// merge container config into commit config before commit
MergeConfigs bool
Config *container.Config
}
// ExecConfig is a small subset of the Config struct that holds the configuration // ExecConfig is a small subset of the Config struct that holds the configuration
// for the exec feature of docker. // for the exec feature of docker.
type ExecConfig struct { type ExecConfig struct {
@ -51,6 +37,7 @@ type ExecConfig struct {
Detach bool // Execute in detach mode Detach bool // Execute in detach mode
DetachKeys string // Escape keys for detach DetachKeys string // Escape keys for detach
Env []string // Environment variables Env []string // Environment variables
WorkingDir string // Working directory
Cmd []string // Execution commands and args Cmd []string // Execution commands and args
} }

View File

@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerChangeResponseItem container change response item // ContainerChangeResponseItem change item in response to ContainerChanges operation
// swagger:model ContainerChangeResponseItem // swagger:model ContainerChangeResponseItem
type ContainerChangeResponseItem struct { type ContainerChangeResponseItem struct {

View File

@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerCreateCreatedBody container create created body // ContainerCreateCreatedBody OK response to ContainerCreate operation
// swagger:model ContainerCreateCreatedBody // swagger:model ContainerCreateCreatedBody
type ContainerCreateCreatedBody struct { type ContainerCreateCreatedBody struct {

View File

@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerTopOKBody container top o k body // ContainerTopOKBody OK response to ContainerTop operation
// swagger:model ContainerTopOKBody // swagger:model ContainerTopOKBody
type ContainerTopOKBody struct { type ContainerTopOKBody struct {

View File

@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerUpdateOKBody container update o k body // ContainerUpdateOKBody OK response to ContainerUpdate operation
// swagger:model ContainerUpdateOKBody // swagger:model ContainerUpdateOKBody
type ContainerUpdateOKBody struct { type ContainerUpdateOKBody struct {

View File

@ -7,10 +7,22 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerWaitOKBody container wait o k body // ContainerWaitOKBodyError container waiting error, if any
// swagger:model ContainerWaitOKBodyError
type ContainerWaitOKBodyError struct {
// Details of an error
Message string `json:"Message,omitempty"`
}
// ContainerWaitOKBody OK response to ContainerWait operation
// swagger:model ContainerWaitOKBody // swagger:model ContainerWaitOKBody
type ContainerWaitOKBody struct { type ContainerWaitOKBody struct {
// error
// Required: true
Error *ContainerWaitOKBodyError `json:"Error"`
// Exit code of the container // Exit code of the container
// Required: true // Required: true
StatusCode int64 `json:"StatusCode"` StatusCode int64 `json:"StatusCode"`

View File

@ -20,44 +20,70 @@ func (i Isolation) IsDefault() bool {
return strings.ToLower(string(i)) == "default" || string(i) == "" return strings.ToLower(string(i)) == "default" || string(i) == ""
} }
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
const (
// IsolationEmpty is unspecified (same behavior as default)
IsolationEmpty = Isolation("")
// IsolationDefault is the default isolation mode on current daemon
IsolationDefault = Isolation("default")
// IsolationProcess is process isolation mode
IsolationProcess = Isolation("process")
// IsolationHyperV is HyperV isolation mode
IsolationHyperV = Isolation("hyperv")
)
// IpcMode represents the container ipc stack. // IpcMode represents the container ipc stack.
type IpcMode string type IpcMode string
// IsPrivate indicates whether the container uses its private ipc stack. // IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
func (n IpcMode) IsPrivate() bool { func (n IpcMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer()) return n == "private"
} }
// IsHost indicates whether the container uses the host's ipc stack. // IsHost indicates whether the container shares the host's ipc namespace.
func (n IpcMode) IsHost() bool { func (n IpcMode) IsHost() bool {
return n == "host" return n == "host"
} }
// IsContainer indicates whether the container uses a container's ipc stack. // IsShareable indicates whether the container's ipc namespace can be shared with another container.
func (n IpcMode) IsShareable() bool {
return n == "shareable"
}
// IsContainer indicates whether the container uses another container's ipc namespace.
func (n IpcMode) IsContainer() bool { func (n IpcMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container" return len(parts) > 1 && parts[0] == "container"
} }
// Valid indicates whether the ipc stack is valid. // IsNone indicates whether container IpcMode is set to "none".
func (n IpcMode) IsNone() bool {
return n == "none"
}
// IsEmpty indicates whether container IpcMode is empty
func (n IpcMode) IsEmpty() bool {
return n == ""
}
// Valid indicates whether the ipc mode is valid.
func (n IpcMode) Valid() bool { func (n IpcMode) Valid() bool {
parts := strings.Split(string(n), ":") return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
switch mode := parts[0]; mode {
case "", "host":
case "container":
if len(parts) != 2 || parts[1] == "" {
return false
}
default:
return false
}
return true
} }
// Container returns the name of the container ipc stack is going to be used. // Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string { func (n IpcMode) Container() string {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 { if len(parts) > 1 && parts[0] == "container" {
return parts[1] return parts[1]
} }
return "" return ""
@ -375,6 +401,12 @@ type HostConfig struct {
// Mounts specs used by the container // Mounts specs used by the container
Mounts []mount.Mount `json:",omitempty"` Mounts []mount.Mount `json:",omitempty"`
// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
MaskedPaths []string
// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
ReadonlyPaths []string
// Run a custom init inside the container, if null, use the daemon's configured settings // Run a custom init inside the container, if null, use the daemon's configured settings
Init *bool `json:",omitempty"` Init *bool `json:",omitempty"`
} }

View File

@ -1,9 +1,5 @@
package container package container
import (
"strings"
)
// IsBridge indicates whether container uses the bridge network stack // IsBridge indicates whether container uses the bridge network stack
// in windows it is given the name NAT // in windows it is given the name NAT
func (n NetworkMode) IsBridge() bool { func (n NetworkMode) IsBridge() bool {
@ -21,16 +17,6 @@ func (n NetworkMode) IsUserDefined() bool {
return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer() return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer()
} }
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
// IsValid indicates if an isolation technology is valid // IsValid indicates if an isolation technology is valid
func (i Isolation) IsValid() bool { func (i Isolation) IsValid() bool {
return i.IsDefault() || i.IsHyperV() || i.IsProcess() return i.IsDefault() || i.IsHyperV() || i.IsProcess()

View File

@ -1,38 +1,45 @@
// Package filters provides helper function to parse and handle command line /*Package filters provides tools for encoding a mapping of keys to a set of
// filter, used for example in docker ps or docker images commands. multiple values.
*/
package filters package filters
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"regexp" "regexp"
"strings" "strings"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
) )
// Args stores filter arguments as map key:{map key: bool}. // Args stores a mapping of keys to a set of multiple values.
// It contains an aggregation of the map of arguments (which are in the form
// of -f 'key=value') based on the key, and stores values for the same key
// in a map with string keys and boolean values.
// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu'
// the args will be {"image.name":{"ubuntu":true},"label":{"label1=1":true,"label2=2":true}}
type Args struct { type Args struct {
fields map[string]map[string]bool fields map[string]map[string]bool
} }
// NewArgs initializes a new Args struct. // KeyValuePair are used to initialize a new Args
func NewArgs() Args { type KeyValuePair struct {
return Args{fields: map[string]map[string]bool{}} Key string
Value string
} }
// ParseFlag parses the argument to the filter flag. Like // Arg creates a new KeyValuePair for initializing Args
func Arg(key, value string) KeyValuePair {
return KeyValuePair{Key: key, Value: value}
}
// NewArgs returns a new Args populated with the initial args
func NewArgs(initialArgs ...KeyValuePair) Args {
args := Args{fields: map[string]map[string]bool{}}
for _, arg := range initialArgs {
args.Add(arg.Key, arg.Value)
}
return args
}
// ParseFlag parses a key=value string and adds it to an Args.
// //
// `docker ps -f 'created=today' -f 'image.name=ubuntu*'` // Deprecated: Use Args.Add()
//
// If prev map is provided, then it is appended to, and returned. By default a new
// map is created.
func ParseFlag(arg string, prev Args) (Args, error) { func ParseFlag(arg string, prev Args) (Args, error) {
filters := prev filters := prev
if len(arg) == 0 { if len(arg) == 0 {
@ -53,74 +60,95 @@ func ParseFlag(arg string, prev Args) (Args, error) {
return filters, nil return filters, nil
} }
// ErrBadFormat is an error returned in case of bad format for a filter. // ErrBadFormat is an error returned when a filter is not in the form key=value
//
// Deprecated: this error will be removed in a future version
var ErrBadFormat = errors.New("bad format of filter (expected name=value)") var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
// ToParam packs the Args into a string for easy transport from client to server. // ToParam encodes the Args as args JSON encoded string
//
// Deprecated: use ToJSON
func ToParam(a Args) (string, error) { func ToParam(a Args) (string, error) {
// this way we don't URL encode {}, just empty space return ToJSON(a)
}
// MarshalJSON returns a JSON byte representation of the Args
func (args Args) MarshalJSON() ([]byte, error) {
if len(args.fields) == 0 {
return []byte{}, nil
}
return json.Marshal(args.fields)
}
// ToJSON returns the Args as a JSON encoded string
func ToJSON(a Args) (string, error) {
if a.Len() == 0 { if a.Len() == 0 {
return "", nil return "", nil
} }
buf, err := json.Marshal(a)
buf, err := json.Marshal(a.fields) return string(buf), err
if err != nil {
return "", err
}
return string(buf), nil
} }
// ToParamWithVersion packs the Args into a string for easy transport from client to server. // ToParamWithVersion encodes Args as a JSON string. If version is less than 1.22
// The generated string will depend on the specified version (corresponding to the API version). // then the encoded format will use an older legacy format where the values are a
// list of strings, instead of a set.
//
// Deprecated: Use ToJSON
func ToParamWithVersion(version string, a Args) (string, error) { func ToParamWithVersion(version string, a Args) (string, error) {
// this way we don't URL encode {}, just empty space
if a.Len() == 0 { if a.Len() == 0 {
return "", nil return "", nil
} }
// for daemons older than v1.10, filter must be of the form map[string][]string
var buf []byte
var err error
if version != "" && versions.LessThan(version, "1.22") { if version != "" && versions.LessThan(version, "1.22") {
buf, err = json.Marshal(convertArgsToSlice(a.fields)) buf, err := json.Marshal(convertArgsToSlice(a.fields))
} else { return string(buf), err
buf, err = json.Marshal(a.fields)
} }
if err != nil {
return "", err return ToJSON(a)
}
return string(buf), nil
} }
// FromParam unpacks the filter Args. // FromParam decodes a JSON encoded string into Args
//
// Deprecated: use FromJSON
func FromParam(p string) (Args, error) { func FromParam(p string) (Args, error) {
if len(p) == 0 { return FromJSON(p)
return NewArgs(), nil
}
r := strings.NewReader(p)
d := json.NewDecoder(r)
m := map[string]map[string]bool{}
if err := d.Decode(&m); err != nil {
r.Seek(0, 0)
// Allow parsing old arguments in slice format.
// Because other libraries might be sending them in this format.
deprecated := map[string][]string{}
if deprecatedErr := d.Decode(&deprecated); deprecatedErr == nil {
m = deprecatedArgs(deprecated)
} else {
return NewArgs(), err
}
}
return Args{m}, nil
} }
// Get returns the list of values associates with a field. // FromJSON decodes a JSON encoded string into Args
// It returns a slice of strings to keep backwards compatibility with old code. func FromJSON(p string) (Args, error) {
func (filters Args) Get(field string) []string { args := NewArgs()
values := filters.fields[field]
if p == "" {
return args, nil
}
raw := []byte(p)
err := json.Unmarshal(raw, &args)
if err == nil {
return args, nil
}
// Fallback to parsing arguments in the legacy slice format
deprecated := map[string][]string{}
if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil {
return args, err
}
args.fields = deprecatedArgs(deprecated)
return args, nil
}
// UnmarshalJSON populates the Args from JSON encode bytes
func (args Args) UnmarshalJSON(raw []byte) error {
if len(raw) == 0 {
return nil
}
return json.Unmarshal(raw, &args.fields)
}
// Get returns the list of values associated with the key
func (args Args) Get(key string) []string {
values := args.fields[key]
if values == nil { if values == nil {
return make([]string, 0) return make([]string, 0)
} }
@ -131,37 +159,34 @@ func (filters Args) Get(field string) []string {
return slice return slice
} }
// Add adds a new value to a filter field. // Add a new value to the set of values
func (filters Args) Add(name, value string) { func (args Args) Add(key, value string) {
if _, ok := filters.fields[name]; ok { if _, ok := args.fields[key]; ok {
filters.fields[name][value] = true args.fields[key][value] = true
} else { } else {
filters.fields[name] = map[string]bool{value: true} args.fields[key] = map[string]bool{value: true}
} }
} }
// Del removes a value from a filter field. // Del removes a value from the set
func (filters Args) Del(name, value string) { func (args Args) Del(key, value string) {
if _, ok := filters.fields[name]; ok { if _, ok := args.fields[key]; ok {
delete(filters.fields[name], value) delete(args.fields[key], value)
if len(filters.fields[name]) == 0 { if len(args.fields[key]) == 0 {
delete(filters.fields, name) delete(args.fields, key)
} }
} }
} }
// Len returns the number of fields in the arguments. // Len returns the number of keys in the mapping
func (filters Args) Len() int { func (args Args) Len() int {
return len(filters.fields) return len(args.fields)
} }
// MatchKVList returns true if the values for the specified field matches the ones // MatchKVList returns true if all the pairs in sources exist as key=value
// from the sources. // pairs in the mapping at key, or if there are no values at key.
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}}, func (args Args) MatchKVList(key string, sources map[string]string) bool {
// field is 'label' and sources are {'label1': '1', 'label2': '2'} fieldValues := args.fields[key]
// it returns true.
func (filters Args) MatchKVList(field string, sources map[string]string) bool {
fieldValues := filters.fields[field]
//do not filter if there is no filter set or cannot determine filter //do not filter if there is no filter set or cannot determine filter
if len(fieldValues) == 0 { if len(fieldValues) == 0 {
@ -172,8 +197,8 @@ func (filters Args) MatchKVList(field string, sources map[string]string) bool {
return false return false
} }
for name2match := range fieldValues { for value := range fieldValues {
testKV := strings.SplitN(name2match, "=", 2) testKV := strings.SplitN(value, "=", 2)
v, ok := sources[testKV[0]] v, ok := sources[testKV[0]]
if !ok { if !ok {
@ -187,16 +212,13 @@ func (filters Args) MatchKVList(field string, sources map[string]string) bool {
return true return true
} }
// Match returns true if the values for the specified field matches the source string // Match returns true if any of the values at key match the source string
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}}, func (args Args) Match(field, source string) bool {
// field is 'image.name' and source is 'ubuntu' if args.ExactMatch(field, source) {
// it returns true.
func (filters Args) Match(field, source string) bool {
if filters.ExactMatch(field, source) {
return true return true
} }
fieldValues := filters.fields[field] fieldValues := args.fields[field]
for name2match := range fieldValues { for name2match := range fieldValues {
match, err := regexp.MatchString(name2match, source) match, err := regexp.MatchString(name2match, source)
if err != nil { if err != nil {
@ -209,9 +231,9 @@ func (filters Args) Match(field, source string) bool {
return false return false
} }
// ExactMatch returns true if the source matches exactly one of the filters. // ExactMatch returns true if the source matches exactly one of the values.
func (filters Args) ExactMatch(field, source string) bool { func (args Args) ExactMatch(key, source string) bool {
fieldValues, ok := filters.fields[field] fieldValues, ok := args.fields[key]
//do not filter if there is no filter set or cannot determine filter //do not filter if there is no filter set or cannot determine filter
if !ok || len(fieldValues) == 0 { if !ok || len(fieldValues) == 0 {
return true return true
@ -221,14 +243,15 @@ func (filters Args) ExactMatch(field, source string) bool {
return fieldValues[source] return fieldValues[source]
} }
// UniqueExactMatch returns true if there is only one filter and the source matches exactly this one. // UniqueExactMatch returns true if there is only one value and the source
func (filters Args) UniqueExactMatch(field, source string) bool { // matches exactly the value.
fieldValues := filters.fields[field] func (args Args) UniqueExactMatch(key, source string) bool {
fieldValues := args.fields[key]
//do not filter if there is no filter set or cannot determine filter //do not filter if there is no filter set or cannot determine filter
if len(fieldValues) == 0 { if len(fieldValues) == 0 {
return true return true
} }
if len(filters.fields[field]) != 1 { if len(args.fields[key]) != 1 {
return false return false
} }
@ -236,14 +259,14 @@ func (filters Args) UniqueExactMatch(field, source string) bool {
return fieldValues[source] return fieldValues[source]
} }
// FuzzyMatch returns true if the source matches exactly one of the filters, // FuzzyMatch returns true if the source matches exactly one value, or the
// or the source has one of the filters as a prefix. // source has one of the values as a prefix.
func (filters Args) FuzzyMatch(field, source string) bool { func (args Args) FuzzyMatch(key, source string) bool {
if filters.ExactMatch(field, source) { if args.ExactMatch(key, source) {
return true return true
} }
fieldValues := filters.fields[field] fieldValues := args.fields[key]
for prefix := range fieldValues { for prefix := range fieldValues {
if strings.HasPrefix(source, prefix) { if strings.HasPrefix(source, prefix) {
return true return true
@ -252,30 +275,47 @@ func (filters Args) FuzzyMatch(field, source string) bool {
return false return false
} }
// Include returns true if the name of the field to filter is in the filters. // Include returns true if the key exists in the mapping
func (filters Args) Include(field string) bool { //
_, ok := filters.fields[field] // Deprecated: use Contains
func (args Args) Include(field string) bool {
_, ok := args.fields[field]
return ok return ok
} }
// Validate ensures that all the fields in the filter are valid. // Contains returns true if the key exists in the mapping
// It returns an error as soon as it finds an invalid field. func (args Args) Contains(field string) bool {
func (filters Args) Validate(accepted map[string]bool) error { _, ok := args.fields[field]
for name := range filters.fields { return ok
}
type invalidFilter string
func (e invalidFilter) Error() string {
return "Invalid filter '" + string(e) + "'"
}
func (invalidFilter) InvalidParameter() {}
// Validate compared the set of accepted keys against the keys in the mapping.
// An error is returned if any mapping keys are not in the accepted set.
func (args Args) Validate(accepted map[string]bool) error {
for name := range args.fields {
if !accepted[name] { if !accepted[name] {
return fmt.Errorf("Invalid filter '%s'", name) return invalidFilter(name)
} }
} }
return nil return nil
} }
// WalkValues iterates over the list of filtered values for a field. // WalkValues iterates over the list of values for a key in the mapping and calls
// It stops the iteration if it finds an error and it returns that error. // op() for each value. If op returns an error the iteration stops and the
func (filters Args) WalkValues(field string, op func(value string) error) error { // error is returned.
if _, ok := filters.fields[field]; !ok { func (args Args) WalkValues(field string, op func(value string) error) error {
if _, ok := args.fields[field]; !ok {
return nil return nil
} }
for v := range filters.fields[field] { for v := range args.fields[field] {
if err := op(v); err != nil { if err := op(v); err != nil {
return err return err
} }

View File

@ -7,7 +7,7 @@ package image
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// HistoryResponseItem history response item // HistoryResponseItem individual image layer information in response to ImageHistory operation
// swagger:model HistoryResponseItem // swagger:model HistoryResponseItem
type HistoryResponseItem struct { type HistoryResponseItem struct {

View File

@ -15,6 +15,8 @@ const (
TypeVolume Type = "volume" TypeVolume Type = "volume"
// TypeTmpfs is the type for mounting tmpfs // TypeTmpfs is the type for mounting tmpfs
TypeTmpfs Type = "tmpfs" TypeTmpfs Type = "tmpfs"
// TypeNamedPipe is the type for mounting Windows named pipes
TypeNamedPipe Type = "npipe"
) )
// Mount represents a mount (volume). // Mount represents a mount (volume).
@ -65,7 +67,7 @@ var Propagations = []Propagation{
type Consistency string type Consistency string
const ( const (
// ConsistencyFull guarantees bind-mount-like consistency // ConsistencyFull guarantees bind mount-like consistency
ConsistencyFull Consistency = "consistent" ConsistencyFull Consistency = "consistent"
// ConsistencyCached mounts can cache read data and FS structure // ConsistencyCached mounts can cache read data and FS structure
ConsistencyCached Consistency = "cached" ConsistencyCached Consistency = "cached"

View File

@ -121,6 +121,9 @@ type PluginConfigArgs struct {
// swagger:model PluginConfigInterface // swagger:model PluginConfigInterface
type PluginConfigInterface struct { type PluginConfigInterface struct {
// Protocol to use for clients connecting to the plugin.
ProtocolScheme string `json:"ProtocolScheme,omitempty"`
// socket // socket
// Required: true // Required: true
Socket string `json:"Socket"` Socket string `json:"Socket"`

View File

@ -7,7 +7,7 @@ package types
// swagger:model Port // swagger:model Port
type Port struct { type Port struct {
// IP // Host IP address that the container's port is mapped to
IP string `json:"IP,omitempty"` IP string `json:"IP,omitempty"`
// Port on the container // Port on the container

View File

@ -20,7 +20,7 @@ type Annotations struct {
Labels map[string]string `json:"Labels"` Labels map[string]string `json:"Labels"`
} }
// Driver represents a driver (network, logging). // Driver represents a driver (network, logging, secrets backend).
type Driver struct { type Driver struct {
Name string `json:",omitempty"` Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"` Options map[string]string `json:",omitempty"`

View File

@ -13,6 +13,10 @@ type Config struct {
type ConfigSpec struct { type ConfigSpec struct {
Annotations Annotations
Data []byte `json:",omitempty"` Data []byte `json:",omitempty"`
// Templating controls whether and how to evaluate the config payload as
// a template. If it is not set, no templating is used.
Templating *Driver `json:",omitempty"`
} }
// ConfigReferenceFileTarget is a file target in a config reference // ConfigReferenceFileTarget is a file target in a config reference

View File

@ -55,6 +55,7 @@ type ContainerSpec struct {
User string `json:",omitempty"` User string `json:",omitempty"`
Groups []string `json:",omitempty"` Groups []string `json:",omitempty"`
Privileges *Privileges `json:",omitempty"` Privileges *Privileges `json:",omitempty"`
Init *bool `json:",omitempty"`
StopSignal string `json:",omitempty"` StopSignal string `json:",omitempty"`
TTY bool `json:",omitempty"` TTY bool `json:",omitempty"`
OpenStdin bool `json:",omitempty"` OpenStdin bool `json:",omitempty"`
@ -69,4 +70,5 @@ type ContainerSpec struct {
DNSConfig *DNSConfig `json:",omitempty"` DNSConfig *DNSConfig `json:",omitempty"`
Secrets []*SecretReference `json:",omitempty"` Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"` Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"`
} }

View File

@ -62,6 +62,8 @@ const (
PortConfigProtocolTCP PortConfigProtocol = "tcp" PortConfigProtocolTCP PortConfigProtocol = "tcp"
// PortConfigProtocolUDP UDP // PortConfigProtocolUDP UDP
PortConfigProtocolUDP PortConfigProtocol = "udp" PortConfigProtocolUDP PortConfigProtocol = "udp"
// PortConfigProtocolSCTP SCTP
PortConfigProtocolSCTP PortConfigProtocol = "sctp"
) )
// EndpointVirtualIP represents the virtual ip of a port. // EndpointVirtualIP represents the virtual ip of a port.

View File

@ -11,9 +11,17 @@ const (
RuntimeContainer RuntimeType = "container" RuntimeContainer RuntimeType = "container"
// RuntimePlugin is the plugin based runtime // RuntimePlugin is the plugin based runtime
RuntimePlugin RuntimeType = "plugin" RuntimePlugin RuntimeType = "plugin"
// RuntimeNetworkAttachment is the network attachment runtime
RuntimeNetworkAttachment RuntimeType = "attachment"
// RuntimeURLContainer is the proto url for the container type // RuntimeURLContainer is the proto url for the container type
RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer" RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer"
// RuntimeURLPlugin is the proto url for the plugin type // RuntimeURLPlugin is the proto url for the plugin type
RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin" RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin"
) )
// NetworkAttachmentSpec represents the runtime spec type for network
// attachment tasks
type NetworkAttachmentSpec struct {
ContainerID string
}

View File

@ -1,5 +1,7 @@
syntax = "proto3"; syntax = "proto3";
option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime";
// PluginSpec defines the base payload which clients can specify for creating // PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime. // a service with the plugin runtime.
message PluginSpec { message PluginSpec {

View File

@ -14,6 +14,10 @@ type SecretSpec struct {
Annotations Annotations
Data []byte `json:",omitempty"` Data []byte `json:",omitempty"`
Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store
// Templating controls whether and how to evaluate the secret payload as
// a template. If it is not set, no templating is used.
Templating *Driver `json:",omitempty"`
} }
// SecretReferenceFileTarget is a file target in a secret reference // SecretReferenceFileTarget is a file target in a secret reference

View File

@ -36,6 +36,10 @@ const (
TaskStateFailed TaskState = "failed" TaskStateFailed TaskState = "failed"
// TaskStateRejected REJECTED // TaskStateRejected REJECTED
TaskStateRejected TaskState = "rejected" TaskStateRejected TaskState = "rejected"
// TaskStateRemove REMOVE
TaskStateRemove TaskState = "remove"
// TaskStateOrphaned ORPHANED
TaskStateOrphaned TaskState = "orphaned"
) )
// Task represents a task. // Task represents a task.
@ -56,10 +60,13 @@ type Task struct {
// TaskSpec represents the spec of a task. // TaskSpec represents the spec of a task.
type TaskSpec struct { type TaskSpec struct {
// ContainerSpec and PluginSpec are mutually exclusive. // ContainerSpec, NetworkAttachmentSpec, and PluginSpec are mutually exclusive.
// PluginSpec will only be used when the `Runtime` field is set to `plugin` // PluginSpec is only used when the `Runtime` field is set to `plugin`
// NetworkAttachmentSpec is used if the `Runtime` field is set to
// `attachment`.
ContainerSpec *ContainerSpec `json:",omitempty"` ContainerSpec *ContainerSpec `json:",omitempty"`
PluginSpec *runtime.PluginSpec `json:",omitempty"` PluginSpec *runtime.PluginSpec `json:",omitempty"`
NetworkAttachmentSpec *NetworkAttachmentSpec `json:",omitempty"`
Resources *ResourceRequirements `json:",omitempty"` Resources *ResourceRequirements `json:",omitempty"`
RestartPolicy *RestartPolicy `json:",omitempty"` RestartPolicy *RestartPolicy `json:",omitempty"`
@ -166,15 +173,15 @@ type TaskStatus struct {
State TaskState `json:",omitempty"` State TaskState `json:",omitempty"`
Message string `json:",omitempty"` Message string `json:",omitempty"`
Err string `json:",omitempty"` Err string `json:",omitempty"`
ContainerStatus ContainerStatus `json:",omitempty"` ContainerStatus *ContainerStatus `json:",omitempty"`
PortStatus PortStatus `json:",omitempty"` PortStatus PortStatus `json:",omitempty"`
} }
// ContainerStatus represents the status of a container. // ContainerStatus represents the status of a container.
type ContainerStatus struct { type ContainerStatus struct {
ContainerID string `json:",omitempty"` ContainerID string
PID int `json:",omitempty"` PID int
ExitCode int `json:",omitempty"` ExitCode int
} }
// PortStatus represents the port status of a task's host ports whose // PortStatus represents the port status of a task's host ports whose

View File

@ -29,10 +29,8 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
} }
var format string var format string
var parseInLocation bool
// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation // if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
parseInLocation = !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3) parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
if strings.Contains(value, ".") { if strings.Contains(value, ".") {
if parseInLocation { if parseInLocation {
@ -84,11 +82,14 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
} }
if err != nil { if err != nil {
// if there is a `-` then it's an RFC3339 like timestamp otherwise assume unixtimestamp // if there is a `-` then it's an RFC3339 like timestamp
if strings.Contains(value, "-") { if strings.Contains(value, "-") {
return "", err // was probably an RFC3339 like timestamp but the parser failed with an error return "", err // was probably an RFC3339 like timestamp but the parser failed with an error
} }
return value, nil // unixtimestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server) if _, _, err := parseTimestamp(value); err != nil {
return "", fmt.Errorf("failed to parse value as time or duration: %q", value)
}
return value, nil // unix timestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server)
} }
return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil
@ -106,6 +107,10 @@ func ParseTimestamps(value string, def int64) (int64, int64, error) {
if value == "" { if value == "" {
return def, 0, nil return def, 0, nil
} }
return parseTimestamp(value)
}
func parseTimestamp(value string) (int64, int64, error) {
sa := strings.SplitN(value, ".", 2) sa := strings.SplitN(value, ".", 2)
s, err := strconv.ParseInt(sa[0], 10, 64) s, err := strconv.ParseInt(sa[0], 10, 64)
if err != nil { if err != nil {

View File

@ -107,9 +107,21 @@ type Ping struct {
Experimental bool Experimental bool
} }
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
Name string
Version string
Details map[string]string `json:",omitempty"`
}
// Version contains response of Engine API: // Version contains response of Engine API:
// GET "/version" // GET "/version"
type Version struct { type Version struct {
Platform struct{ Name string } `json:",omitempty"`
Components []ComponentVersion `json:",omitempty"`
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
Version string Version string
APIVersion string `json:"ApiVersion"` APIVersion string `json:"ApiVersion"`
MinAPIVersion string `json:"MinAPIVersion,omitempty"` MinAPIVersion string `json:"MinAPIVersion,omitempty"`

View File

@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"volumes_create.go", "volume_create.go",
"volumes_list.go", "volume_list.go",
], ],
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/volume", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/volume",
importpath = "github.com/docker/docker/api/types/volume", importpath = "github.com/docker/docker/api/types/volume",

View File

@ -7,9 +7,9 @@ package volume
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// VolumesCreateBody volumes create body // VolumeCreateBody
// swagger:model VolumesCreateBody // swagger:model VolumeCreateBody
type VolumesCreateBody struct { type VolumeCreateBody struct {
// Name of the volume driver to use. // Name of the volume driver to use.
// Required: true // Required: true

View File

@ -9,9 +9,9 @@ package volume
import "github.com/docker/docker/api/types" import "github.com/docker/docker/api/types"
// VolumesListOKBody volumes list o k body // VolumeListOKBody
// swagger:model VolumesListOKBody // swagger:model VolumeListOKBody
type VolumesListOKBody struct { type VolumeListOKBody struct {
// List of volumes // List of volumes
// Required: true // Required: true

View File

@ -74,7 +74,6 @@ go_library(
"node_list.go", "node_list.go",
"node_remove.go", "node_remove.go",
"node_update.go", "node_update.go",
"parse_logs.go",
"ping.go", "ping.go",
"plugin_create.go", "plugin_create.go",
"plugin_disable.go", "plugin_disable.go",
@ -135,12 +134,10 @@ go_library(
"//vendor/github.com/docker/docker/api/types/time:go_default_library", "//vendor/github.com/docker/docker/api/types/time:go_default_library",
"//vendor/github.com/docker/docker/api/types/versions:go_default_library", "//vendor/github.com/docker/docker/api/types/versions:go_default_library",
"//vendor/github.com/docker/docker/api/types/volume:go_default_library", "//vendor/github.com/docker/docker/api/types/volume:go_default_library",
"//vendor/github.com/docker/docker/pkg/tlsconfig:go_default_library",
"//vendor/github.com/docker/go-connections/sockets:go_default_library", "//vendor/github.com/docker/go-connections/sockets:go_default_library",
"//vendor/github.com/docker/go-connections/tlsconfig:go_default_library", "//vendor/github.com/docker/go-connections/tlsconfig:go_default_library",
"//vendor/github.com/opencontainers/go-digest:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/golang.org/x/net/context/ctxhttp:go_default_library",
], ],
) )

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// BuildCachePrune requests the daemon to delete unused cache data // BuildCachePrune requests the daemon to delete unused cache data

View File

@ -1,8 +1,9 @@
package client package client
import ( import (
"context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointCreate creates a checkpoint from the given container with the given name // CheckpointCreate creates a checkpoint from the given container with the given name

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointDelete deletes the checkpoint with the given name from the given container // CheckpointDelete deletes the checkpoint with the given name from the given container

View File

@ -1,12 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointList returns the checkpoints of the given container in the docker host // CheckpointList returns the checkpoints of the given container in the docker host
@ -20,10 +19,7 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil)
if err != nil { if err != nil {
if resp.statusCode == http.StatusNotFound { return checkpoints, wrapResponseError(err, resp, "container", container)
return checkpoints, containerNotFoundError{container}
}
return checkpoints, err
} }
err = json.NewDecoder(resp.body).Decode(&checkpoints) err = json.NewDecoder(resp.body).Decode(&checkpoints)

View File

@ -1,10 +1,6 @@
/* /*
Package client is a Go client for the Docker Engine API. Package client is a Go client for the Docker Engine API.
The "docker" command uses this package to communicate with the daemon. It can also
be used by your own Go applications to do anything the command-line interface does
- running containers, pulling images, managing swarms, etc.
For more information about the Engine API, see the documentation: For more information about the Engine API, see the documentation:
https://docs.docker.com/engine/reference/api/ https://docs.docker.com/engine/reference/api/
@ -46,11 +42,13 @@ For example, to list running containers (the equivalent of "docker ps"):
package client package client
import ( import (
"errors" "context"
"fmt" "fmt"
"net"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -59,7 +57,7 @@ import (
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/go-connections/sockets" "github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig" "github.com/docker/go-connections/tlsconfig"
"golang.org/x/net/context" "github.com/pkg/errors"
) )
// ErrRedirect is the error returned by checkRedirect when the request is non-GET. // ErrRedirect is the error returned by checkRedirect when the request is non-GET.
@ -106,12 +104,21 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
} }
// NewEnvClient initializes a new API client based on environment variables. // NewEnvClient initializes a new API client based on environment variables.
// Use DOCKER_HOST to set the url to the docker server. // See FromEnv for a list of support environment variables.
// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest. //
// Use DOCKER_CERT_PATH to load the TLS certificates from. // Deprecated: use NewClientWithOpts(FromEnv)
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func NewEnvClient() (*Client, error) { func NewEnvClient() (*Client, error) {
var client *http.Client return NewClientWithOpts(FromEnv)
}
// FromEnv configures the client with values from environment variables.
//
// Supported environment variables:
// DOCKER_HOST to set the url to the docker server.
// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// DOCKER_CERT_PATH to load the TLS certificates from.
// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func FromEnv(c *Client) error {
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" { if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{ options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"), CAFile: filepath.Join(dockerCertPath, "ca.pem"),
@ -121,34 +128,159 @@ func NewEnvClient() (*Client, error) {
} }
tlsc, err := tlsconfig.Client(options) tlsc, err := tlsconfig.Client(options)
if err != nil { if err != nil {
return nil, err return err
} }
client = &http.Client{ c.client = &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{TLSClientConfig: tlsc},
TLSClientConfig: tlsc,
},
CheckRedirect: CheckRedirect, CheckRedirect: CheckRedirect,
} }
} }
host := os.Getenv("DOCKER_HOST") if host := os.Getenv("DOCKER_HOST"); host != "" {
if host == "" { if err := WithHost(host)(c); err != nil {
host = DefaultDockerHost return err
} }
version := os.Getenv("DOCKER_API_VERSION")
if version == "" {
version = api.DefaultVersion
} }
cli, err := NewClient(host, version, client, nil) if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
c.version = version
c.manualOverride = true
}
return nil
}
// WithTLSClientConfig applies a tls config to the client transport.
func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) error {
return func(c *Client) error {
opts := tlsconfig.Options{
CAFile: cacertPath,
CertFile: certPath,
KeyFile: keyPath,
ExclusiveRootPools: true,
}
config, err := tlsconfig.Client(opts)
if err != nil { if err != nil {
return cli, err return errors.Wrap(err, "failed to create tls config")
} }
if os.Getenv("DOCKER_API_VERSION") != "" { if transport, ok := c.client.Transport.(*http.Transport); ok {
cli.manualOverride = true transport.TLSClientConfig = config
return nil
} }
return cli, nil return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
}
}
// WithDialer applies the dialer.DialContext to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
func WithDialer(dialer *net.Dialer) func(*Client) error {
return func(c *Client) error {
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.DialContext = dialer.DialContext
return nil
}
return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
}
}
// WithVersion overrides the client version with the specified one
func WithVersion(version string) func(*Client) error {
return func(c *Client) error {
c.version = version
return nil
}
}
// WithHost overrides the client host with the specified one.
func WithHost(host string) func(*Client) error {
return func(c *Client) error {
hostURL, err := ParseHostURL(host)
if err != nil {
return err
}
c.host = host
c.proto = hostURL.Scheme
c.addr = hostURL.Host
c.basePath = hostURL.Path
if transport, ok := c.client.Transport.(*http.Transport); ok {
return sockets.ConfigureTransport(transport, c.proto, c.addr)
}
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
}
}
// WithHTTPClient overrides the client http client with the specified one
func WithHTTPClient(client *http.Client) func(*Client) error {
return func(c *Client) error {
if client != nil {
c.client = client
}
return nil
}
}
// WithHTTPHeaders overrides the client default http headers
func WithHTTPHeaders(headers map[string]string) func(*Client) error {
return func(c *Client) error {
c.customHTTPHeaders = headers
return nil
}
}
// NewClientWithOpts initializes a new API client with default values. It takes functors
// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))`
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
client, err := defaultHTTPClient(DefaultDockerHost)
if err != nil {
return nil, err
}
c := &Client{
host: DefaultDockerHost,
version: api.DefaultVersion,
scheme: "http",
client: client,
proto: defaultProto,
addr: defaultAddr,
}
for _, op := range ops {
if err := op(c); err != nil {
return nil, err
}
}
if _, ok := c.client.Transport.(http.RoundTripper); !ok {
return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport)
}
tlsConfig := resolveTLSConfig(c.client.Transport)
if tlsConfig != nil {
// TODO(stevvooe): This isn't really the right way to write clients in Go.
// `NewClient` should probably only take an `*http.Client` and work from there.
// Unfortunately, the model of having a host-ish/url-thingy as the connection
// string has us confusing protocol and transport layers. We continue doing
// this to avoid breaking existing clients but this should be addressed.
c.scheme = "https"
}
return c, nil
}
func defaultHTTPClient(host string) (*http.Client, error) {
url, err := ParseHostURL(host)
if err != nil {
return nil, err
}
transport := new(http.Transport)
sockets.ConfigureTransport(transport, url.Scheme, url.Host)
return &http.Client{
Transport: transport,
CheckRedirect: CheckRedirect,
}, nil
} }
// NewClient initializes a new API client for the given host and API version. // NewClient initializes a new API client for the given host and API version.
@ -158,58 +290,16 @@ func NewEnvClient() (*Client, error) {
// It won't send any version information if the version number is empty. It is // It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the // highly recommended that you set a version or your client may break if the
// server is upgraded. // server is upgraded.
// Deprecated: use NewClientWithOpts
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) { func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
proto, addr, basePath, err := ParseHost(host) return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
if err != nil {
return nil, err
}
if client != nil {
if _, ok := client.Transport.(*http.Transport); !ok {
return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport)
}
} else {
transport := new(http.Transport)
sockets.ConfigureTransport(transport, proto, addr)
client = &http.Client{
Transport: transport,
CheckRedirect: CheckRedirect,
}
}
scheme := "http"
tlsConfig := resolveTLSConfig(client.Transport)
if tlsConfig != nil {
// TODO(stevvooe): This isn't really the right way to write clients in Go.
// `NewClient` should probably only take an `*http.Client` and work from there.
// Unfortunately, the model of having a host-ish/url-thingy as the connection
// string has us confusing protocol and transport layers. We continue doing
// this to avoid breaking existing clients but this should be addressed.
scheme = "https"
}
return &Client{
scheme: scheme,
host: host,
proto: proto,
addr: addr,
basePath: basePath,
client: client,
version: version,
customHTTPHeaders: httpHeaders,
}, nil
} }
// Close ensures that transport.Client is closed // Close the transport used by the client
// especially needed while using NewClient with *http.Client = nil
// for example
// client.NewClient("unix:///var/run/docker.sock", nil, "v1.18", map[string]string{"User-Agent": "engine-api-cli-1.0"})
func (cli *Client) Close() error { func (cli *Client) Close() error {
if t, ok := cli.client.Transport.(*http.Transport); ok { if t, ok := cli.client.Transport.(*http.Transport); ok {
t.CloseIdleConnections() t.CloseIdleConnections()
} }
return nil return nil
} }
@ -219,37 +309,27 @@ func (cli *Client) getAPIPath(p string, query url.Values) string {
var apiPath string var apiPath string
if cli.version != "" { if cli.version != "" {
v := strings.TrimPrefix(cli.version, "v") v := strings.TrimPrefix(cli.version, "v")
apiPath = cli.basePath + "/v" + v + p apiPath = path.Join(cli.basePath, "/v"+v, p)
} else { } else {
apiPath = cli.basePath + p apiPath = path.Join(cli.basePath, p)
} }
return (&url.URL{Path: apiPath, RawQuery: query.Encode()}).String()
u := &url.URL{
Path: apiPath,
}
if len(query) > 0 {
u.RawQuery = query.Encode()
}
return u.String()
} }
// ClientVersion returns the version string associated with this // ClientVersion returns the API version used by this client.
// instance of the Client. Note that this value can be changed
// via the DOCKER_API_VERSION env var.
// This operation doesn't acquire a mutex.
func (cli *Client) ClientVersion() string { func (cli *Client) ClientVersion() string {
return cli.version return cli.version
} }
// NegotiateAPIVersion updates the version string associated with this // NegotiateAPIVersion queries the API and updates the version to match the
// instance of the Client to match the latest version the server supports // API version. Any errors are silently ignored.
func (cli *Client) NegotiateAPIVersion(ctx context.Context) { func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
ping, _ := cli.Ping(ctx) ping, _ := cli.Ping(ctx)
cli.NegotiateAPIVersionPing(ping) cli.NegotiateAPIVersionPing(ping)
} }
// NegotiateAPIVersionPing updates the version string associated with this // NegotiateAPIVersionPing updates the client version to match the Ping.APIVersion
// instance of the Client to match the latest version the server supports // if the ping version is less than the default version.
func (cli *Client) NegotiateAPIVersionPing(p types.Ping) { func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
if cli.manualOverride { if cli.manualOverride {
return return
@ -265,23 +345,28 @@ func (cli *Client) NegotiateAPIVersionPing(p types.Ping) {
cli.version = api.DefaultVersion cli.version = api.DefaultVersion
} }
// if server version is lower than the maximum version supported by the Client, downgrade // if server version is lower than the client version, downgrade
if versions.LessThan(p.APIVersion, api.DefaultVersion) { if versions.LessThan(p.APIVersion, cli.version) {
cli.version = p.APIVersion cli.version = p.APIVersion
} }
} }
// DaemonHost returns the host associated with this instance of the Client. // DaemonHost returns the host address used by the client
// This operation doesn't acquire a mutex.
func (cli *Client) DaemonHost() string { func (cli *Client) DaemonHost() string {
return cli.host return cli.host
} }
// ParseHost verifies that the given host strings is valid. // HTTPClient returns a copy of the HTTP client bound to the server
func ParseHost(host string) (string, string, string, error) { func (cli *Client) HTTPClient() *http.Client {
return &*cli.client
}
// ParseHostURL parses a url string, validates the string is a host url, and
// returns the parsed URL
func ParseHostURL(host string) (*url.URL, error) {
protoAddrParts := strings.SplitN(host, "://", 2) protoAddrParts := strings.SplitN(host, "://", 2)
if len(protoAddrParts) == 1 { if len(protoAddrParts) == 1 {
return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host) return nil, fmt.Errorf("unable to parse docker host `%s`", host)
} }
var basePath string var basePath string
@ -289,16 +374,19 @@ func ParseHost(host string) (string, string, string, error) {
if proto == "tcp" { if proto == "tcp" {
parsed, err := url.Parse("tcp://" + addr) parsed, err := url.Parse("tcp://" + addr)
if err != nil { if err != nil {
return "", "", "", err return nil, err
} }
addr = parsed.Host addr = parsed.Host
basePath = parsed.Path basePath = parsed.Path
} }
return proto, addr, basePath, nil return &url.URL{
Scheme: proto,
Host: addr,
Path: basePath,
}, nil
} }
// CustomHTTPHeaders returns the custom http headers associated with this // CustomHTTPHeaders returns the custom http headers stored by the client.
// instance of the Client. This operation doesn't acquire a mutex.
func (cli *Client) CustomHTTPHeaders() map[string]string { func (cli *Client) CustomHTTPHeaders() map[string]string {
m := make(map[string]string) m := make(map[string]string)
for k, v := range cli.customHTTPHeaders { for k, v := range cli.customHTTPHeaders {
@ -307,8 +395,8 @@ func (cli *Client) CustomHTTPHeaders() map[string]string {
return m return m
} }
// SetCustomHTTPHeaders updates the custom http headers associated with this // SetCustomHTTPHeaders that will be set on every HTTP request made by the client.
// instance of the Client. This operation doesn't acquire a mutex. // Deprecated: use WithHTTPHeaders when creating the client.
func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) { func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) {
cli.customHTTPHeaders = headers cli.customHTTPHeaders = headers
} }

View File

@ -1,6 +1,9 @@
// +build linux freebsd solaris openbsd darwin // +build linux freebsd openbsd darwin
package client package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset // DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "unix:///var/run/docker.sock" const DefaultDockerHost = "unix:///var/run/docker.sock"
const defaultProto = "unix"
const defaultAddr = "/var/run/docker.sock"

View File

@ -2,3 +2,6 @@ package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset // DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "npipe:////./pipe/docker_engine" const DefaultDockerHost = "npipe:////./pipe/docker_engine"
const defaultProto = "npipe"
const defaultAddr = "//./pipe/docker_engine"

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigCreate creates a new Config. // ConfigCreate creates a new Config.

View File

@ -2,25 +2,24 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigInspectWithRaw returns the config information with raw data // ConfigInspectWithRaw returns the config information with raw data
func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
if id == "" {
return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id}
}
if err := cli.NewVersionError("1.30", "config inspect"); err != nil { if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
return swarm.Config{}, nil, err return swarm.Config{}, nil, err
} }
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
if err != nil { if err != nil {
if resp.statusCode == http.StatusNotFound { return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
return swarm.Config{}, nil, configNotFoundError{id}
}
return swarm.Config{}, nil, err
} }
defer ensureReaderClosed(resp) defer ensureReaderClosed(resp)

View File

@ -1,13 +1,13 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigList returns the list of configs. // ConfigList returns the list of configs.
@ -18,7 +18,7 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio
query := url.Values{} query := url.Values{}
if options.Filters.Len() > 0 { if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters) filterJSON, err := filters.ToJSON(options.Filters)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,6 @@
package client package client
import "golang.org/x/net/context" import "context"
// ConfigRemove removes a Config. // ConfigRemove removes a Config.
func (cli *Client) ConfigRemove(ctx context.Context, id string) error { func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
@ -9,5 +9,5 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
} }
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return wrapResponseError(err, resp, "config", id)
} }

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"strconv" "strconv"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigUpdate attempts to update a Config // ConfigUpdate attempts to update a Config

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerAttach attaches a connection to a container in the server. // ContainerAttach attaches a connection to a container in the server.

View File

@ -1,13 +1,13 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"net/url" "net/url"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerCommit applies changes into a container and creates a new tagged image. // ContainerCommit applies changes into a container and creates a new tagged image.
@ -39,7 +39,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option
for _, change := range options.Changes { for _, change := range options.Changes {
query.Add("changes", change) query.Add("changes", change)
} }
if options.Pause != true { if !options.Pause {
query.Set("pause", "0") query.Set("pause", "0")
} }

View File

@ -1,6 +1,7 @@
package client package client
import ( import (
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -10,8 +11,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
) )
@ -23,17 +22,17 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri
urlStr := "/containers/" + containerID + "/archive" urlStr := "/containers/" + containerID + "/archive"
response, err := cli.head(ctx, urlStr, query, nil) response, err := cli.head(ctx, urlStr, query, nil)
if err != nil { if err != nil {
return types.ContainerPathStat{}, err return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
} }
defer ensureReaderClosed(response) defer ensureReaderClosed(response)
return getContainerPathStatFromHeader(response.header) return getContainerPathStatFromHeader(response.header)
} }
// CopyToContainer copies content into the container filesystem. // CopyToContainer copies content into the container filesystem.
// Note that `content` must be a Reader for a TAR // Note that `content` must be a Reader for a TAR archive
func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error { func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options types.CopyToContainerOptions) error {
query := url.Values{} query := url.Values{}
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API.
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa. // Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
if !options.AllowOverwriteDirWithFile { if !options.AllowOverwriteDirWithFile {
query.Set("noOverwriteDirNonDir", "true") query.Set("noOverwriteDirNonDir", "true")
@ -43,11 +42,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string,
query.Set("copyUIDGID", "true") query.Set("copyUIDGID", "true")
} }
apiPath := "/containers/" + container + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.putRaw(ctx, apiPath, query, content, nil) response, err := cli.putRaw(ctx, apiPath, query, content, nil)
if err != nil { if err != nil {
return err return wrapResponseError(err, response, "container:path", containerID+":"+dstPath)
} }
defer ensureReaderClosed(response) defer ensureReaderClosed(response)
@ -59,15 +58,15 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string,
} }
// CopyFromContainer gets the content from the container and returns it as a Reader // CopyFromContainer gets the content from the container and returns it as a Reader
// to manipulate it in the host. It's up to the caller to close the reader. // for a TAR archive to manipulate it in the host. It's up to the caller to close the reader.
func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) { func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
query := make(url.Values, 1) query := make(url.Values, 1)
query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API.
apiPath := "/containers/" + container + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.get(ctx, apiPath, query, nil) response, err := cli.get(ctx, apiPath, query, nil)
if err != nil { if err != nil {
return nil, types.ContainerPathStat{}, err return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath)
} }
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {

View File

@ -1,6 +1,7 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings" "strings"
@ -8,7 +9,6 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"golang.org/x/net/context"
) )
type configWrapper struct { type configWrapper struct {
@ -45,7 +45,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
if err != nil { if err != nil {
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") { if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, imageNotFoundError{config.Image} return response, objectNotFoundError{object: "image", id: config.Image}
} }
return response, err return response, err
} }

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerDiff shows differences in a container filesystem since it was started. // ContainerDiff shows differences in a container filesystem since it was started.

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerExecCreate creates a new exec configuration to run an exec process. // ContainerExecCreate creates a new exec configuration to run an exec process.
@ -35,7 +35,7 @@ func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config
// It returns a types.HijackedConnection with the hijacked connection // It returns a types.HijackedConnection with the hijacked connection
// and the a reader to get output. It's up to the called to close // and the a reader to get output. It's up to the called to close
// the hijacked connection by calling types.HijackedResponse.Close. // the hijacked connection by calling types.HijackedResponse.Close.
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) { func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) {
headers := map[string][]string{"Content-Type": {"application/json"}} headers := map[string][]string{"Content-Type": {"application/json"}}
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers) return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
} }

View File

@ -1,10 +1,9 @@
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerExport retrieves the raw contents of a container // ContainerExport retrieves the raw contents of a container

View File

@ -2,23 +2,22 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerInspect returns the container information. // ContainerInspect returns the container information.
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
if containerID == "" {
return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
}
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
return types.ContainerJSON{}, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, err
} }
var response types.ContainerJSON var response types.ContainerJSON
@ -29,16 +28,16 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
// ContainerInspectWithRaw returns the container information and its raw representation. // ContainerInspectWithRaw returns the container information and its raw representation.
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) { func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
if containerID == "" {
return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID}
}
query := url.Values{} query := url.Values{}
if getSize { if getSize {
query.Set("size", "1") query.Set("size", "1")
} }
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, nil, err
} }
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)

View File

@ -1,9 +1,8 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerKill terminates the container process but does not remove the container from the docker host. // ContainerKill terminates the container process but does not remove the container from the docker host.

View File

@ -1,13 +1,13 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strconv" "strconv"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
) )
// ContainerList returns the list of containers in the docker host. // ContainerList returns the list of containers in the docker host.

View File

@ -1,14 +1,14 @@
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"time" "time"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"github.com/pkg/errors"
) )
// ContainerLogs returns the logs generated by a container in an io.ReadCloser. // ContainerLogs returns the logs generated by a container in an io.ReadCloser.
@ -46,11 +46,19 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options
if options.Since != "" { if options.Since != "" {
ts, err := timetypes.GetTimestamp(options.Since, time.Now()) ts, err := timetypes.GetTimestamp(options.Since, time.Now())
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, `invalid value for "since"`)
} }
query.Set("since", ts) query.Set("since", ts)
} }
if options.Until != "" {
ts, err := timetypes.GetTimestamp(options.Until, time.Now())
if err != nil {
return nil, errors.Wrap(err, `invalid value for "until"`)
}
query.Set("until", ts)
}
if options.Timestamps { if options.Timestamps {
query.Set("timestamps", "1") query.Set("timestamps", "1")
} }
@ -66,7 +74,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options
resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
if err != nil { if err != nil {
return nil, err return nil, wrapResponseError(err, resp, "container", container)
} }
return resp.body, nil return resp.body, nil
} }

View File

@ -1,6 +1,6 @@
package client package client
import "golang.org/x/net/context" import "context"
// ContainerPause pauses the main process of a given container without terminating it. // ContainerPause pauses the main process of a given container without terminating it.
func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { func (cli *Client) ContainerPause(ctx context.Context, containerID string) error {

View File

@ -1,12 +1,12 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
) )
// ContainersPrune requests the daemon to delete unused data // ContainersPrune requests the daemon to delete unused data

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerRemove kills and removes a container from the docker host. // ContainerRemove kills and removes a container from the docker host.
@ -23,5 +23,5 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return wrapResponseError(err, resp, "container", containerID)
} }

View File

@ -1,9 +1,8 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerRename changes the name of a given container. // ContainerRename changes the name of a given container.

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"strconv" "strconv"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerResize changes the size of the tty for a container. // ContainerResize changes the size of the tty for a container.

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"time" "time"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"golang.org/x/net/context"
) )
// ContainerRestart stops and starts a container again. // ContainerRestart stops and starts a container again.

View File

@ -1,10 +1,9 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
) )

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerStats returns near realtime stats for a given container. // ContainerStats returns near realtime stats for a given container.

View File

@ -1,15 +1,20 @@
package client package client
import ( import (
"context"
"net/url" "net/url"
"time" "time"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"golang.org/x/net/context"
) )
// ContainerStop stops a container without terminating the process. // ContainerStop stops a container. In case the container fails to stop
// The process is blocked until the container stops or the timeout expires. // gracefully within a time frame specified by the timeout argument,
// it is forcefully terminated (killed).
//
// If the timeout is nil, the container's StopTimeout value is used, if set,
// otherwise the engine default. A negative timeout value can be specified,
// meaning no timeout, i.e. no forceful termination is performed.
func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error { func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error {
query := url.Values{} query := url.Values{}
if timeout != nil { if timeout != nil {

View File

@ -1,12 +1,12 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings" "strings"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerTop shows process information from within a container. // ContainerTop shows process information from within a container.

View File

@ -1,6 +1,6 @@
package client package client
import "golang.org/x/net/context" import "context"
// ContainerUnpause resumes the process execution within a container // ContainerUnpause resumes the process execution within a container
func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error {

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerUpdate updates resources of a container // ContainerUpdate updates resources of a container

View File

@ -1,11 +1,10 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"golang.org/x/net/context"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
) )

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// DiskUsage requests the current data usage from the daemon // DiskUsage requests the current data usage from the daemon

View File

@ -1,17 +1,20 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
registrytypes "github.com/docker/docker/api/types/registry" registrytypes "github.com/docker/docker/api/types/registry"
"golang.org/x/net/context"
) )
// DistributionInspect returns the image digest with full Manifest // DistributionInspect returns the image digest with full Manifest
func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) { func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) {
// Contact the registry to retrieve digest and platform information // Contact the registry to retrieve digest and platform information
var distributionInspect registrytypes.DistributionInspect var distributionInspect registrytypes.DistributionInspect
if image == "" {
return distributionInspect, objectNotFoundError{object: "distribution", id: image}
}
if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil { if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
return distributionInspect, err return distributionInspect, err

View File

@ -2,6 +2,7 @@ package client
import ( import (
"fmt" "fmt"
"net/http"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -36,95 +37,37 @@ type notFound interface {
NotFound() bool // Is the error a NotFound error NotFound() bool // Is the error a NotFound error
} }
// IsErrNotFound returns true if the error is caused with an // IsErrNotFound returns true if the error is a NotFound error, which is returned
// object (image, container, network, volume, …) is not found in the docker host. // by the API when some object is not found.
func IsErrNotFound(err error) bool { func IsErrNotFound(err error) bool {
te, ok := err.(notFound) te, ok := err.(notFound)
return ok && te.NotFound() return ok && te.NotFound()
} }
// imageNotFoundError implements an error returned when an image is not in the docker host. type objectNotFoundError struct {
type imageNotFoundError struct { object string
imageID string id string
} }
// NotFound indicates that this error type is of NotFound func (e objectNotFoundError) NotFound() bool {
func (e imageNotFoundError) NotFound() bool {
return true return true
} }
// Error returns a string representation of an imageNotFoundError func (e objectNotFoundError) Error() string {
func (e imageNotFoundError) Error() string { return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
return fmt.Sprintf("Error: No such image: %s", e.imageID)
} }
// IsErrImageNotFound returns true if the error is caused func wrapResponseError(err error, resp serverResponse, object, id string) error {
// when an image is not found in the docker host. switch {
func IsErrImageNotFound(err error) bool { case err == nil:
return IsErrNotFound(err) return nil
} case resp.statusCode == http.StatusNotFound:
return objectNotFoundError{object: object, id: id}
// containerNotFoundError implements an error returned when a container is not in the docker host. case resp.statusCode == http.StatusNotImplemented:
type containerNotFoundError struct { return notImplementedError{message: err.Error()}
containerID string default:
} return err
}
// NotFound indicates that this error type is of NotFound
func (e containerNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a containerNotFoundError
func (e containerNotFoundError) Error() string {
return fmt.Sprintf("Error: No such container: %s", e.containerID)
}
// IsErrContainerNotFound returns true if the error is caused
// when a container is not found in the docker host.
func IsErrContainerNotFound(err error) bool {
return IsErrNotFound(err)
}
// networkNotFoundError implements an error returned when a network is not in the docker host.
type networkNotFoundError struct {
networkID string
}
// NotFound indicates that this error type is of NotFound
func (e networkNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a networkNotFoundError
func (e networkNotFoundError) Error() string {
return fmt.Sprintf("Error: No such network: %s", e.networkID)
}
// IsErrNetworkNotFound returns true if the error is caused
// when a network is not found in the docker host.
func IsErrNetworkNotFound(err error) bool {
return IsErrNotFound(err)
}
// volumeNotFoundError implements an error returned when a volume is not in the docker host.
type volumeNotFoundError struct {
volumeID string
}
// NotFound indicates that this error type is of NotFound
func (e volumeNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a volumeNotFoundError
func (e volumeNotFoundError) Error() string {
return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
}
// IsErrVolumeNotFound returns true if the error is caused
// when a volume is not found in the docker host.
func IsErrVolumeNotFound(err error) bool {
return IsErrNotFound(err)
} }
// unauthorizedError represents an authorization error in a remote registry. // unauthorizedError represents an authorization error in a remote registry.
@ -144,72 +87,6 @@ func IsErrUnauthorized(err error) bool {
return ok return ok
} }
// nodeNotFoundError implements an error returned when a node is not found.
type nodeNotFoundError struct {
nodeID string
}
// Error returns a string representation of a nodeNotFoundError
func (e nodeNotFoundError) Error() string {
return fmt.Sprintf("Error: No such node: %s", e.nodeID)
}
// NotFound indicates that this error type is of NotFound
func (e nodeNotFoundError) NotFound() bool {
return true
}
// IsErrNodeNotFound returns true if the error is caused
// when a node is not found.
func IsErrNodeNotFound(err error) bool {
_, ok := err.(nodeNotFoundError)
return ok
}
// serviceNotFoundError implements an error returned when a service is not found.
type serviceNotFoundError struct {
serviceID string
}
// Error returns a string representation of a serviceNotFoundError
func (e serviceNotFoundError) Error() string {
return fmt.Sprintf("Error: No such service: %s", e.serviceID)
}
// NotFound indicates that this error type is of NotFound
func (e serviceNotFoundError) NotFound() bool {
return true
}
// IsErrServiceNotFound returns true if the error is caused
// when a service is not found.
func IsErrServiceNotFound(err error) bool {
_, ok := err.(serviceNotFoundError)
return ok
}
// taskNotFoundError implements an error returned when a task is not found.
type taskNotFoundError struct {
taskID string
}
// Error returns a string representation of a taskNotFoundError
func (e taskNotFoundError) Error() string {
return fmt.Sprintf("Error: No such task: %s", e.taskID)
}
// NotFound indicates that this error type is of NotFound
func (e taskNotFoundError) NotFound() bool {
return true
}
// IsErrTaskNotFound returns true if the error is caused
// when a task is not found.
func IsErrTaskNotFound(err error) bool {
_, ok := err.(taskNotFoundError)
return ok
}
type pluginPermissionDenied struct { type pluginPermissionDenied struct {
name string name string
} }
@ -225,6 +102,26 @@ func IsErrPluginPermissionDenied(err error) bool {
return ok return ok
} }
type notImplementedError struct {
message string
}
func (e notImplementedError) Error() string {
return e.message
}
func (e notImplementedError) NotImplemented() bool {
return true
}
// IsErrNotImplemented returns true if the error is a NotImplemented error.
// This is returned by the API when a requested feature has not been
// implemented.
func IsErrNotImplemented(err error) bool {
te, ok := err.(notImplementedError)
return ok && te.NotImplemented()
}
// NewVersionError returns an error if the APIVersion required // NewVersionError returns an error if the APIVersion required
// if less than the current supported version // if less than the current supported version
func (cli *Client) NewVersionError(APIrequired, feature string) error { func (cli *Client) NewVersionError(APIrequired, feature string) error {
@ -233,68 +130,3 @@ func (cli *Client) NewVersionError(APIrequired, feature string) error {
} }
return nil return nil
} }
// secretNotFoundError implements an error returned when a secret is not found.
type secretNotFoundError struct {
name string
}
// Error returns a string representation of a secretNotFoundError
func (e secretNotFoundError) Error() string {
return fmt.Sprintf("Error: no such secret: %s", e.name)
}
// NotFound indicates that this error type is of NotFound
func (e secretNotFoundError) NotFound() bool {
return true
}
// IsErrSecretNotFound returns true if the error is caused
// when a secret is not found.
func IsErrSecretNotFound(err error) bool {
_, ok := err.(secretNotFoundError)
return ok
}
// configNotFoundError implements an error returned when a config is not found.
type configNotFoundError struct {
name string
}
// Error returns a string representation of a configNotFoundError
func (e configNotFoundError) Error() string {
return fmt.Sprintf("Error: no such config: %s", e.name)
}
// NotFound indicates that this error type is of NotFound
func (e configNotFoundError) NotFound() bool {
return true
}
// IsErrConfigNotFound returns true if the error is caused
// when a config is not found.
func IsErrConfigNotFound(err error) bool {
_, ok := err.(configNotFoundError)
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)
}

View File

@ -1,12 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"time" "time"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"

View File

@ -2,37 +2,20 @@ package client
import ( import (
"bufio" "bufio"
"context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strings"
"time" "time"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/tlsconfig"
"github.com/docker/go-connections/sockets" "github.com/docker/go-connections/sockets"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/net/context"
) )
// tlsClientCon holds tls information and a dialed connection.
type tlsClientCon struct {
*tls.Conn
rawConn net.Conn
}
func (c *tlsClientCon) CloseWrite() error {
// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
// on its underlying connection.
if conn, ok := c.rawConn.(types.CloseWriter); ok {
return conn.CloseWrite()
}
return nil
}
// postHijacked sends a POST request and hijacks the connection. // postHijacked sends a POST request and hijacks the connection.
func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) { func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
bodyEncoded, err := encodeData(body) bodyEncoded, err := encodeData(body)
@ -55,96 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
} }
func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
return tlsDialWithDialer(new(net.Dialer), network, addr, config)
}
// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
// order to return our custom tlsClientCon struct which holds both the tls.Conn
// object _and_ its underlying raw connection. The rationale for this is that
// we need to be able to close the write end of the connection when attaching,
// which tls.Conn does not provide.
func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
// We want the Timeout and Deadline values from dialer to cover the
// whole process: TCP connection and TLS handshake. This means that we
// also need to start our own timers now.
timeout := dialer.Timeout
if !dialer.Deadline.IsZero() {
deadlineTimeout := dialer.Deadline.Sub(time.Now())
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
}
var errChannel chan error
if timeout != 0 {
errChannel = make(chan error, 2)
time.AfterFunc(timeout, func() {
errChannel <- errors.New("")
})
}
proxyDialer, err := sockets.DialerFromEnvironment(dialer)
if err != nil {
return nil, err
}
rawConn, err := proxyDialer.Dial(network, addr)
if err != nil {
return nil, err
}
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := rawConn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
hostname := addr[:colonPos]
// If no ServerName is set, infer the ServerName
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
config = tlsconfig.Clone(config)
config.ServerName = hostname
}
conn := tls.Client(rawConn, config)
if timeout == 0 {
err = conn.Handshake()
} else {
go func() {
errChannel <- conn.Handshake()
}()
err = <-errChannel
}
if err != nil {
rawConn.Close()
return nil, err
}
// This is Docker difference with standard's crypto/tls package: returned a
// wrapper which holds both the TLS and raw connections.
return &tlsClientCon{conn, rawConn}, nil
}
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
if tlsConfig != nil && proto != "unix" && proto != "npipe" { if tlsConfig != nil && proto != "unix" && proto != "npipe" {
// Notice this isn't Go standard's tls.Dial function return tls.Dial(proto, addr, tlsConfig)
return tlsDial(proto, addr, tlsConfig)
} }
if proto == "npipe" { if proto == "npipe" {
return sockets.DialPipe(addr, 32*time.Second) return sockets.DialPipe(addr, 32*time.Second)
@ -189,8 +85,14 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
c, br := clientconn.Hijack() c, br := clientconn.Hijack()
if br.Buffered() > 0 { if br.Buffered() > 0 {
// If there is buffered content, wrap the connection // If there is buffered content, wrap the connection. We return an
// object that implements CloseWrite iff the underlying connection
// implements it.
if _, ok := c.(types.CloseWriter); ok {
c = &hijackedConnCloseWriter{&hijackedConn{c, br}}
} else {
c = &hijackedConn{c, br} c = &hijackedConn{c, br}
}
} else { } else {
br.Reset(nil) br.Reset(nil)
} }
@ -198,6 +100,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
return c, nil return c, nil
} }
// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
// that a) there was already buffered data in the http layer when Hijack() was
// called, and b) the underlying net.Conn does *not* implement CloseWrite().
// hijackedConn does not implement CloseWrite() either.
type hijackedConn struct { type hijackedConn struct {
net.Conn net.Conn
r *bufio.Reader r *bufio.Reader
@ -206,3 +112,18 @@ type hijackedConn struct {
func (c *hijackedConn) Read(b []byte) (int, error) { func (c *hijackedConn) Read(b []byte) (int, error) {
return c.r.Read(b) return c.r.Read(b)
} }
// hijackedConnCloseWriter is a hijackedConn which additionally implements
// CloseWrite(). It is returned by setupHijackConn in the case that a) there
// was already buffered data in the http layer when Hijack() was called, and b)
// the underlying net.Conn *does* implement CloseWrite().
type hijackedConnCloseWriter struct {
*hijackedConn
}
var _ types.CloseWriter = &hijackedConnCloseWriter{}
func (c *hijackedConnCloseWriter) CloseWrite() error {
conn := c.Conn.(types.CloseWriter)
return conn.CloseWrite()
}

View File

@ -1,14 +1,14 @@
package client package client
import ( import (
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@ -29,6 +29,13 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
return types.ImageBuildResponse{}, err return types.ImageBuildResponse{}, err
} }
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
if options.Platform != "" {
if err := cli.NewVersionError("1.32", "platform"); err != nil {
return types.ImageBuildResponse{}, err
}
query.Set("platform", options.Platform)
}
headers.Set("Content-Type", "application/x-tar") headers.Set("Content-Type", "application/x-tar")
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
@ -123,6 +130,8 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
if options.SessionID != "" { if options.SessionID != "" {
query.Set("session", options.SessionID) query.Set("session", options.SessionID)
} }
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
return query, nil return query, nil
} }

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"strings"
"golang.org/x/net/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -21,6 +21,9 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
query := url.Values{} query := url.Values{}
query.Set("fromImage", reference.FamiliarName(ref)) query.Set("fromImage", reference.FamiliarName(ref))
query.Set("tag", getAPITagFromNamedRef(ref)) query.Set("tag", getAPITagFromNamedRef(ref))
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,11 +1,11 @@
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"golang.org/x/net/context"
) )
// ImageHistory returns the changes in an image in history format. // ImageHistory returns the changes in an image in history format.

View File

@ -1,10 +1,10 @@
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"strings"
"golang.org/x/net/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
@ -25,6 +25,9 @@ func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSour
query.Set("repo", ref) query.Set("repo", ref)
query.Set("tag", options.Tag) query.Set("tag", options.Tag)
query.Set("message", options.Message) query.Set("message", options.Message)
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
for _, change := range options.Changes { for _, change := range options.Changes {
query.Add("changes", change) query.Add("changes", change)
} }

View File

@ -2,22 +2,21 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ImageInspectWithRaw returns the image information and its raw representation. // ImageInspectWithRaw returns the image information and its raw representation.
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
if imageID == "" {
return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID}
}
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
return types.ImageInspect{}, nil, imageNotFoundError{imageID}
}
return types.ImageInspect{}, nil, err
} }
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)

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