docker's network disconnect api now supports `Force` option which can be
used to force cleanup an endpoint from any host in the cluster.
Signed-off-by: Madhu Venugopal <madhu@docker.com>
| ... | ... |
@@ -137,12 +137,13 @@ func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
| 137 | 137 |
// Usage: docker network disconnect <NETWORK> <CONTAINER> |
| 138 | 138 |
func (cli *DockerCli) CmdNetworkDisconnect(args ...string) error {
|
| 139 | 139 |
cmd := Cli.Subcmd("network disconnect", []string{"NETWORK CONTAINER"}, "Disconnects container from a network", false)
|
| 140 |
+ force := cmd.Bool([]string{"f", "-force"}, false, "Force the container to disconnect from a network")
|
|
| 140 | 141 |
cmd.Require(flag.Exact, 2) |
| 141 | 142 |
if err := cmd.ParseFlags(args, true); err != nil {
|
| 142 | 143 |
return err |
| 143 | 144 |
} |
| 144 | 145 |
|
| 145 |
- return cli.client.NetworkDisconnect(cmd.Arg(0), cmd.Arg(1), false) |
|
| 146 |
+ return cli.client.NetworkDisconnect(cmd.Arg(0), cmd.Arg(1), *force) |
|
| 146 | 147 |
} |
| 147 | 148 |
|
| 148 | 149 |
// CmdNetworkLs lists all the networks managed by docker daemon |
| ... | ... |
@@ -16,7 +16,7 @@ type Backend interface {
|
| 16 | 16 |
options map[string]string, internal bool) (libnetwork.Network, error) |
| 17 | 17 |
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error |
| 18 | 18 |
DisconnectContainerFromNetwork(containerName string, |
| 19 |
- network libnetwork.Network) error |
|
| 19 |
+ network libnetwork.Network, force bool) error |
|
| 20 | 20 |
NetworkControllerEnabled() bool |
| 21 | 21 |
DeleteNetwork(name string) error |
| 22 | 22 |
} |
| ... | ... |
@@ -144,7 +144,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon |
| 144 | 144 |
return err |
| 145 | 145 |
} |
| 146 | 146 |
|
| 147 |
- return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw) |
|
| 147 |
+ return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw, disconnect.Force) |
|
| 148 | 148 |
} |
| 149 | 149 |
|
| 150 | 150 |
func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| ... | ... |
@@ -833,8 +833,17 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName |
| 833 | 833 |
return nil |
| 834 | 834 |
} |
| 835 | 835 |
|
| 836 |
+// ForceEndpointDelete deletes an endpoing from a network forcefully |
|
| 837 |
+func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
|
|
| 838 |
+ ep, err := n.EndpointByName(name) |
|
| 839 |
+ if err != nil {
|
|
| 840 |
+ return err |
|
| 841 |
+ } |
|
| 842 |
+ return ep.Delete(true) |
|
| 843 |
+} |
|
| 844 |
+ |
|
| 836 | 845 |
// DisconnectFromNetwork disconnects container from network n. |
| 837 |
-func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network) error {
|
|
| 846 |
+func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
|
| 838 | 847 |
if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
|
| 839 | 848 |
return runconfig.ErrConflictHostNetwork |
| 840 | 849 |
} |
| ... | ... |
@@ -848,7 +857,7 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n li |
| 848 | 848 |
return fmt.Errorf("container %s is not connected to the network %s", container.ID, n.Name())
|
| 849 | 849 |
} |
| 850 | 850 |
} else {
|
| 851 |
- if err := disconnectFromNetwork(container, n); err != nil {
|
|
| 851 |
+ if err := disconnectFromNetwork(container, n, false); err != nil {
|
|
| 852 | 852 |
return err |
| 853 | 853 |
} |
| 854 | 854 |
} |
| ... | ... |
@@ -864,7 +873,7 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n li |
| 864 | 864 |
return nil |
| 865 | 865 |
} |
| 866 | 866 |
|
| 867 |
-func disconnectFromNetwork(container *container.Container, n libnetwork.Network) error {
|
|
| 867 |
+func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
|
| 868 | 868 |
var ( |
| 869 | 869 |
ep libnetwork.Endpoint |
| 870 | 870 |
sbox libnetwork.Sandbox |
| ... | ... |
@@ -886,6 +895,15 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network) |
| 886 | 886 |
} |
| 887 | 887 |
n.WalkEndpoints(s) |
| 888 | 888 |
|
| 889 |
+ if ep == nil && force {
|
|
| 890 |
+ epName := strings.TrimPrefix(container.Name, "/") |
|
| 891 |
+ ep, err := n.EndpointByName(epName) |
|
| 892 |
+ if err != nil {
|
|
| 893 |
+ return err |
|
| 894 |
+ } |
|
| 895 |
+ return ep.Delete(force) |
|
| 896 |
+ } |
|
| 897 |
+ |
|
| 889 | 898 |
if ep == nil {
|
| 890 | 899 |
return fmt.Errorf("container %s is not connected to the network", container.ID)
|
| 891 | 900 |
} |
| ... | ... |
@@ -32,8 +32,13 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName |
| 32 | 32 |
return nil |
| 33 | 33 |
} |
| 34 | 34 |
|
| 35 |
+// ForceEndpointDelete deletes an endpoing from a network forcefully |
|
| 36 |
+func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
|
|
| 37 |
+ return nil |
|
| 38 |
+} |
|
| 39 |
+ |
|
| 35 | 40 |
// DisconnectFromNetwork disconnects a container from the network. |
| 36 |
-func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network) error {
|
|
| 41 |
+func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
|
| 37 | 42 |
return nil |
| 38 | 43 |
} |
| 39 | 44 |
|
| ... | ... |
@@ -163,12 +163,15 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin |
| 163 | 163 |
|
| 164 | 164 |
// DisconnectContainerFromNetwork disconnects the given container from |
| 165 | 165 |
// the given network. If either cannot be found, an err is returned. |
| 166 |
-func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network) error {
|
|
| 166 |
+func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error {
|
|
| 167 | 167 |
container, err := daemon.GetContainer(containerName) |
| 168 | 168 |
if err != nil {
|
| 169 |
+ if force {
|
|
| 170 |
+ return daemon.ForceEndpointDelete(containerName, network) |
|
| 171 |
+ } |
|
| 169 | 172 |
return err |
| 170 | 173 |
} |
| 171 |
- return daemon.DisconnectFromNetwork(container, network) |
|
| 174 |
+ return daemon.DisconnectFromNetwork(container, network, force) |
|
| 172 | 175 |
} |
| 173 | 176 |
|
| 174 | 177 |
// GetNetworkDriverList returns the list of plugins drivers |
| ... | ... |
@@ -115,6 +115,7 @@ This section lists each version from latest to oldest. Each listing includes a |
| 115 | 115 |
* `POST /networks/(id)/connect` now allows you to set the static IPv4 and/or IPv6 address for the container. |
| 116 | 116 |
* `GET /info` now includes the number of containers running, stopped, and paused. |
| 117 | 117 |
* `POST /networks/create` now supports restricting external access to the network by setting the `internal` field. |
| 118 |
+* `POST /networks/(id)/disconnect` now includes a `Force` option to forcefully disconnect a container from network |
|
| 118 | 119 |
|
| 119 | 120 |
### v1.21 API changes |
| 120 | 121 |
|
| ... | ... |
@@ -3073,7 +3073,8 @@ POST /networks/22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30/ |
| 3073 | 3073 |
Content-Type: application/json |
| 3074 | 3074 |
|
| 3075 | 3075 |
{
|
| 3076 |
- "Container":"3613f73ba0e4" |
|
| 3076 |
+ "Container":"3613f73ba0e4", |
|
| 3077 |
+ "Force":false |
|
| 3077 | 3078 |
} |
| 3078 | 3079 |
``` |
| 3079 | 3080 |
|
| ... | ... |
@@ -3090,6 +3091,7 @@ Status Codes: |
| 3090 | 3090 |
JSON Parameters: |
| 3091 | 3091 |
|
| 3092 | 3092 |
- **Container** - container-id/name to be disconnected from a network |
| 3093 |
+- **Force** - Force the container to disconnect from a network |
|
| 3093 | 3094 |
|
| 3094 | 3095 |
### Remove a network |
| 3095 | 3096 |
|
| ... | ... |
@@ -12,8 +12,10 @@ parent = "smn_cli" |
| 12 | 12 |
|
| 13 | 13 |
Usage: docker network disconnect [OPTIONS] NETWORK CONTAINER |
| 14 | 14 |
|
| 15 |
+ |
|
| 15 | 16 |
Disconnects a container from a network |
| 16 | 17 |
|
| 18 |
+ -f, --force Force the container to disconnect from a network |
|
| 17 | 19 |
--help Print usage |
| 18 | 20 |
|
| 19 | 21 |
Disconnects a container from a network. The container must be running to disconnect it from the network. |
| ... | ... |
@@ -448,6 +448,22 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
|
| 448 | 448 |
c.Assert(nr.Name, checker.Equals, "test") |
| 449 | 449 |
c.Assert(len(nr.Containers), checker.Equals, 0) |
| 450 | 450 |
|
| 451 |
+ // run another container |
|
| 452 |
+ out, _ = dockerCmd(c, "run", "-d", "--net", "test", "--name", "test2", "busybox", "top") |
|
| 453 |
+ c.Assert(waitRun("test2"), check.IsNil)
|
|
| 454 |
+ containerID = strings.TrimSpace(out) |
|
| 455 |
+ |
|
| 456 |
+ nr = getNwResource(c, "test") |
|
| 457 |
+ c.Assert(nr.Name, checker.Equals, "test") |
|
| 458 |
+ c.Assert(len(nr.Containers), checker.Equals, 1) |
|
| 459 |
+ |
|
| 460 |
+ // force disconnect the container to the test network |
|
| 461 |
+ dockerCmd(c, "network", "disconnect", "-f", "test", containerID) |
|
| 462 |
+ |
|
| 463 |
+ nr = getNwResource(c, "test") |
|
| 464 |
+ c.Assert(nr.Name, checker.Equals, "test") |
|
| 465 |
+ c.Assert(len(nr.Containers), checker.Equals, 0) |
|
| 466 |
+ |
|
| 451 | 467 |
dockerCmd(c, "network", "rm", "test") |
| 452 | 468 |
assertNwNotAvailable(c, "test") |
| 453 | 469 |
} |
| ... | ... |
@@ -7,6 +7,7 @@ docker-network-disconnect - disconnect a container from a network |
| 7 | 7 |
# SYNOPSIS |
| 8 | 8 |
**docker network disconnect** |
| 9 | 9 |
[**--help**] |
| 10 |
+[**--force**] |
|
| 10 | 11 |
NETWORK CONTAINER |
| 11 | 12 |
|
| 12 | 13 |
# DESCRIPTION |
| ... | ... |
@@ -25,6 +26,9 @@ Disconnects a container from a network. |
| 25 | 25 |
**CONTAINER** |
| 26 | 26 |
Specify container name |
| 27 | 27 |
|
| 28 |
+**--force** |
|
| 29 |
+ Force the container to disconnect from a network |
|
| 30 |
+ |
|
| 28 | 31 |
**--help** |
| 29 | 32 |
Print usage statement |
| 30 | 33 |
|