diff --git a/agent/exec/container/api_client_test.mock.go b/agent/exec/container/api_client_test.mock.go
index 0d3ea82bba..590811c662 100644
--- a/agent/exec/container/api_client_test.mock.go
+++ b/agent/exec/container/api_client_test.mock.go
@@ -378,7 +378,7 @@ func (_mr *_MockAPIClientRecorder) ContainerWait(arg0, arg1 interface{}) *gomock
return _mr.mock.ctrl.RecordCall(_mr.mock, "ContainerWait", arg0, arg1)
}
-func (_m *MockAPIClient) ContainersPrune(_param0 context.Context, _param1 types.ContainersPruneConfig) (types.ContainersPruneReport, error) {
+func (_m *MockAPIClient) ContainersPrune(_param0 context.Context, _param1 filters.Args) (types.ContainersPruneReport, error) {
ret := _m.ctrl.Call(_m, "ContainersPrune", _param0, _param1)
ret0, _ := ret[0].(types.ContainersPruneReport)
ret1, _ := ret[1].(error)
@@ -576,7 +576,7 @@ func (_mr *_MockAPIClientRecorder) ImageTag(arg0, arg1, arg2 interface{}) *gomoc
return _mr.mock.ctrl.RecordCall(_mr.mock, "ImageTag", arg0, arg1, arg2)
}
-func (_m *MockAPIClient) ImagesPrune(_param0 context.Context, _param1 types.ImagesPruneConfig) (types.ImagesPruneReport, error) {
+func (_m *MockAPIClient) ImagesPrune(_param0 context.Context, _param1 filters.Args) (types.ImagesPruneReport, error) {
ret := _m.ctrl.Call(_m, "ImagesPrune", _param0, _param1)
ret0, _ := ret[0].(types.ImagesPruneReport)
ret1, _ := ret[1].(error)
@@ -673,7 +673,7 @@ func (_mr *_MockAPIClientRecorder) NetworkRemove(arg0, arg1 interface{}) *gomock
return _mr.mock.ctrl.RecordCall(_mr.mock, "NetworkRemove", arg0, arg1)
}
-func (_m *MockAPIClient) NetworksPrune(_param0 context.Context, _param1 types.NetworksPruneConfig) (types.NetworksPruneReport, error) {
+func (_m *MockAPIClient) NetworksPrune(_param0 context.Context, _param1 filters.Args) (types.NetworksPruneReport, error) {
ret := _m.ctrl.Call(_m, "NetworksPrune", _param0, _param1)
ret0, _ := ret[0].(types.NetworksPruneReport)
ret1, _ := ret[1].(error)
@@ -748,14 +748,14 @@ func (_mr *_MockAPIClientRecorder) PluginCreate(arg0, arg1, arg2 interface{}) *g
return _mr.mock.ctrl.RecordCall(_mr.mock, "PluginCreate", arg0, arg1, arg2)
}
-func (_m *MockAPIClient) PluginDisable(_param0 context.Context, _param1 string) error {
- ret := _m.ctrl.Call(_m, "PluginDisable", _param0, _param1)
+func (_m *MockAPIClient) PluginDisable(_param0 context.Context, _param1 string, _param2 types.PluginDisableOptions) error {
+ ret := _m.ctrl.Call(_m, "PluginDisable", _param0, _param1, _param2)
ret0, _ := ret[0].(error)
return ret0
}
-func (_mr *_MockAPIClientRecorder) PluginDisable(arg0, arg1 interface{}) *gomock.Call {
- return _mr.mock.ctrl.RecordCall(_mr.mock, "PluginDisable", arg0, arg1)
+func (_mr *_MockAPIClientRecorder) PluginDisable(arg0, arg1, arg2 interface{}) *gomock.Call {
+ return _mr.mock.ctrl.RecordCall(_mr.mock, "PluginDisable", arg0, arg1, arg2)
}
func (_m *MockAPIClient) PluginEnable(_param0 context.Context, _param1 string, _param2 types.PluginEnableOptions) error {
@@ -780,10 +780,11 @@ func (_mr *_MockAPIClientRecorder) PluginInspectWithRaw(arg0, arg1 interface{})
return _mr.mock.ctrl.RecordCall(_mr.mock, "PluginInspectWithRaw", arg0, arg1)
}
-func (_m *MockAPIClient) PluginInstall(_param0 context.Context, _param1 string, _param2 types.PluginInstallOptions) error {
+func (_m *MockAPIClient) PluginInstall(_param0 context.Context, _param1 string, _param2 types.PluginInstallOptions) (io.ReadCloser, error) {
ret := _m.ctrl.Call(_m, "PluginInstall", _param0, _param1, _param2)
- ret0, _ := ret[0].(error)
- return ret0
+ ret0, _ := ret[0].(io.ReadCloser)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
}
func (_mr *_MockAPIClientRecorder) PluginInstall(arg0, arg1, arg2 interface{}) *gomock.Call {
@@ -801,10 +802,11 @@ func (_mr *_MockAPIClientRecorder) PluginList(arg0 interface{}) *gomock.Call {
return _mr.mock.ctrl.RecordCall(_mr.mock, "PluginList", arg0)
}
-func (_m *MockAPIClient) PluginPush(_param0 context.Context, _param1 string, _param2 string) error {
+func (_m *MockAPIClient) PluginPush(_param0 context.Context, _param1 string, _param2 string) (io.ReadCloser, error) {
ret := _m.ctrl.Call(_m, "PluginPush", _param0, _param1, _param2)
- ret0, _ := ret[0].(error)
- return ret0
+ ret0, _ := ret[0].(io.ReadCloser)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
}
func (_mr *_MockAPIClientRecorder) PluginPush(arg0, arg1, arg2 interface{}) *gomock.Call {
@@ -1122,7 +1124,7 @@ func (_mr *_MockAPIClientRecorder) VolumeRemove(arg0, arg1, arg2 interface{}) *g
return _mr.mock.ctrl.RecordCall(_mr.mock, "VolumeRemove", arg0, arg1, arg2)
}
-func (_m *MockAPIClient) VolumesPrune(_param0 context.Context, _param1 types.VolumesPruneConfig) (types.VolumesPruneReport, error) {
+func (_m *MockAPIClient) VolumesPrune(_param0 context.Context, _param1 filters.Args) (types.VolumesPruneReport, error) {
ret := _m.ctrl.Call(_m, "VolumesPrune", _param0, _param1)
ret0, _ := ret[0].(types.VolumesPruneReport)
ret1, _ := ret[1].(error)
diff --git a/agent/exec/container/executor.go b/agent/exec/container/executor.go
index a043b1dd33..433e3001a0 100644
--- a/agent/exec/container/executor.go
+++ b/agent/exec/container/executor.go
@@ -64,13 +64,9 @@ func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
} else if typ.Capability == "networkdriver" {
plgnTyp = "Network"
}
- plgnName := plgn.Name
- if plgn.Tag != "" {
- plgnName += ":" + plgn.Tag
- }
plugins[api.PluginDescription{
Type: plgnTyp,
- Name: plgnName,
+ Name: plgn.Name,
}] = struct{}{}
}
}
diff --git a/manager/allocator/networkallocator/networkallocator.go b/manager/allocator/networkallocator/networkallocator.go
index 68820c8f24..21b1465fe1 100644
--- a/manager/allocator/networkallocator/networkallocator.go
+++ b/manager/allocator/networkallocator/networkallocator.go
@@ -9,6 +9,7 @@ import (
"github.com/docker/libnetwork/driverapi"
"github.com/docker/libnetwork/drvregistry"
"github.com/docker/libnetwork/ipamapi"
+ "github.com/docker/libnetwork/netlabel"
"github.com/docker/swarmkit/api"
"github.com/docker/swarmkit/log"
"github.com/pkg/errors"
@@ -435,6 +436,7 @@ func (na *NetworkAllocator) releaseEndpoints(networks []*api.NetworkAttachment)
// allocate virtual IP for a single endpoint attachment of the service.
func (na *NetworkAllocator) allocateVIP(vip *api.Endpoint_VirtualIP) error {
+ var opts map[string]string
localNet := na.getNetwork(vip.NetworkID)
if localNet == nil {
return fmt.Errorf("networkallocator: could not find local network state")
@@ -461,8 +463,13 @@ func (na *NetworkAllocator) allocateVIP(vip *api.Endpoint_VirtualIP) error {
}
}
+ if localNet.nw.IPAM != nil && localNet.nw.IPAM.Driver != nil {
+ // set ipam allocation method to serial
+ opts = setIPAMSerialAlloc(localNet.nw.IPAM.Driver.Options)
+ }
+
for _, poolID := range localNet.pools {
- ip, _, err := ipam.RequestAddress(poolID, addr, nil)
+ ip, _, err := ipam.RequestAddress(poolID, addr, opts)
if err != nil && err != ipamapi.ErrNoAvailableIPs && err != ipamapi.ErrIPOutOfRange {
return errors.Wrap(err, "could not allocate VIP from IPAM")
}
@@ -511,6 +518,7 @@ func (na *NetworkAllocator) deallocateVIP(vip *api.Endpoint_VirtualIP) error {
// allocate the IP addresses for a single network attachment of the task.
func (na *NetworkAllocator) allocateNetworkIPs(nAttach *api.NetworkAttachment) error {
+ var opts map[string]string
var ip *net.IPNet
ipam, _, _, err := na.resolveIPAM(nAttach.Network)
@@ -542,10 +550,16 @@ func (na *NetworkAllocator) allocateNetworkIPs(nAttach *api.NetworkAttachment) e
}
}
+ // Set the ipam options if the network has an ipam driver.
+ if localNet.nw.IPAM != nil && localNet.nw.IPAM.Driver != nil {
+ // set ipam allocation method to serial
+ opts = setIPAMSerialAlloc(localNet.nw.IPAM.Driver.Options)
+ }
+
for _, poolID := range localNet.pools {
var err error
- ip, _, err = ipam.RequestAddress(poolID, addr, nil)
+ ip, _, err = ipam.RequestAddress(poolID, addr, opts)
if err != nil && err != ipamapi.ErrNoAvailableIPs && err != ipamapi.ErrIPOutOfRange {
return errors.Wrap(err, "could not allocate IP from IPAM")
}
@@ -667,7 +681,7 @@ func (na *NetworkAllocator) loadDriver(name string) error {
if pg == nil {
return fmt.Errorf("plugin store is unintialized")
}
- _, err := pg.Get(name, driverapi.NetworkPluginEndpointType, plugingetter.LOOKUP)
+ _, err := pg.Get(name, driverapi.NetworkPluginEndpointType, plugingetter.Lookup)
return err
}
@@ -764,7 +778,21 @@ func (na *NetworkAllocator) allocatePools(n *api.Network) (map[string]string, er
}
pools[poolIP.String()] = poolID
- gwIP, _, err := ipam.RequestAddress(poolID, net.ParseIP(ic.Gateway), nil)
+ // This change is a backport that leverage a new allocation policy offered by the libnetwork IPAM
+ // This will let the ipam driver allocate IP sequentially differently from before that was the leftmost free bit of the pool.
+ // The objective is to reduce the occurrence of address already in use error that is due to a non synchronous handling
+ // of resources made by swarmkit, where the state of container is deleted from raft and
+ // the resources (like IP) is made available for other tasks to use immediately while the previous owner is
+ // still shutting down
+ if dOptions == nil {
+ dOptions = make(map[string]string)
+ }
+ dOptions[ipamapi.RequestAddressType] = netlabel.Gateway
+ // set ipam allocation method to serial
+ dOptions = setIPAMSerialAlloc(dOptions)
+ defer delete(dOptions, ipamapi.RequestAddressType)
+
+ gwIP, _, err := ipam.RequestAddress(poolID, net.ParseIP(ic.Gateway), dOptions)
if err != nil {
// Rollback by releasing all the resources allocated so far.
releasePools(ipam, ipamConfigs[:i], pools)
@@ -792,3 +820,14 @@ func initializeDrivers(reg *drvregistry.DrvRegistry) error {
}
return nil
}
+
+// setIPAMSerialAlloc sets the ipam allocation method to serial
+func setIPAMSerialAlloc(opts map[string]string) map[string]string {
+ if opts == nil {
+ opts = make(map[string]string)
+ }
+ if _, ok := opts[ipamapi.AllocSerialPrefix]; !ok {
+ opts[ipamapi.AllocSerialPrefix] = "true"
+ }
+ return opts
+}
diff --git a/manager/allocator/networkallocator/networkallocator_test.go b/manager/allocator/networkallocator/networkallocator_test.go
index 66db705f1e..a1bd0d40a4 100644
--- a/manager/allocator/networkallocator/networkallocator_test.go
+++ b/manager/allocator/networkallocator/networkallocator_test.go
@@ -753,6 +753,10 @@ func (a *mockIpam) DiscoverDelete(dType discoverapi.DiscoveryType, data interfac
return nil
}
+func (a *mockIpam) IsBuiltIn() bool {
+ return true
+}
+
func TestCorrectlyPassIPAMOptions(t *testing.T) {
var err error
expectedIpamOptions := map[string]string{"network-name": "freddie"}
diff --git a/manager/allocator/networkallocator/portallocator.go b/manager/allocator/networkallocator/portallocator.go
index a070c65c06..959482d813 100644
--- a/manager/allocator/networkallocator/portallocator.go
+++ b/manager/allocator/networkallocator/portallocator.go
@@ -371,7 +371,7 @@ func (ps *portSpace) allocate(p *api.PortConfig) (err error) {
}
// Check out an arbitrary port from dynamic port space.
- swarmPort, err := ps.dynamicPortSpace.GetID()
+ swarmPort, err := ps.dynamicPortSpace.GetID(true)
if err != nil {
return
}
diff --git a/manager/controlapi/common.go b/manager/controlapi/common.go
index 8993edda87..a0f5e3360e 100644
--- a/manager/controlapi/common.go
+++ b/manager/controlapi/common.go
@@ -94,7 +94,7 @@ func validateDriver(driver *api.Driver, pg plugingetter.PluginGetter, pluginType
return nil
}
- p, err := pg.Get(driver.Name, pluginType, plugingetter.LOOKUP)
+ p, err := pg.Get(driver.Name, pluginType, plugingetter.Lookup)
if err != nil {
return grpc.Errorf(codes.InvalidArgument, "error during lookup of plugin %s", driver.Name)
}
diff --git a/vendor.conf b/vendor.conf
index 92108159f2..a1ddd2deaa 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -14,18 +14,18 @@ github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8
github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
github.com/docker/distribution 7230e9def796c63a4033211dc5107742d689fc1e
-github.com/docker/docker 0fb0d67008157add34f1e11685e23a691db92644
+github.com/docker/docker 428600108cce0a11e65ec4ebd9e439e947b55da7
github.com/docker/go-connections 34b5052da6b11e27f5f2e357b38b571ddddd3928
github.com/docker/go-events 37d35add5005832485c0225ec870121b78fcff1c
github.com/docker/go-units 954fed01cc617c55d838fa2230073f2cb17386c8
github.com/docker/libkv 9fd56606e928ff1f309808f5d5a0b7a2ef73f9a8
-github.com/docker/libnetwork 3ab699ea36573d98f481d233c30c742ade737565
+github.com/docker/libnetwork 878043960238db64a7e783199f688211560dd84c https://github.com/fcrisciani/libnetwork
github.com/opencontainers/runc 8e8d01d38d7b4fb0a35bf89b72bc3e18c98882d7
github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
github.com/Microsoft/go-winio f778f05015353be65d242f3fedc18695756153bb
github.com/Sirupsen/logrus f76d643702a30fbffecdfe50831e11881c96ceb3 https://github.com/aaronlehmann/logrus
-github.com/beorn7/perks/quantile 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
+github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/boltdb/bolt e72f08ddb5a52992c0a44c7dda9316c7333938b2
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
github.com/dustin/go-humanize 8929fe90cee4b2cb9deb468b51fb34eba64d1bf0
diff --git a/vendor/github.com/docker/docker/README.md b/vendor/github.com/docker/docker/README.md
new file mode 100644
index 0000000000..0b33bdca0d
--- /dev/null
+++ b/vendor/github.com/docker/docker/README.md
@@ -0,0 +1,304 @@
+Docker: the container engine [](https://github.com/docker/docker/releases/latest)
+============================
+
+Docker is an open source project to pack, ship and run any application
+as a lightweight container.
+
+Docker containers are both *hardware-agnostic* and *platform-agnostic*.
+This means they can run anywhere, from your laptop to the largest
+cloud compute instance and everything in between - and they don't require
+you to use a particular language, framework or packaging system. That
+makes them great building blocks for deploying and scaling web apps,
+databases, and backend services without depending on a particular stack
+or provider.
+
+Docker began as an open-source implementation of the deployment engine which
+powered [dotCloud](http://web.archive.org/web/20130530031104/https://www.dotcloud.com/),
+a popular Platform-as-a-Service. It benefits directly from the experience
+accumulated over several years of large-scale operation and support of hundreds
+of thousands of applications and databases.
+
+
+
+## Security Disclosure
+
+Security is very important to us. If you have any issue regarding security,
+please disclose the information responsibly by sending an email to
+security@docker.com and not by creating a GitHub issue.
+
+## Better than VMs
+
+A common method for distributing applications and sandboxing their
+execution is to use virtual machines, or VMs. Typical VM formats are
+VMware's vmdk, Oracle VirtualBox's vdi, and Amazon EC2's ami. In theory
+these formats should allow every developer to automatically package
+their application into a "machine" for easy distribution and deployment.
+In practice, that almost never happens, for a few reasons:
+
+ * *Size*: VMs are very large which makes them impractical to store
+ and transfer.
+ * *Performance*: running VMs consumes significant CPU and memory,
+ which makes them impractical in many scenarios, for example local
+ development of multi-tier applications, and large-scale deployment
+ of cpu and memory-intensive applications on large numbers of
+ machines.
+ * *Portability*: competing VM environments don't play well with each
+ other. Although conversion tools do exist, they are limited and
+ add even more overhead.
+ * *Hardware-centric*: VMs were designed with machine operators in
+ mind, not software developers. As a result, they offer very
+ limited tooling for what developers need most: building, testing
+ and running their software. For example, VMs offer no facilities
+ for application versioning, monitoring, configuration, logging or
+ service discovery.
+
+By contrast, Docker relies on a different sandboxing method known as
+*containerization*. Unlike traditional virtualization, containerization
+takes place at the kernel level. Most modern operating system kernels
+now support the primitives necessary for containerization, including
+Linux with [openvz](https://openvz.org),
+[vserver](http://linux-vserver.org) and more recently
+[lxc](https://linuxcontainers.org/), Solaris with
+[zones](https://docs.oracle.com/cd/E26502_01/html/E29024/preface-1.html#scrolltoc),
+and FreeBSD with
+[Jails](https://www.freebsd.org/doc/handbook/jails.html).
+
+Docker builds on top of these low-level primitives to offer developers a
+portable format and runtime environment that solves all four problems.
+Docker containers are small (and their transfer can be optimized with
+layers), they have basically zero memory and cpu overhead, they are
+completely portable, and are designed from the ground up with an
+application-centric design.
+
+Perhaps best of all, because Docker operates at the OS level, it can still be
+run inside a VM!
+
+## Plays well with others
+
+Docker does not require you to buy into a particular programming
+language, framework, packaging system, or configuration language.
+
+Is your application a Unix process? Does it use files, tcp connections,
+environment variables, standard Unix streams and command-line arguments
+as inputs and outputs? Then Docker can run it.
+
+Can your application's build be expressed as a sequence of such
+commands? Then Docker can build it.
+
+## Escape dependency hell
+
+A common problem for developers is the difficulty of managing all
+their application's dependencies in a simple and automated way.
+
+This is usually difficult for several reasons:
+
+ * *Cross-platform dependencies*. Modern applications often depend on
+ a combination of system libraries and binaries, language-specific
+ packages, framework-specific modules, internal components
+ developed for another project, etc. These dependencies live in
+ different "worlds" and require different tools - these tools
+ typically don't work well with each other, requiring awkward
+ custom integrations.
+
+ * *Conflicting dependencies*. Different applications may depend on
+ different versions of the same dependency. Packaging tools handle
+ these situations with various degrees of ease - but they all
+ handle them in different and incompatible ways, which again forces
+ the developer to do extra work.
+
+ * *Custom dependencies*. A developer may need to prepare a custom
+ version of their application's dependency. Some packaging systems
+ can handle custom versions of a dependency, others can't - and all
+ of them handle it differently.
+
+
+Docker solves the problem of dependency hell by giving the developer a simple
+way to express *all* their application's dependencies in one place, while
+streamlining the process of assembling them. If this makes you think of
+[XKCD 927](https://xkcd.com/927/), don't worry. Docker doesn't
+*replace* your favorite packaging systems. It simply orchestrates
+their use in a simple and repeatable way. How does it do that? With
+layers.
+
+Docker defines a build as running a sequence of Unix commands, one
+after the other, in the same container. Build commands modify the
+contents of the container (usually by installing new files on the
+filesystem), the next command modifies it some more, etc. Since each
+build command inherits the result of the previous commands, the
+*order* in which the commands are executed expresses *dependencies*.
+
+Here's a typical Docker build process:
+
+```bash
+FROM ubuntu:12.04
+RUN apt-get update && apt-get install -y python python-pip curl
+RUN curl -sSL https://github.com/shykes/helloflask/archive/master.tar.gz | tar -xzv
+RUN cd helloflask-master && pip install -r requirements.txt
+```
+
+Note that Docker doesn't care *how* dependencies are built - as long
+as they can be built by running a Unix command in a container.
+
+
+Getting started
+===============
+
+Docker can be installed either on your computer for building applications or
+on servers for running them. To get started, [check out the installation
+instructions in the
+documentation](https://docs.docker.com/engine/installation/).
+
+Usage examples
+==============
+
+Docker can be used to run short-lived commands, long-running daemons
+(app servers, databases, etc.), interactive shell sessions, etc.
+
+You can find a [list of real-world
+examples](https://docs.docker.com/engine/examples/) in the
+documentation.
+
+Under the hood
+--------------
+
+Under the hood, Docker is built on the following components:
+
+* The
+ [cgroups](https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt)
+ and
+ [namespaces](http://man7.org/linux/man-pages/man7/namespaces.7.html)
+ capabilities of the Linux kernel
+* The [Go](https://golang.org) programming language
+* The [Docker Image Specification](https://github.com/docker/docker/blob/master/image/spec/v1.md)
+* The [Libcontainer Specification](https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md)
+
+Contributing to Docker [](https://godoc.org/github.com/docker/docker)
+======================
+
+| **Master** (Linux) | **Experimental** (Linux) | **Windows** | **FreeBSD** |
+|------------------|----------------------|---------|---------|
+| [](https://jenkins.dockerproject.org/view/Docker/job/Docker%20Master/) | [](https://jenkins.dockerproject.org/view/Docker/job/Docker%20Master%20%28experimental%29/) | [/badge/icon)](http://jenkins.dockerproject.org/job/Docker%20Master%20(windows)/) | [/badge/icon)](http://jenkins.dockerproject.org/job/Docker%20Master%20(freebsd)/) |
+
+Want to hack on Docker? Awesome! We have [instructions to help you get
+started contributing code or documentation](https://docs.docker.com/opensource/project/who-written-for/).
+
+These instructions are probably not perfect, please let us know if anything
+feels wrong or incomplete. Better yet, submit a PR and improve them yourself.
+
+Getting the development builds
+==============================
+
+Want to run Docker from a master build? You can download
+master builds at [master.dockerproject.org](https://master.dockerproject.org).
+They are updated with each commit merged into the master branch.
+
+Don't know how to use that super cool new feature in the master build? Check
+out the master docs at
+[docs.master.dockerproject.org](http://docs.master.dockerproject.org).
+
+How the project is run
+======================
+
+Docker is a very, very active project. If you want to learn more about how it is run,
+or want to get more involved, the best place to start is [the project directory](https://github.com/docker/docker/tree/master/project).
+
+We are always open to suggestions on process improvements, and are always looking for more maintainers.
+
+### Talking to other Docker users and contributors
+
+
+
+
+
+ | Internet Relay Chat (IRC) |
+
+
+ IRC is a direct line to our most knowledgeable Docker users; we have
+ both the #docker and #docker-dev group on
+ irc.freenode.net.
+ IRC is a rich chat protocol but it can overwhelm new users. You can search
+ our chat archives.
+
+ Read our IRC quickstart guide for an easy way to get started.
+ |
+
+
+ | Docker Community Forums |
+
+ The Docker Engine
+ group is for users of the Docker Engine project.
+ |
+
+
+ | Google Groups |
+
+ The docker-dev group is for contributors and other people
+ contributing to the Docker project. You can join this group without a
+ Google account by sending an email to docker-dev+subscribe@googlegroups.com.
+ You'll receive a join-request message; simply reply to the message to
+ confirm your subscription.
+ |
+
+
+ | Twitter |
+
+ You can follow Docker's Twitter feed
+ to get updates on our products. You can also tweet us questions or just
+ share blogs or stories.
+ |
+
+
+ | Stack Overflow |
+
+ Stack Overflow has over 7000 Docker questions listed. We regularly
+ monitor Docker questions
+ and so do many other knowledgeable Docker users.
+ |
+
+
+
+### Legal
+
+*Brought to you courtesy of our legal counsel. For more context,
+please see the [NOTICE](https://github.com/docker/docker/blob/master/NOTICE) document in this repo.*
+
+Use and transfer of Docker may be subject to certain restrictions by the
+United States and other governments.
+
+It is your responsibility to ensure that your use and/or transfer does not
+violate applicable laws.
+
+For more information, please see https://www.bis.doc.gov
+
+
+Licensing
+=========
+Docker is licensed under the Apache License, Version 2.0. See
+[LICENSE](https://github.com/docker/docker/blob/master/LICENSE) for the full
+license text.
+
+Other Docker Related Projects
+=============================
+There are a number of projects under development that are based on Docker's
+core technology. These projects expand the tooling built around the
+Docker platform to broaden its application and utility.
+
+* [Docker Registry](https://github.com/docker/distribution): Registry
+server for Docker (hosting/delivery of repositories and images)
+* [Docker Machine](https://github.com/docker/machine): Machine management
+for a container-centric world
+* [Docker Swarm](https://github.com/docker/swarm): A Docker-native clustering
+system
+* [Docker Compose](https://github.com/docker/compose) (formerly Fig):
+Define and run multi-container apps
+* [Kitematic](https://github.com/docker/kitematic): The easiest way to use
+Docker on Mac and Windows
+
+If you know of another project underway that should be listed here, please help
+us keep this list up-to-date by submitting a PR.
+
+Awesome-Docker
+==============
+You can find more projects, tools and articles related to Docker on the [awesome-docker list](https://github.com/veggiemonk/awesome-docker). Add your project there.
diff --git a/vendor/github.com/docker/docker/api/README.md b/vendor/github.com/docker/docker/api/README.md
new file mode 100644
index 0000000000..8954ed0174
--- /dev/null
+++ b/vendor/github.com/docker/docker/api/README.md
@@ -0,0 +1,42 @@
+# Working on the Engine API
+
+The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon.
+
+It consists of various components in this repository:
+
+- `api/swagger.yaml` A Swagger definition of the API.
+- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this.
+- `cli/` The command-line client.
+- `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.
+
+## Swagger definition
+
+The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
+
+1. To automatically generate documentation.
+2. To automatically generate the Go server and client. (A work-in-progress.)
+3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc.
+
+## 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 file is split into two main sections:
+
+- `definitions`, which defines re-usable objects used in requests and responses
+- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable)
+
+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)
+
+`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.
+
+## Viewing the API documentation
+
+When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
+
+Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
+
+The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go
index 850e19e6e3..7900d64f0d 100644
--- a/vendor/github.com/docker/docker/api/types/client.go
+++ b/vendor/github.com/docker/docker/api/types/client.go
@@ -160,10 +160,13 @@ type ImageBuildOptions struct {
ShmSize int64
Dockerfile string
Ulimits []*units.Ulimit
- BuildArgs map[string]string
- AuthConfigs map[string]AuthConfig
- Context io.Reader
- Labels map[string]string
+ // See the parsing of buildArgs in api/server/router/build/build_routes.go
+ // for an explaination of why BuildArgs needs to use *string instead of
+ // just a string
+ BuildArgs map[string]*string
+ AuthConfigs map[string]AuthConfig
+ Context io.Reader
+ Labels map[string]string
// squash the resulting image's layers to the parent
// preserves the original image and creates a new one from the parent with all
// the changes applied to a single layer
@@ -337,11 +340,17 @@ type PluginEnableOptions struct {
Timeout int
}
+// PluginDisableOptions holds parameters to disable plugins.
+type PluginDisableOptions struct {
+ Force bool
+}
+
// PluginInstallOptions holds parameters to install a plugin.
type PluginInstallOptions struct {
Disabled bool
AcceptAllPermissions bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
+ RemoteRef string // RemoteRef is the plugin name on the registry
PrivilegeFunc RequestPrivilegeFunc
AcceptPermissionsFunc func(PluginPrivileges) (bool, error)
Args []string
diff --git a/vendor/github.com/docker/docker/api/types/configs.go b/vendor/github.com/docker/docker/api/types/configs.go
index 4086126232..20c19f2132 100644
--- a/vendor/github.com/docker/docker/api/types/configs.go
+++ b/vendor/github.com/docker/docker/api/types/configs.go
@@ -53,14 +53,17 @@ type ExecConfig struct {
Cmd []string // Execution commands and args
}
-// PluginRmConfig holds arguments for the plugin remove
-// operation. This struct is used to tell the backend what operations
-// to perform.
+// PluginRmConfig holds arguments for plugin remove.
type PluginRmConfig struct {
ForceRemove bool
}
-// PluginEnableConfig holds arguments for the plugin enable
+// PluginEnableConfig holds arguments for plugin enable
type PluginEnableConfig struct {
Timeout int
}
+
+// PluginDisableConfig holds arguments for plugin disable.
+type PluginDisableConfig struct {
+ ForceDisable bool
+}
diff --git a/vendor/github.com/docker/docker/api/types/container/config.go b/vendor/github.com/docker/docker/api/types/container/config.go
index db8d8ee68c..fc050e5dba 100644
--- a/vendor/github.com/docker/docker/api/types/container/config.go
+++ b/vendor/github.com/docker/docker/api/types/container/config.go
@@ -34,29 +34,29 @@ type HealthConfig struct {
// All fields added to this struct must be marked `omitempty` to keep getting
// predictable hashes from the old `v1Compatibility` configuration.
type Config struct {
- Hostname string // Hostname
- Domainname string // Domainname
- User string // User that will run the command(s) inside the container, also support user:group
- AttachStdin bool // Attach the standard input, makes possible user interaction
- AttachStdout bool // Attach the standard output
- AttachStderr bool // Attach the standard error
- ExposedPorts nat.PortSet `json:",omitempty"` // List of exposed ports
- Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
- OpenStdin bool // Open stdin
- StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
- Env []string // List of environment variable to set in the container
- Cmd strslice.StrSlice // Command to run when starting the container
- Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
- ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
- Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
- Volumes map[string]struct{} // List of volumes (mounts) used for the container
- WorkingDir string // Current directory (PWD) in the command will be launched
- Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
- NetworkDisabled bool `json:",omitempty"` // Is network disabled
- MacAddress string `json:",omitempty"` // Mac Address of the container
- OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
- Labels map[string]string // List of labels set to this container
- StopSignal string `json:",omitempty"` // Signal to stop a container
- StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
- Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
+ Hostname string // Hostname
+ Domainname string // Domainname
+ User string // User that will run the command(s) inside the container, also support user:group
+ AttachStdin bool // Attach the standard input, makes possible user interaction
+ AttachStdout bool // Attach the standard output
+ AttachStderr bool // Attach the standard error
+ ExposedPorts nat.PortSet `json:",omitempty"` // List of exposed ports
+ Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
+ OpenStdin bool // Open stdin
+ StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
+ Env []string // List of environment variable to set in the container
+ Cmd strslice.StrSlice // Command to run when starting the container
+ Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
+ ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
+ Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
+ Volumes map[string]struct{} // List of volumes (mounts) used for the container
+ WorkingDir string // Current directory (PWD) in the command will be launched
+ Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
+ NetworkDisabled bool `json:",omitempty"` // Is network disabled
+ MacAddress string `json:",omitempty"` // Mac Address of the container
+ OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
+ Labels map[string]string // List of labels set to this container
+ StopSignal string `json:",omitempty"` // Signal to stop a container
+ StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
+ Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
}
diff --git a/vendor/github.com/docker/docker/api/types/container/host_config.go b/vendor/github.com/docker/docker/api/types/container/host_config.go
index 0c82d625e8..d34fa1405c 100644
--- a/vendor/github.com/docker/docker/api/types/container/host_config.go
+++ b/vendor/github.com/docker/docker/api/types/container/host_config.go
@@ -317,7 +317,7 @@ type HostConfig struct {
// Applicable to Windows
ConsoleSize [2]uint // Initial console size (height,width)
- Isolation Isolation // Isolation technology of the container (eg default, hyperv)
+ Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
// Contains container's resources (cgroups, ulimits)
Resources
diff --git a/vendor/github.com/docker/docker/api/types/mount/mount.go b/vendor/github.com/docker/docker/api/types/mount/mount.go
index 8ac89402f9..31f2365b8e 100644
--- a/vendor/github.com/docker/docker/api/types/mount/mount.go
+++ b/vendor/github.com/docker/docker/api/types/mount/mount.go
@@ -50,6 +50,16 @@ const (
PropagationSlave Propagation = "slave"
)
+// Propagations is the list of all valid mount propagations
+var Propagations = []Propagation{
+ PropagationRPrivate,
+ PropagationPrivate,
+ PropagationRShared,
+ PropagationShared,
+ PropagationRSlave,
+ PropagationSlave,
+}
+
// BindOptions defines options specific to mounts of type "bind".
type BindOptions struct {
Propagation Propagation `json:",omitempty"`
diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go
index 832b3edb9f..07ea05035b 100644
--- a/vendor/github.com/docker/docker/api/types/network/network.go
+++ b/vendor/github.com/docker/docker/api/types/network/network.go
@@ -28,7 +28,7 @@ type EndpointIPAMConfig struct {
LinkLocalIPs []string `json:",omitempty"`
}
-// PeerInfo represents one peer of a overlay network
+// PeerInfo represents one peer of an overlay network
type PeerInfo struct {
Name string
IP string
diff --git a/vendor/github.com/docker/docker/api/types/plugin.go b/vendor/github.com/docker/docker/api/types/plugin.go
index 2bd2a6eeac..44c7f52721 100644
--- a/vendor/github.com/docker/docker/api/types/plugin.go
+++ b/vendor/github.com/docker/docker/api/types/plugin.go
@@ -25,10 +25,6 @@ type Plugin struct {
// settings
// Required: true
Settings PluginSettings `json:"Settings"`
-
- // tag
- // Required: true
- Tag string `json:"Tag"`
}
// PluginConfig The config of a plugin.
@@ -71,12 +67,19 @@ type PluginConfig struct {
// Required: true
Network PluginConfigNetwork `json:"Network"`
+ // propagated mount
+ // Required: true
+ PropagatedMount string `json:"PropagatedMount"`
+
// user
User PluginConfigUser `json:"User,omitempty"`
- // workdir
+ // work dir
// Required: true
- Workdir string `json:"Workdir"`
+ WorkDir string `json:"WorkDir"`
+
+ // rootfs
+ Rootfs *PluginConfigRootfs `json:"rootfs,omitempty"`
}
// PluginConfigArgs plugin config args
@@ -139,6 +142,17 @@ type PluginConfigNetwork struct {
Type string `json:"Type"`
}
+// PluginConfigRootfs plugin config rootfs
+// swagger:model PluginConfigRootfs
+type PluginConfigRootfs struct {
+
+ // diff ids
+ DiffIds []string `json:"diff_ids"`
+
+ // type
+ Type string `json:"type,omitempty"`
+}
+
// PluginConfigUser plugin config user
// swagger:model PluginConfigUser
type PluginConfigUser struct {
diff --git a/vendor/github.com/docker/docker/api/types/seccomp.go b/vendor/github.com/docker/docker/api/types/seccomp.go
index 4f02ef36b8..7d62c9a43f 100644
--- a/vendor/github.com/docker/docker/api/types/seccomp.go
+++ b/vendor/github.com/docker/docker/api/types/seccomp.go
@@ -10,7 +10,7 @@ type Seccomp struct {
Syscalls []*Syscall `json:"syscalls"`
}
-// Architecture is used to represent an specific architecture
+// Architecture is used to represent a specific architecture
// and its sub-architectures
type Architecture struct {
Arch Arch `json:"architecture"`
diff --git a/vendor/github.com/docker/docker/api/types/swarm/common.go b/vendor/github.com/docker/docker/api/types/swarm/common.go
index 589e2cfdf2..64a648bad1 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/common.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/common.go
@@ -19,3 +19,9 @@ type Annotations struct {
Name string `json:",omitempty"`
Labels map[string]string `json:",omitempty"`
}
+
+// Driver represents a driver (network, logging).
+type Driver struct {
+ Name string `json:",omitempty"`
+ Options map[string]string `json:",omitempty"`
+}
diff --git a/vendor/github.com/docker/docker/api/types/swarm/network.go b/vendor/github.com/docker/docker/api/types/swarm/network.go
index 2ba5339117..5a5e11bdba 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/network.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/network.go
@@ -109,9 +109,3 @@ type IPAMConfig struct {
Range string `json:",omitempty"`
Gateway string `json:",omitempty"`
}
-
-// Driver represents a network driver.
-type Driver struct {
- Name string `json:",omitempty"`
- Options map[string]string `json:",omitempty"`
-}
diff --git a/vendor/github.com/docker/docker/api/types/swarm/service.go b/vendor/github.com/docker/docker/api/types/swarm/service.go
index 2cf2642c1f..04f59de862 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/service.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/service.go
@@ -6,10 +6,10 @@ import "time"
type Service struct {
ID string
Meta
- Spec ServiceSpec `json:",omitempty"`
- PreviousSpec *ServiceSpec `json:",omitempty"`
- Endpoint Endpoint `json:",omitempty"`
- UpdateStatus UpdateStatus `json:",omitempty"`
+ Spec ServiceSpec `json:",omitempty"`
+ PreviousSpec *ServiceSpec `json:",omitempty"`
+ Endpoint Endpoint `json:",omitempty"`
+ UpdateStatus *UpdateStatus `json:",omitempty"`
}
// ServiceSpec represents the spec of a service.
@@ -50,8 +50,8 @@ const (
// UpdateStatus reports the status of a service update.
type UpdateStatus struct {
State UpdateState `json:",omitempty"`
- StartedAt time.Time `json:",omitempty"`
- CompletedAt time.Time `json:",omitempty"`
+ StartedAt *time.Time `json:",omitempty"`
+ CompletedAt *time.Time `json:",omitempty"`
Message string `json:",omitempty"`
}
diff --git a/vendor/github.com/docker/docker/api/types/time/timestamp.go b/vendor/github.com/docker/docker/api/types/time/timestamp.go
index d3695ba723..7d2798af76 100644
--- a/vendor/github.com/docker/docker/api/types/time/timestamp.go
+++ b/vendor/github.com/docker/docker/api/types/time/timestamp.go
@@ -84,7 +84,7 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
}
if err != nil {
- // if there is a `-` then its an RFC3339 like timestamp otherwise assume unixtimestamp
+ // if there is a `-` then it's an RFC3339 like timestamp otherwise assume unixtimestamp
if strings.Contains(value, "-") {
return "", err // was probably an RFC3339 like timestamp but the parser failed with an error
}
diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go
index 4a96ec556a..e97df9bc9c 100644
--- a/vendor/github.com/docker/docker/api/types/types.go
+++ b/vendor/github.com/docker/docker/api/types/types.go
@@ -154,11 +154,11 @@ type Version struct {
BuildTime string `json:",omitempty"`
}
-// Commit records a external tool actual commit id version along the
-// one expect by dockerd as set at build time
+// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
+// in the version-string of external tools, such as containerd, or runC.
type Commit struct {
- ID string
- Expected string
+ ID string // ID is the actual commit ID of external tool.
+ Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time.
}
// Info contains response of Engine API:
@@ -509,27 +509,6 @@ type DiskUsage struct {
Volumes []*Volume
}
-// ImagesPruneConfig contains the configuration for Engine API:
-// POST "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/images/prune"
-type ImagesPruneConfig struct {
- DanglingOnly bool
-}
-
-// ContainersPruneConfig contains the configuration for Engine API:
-// POST "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/images/prune"
-type ContainersPruneConfig struct {
-}
-
-// VolumesPruneConfig contains the configuration for Engine API:
-// POST "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/images/prune"
-type VolumesPruneConfig struct {
-}
-
-// NetworksPruneConfig contains the configuration for Engine API:
-// POST "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/networks/prune"
-type NetworksPruneConfig struct {
-}
-
// ContainersPruneReport contains the response for Engine API:
// POST "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/containers/prune"
type ContainersPruneReport struct {
@@ -568,3 +547,12 @@ type SecretCreateResponse struct {
type SecretListOptions struct {
Filters filters.Args
}
+
+// PushResult contains the tag, manifest digest, and manifest size from the
+// push. It's used to signal this information to the trust code in the client
+// so it can sign the manifest if necessary.
+type PushResult struct {
+ Tag string
+ Digest string
+ Size int
+}
diff --git a/vendor/github.com/docker/docker/api/types/versions/README.md b/vendor/github.com/docker/docker/api/types/versions/README.md
new file mode 100644
index 0000000000..1ef911edb0
--- /dev/null
+++ b/vendor/github.com/docker/docker/api/types/versions/README.md
@@ -0,0 +1,14 @@
+# Legacy API type versions
+
+This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
+
+Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
+
+## Package name conventions
+
+The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
+
+1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
+2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
+
+For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.
diff --git a/vendor/github.com/docker/docker/client/README.md b/vendor/github.com/docker/docker/client/README.md
new file mode 100644
index 0000000000..059dfb3ce7
--- /dev/null
+++ b/vendor/github.com/docker/docker/client/README.md
@@ -0,0 +1,35 @@
+# 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 example, to list running containers (the equivalent of `docker ps`):
+
+```go
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/docker/docker/api/types"
+ "github.com/docker/docker/client"
+)
+
+func main() {
+ cli, err := client.NewEnvClient()
+ if err != nil {
+ panic(err)
+ }
+
+ containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
+ if err != nil {
+ panic(err)
+ }
+
+ for _, container := range containers {
+ fmt.Printf("%s %s\n", container.ID[:10], container.Image)
+ }
+}
+```
+
+[Full documentation is available on GoDoc.](https://godoc.org/github.com/docker/docker/client)
diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go
index 4c0f097e53..75cfc8698b 100644
--- a/vendor/github.com/docker/docker/client/client.go
+++ b/vendor/github.com/docker/docker/client/client.go
@@ -86,7 +86,7 @@ type Client struct {
// NewEnvClient initializes a new API client based on environment variables.
// Use DOCKER_HOST to set the url to the docker server.
// 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.
+// Use DOCKER_CERT_PATH to load the TLS certificates from.
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func NewEnvClient() (*Client, error) {
var client *http.Client
diff --git a/vendor/github.com/docker/docker/client/container_prune.go b/vendor/github.com/docker/docker/client/container_prune.go
index 3eabe71a7f..b582170867 100644
--- a/vendor/github.com/docker/docker/client/container_prune.go
+++ b/vendor/github.com/docker/docker/client/container_prune.go
@@ -5,18 +5,24 @@ import (
"fmt"
"github.com/docker/docker/api/types"
+ "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
)
// ContainersPrune requests the daemon to delete unused data
-func (cli *Client) ContainersPrune(ctx context.Context, cfg types.ContainersPruneConfig) (types.ContainersPruneReport, error) {
+func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
var report types.ContainersPruneReport
if err := cli.NewVersionError("1.25", "container prune"); err != nil {
return report, err
}
- serverResp, err := cli.post(ctx, "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/containers/prune", nil, cfg, nil)
+ query, err := getFiltersQuery(pruneFilters)
+ if err != nil {
+ return report, err
+ }
+
+ serverResp, err := cli.post(ctx, "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/containers/prune", query, nil, nil)
if err != nil {
return report, err
}
diff --git a/vendor/github.com/docker/docker/client/errors.go b/vendor/github.com/docker/docker/client/errors.go
index 854516669c..2912692ec1 100644
--- a/vendor/github.com/docker/docker/client/errors.go
+++ b/vendor/github.com/docker/docker/client/errors.go
@@ -244,7 +244,7 @@ func (e secretNotFoundError) Error() string {
return fmt.Sprintf("Error: no such secret: %s", e.name)
}
-// NoFound indicates that this error type is of NotFound
+// NotFound indicates that this error type is of NotFound
func (e secretNotFoundError) NotFound() bool {
return true
}
@@ -255,3 +255,24 @@ func IsErrSecretNotFound(err error) bool {
_, ok := err.(secretNotFoundError)
return ok
}
+
+// pluginNotFoundError implements an error returned when a plugin is not in the docker host.
+type pluginNotFoundError struct {
+ name string
+}
+
+// NotFound indicates that this error type is of NotFound
+func (e pluginNotFoundError) NotFound() bool {
+ return true
+}
+
+// Error returns a string representation of a pluginNotFoundError
+func (e pluginNotFoundError) Error() string {
+ return fmt.Sprintf("Error: No such plugin: %s", e.name)
+}
+
+// IsErrPluginNotFound returns true if the error is caused
+// when a plugin is not found in the docker host.
+func IsErrPluginNotFound(err error) bool {
+ return IsErrNotFound(err)
+}
diff --git a/vendor/github.com/docker/docker/client/events.go b/vendor/github.com/docker/docker/client/events.go
index c154f7dcf9..af47aefa74 100644
--- a/vendor/github.com/docker/docker/client/events.go
+++ b/vendor/github.com/docker/docker/client/events.go
@@ -22,17 +22,20 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c
messages := make(chan events.Message)
errs := make(chan error, 1)
+ started := make(chan struct{})
go func() {
defer close(errs)
query, err := buildEventsQueryParams(cli.version, options)
if err != nil {
+ close(started)
errs <- err
return
}
resp, err := cli.get(ctx, "/events", query, nil)
if err != nil {
+ close(started)
errs <- err
return
}
@@ -40,6 +43,7 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c
decoder := json.NewDecoder(resp.body)
+ close(started)
for {
select {
case <-ctx.Done():
@@ -61,6 +65,7 @@ func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (<-c
}
}
}()
+ <-started
return messages, errs
}
diff --git a/vendor/github.com/docker/docker/client/image_prune.go b/vendor/github.com/docker/docker/client/image_prune.go
index d5e69d5b19..5ef98b7f02 100644
--- a/vendor/github.com/docker/docker/client/image_prune.go
+++ b/vendor/github.com/docker/docker/client/image_prune.go
@@ -5,18 +5,24 @@ import (
"fmt"
"github.com/docker/docker/api/types"
+ "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
)
// ImagesPrune requests the daemon to delete unused data
-func (cli *Client) ImagesPrune(ctx context.Context, cfg types.ImagesPruneConfig) (types.ImagesPruneReport, error) {
+func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (types.ImagesPruneReport, error) {
var report types.ImagesPruneReport
if err := cli.NewVersionError("1.25", "image prune"); err != nil {
return report, err
}
- serverResp, err := cli.post(ctx, "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/images/prune", nil, cfg, nil)
+ query, err := getFiltersQuery(pruneFilters)
+ if err != nil {
+ return report, err
+ }
+
+ serverResp, err := cli.post(ctx, "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/images/prune", query, nil, nil)
if err != nil {
return report, err
}
diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/interface.go
index 0d722d9075..00b9adea32 100644
--- a/vendor/github.com/docker/docker/client/interface.go
+++ b/vendor/github.com/docker/docker/client/interface.go
@@ -64,7 +64,7 @@ type ContainerAPIClient interface {
ContainerWait(ctx context.Context, container string) (int64, error)
CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
- ContainersPrune(ctx context.Context, cfg types.ContainersPruneConfig) (types.ContainersPruneReport, error)
+ ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
}
// ImageAPIClient defines API client methods for the images
@@ -82,7 +82,7 @@ type ImageAPIClient interface {
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
ImageTag(ctx context.Context, image, ref string) error
- ImagesPrune(ctx context.Context, cfg types.ImagesPruneConfig) (types.ImagesPruneReport, error)
+ ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error)
}
// NetworkAPIClient defines API client methods for the networks
@@ -94,7 +94,7 @@ type NetworkAPIClient interface {
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
NetworkRemove(ctx context.Context, networkID string) error
- NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error)
+ NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error)
}
// NodeAPIClient defines API client methods for the nodes
@@ -110,9 +110,9 @@ type PluginAPIClient interface {
PluginList(ctx context.Context) (types.PluginsListResponse, error)
PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error
PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error
- PluginDisable(ctx context.Context, name string) error
- PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error
- PluginPush(ctx context.Context, name string, registryAuth string) error
+ PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error
+ PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error)
+ PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error)
PluginSet(ctx context.Context, name string, args []string) error
PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error)
PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error
@@ -157,7 +157,7 @@ type VolumeAPIClient interface {
VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error)
VolumeRemove(ctx context.Context, volumeID string, force bool) error
- VolumesPrune(ctx context.Context, cfg types.VolumesPruneConfig) (types.VolumesPruneReport, error)
+ VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
}
// SecretAPIClient defines API client methods for secrets
diff --git a/vendor/github.com/docker/docker/client/network_prune.go b/vendor/github.com/docker/docker/client/network_prune.go
index 01185f2e02..7352a7f0c5 100644
--- a/vendor/github.com/docker/docker/client/network_prune.go
+++ b/vendor/github.com/docker/docker/client/network_prune.go
@@ -5,14 +5,24 @@ import (
"fmt"
"github.com/docker/docker/api/types"
+ "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
)
// NetworksPrune requests the daemon to delete unused networks
-func (cli *Client) NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error) {
+func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (types.NetworksPruneReport, error) {
var report types.NetworksPruneReport
- serverResp, err := cli.post(ctx, "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/networks/prune", nil, cfg, nil)
+ if err := cli.NewVersionError("1.25", "network prune"); err != nil {
+ return report, err
+ }
+
+ query, err := getFiltersQuery(pruneFilters)
+ if err != nil {
+ return report, err
+ }
+
+ serverResp, err := cli.post(ctx, "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/networks/prune", query, nil, nil)
if err != nil {
return report, err
}
diff --git a/vendor/github.com/docker/docker/client/ping.go b/vendor/github.com/docker/docker/client/ping.go
index 22dcda24fd..150b1dc8d8 100644
--- a/vendor/github.com/docker/docker/client/ping.go
+++ b/vendor/github.com/docker/docker/client/ping.go
@@ -7,7 +7,7 @@ import (
"golang.org/x/net/context"
)
-// Ping pings the server and return the value of the "Docker-Experimental" & "API-Version" headers
+// Ping pings the server and returns the value of the "Docker-Experimental" & "API-Version" headers
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping
req, err := cli.buildRequest("GET", fmt.Sprintf("%s/_ping", cli.basePath), nil, nil)
diff --git a/vendor/github.com/docker/docker/client/plugin_disable.go b/vendor/github.com/docker/docker/client/plugin_disable.go
index 51e4565125..30467db742 100644
--- a/vendor/github.com/docker/docker/client/plugin_disable.go
+++ b/vendor/github.com/docker/docker/client/plugin_disable.go
@@ -1,12 +1,19 @@
package client
import (
+ "net/url"
+
+ "github.com/docker/docker/api/types"
"golang.org/x/net/context"
)
// PluginDisable disables a plugin
-func (cli *Client) PluginDisable(ctx context.Context, name string) error {
- resp, err := cli.post(ctx, "/plugins/"+name+"/disable", nil, nil, nil)
+func (cli *Client) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error {
+ query := url.Values{}
+ if options.Force {
+ query.Set("force", "1")
+ }
+ resp, err := cli.post(ctx, "/plugins/"+name+"/disable", query, nil, nil)
ensureReaderClosed(resp)
return err
}
diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go
index e9474b5a98..89f39ee2c6 100644
--- a/vendor/github.com/docker/docker/client/plugin_inspect.go
+++ b/vendor/github.com/docker/docker/client/plugin_inspect.go
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"io/ioutil"
+ "net/http"
"github.com/docker/docker/api/types"
"golang.org/x/net/context"
@@ -11,8 +12,11 @@ import (
// PluginInspectWithRaw inspects an existing plugin
func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) {
- resp, err := cli.get(ctx, "/plugins/"+name, nil, nil)
+ resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
if err != nil {
+ if resp.statusCode == http.StatusNotFound {
+ return nil, nil, pluginNotFoundError{name}
+ }
return nil, nil, err
}
diff --git a/vendor/github.com/docker/docker/client/plugin_install.go b/vendor/github.com/docker/docker/client/plugin_install.go
index f73362ccd3..b305780cfb 100644
--- a/vendor/github.com/docker/docker/client/plugin_install.go
+++ b/vendor/github.com/docker/docker/client/plugin_install.go
@@ -2,70 +2,104 @@ package client
import (
"encoding/json"
+ "io"
"net/http"
"net/url"
+ "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
+ "github.com/pkg/errors"
"golang.org/x/net/context"
)
// PluginInstall installs a plugin
-func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (err error) {
- // FIXME(vdemeester) name is a ref, we might want to parse/validate it here.
+func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) {
query := url.Values{}
- query.Set("name", name)
- resp, err := cli.tryPluginPull(ctx, query, options.RegistryAuth)
+ if _, err := reference.ParseNamed(options.RemoteRef); err != nil {
+ return nil, errors.Wrap(err, "invalid remote reference")
+ }
+ query.Set("remote", options.RemoteRef)
+
+ resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
+ // todo: do inspect before to check existing name before checking privileges
newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil {
ensureReaderClosed(resp)
- return privilegeErr
+ return nil, privilegeErr
}
- resp, err = cli.tryPluginPull(ctx, query, newAuthHeader)
+ options.RegistryAuth = newAuthHeader
+ resp, err = cli.tryPluginPrivileges(ctx, query, options.RegistryAuth)
}
if err != nil {
ensureReaderClosed(resp)
- return err
+ return nil, err
}
- defer func() {
- if err != nil {
- delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
- ensureReaderClosed(delResp)
- }
- }()
-
var privileges types.PluginPrivileges
if err := json.NewDecoder(resp.body).Decode(&privileges); err != nil {
ensureReaderClosed(resp)
- return err
+ return nil, err
}
ensureReaderClosed(resp)
if !options.AcceptAllPermissions && options.AcceptPermissionsFunc != nil && len(privileges) > 0 {
accept, err := options.AcceptPermissionsFunc(privileges)
if err != nil {
- return err
+ return nil, err
}
if !accept {
- return pluginPermissionDenied{name}
+ return nil, pluginPermissionDenied{options.RemoteRef}
}
}
- if len(options.Args) > 0 {
- if err := cli.PluginSet(ctx, name, options.Args); err != nil {
- return err
- }
- }
+ // set name for plugin pull, if empty should default to remote reference
+ query.Set("name", name)
- if options.Disabled {
- return nil
+ resp, err = cli.tryPluginPull(ctx, query, privileges, options.RegistryAuth)
+ if err != nil {
+ return nil, err
}
- return cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0})
+ name = resp.header.Get("Docker-Plugin-Name")
+
+ pr, pw := io.Pipe()
+ go func() { // todo: the client should probably be designed more around the actual api
+ _, err := io.Copy(pw, resp.body)
+ if err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ defer func() {
+ if err != nil {
+ delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
+ ensureReaderClosed(delResp)
+ }
+ }()
+ if len(options.Args) > 0 {
+ if err := cli.PluginSet(ctx, name, options.Args); err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ }
+
+ if options.Disabled {
+ pw.Close()
+ return
+ }
+
+ err = cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0})
+ pw.CloseWithError(err)
+ }()
+ return pr, nil
+}
+
+func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
+ headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
+ return cli.get(ctx, "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/plugins/privileges", query, headers)
}
-func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
+func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
- return cli.post(ctx, "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/plugins/pull", query, nil, headers)
+ return cli.post(ctx, "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/plugins/pull", query, privileges, headers)
}
diff --git a/vendor/github.com/docker/docker/client/plugin_push.go b/vendor/github.com/docker/docker/client/plugin_push.go
index d83bbdc358..1e5f963251 100644
--- a/vendor/github.com/docker/docker/client/plugin_push.go
+++ b/vendor/github.com/docker/docker/client/plugin_push.go
@@ -1,13 +1,17 @@
package client
import (
+ "io"
+
"golang.org/x/net/context"
)
// PluginPush pushes a plugin to a registry
-func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) error {
+func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers)
- ensureReaderClosed(resp)
- return err
+ if err != nil {
+ return nil, err
+ }
+ return resp.body, nil
}
diff --git a/vendor/github.com/docker/docker/client/swarm_init.go b/vendor/github.com/docker/docker/client/swarm_init.go
index fd45d066e3..9e65e1cca4 100644
--- a/vendor/github.com/docker/docker/client/swarm_init.go
+++ b/vendor/github.com/docker/docker/client/swarm_init.go
@@ -7,7 +7,7 @@ import (
"golang.org/x/net/context"
)
-// SwarmInit initializes the Swarm.
+// SwarmInit initializes the swarm.
func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) {
serverResp, err := cli.post(ctx, "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/swarm/init", nil, req, nil)
if err != nil {
diff --git a/vendor/github.com/docker/docker/client/swarm_inspect.go b/vendor/github.com/docker/docker/client/swarm_inspect.go
index 6d95cfc05e..77e72f8466 100644
--- a/vendor/github.com/docker/docker/client/swarm_inspect.go
+++ b/vendor/github.com/docker/docker/client/swarm_inspect.go
@@ -7,7 +7,7 @@ import (
"golang.org/x/net/context"
)
-// SwarmInspect inspects the Swarm.
+// SwarmInspect inspects the swarm.
func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) {
serverResp, err := cli.get(ctx, "/swarm", nil, nil)
if err != nil {
diff --git a/vendor/github.com/docker/docker/client/swarm_join.go b/vendor/github.com/docker/docker/client/swarm_join.go
index cda99930eb..19e5192b9e 100644
--- a/vendor/github.com/docker/docker/client/swarm_join.go
+++ b/vendor/github.com/docker/docker/client/swarm_join.go
@@ -5,7 +5,7 @@ import (
"golang.org/x/net/context"
)
-// SwarmJoin joins the Swarm.
+// SwarmJoin joins the swarm.
func (cli *Client) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error {
resp, err := cli.post(ctx, "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/swarm/join", nil, req, nil)
ensureReaderClosed(resp)
diff --git a/vendor/github.com/docker/docker/client/swarm_leave.go b/vendor/github.com/docker/docker/client/swarm_leave.go
index a4df732174..3a205cf3b5 100644
--- a/vendor/github.com/docker/docker/client/swarm_leave.go
+++ b/vendor/github.com/docker/docker/client/swarm_leave.go
@@ -6,7 +6,7 @@ import (
"golang.org/x/net/context"
)
-// SwarmLeave leaves the Swarm.
+// SwarmLeave leaves the swarm.
func (cli *Client) SwarmLeave(ctx context.Context, force bool) error {
query := url.Values{}
if force {
diff --git a/vendor/github.com/docker/docker/client/swarm_update.go b/vendor/github.com/docker/docker/client/swarm_update.go
index cc8eeb6554..7245fd4e38 100644
--- a/vendor/github.com/docker/docker/client/swarm_update.go
+++ b/vendor/github.com/docker/docker/client/swarm_update.go
@@ -9,7 +9,7 @@ import (
"golang.org/x/net/context"
)
-// SwarmUpdate updates the Swarm.
+// SwarmUpdate updates the swarm.
func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error {
query := url.Values{}
query.Set("version", strconv.FormatUint(version.Index, 10))
diff --git a/vendor/github.com/docker/docker/client/transport.go b/vendor/github.com/docker/docker/client/transport.go
index f04e601649..401ab15d30 100644
--- a/vendor/github.com/docker/docker/client/transport.go
+++ b/vendor/github.com/docker/docker/client/transport.go
@@ -2,12 +2,9 @@ package client
import (
"crypto/tls"
- "errors"
"net/http"
)
-var errTLSConfigUnavailable = errors.New("TLSConfig unavailable")
-
// transportFunc allows us to inject a mock transport for testing. We define it
// here so we can detect the tlsconfig and return nil for only this type.
type transportFunc func(*http.Request) (*http.Response, error)
@@ -16,7 +13,7 @@ func (tf transportFunc) RoundTrip(req *http.Request) (*http.Response, error) {
return tf(req)
}
-// resolveTLSConfig attempts to resolve the tls configuration from the
+// resolveTLSConfig attempts to resolve the TLS configuration from the
// RoundTripper.
func resolveTLSConfig(transport http.RoundTripper) *tls.Config {
switch tr := transport.(type) {
diff --git a/vendor/github.com/docker/docker/client/utils.go b/vendor/github.com/docker/docker/client/utils.go
index 03bf4c82fa..23d520ecb8 100644
--- a/vendor/github.com/docker/docker/client/utils.go
+++ b/vendor/github.com/docker/docker/client/utils.go
@@ -1,6 +1,10 @@
package client
-import "regexp"
+import (
+ "github.com/docker/docker/api/types/filters"
+ "net/url"
+ "regexp"
+)
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
@@ -13,3 +17,17 @@ func getDockerOS(serverHeader string) string {
}
return osType
}
+
+// getFiltersQuery returns a url query with "filters" query term, based on the
+// filters provided.
+func getFiltersQuery(f filters.Args) (url.Values, error) {
+ query := url.Values{}
+ if f.Len() > 0 {
+ filterJSON, err := filters.ToParam(f)
+ if err != nil {
+ return query, err
+ }
+ query.Set("filters", filterJSON)
+ }
+ return query, nil
+}
diff --git a/vendor/github.com/docker/docker/client/volume_prune.go b/vendor/github.com/docker/docker/client/volume_prune.go
index ea4e234a30..a07e4ce637 100644
--- a/vendor/github.com/docker/docker/client/volume_prune.go
+++ b/vendor/github.com/docker/docker/client/volume_prune.go
@@ -5,18 +5,24 @@ import (
"fmt"
"github.com/docker/docker/api/types"
+ "github.com/docker/docker/api/types/filters"
"golang.org/x/net/context"
)
// VolumesPrune requests the daemon to delete unused data
-func (cli *Client) VolumesPrune(ctx context.Context, cfg types.VolumesPruneConfig) (types.VolumesPruneReport, error) {
+func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (types.VolumesPruneReport, error) {
var report types.VolumesPruneReport
if err := cli.NewVersionError("1.25", "volume prune"); err != nil {
return report, err
}
- serverResp, err := cli.post(ctx, "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/volumes/prune", nil, cfg, nil)
+ query, err := getFiltersQuery(pruneFilters)
+ if err != nil {
+ return report, err
+ }
+
+ serverResp, err := cli.post(ctx, "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/volumes/prune", query, nil, nil)
if err != nil {
return report, err
}
diff --git a/vendor/github.com/docker/docker/pkg/README.md b/vendor/github.com/docker/docker/pkg/README.md
new file mode 100644
index 0000000000..c4b78a8ad8
--- /dev/null
+++ b/vendor/github.com/docker/docker/pkg/README.md
@@ -0,0 +1,11 @@
+pkg/ is a collection of utility packages used by the Docker project without being specific to its internals.
+
+Utility packages are kept separate from the docker core codebase to keep it as small and concise as possible.
+If some utilities grow larger and their APIs stabilize, they may be moved to their own repository under the
+Docker organization, to facilitate re-use by other projects. However that is not the priority.
+
+The directory `pkg` is named after the same directory in the camlistore project. Since Brad is a core
+Go maintainer, we thought it made sense to copy his methods for organizing Go code :) Thanks Brad!
+
+Because utility packages are small and neatly separated from the rest of the codebase, they are a good
+place to start for aspiring maintainers and contributors. Get in touch if you want to help maintain them!
diff --git a/vendor/github.com/docker/docker/pkg/plugingetter/getter.go b/vendor/github.com/docker/docker/pkg/plugingetter/getter.go
index cd8214cae9..b04b7bc828 100644
--- a/vendor/github.com/docker/docker/pkg/plugingetter/getter.go
+++ b/vendor/github.com/docker/docker/pkg/plugingetter/getter.go
@@ -3,24 +3,33 @@ package plugingetter
import "github.com/docker/docker/pkg/plugins"
const (
- // LOOKUP doesn't update RefCount
- LOOKUP = 0
- // CREATE increments RefCount
- CREATE = 1
- // REMOVE decrements RefCount
- REMOVE = -1
+ // Lookup doesn't update RefCount
+ Lookup = 0
+ // Acquire increments RefCount
+ Acquire = 1
+ // Release decrements RefCount
+ Release = -1
)
-// CompatPlugin is a abstraction to handle both v2(new) and v1(legacy) plugins.
+// CompatPlugin is an abstraction to handle both v2(new) and v1(legacy) plugins.
type CompatPlugin interface {
Client() *plugins.Client
Name() string
+ BasePath() string
IsV1() bool
}
+// CountedPlugin is a plugin which is reference counted.
+type CountedPlugin interface {
+ Acquire()
+ Release()
+ CompatPlugin
+}
+
// PluginGetter is the interface implemented by Store
type PluginGetter interface {
Get(name, capability string, mode int) (CompatPlugin, error)
GetAllByCap(capability string) ([]CompatPlugin, error)
+ GetAllManagedPluginsByCap(capability string) []CompatPlugin
Handle(capability string, callback func(string, *plugins.Client))
}
diff --git a/vendor/github.com/docker/docker/pkg/plugins/plugins.go b/vendor/github.com/docker/docker/pkg/plugins/plugins.go
index 432c47d8e5..125e6c7d66 100644
--- a/vendor/github.com/docker/docker/pkg/plugins/plugins.go
+++ b/vendor/github.com/docker/docker/pkg/plugins/plugins.go
@@ -70,12 +70,18 @@ type Plugin struct {
// Manifest of the plugin (see above)
Manifest *Manifest `json:"-"`
- // error produced by activation
- activateErr error
- // specifies if the activation sequence is completed (not if it is successful or not)
- activated bool
// wait for activation to finish
activateWait *sync.Cond
+ // error produced by activation
+ activateErr error
+ // keeps track of callback handlers run against this plugin
+ handlersRun bool
+}
+
+// BasePath returns the path to which all paths returned by the plugin are relative to.
+// For v1 plugins, this always returns the host's root directory.
+func (p *Plugin) BasePath() string {
+ return "/"
}
// Name returns the name of the plugin.
@@ -106,19 +112,51 @@ func NewLocalPlugin(name, addr string) *Plugin {
func (p *Plugin) activate() error {
p.activateWait.L.Lock()
- if p.activated {
+
+ if p.activated() {
+ p.runHandlers()
p.activateWait.L.Unlock()
return p.activateErr
}
p.activateErr = p.activateWithLock()
- p.activated = true
+ p.runHandlers()
p.activateWait.L.Unlock()
p.activateWait.Broadcast()
return p.activateErr
}
+// runHandlers runs the registered handlers for the implemented plugin types
+// This should only be run after activation, and while the activation lock is held.
+func (p *Plugin) runHandlers() {
+ if !p.activated() {
+ return
+ }
+
+ handlers.RLock()
+ if !p.handlersRun {
+ for _, iface := range p.Manifest.Implements {
+ hdlrs, handled := handlers.extpointHandlers[iface]
+ if !handled {
+ continue
+ }
+ for _, handler := range hdlrs {
+ handler(p.name, p.client)
+ }
+ }
+ p.handlersRun = true
+ }
+ handlers.RUnlock()
+
+}
+
+// activated returns if the plugin has already been activated.
+// This should only be called with the activation lock held
+func (p *Plugin) activated() bool {
+ return p.Manifest != nil
+}
+
func (p *Plugin) activateWithLock() error {
c, err := NewClient(p.Addr, p.TLSConfig)
if err != nil {
@@ -132,24 +170,12 @@ func (p *Plugin) activateWithLock() error {
}
p.Manifest = m
-
- handlers.RLock()
- for _, iface := range m.Implements {
- hdlrs, handled := handlers.extpointHandlers[iface]
- if !handled {
- continue
- }
- for _, handler := range hdlrs {
- handler(p.name, p.client)
- }
- }
- handlers.RUnlock()
return nil
}
func (p *Plugin) waitActive() error {
p.activateWait.L.Lock()
- for !p.activated {
+ for !p.activated() {
p.activateWait.Wait()
}
p.activateWait.L.Unlock()
@@ -157,7 +183,7 @@ func (p *Plugin) waitActive() error {
}
func (p *Plugin) implements(kind string) bool {
- if err := p.waitActive(); err != nil {
+ if p.Manifest == nil {
return false
}
for _, driver := range p.Manifest.Implements {
@@ -226,7 +252,7 @@ func Get(name, imp string) (*Plugin, error) {
if err != nil {
return nil, err
}
- if pl.implements(imp) {
+ if err := pl.waitActive(); err == nil && pl.implements(imp) {
logrus.Debugf("%s implements: %s", name, imp)
return pl, nil
}
@@ -243,9 +269,17 @@ func Handle(iface string, fn func(string, *Client)) {
hdlrs = append(hdlrs, fn)
handlers.extpointHandlers[iface] = hdlrs
+
+ storage.Lock()
for _, p := range storage.plugins {
- p.activated = false
+ p.activateWait.L.Lock()
+ if p.activated() && p.implements(iface) {
+ p.handlersRun = false
+ }
+ p.activateWait.L.Unlock()
}
+ storage.Unlock()
+
handlers.Unlock()
}
@@ -286,7 +320,7 @@ func GetAll(imp string) ([]*Plugin, error) {
logrus.Error(pl.err)
continue
}
- if pl.pl.implements(imp) {
+ if err := pl.pl.waitActive(); err == nil && pl.pl.implements(imp) {
out = append(out, pl.pl)
}
}
diff --git a/vendor/github.com/docker/docker/vendor.conf b/vendor/github.com/docker/docker/vendor.conf
new file mode 100644
index 0000000000..de87f9321a
--- /dev/null
+++ b/vendor/github.com/docker/docker/vendor.conf
@@ -0,0 +1,141 @@
+# the following lines are in sorted order, FYI
+github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
+github.com/Microsoft/hcsshim v0.5.9
+github.com/Microsoft/go-winio v0.3.7
+github.com/Sirupsen/logrus f76d643702a30fbffecdfe50831e11881c96ceb3 https://github.com/aaronlehmann/logrus
+github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9
+github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
+github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
+github.com/gorilla/context v1.1
+github.com/gorilla/mux v1.1
+github.com/kr/pty 5cf931ef8f
+github.com/mattn/go-shellwords v1.0.0
+github.com/mattn/go-sqlite3 v1.1.0
+github.com/tchap/go-patricia v2.2.6
+github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3
+# forked golang.org/x/net package includes a patch for lazy loading trace templates
+golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://github.com/tonistiigi/net.git
+golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
+github.com/docker/go-units e30f1e79f3cd72542f2026ceec18d3bd67ab859c
+github.com/docker/go-connections 4ccf312bf1d35e5dbda654e57a9be4c3f3cd0366
+
+github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5
+github.com/imdario/mergo 0.2.1
+
+#get libnetwork packages
+github.com/docker/libnetwork 382be38ce860738d80b53d7875d83abd5970d9d6 https://github.com/aaronlehmann/libnetwork
+github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894
+github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
+github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
+github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
+github.com/hashicorp/memberlist 88ac4de0d1a0ca6def284b571342db3b777a4c37
+github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
+github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
+github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef
+github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
+github.com/vishvananda/netlink 482f7a52b758233521878cb6c5904b6bd63f3457
+github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060
+github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
+github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d
+github.com/coreos/etcd 3a49cbb769ebd8d1dd25abb1e83386e9883a5707
+github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
+github.com/hashicorp/consul v0.5.2
+github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904
+github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7
+
+# get graph and distribution packages
+github.com/docker/distribution 28602af35aceda2f8d571bad7ca37a54cf0250bc
+github.com/vbatts/tar-split v0.10.1
+
+# get go-zfs packages
+github.com/mistifyio/go-zfs 22c9b32c84eb0d0c6f4043b6e90fc94073de92fa
+github.com/pborman/uuid v1.0
+
+# get desired notary commit, might also need to be updated in Dockerfile
+github.com/docker/notary v0.4.2
+
+google.golang.org/grpc v1.0.2
+github.com/miekg/pkcs11 df8ae6ca730422dba20c768ff38ef7d79077a59f
+github.com/docker/go v1.5.1-1-1-gbaf439e
+github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
+
+github.com/opencontainers/runc 51371867a01c467f08af739783b8beafc15 # libcontainer
+github.com/opencontainers/runtime-spec 1c7c27d043c2a5e513a44084d2b10d77d1402b8c # specs
+github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
+# libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
+github.com/coreos/go-systemd v4
+github.com/godbus/dbus v4.0.0
+github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
+github.com/golang/protobuf 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a
+
+# gelf logging driver deps
+github.com/Graylog2/go-gelf aab2f594e4585d43468ac57287b0dece9d806883
+
+github.com/fluent/fluent-logger-golang v1.2.1
+# fluent-logger-golang deps
+github.com/philhofer/fwd 899e4efba8eaa1fea74175308f3fae18ff3319fa
+github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c
+
+# fsnotify
+github.com/fsnotify/fsnotify v1.2.11
+
+# awslogs deps
+github.com/aws/aws-sdk-go v1.4.22
+github.com/go-ini/ini 060d7da055ba6ec5ea7a31f116332fe5efa04ce0
+github.com/jmespath/go-jmespath 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74
+
+# logentries
+github.com/bsphere/le_go d3308aafe090956bc89a65f0769f58251a1b4f03
+
+# gcplogs deps
+golang.org/x/oauth2 96382aa079b72d8c014eb0c50f6c223d1e6a2de0
+google.golang.org/api 3cc2e591b550923a2c5f0ab5a803feda924d5823
+cloud.google.com/go 9d965e63e8cceb1b5d7977a202f0fcb8866d6525
+github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7
+google.golang.org/genproto 9359a8d303c45e3212571b77610f1cefb0c6f3eb
+
+# native credentials
+github.com/docker/docker-credential-helpers f72c04f1d8e71959a6d103f808c50ccbad79b9fd
+
+# containerd
+github.com/docker/containerd 03e5862ec0d8d3b3f750e19fca3ee367e13c090e
+github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4
+
+# cluster
+github.com/docker/swarmkit 9e4bd71a1690cd27400714fcd98c329b752b5c4c
+github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
+github.com/gogo/protobuf v0.3
+github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a
+github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e
+golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2
+golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
+github.com/mreiferson/go-httpclient 63fe23f7434723dc904c901043af07931f293c47
+github.com/hashicorp/go-memdb 608dda3b1410a73eaf3ac8b517c9ae7ebab6aa87 https://github.com/floridoo/go-memdb
+github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990
+github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
+github.com/coreos/pkg fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
+github.com/pivotal-golang/clock 3fd3c1944c59d9742e1cd333672181cd1a6f9fa0
+github.com/prometheus/client_golang 52437c81da6b127a9925d17eb3a382a2e5fd395e
+github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
+github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6
+github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8
+github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5
+bitbucket.org/ww/goautoneg 75cd24fc2f2c2a2088577d12123ddee5f54e0675
+github.com/matttproud/golang_protobuf_extensions fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a
+github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9
+
+# cli
+github.com/spf13/cobra v1.5 https://github.com/dnephin/cobra.git
+github.com/spf13/pflag dabebe21bf790f782ea4c7bbd2efc430de182afd
+github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
+github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff
+
+# metrics
+github.com/docker/go-metrics 86138d05f285fd9737a99bee2d9be30866b59d72
+
+# composefile
+github.com/mitchellh/mapstructure f3009df150dadf309fdee4a54ed65c124afad715
+github.com/xeipuuv/gojsonpointer e0fe6f68307607d540ed8eac07a342c33fa1b54a
+github.com/xeipuuv/gojsonreference e02fc20de94c78484cd5ffb007f8af96be030a45
+github.com/xeipuuv/gojsonschema 93e72a773fade158921402d6a24c819b48aba29d
+gopkg.in/yaml.v2 a83829b6f1293c91addabc89d0571c246397bbf4
diff --git a/vendor/github.com/docker/libnetwork/README.md b/vendor/github.com/docker/libnetwork/README.md
new file mode 100644
index 0000000000..536f8aa2b3
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/README.md
@@ -0,0 +1,89 @@
+# libnetwork - networking for containers
+
+[](https://circleci.com/gh/docker/libnetwork/tree/master) [](https://coveralls.io/r/docker/libnetwork) [](https://godoc.org/github.com/docker/libnetwork)
+
+Libnetwork provides a native Go implementation for connecting containers
+
+The goal of libnetwork is to deliver a robust Container Network Model that provides a consistent programming interface and the required network abstractions for applications.
+
+#### Design
+Please refer to the [design](docs/design.md) for more information.
+
+#### Using libnetwork
+
+There are many networking solutions available to suit a broad range of use-cases. libnetwork uses a driver / plugin model to support all of these solutions while abstracting the complexity of the driver implementations by exposing a simple and consistent Network Model to users.
+
+
+```go
+func main() {
+ if reexec.Init() {
+ return
+ }
+
+ // Select and configure the network driver
+ networkType := "bridge"
+
+ // Create a new controller instance
+ driverOptions := options.Generic{}
+ genericOption := make(map[string]interface{})
+ genericOption[netlabel.GenericData] = driverOptions
+ controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption))
+ if err != nil {
+ log.Fatalf("libnetwork.New: %s", err)
+ }
+
+ // Create a network for containers to join.
+ // NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use.
+ network, err := controller.NewNetwork(networkType, "network1", "")
+ if err != nil {
+ log.Fatalf("controller.NewNetwork: %s", err)
+ }
+
+ // For each new container: allocate IP and interfaces. The returned network
+ // settings will be used for container infos (inspect and such), as well as
+ // iptables rules for port publishing. This info is contained or accessible
+ // from the returned endpoint.
+ ep, err := network.CreateEndpoint("Endpoint1")
+ if err != nil {
+ log.Fatalf("network.CreateEndpoint: %s", err)
+ }
+
+ // Create the sandbox for the container.
+ // NewSandbox accepts Variadic optional arguments which libnetwork can use.
+ sbx, err := controller.NewSandbox("container1",
+ libnetwork.OptionHostname("test"),
+ libnetwork.OptionDomainname("docker.io"))
+ if err != nil {
+ log.Fatalf("controller.NewSandbox: %s", err)
+ }
+
+ // A sandbox can join the endpoint via the join api.
+ err = ep.Join(sbx)
+ if err != nil {
+ log.Fatalf("ep.Join: %s", err)
+ }
+
+ // libnetwork client can check the endpoint's operational data via the Info() API
+ epInfo, err := ep.DriverInfo()
+ if err != nil {
+ log.Fatalf("ep.DriverInfo: %s", err)
+ }
+
+ macAddress, ok := epInfo[netlabel.MacAddress]
+ if !ok {
+ log.Fatalf("failed to get mac address from endpoint info")
+ }
+
+ fmt.Printf("Joined endpoint %s (%s) to sandbox %s (%s)\n", ep.Name(), macAddress, sbx.ContainerID(), sbx.Key())
+}
+```
+
+## Future
+Please refer to [roadmap](ROADMAP.md) for more information.
+
+## Contributing
+
+Want to hack on libnetwork? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply.
+
+## Copyright and license
+Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons.
diff --git a/vendor/github.com/docker/libnetwork/bitseq/sequence.go b/vendor/github.com/docker/libnetwork/bitseq/sequence.go
index 9c815e5e3c..6864c8fa8b 100644
--- a/vendor/github.com/docker/libnetwork/bitseq/sequence.go
+++ b/vendor/github.com/docker/libnetwork/bitseq/sequence.go
@@ -1,5 +1,5 @@
// Package bitseq provides a structure and utilities for representing long bitmask
-// as sequence of run-lenght encoded blocks. It operates direclty on the encoded
+// as sequence of run-length encoded blocks. It operates directly on the encoded
// representation, it does not decode/encode.
package bitseq
@@ -40,6 +40,7 @@ type Handle struct {
id string
dbIndex uint64
dbExists bool
+ curr uint64
store datastore.DataStore
sync.Mutex
}
@@ -192,26 +193,27 @@ func (h *Handle) getCopy() *Handle {
dbIndex: h.dbIndex,
dbExists: h.dbExists,
store: h.store,
+ curr: h.curr,
}
}
// SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal
-func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) {
+func (h *Handle) SetAnyInRange(start, end uint64, serial bool) (uint64, error) {
if end < start || end >= h.bits {
return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end)
}
if h.Unselected() == 0 {
return invalidPos, ErrNoBitAvailable
}
- return h.set(0, start, end, true, false)
+ return h.set(0, start, end, true, false, serial)
}
// SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal
-func (h *Handle) SetAny() (uint64, error) {
+func (h *Handle) SetAny(serial bool) (uint64, error) {
if h.Unselected() == 0 {
return invalidPos, ErrNoBitAvailable
}
- return h.set(0, 0, h.bits-1, true, false)
+ return h.set(0, 0, h.bits-1, true, false, serial)
}
// Set atomically sets the corresponding bit in the sequence
@@ -219,7 +221,7 @@ func (h *Handle) Set(ordinal uint64) error {
if err := h.validateOrdinal(ordinal); err != nil {
return err
}
- _, err := h.set(ordinal, 0, 0, false, false)
+ _, err := h.set(ordinal, 0, 0, false, false, false)
return err
}
@@ -228,7 +230,7 @@ func (h *Handle) Unset(ordinal uint64) error {
if err := h.validateOrdinal(ordinal); err != nil {
return err
}
- _, err := h.set(ordinal, 0, 0, false, true)
+ _, err := h.set(ordinal, 0, 0, false, true, false)
return err
}
@@ -297,7 +299,7 @@ func (h *Handle) CheckConsistency() error {
}
// set/reset the bit
-func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64, error) {
+func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial bool) (uint64, error) {
var (
bitPos uint64
bytePos uint64
@@ -307,6 +309,7 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64
for {
var store datastore.DataStore
+ curr := uint64(0)
h.Lock()
store = h.store
h.Unlock()
@@ -317,15 +320,18 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64
}
h.Lock()
+ if serial {
+ curr = h.curr
+ }
// Get position if available
if release {
bytePos, bitPos = ordinalToPos(ordinal)
} else {
if any {
- bytePos, bitPos, err = getFirstAvailable(h.head, start)
+ bytePos, bitPos, err = getAvailableFromCurrent(h.head, start, curr, end)
ret = posToOrdinal(bytePos, bitPos)
- if end < ret {
- err = ErrNoBitAvailable
+ if err == nil {
+ h.curr = ret + 1
}
} else {
bytePos, bitPos, err = checkIfAvailable(h.head, ordinal)
@@ -496,7 +502,10 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {
// Derive the this sequence offsets
byteOffset := byteStart - inBlockBytePos
bitOffset := inBlockBytePos*8 + bitStart
-
+ var firstOffset uint64
+ if current == head {
+ firstOffset = byteOffset
+ }
for current != nil {
if current.block != blockMAX {
bytePos, bitPos, err := current.getAvailableBit(bitOffset)
@@ -504,12 +513,36 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {
}
// Moving to next block: Reset bit offset.
bitOffset = 0
- byteOffset += current.count * blockBytes
+ byteOffset += (current.count * blockBytes) - firstOffset
+ firstOffset = 0
current = current.next
}
return invalidPos, invalidPos, ErrNoBitAvailable
}
+// getAvailableFromCurrent will look for available ordinal from the current ordinal.
+// If none found then it will loop back to the start to check of the available bit.
+// This can be further optimized to check from start till curr in case of a rollover
+func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, uint64, error) {
+ var bytePos, bitPos uint64
+ if curr != 0 && curr > start {
+ bytePos, bitPos, _ = getFirstAvailable(head, curr)
+ ret := posToOrdinal(bytePos, bitPos)
+ if end < ret {
+ goto begin
+ }
+ return bytePos, bitPos, nil
+ }
+
+begin:
+ bytePos, bitPos, _ = getFirstAvailable(head, start)
+ ret := posToOrdinal(bytePos, bitPos)
+ if end < ret {
+ return invalidPos, invalidPos, ErrNoBitAvailable
+ }
+ return bytePos, bitPos, nil
+}
+
// checkIfAvailable checks if the bit correspondent to the specified ordinal is unset
// If the ordinal is beyond the sequence limits, a negative response is returned
func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) {
diff --git a/vendor/github.com/docker/libnetwork/bitseq/store.go b/vendor/github.com/docker/libnetwork/bitseq/store.go
index 5448927eb1..cdb7f04264 100644
--- a/vendor/github.com/docker/libnetwork/bitseq/store.go
+++ b/vendor/github.com/docker/libnetwork/bitseq/store.go
@@ -87,6 +87,7 @@ func (h *Handle) CopyTo(o datastore.KVObject) error {
dstH.dbIndex = h.dbIndex
dstH.dbExists = h.dbExists
dstH.store = h.store
+ dstH.curr = h.curr
dstH.Unlock()
return nil
diff --git a/vendor/github.com/docker/libnetwork/datastore/datastore.go b/vendor/github.com/docker/libnetwork/datastore/datastore.go
index d7c17b5531..19bf0b026b 100644
--- a/vendor/github.com/docker/libnetwork/datastore/datastore.go
+++ b/vendor/github.com/docker/libnetwork/datastore/datastore.go
@@ -40,6 +40,8 @@ type DataStore interface {
// key. The caller must pass a KVObject of the same type as
// the objects that need to be listed
List(string, KVObject) ([]KVObject, error)
+ // Map returns a Map of KVObjects
+ Map(key string, kvObject KVObject) (map[string]KVObject, error)
// Scope returns the scope of the store
Scope() string
// KVStore returns access to the KV Store
@@ -512,23 +514,34 @@ func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
return ds.cache.list(kvObject)
}
+ var kvol []KVObject
+ cb := func(key string, val KVObject) {
+ kvol = append(kvol, val)
+ }
+ err := ds.iterateKVPairsFromStore(key, kvObject, cb)
+ if err != nil {
+ return nil, err
+ }
+ return kvol, nil
+}
+
+func (ds *datastore) iterateKVPairsFromStore(key string, kvObject KVObject, callback func(string, KVObject)) error {
// Bail out right away if the kvObject does not implement KVConstructor
ctor, ok := kvObject.(KVConstructor)
if !ok {
- return nil, fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
+ return fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
}
// Make sure the parent key exists
if err := ds.ensureParent(key); err != nil {
- return nil, err
+ return err
}
kvList, err := ds.store.List(key)
if err != nil {
- return nil, err
+ return err
}
- var kvol []KVObject
for _, kvPair := range kvList {
if len(kvPair.Value) == 0 {
continue
@@ -536,16 +549,33 @@ func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
dstO := ctor.New()
if err := dstO.SetValue(kvPair.Value); err != nil {
- return nil, err
+ return err
}
// Make sure the object has a correct view of the DB index in
// case we need to modify it and update the DB.
dstO.SetIndex(kvPair.LastIndex)
+ callback(kvPair.Key, dstO)
+ }
+
+ return nil
+}
- kvol = append(kvol, dstO)
+func (ds *datastore) Map(key string, kvObject KVObject) (map[string]KVObject, error) {
+ if ds.sequential {
+ ds.Lock()
+ defer ds.Unlock()
}
+ kvol := make(map[string]KVObject)
+ cb := func(key string, val KVObject) {
+ // Trim the leading & trailing "/" to make it consistent across all stores
+ kvol[strings.Trim(key, "/")] = val
+ }
+ err := ds.iterateKVPairsFromStore(key, kvObject, cb)
+ if err != nil {
+ return nil, err
+ }
return kvol, nil
}
diff --git a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go
index 98bc60ac9d..6e66ea221e 100644
--- a/vendor/github.com/docker/libnetwork/driverapi/driverapi.go
+++ b/vendor/github.com/docker/libnetwork/driverapi/driverapi.go
@@ -74,6 +74,9 @@ type Driver interface {
// Type returns the the type of this driver, the network type this driver manages
Type() string
+
+ // IsBuiltIn returns true if it is a built-in driver
+ IsBuiltIn() bool
}
// NetworkInfo provides a go interface for drivers to provide network
diff --git a/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go b/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go
index 2f69083f25..7e64f45da5 100644
--- a/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go
+++ b/vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go
@@ -57,7 +57,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
config: config,
}
- d.vxlanIdm, err = idm.New(nil, "vxlan-id", 1, vxlanIDEnd)
+ d.vxlanIdm, err = idm.New(nil, "vxlan-id", 0, vxlanIDEnd)
if err != nil {
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
}
@@ -164,7 +164,7 @@ func (n *network) obtainVxlanID(s *subnet) error {
n.Unlock()
if vni == 0 {
- vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd)
+ vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd, true)
if err != nil {
return err
}
@@ -229,6 +229,10 @@ func (d *driver) Type() string {
return networkType
}
+func (d *driver) IsBuiltIn() bool {
+ return true
+}
+
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
return types.NotImplementedErrorf("not implemented")
diff --git a/vendor/github.com/docker/libnetwork/drivers/remote/driver.go b/vendor/github.com/docker/libnetwork/drivers/remote/driver.go
index 04be60124f..f35a941f09 100644
--- a/vendor/github.com/docker/libnetwork/drivers/remote/driver.go
+++ b/vendor/github.com/docker/libnetwork/drivers/remote/driver.go
@@ -29,12 +29,7 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
// Init makes sure a remote driver is registered when a network driver
// plugin is activated.
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
- // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
- handleFunc := plugins.Handle
- if pg := dc.GetPluginGetter(); pg != nil {
- handleFunc = pg.Handle
- }
- handleFunc(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
+ newPluginHandler := func(name string, client *plugins.Client) {
// negotiate driver capability with client
d := newDriver(name, client)
c, err := d.(*driver).getCapabilities()
@@ -45,7 +40,19 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
if err = dc.RegisterDriver(name, d, *c); err != nil {
logrus.Errorf("error registering driver for %s due to %v", name, err)
}
- })
+ }
+
+ // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
+ handleFunc := plugins.Handle
+ if pg := dc.GetPluginGetter(); pg != nil {
+ handleFunc = pg.Handle
+ activePlugins := pg.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
+ for _, ap := range activePlugins {
+ newPluginHandler(ap.Name(), ap.Client())
+ }
+ }
+ handleFunc(driverapi.NetworkPluginEndpointType, newPluginHandler)
+
return nil
}
@@ -305,6 +312,10 @@ func (d *driver) Type() string {
return d.networkType
}
+func (d *driver) IsBuiltIn() bool {
+ return false
+}
+
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
if dType != discoverapi.NodeDiscovery {
diff --git a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go
index a9a7368025..a1cf88fc03 100644
--- a/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go
+++ b/vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go
@@ -164,10 +164,10 @@ func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capa
}
r.Lock()
- _, ok := r.drivers[ntype]
+ dd, ok := r.drivers[ntype]
r.Unlock()
- if ok {
+ if ok && dd.driver.IsBuiltIn() {
return driverapi.ErrActiveRegistration(ntype)
}
@@ -192,9 +192,9 @@ func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps
}
r.Lock()
- _, ok := r.ipamDrivers[name]
+ dd, ok := r.ipamDrivers[name]
r.Unlock()
- if ok {
+ if ok && dd.driver.IsBuiltIn() {
return types.ForbiddenErrorf("ipam driver %q already registered", name)
}
diff --git a/vendor/github.com/docker/libnetwork/idm/idm.go b/vendor/github.com/docker/libnetwork/idm/idm.go
index 84839c1c9b..83098e4f7e 100644
--- a/vendor/github.com/docker/libnetwork/idm/idm.go
+++ b/vendor/github.com/docker/libnetwork/idm/idm.go
@@ -15,7 +15,7 @@ type Idm struct {
handle *bitseq.Handle
}
-// New returns an instance of id manager for a set of [start-end] numerical ids
+// New returns an instance of id manager for a [start,end] set of numerical ids
func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) {
if id == "" {
return nil, fmt.Errorf("Invalid id")
@@ -33,11 +33,11 @@ func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) {
}
// GetID returns the first available id in the set
-func (i *Idm) GetID() (uint64, error) {
+func (i *Idm) GetID(serial bool) (uint64, error) {
if i.handle == nil {
return 0, fmt.Errorf("ID set is not initialized")
}
- ordinal, err := i.handle.SetAny()
+ ordinal, err := i.handle.SetAny(serial)
return i.start + ordinal, err
}
@@ -54,8 +54,8 @@ func (i *Idm) GetSpecificID(id uint64) error {
return i.handle.Set(id - i.start)
}
-// GetIDInRange returns the first available id in the set within a range
-func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) {
+// GetIDInRange returns the first available id in the set within a [start,end] range
+func (i *Idm) GetIDInRange(start, end uint64, serial bool) (uint64, error) {
if i.handle == nil {
return 0, fmt.Errorf("ID set is not initialized")
}
@@ -64,7 +64,9 @@ func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) {
return 0, fmt.Errorf("Requested range does not belong to the set")
}
- return i.handle.SetAnyInRange(start, end-start)
+ ordinal, err := i.handle.SetAnyInRange(start-i.start, end-i.start, serial)
+
+ return i.start + ordinal, err
}
// Release releases the specified id
diff --git a/vendor/github.com/docker/libnetwork/ipam/allocator.go b/vendor/github.com/docker/libnetwork/ipam/allocator.go
index 3d69bd9b4f..6a5e8c2f4f 100644
--- a/vendor/github.com/docker/libnetwork/ipam/allocator.go
+++ b/vendor/github.com/docker/libnetwork/ipam/allocator.go
@@ -413,7 +413,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error)
}
}
- return nil, types.NotFoundErrorf("could not find an available non-overlapping address pool among the defaults to auto assign to the network")
+ return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v)
}
// RequestAddress returns an address from the specified pool ID
@@ -457,7 +457,15 @@ func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s
return nil, nil, types.InternalErrorf("could not find bitmask in datastore for %s on address %v request from pool %s: %v",
k.String(), prefAddress, poolID, err)
}
- ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range)
+ // In order to request for a serial ip address allocation, callers can pass in the option to request
+ // IP allocation serially or first available IP in the subnet
+ var serial bool
+ if opts != nil {
+ if val, ok := opts[ipamapi.AllocSerialPrefix]; ok {
+ serial = (val == "true")
+ }
+ }
+ ip, err := a.getAddress(p.Pool, bm, prefAddress, p.Range, serial)
if err != nil {
return nil, nil, err
}
@@ -522,7 +530,7 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
return bm.Unset(ipToUint64(h))
}
-func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange) (net.IP, error) {
+func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange, serial bool) (net.IP, error) {
var (
ordinal uint64
err error
@@ -535,7 +543,7 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres
return nil, ipamapi.ErrNoAvailableIPs
}
if ipr == nil && prefAddress == nil {
- ordinal, err = bitmask.SetAny()
+ ordinal, err = bitmask.SetAny(serial)
} else if prefAddress != nil {
hostPart, e := types.GetHostPartIP(prefAddress, base.Mask)
if e != nil {
@@ -544,7 +552,7 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres
ordinal = ipToUint64(types.GetMinimalIP(hostPart))
err = bitmask.Set(ordinal)
} else {
- ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End)
+ ordinal, err = bitmask.SetAnyInRange(ipr.Start, ipr.End, serial)
}
switch err {
@@ -594,3 +602,8 @@ func (a *Allocator) DumpDatabase() string {
return s
}
+
+// IsBuiltIn returns true for builtin drivers
+func (a *Allocator) IsBuiltIn() bool {
+ return true
+}
diff --git a/vendor/github.com/docker/libnetwork/ipamapi/contract.go b/vendor/github.com/docker/libnetwork/ipamapi/contract.go
index 090205e11f..7f967863d8 100644
--- a/vendor/github.com/docker/libnetwork/ipamapi/contract.go
+++ b/vendor/github.com/docker/libnetwork/ipamapi/contract.go
@@ -80,6 +80,9 @@ type Ipam interface {
RequestAddress(string, net.IP, map[string]string) (*net.IPNet, map[string]string, error)
// Release the address from the specified pool ID
ReleaseAddress(string, net.IP) error
+
+ //IsBuiltIn returns true if it is a built-in driver.
+ IsBuiltIn() bool
}
// Capability represents the requirements and capabilities of the IPAM driver
diff --git a/vendor/github.com/docker/libnetwork/ipamapi/labels.go b/vendor/github.com/docker/libnetwork/ipamapi/labels.go
new file mode 100644
index 0000000000..e5c7d1cc7e
--- /dev/null
+++ b/vendor/github.com/docker/libnetwork/ipamapi/labels.go
@@ -0,0 +1,10 @@
+package ipamapi
+
+const (
+ // Prefix constant marks the reserved label space for libnetwork
+ Prefix = "com.docker.network"
+
+ // AllocSerialPrefix constant marks the reserved label space for libnetwork ipam
+ // allocation ordering.(serial/first available)
+ AllocSerialPrefix = Prefix + ".ipam.serial"
+)
diff --git a/vendor/github.com/docker/libnetwork/ipams/null/null.go b/vendor/github.com/docker/libnetwork/ipams/null/null.go
index 60119a36ab..339b5308d1 100644
--- a/vendor/github.com/docker/libnetwork/ipams/null/null.go
+++ b/vendor/github.com/docker/libnetwork/ipams/null/null.go
@@ -65,6 +65,10 @@ func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interfa
return nil
}
+func (a *allocator) IsBuiltIn() bool {
+ return true
+}
+
// Init registers a remote ipam when its plugin is activated
func Init(ic ipamapi.Callback, l, g interface{}) error {
return ic.RegisterIpamDriver(ipamapi.NullIPAM, &allocator{})
diff --git a/vendor/github.com/docker/libnetwork/ipams/remote/remote.go b/vendor/github.com/docker/libnetwork/ipams/remote/remote.go
index b23c52a6d0..d2e2b4f3c8 100644
--- a/vendor/github.com/docker/libnetwork/ipams/remote/remote.go
+++ b/vendor/github.com/docker/libnetwork/ipams/remote/remote.go
@@ -31,12 +31,7 @@ func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {
// Init registers a remote ipam when its plugin is activated
func Init(cb ipamapi.Callback, l, g interface{}) error {
- // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
- handleFunc := plugins.Handle
- if pg := cb.GetPluginGetter(); pg != nil {
- handleFunc = pg.Handle
- }
- handleFunc(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
+ newPluginHandler := func(name string, client *plugins.Client) {
a := newAllocator(name, client)
if cps, err := a.(*allocator).getCapabilities(); err == nil {
if err := cb.RegisterIpamDriverWithCapabilities(name, a, cps); err != nil {
@@ -49,7 +44,18 @@ func Init(cb ipamapi.Callback, l, g interface{}) error {
logrus.Errorf("error registering remote ipam driver %s due to %v", name, err)
}
}
- })
+ }
+
+ // Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
+ handleFunc := plugins.Handle
+ if pg := cb.GetPluginGetter(); pg != nil {
+ handleFunc = pg.Handle
+ activePlugins := pg.GetAllManagedPluginsByCap(ipamapi.PluginEndpointType)
+ for _, ap := range activePlugins {
+ newPluginHandler(ap.Name(), ap.Client())
+ }
+ }
+ handleFunc(ipamapi.PluginEndpointType, newPluginHandler)
return nil
}
@@ -143,3 +149,7 @@ func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
return nil
}
+
+func (a *allocator) IsBuiltIn() bool {
+ return false
+}
diff --git a/vendor/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go b/vendor/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go
index 1b9cd5a983..6b124d40d2 100644
--- a/vendor/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go
+++ b/vendor/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go
@@ -101,3 +101,7 @@ func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
return nil
}
+
+func (a *allocator) IsBuiltIn() bool {
+ return true
+}