Skip to content

Commit 43544cf

Browse files
authored
Merge pull request moby#30157 from aboch/att
Remove attachable network on swarm leave
2 parents 93e322f + 3cedca5 commit 43544cf

File tree

5 files changed

+75
-5
lines changed

5 files changed

+75
-5
lines changed

daemon/cluster/cluster.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func (c *Cluster) newNodeRunner(conf nodeStartConfig) (*nodeRunner, error) {
244244
return nil, err
245245
}
246246

247-
c.config.Backend.SetClusterProvider(c)
247+
c.config.Backend.DaemonJoinsCluster(c)
248248

249249
return nr, nil
250250
}
@@ -562,7 +562,7 @@ func (c *Cluster) Leave(force bool) error {
562562
if err := clearPersistentState(c.root); err != nil {
563563
return err
564564
}
565-
c.config.Backend.SetClusterProvider(nil)
565+
c.config.Backend.DaemonLeavesCluster()
566566
return nil
567567
}
568568

daemon/cluster/executor/backend.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ type Backend interface {
4747
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
4848
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
4949
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
50-
SetClusterProvider(provider cluster.Provider)
50+
DaemonJoinsCluster(provider cluster.Provider)
51+
DaemonLeavesCluster()
5152
IsSwarmCompatible() error
5253
SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{})
5354
UnsubscribeFromEvents(listener chan interface{})

daemon/daemon.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,22 @@ func (daemon *Daemon) registerLink(parent, child *container.Container, alias str
433433
return nil
434434
}
435435

436-
// SetClusterProvider sets a component for querying the current cluster state.
437-
func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) {
436+
// DaemonJoinsCluster informs the daemon has joined the cluster and provides
437+
// the handler to query the cluster component
438+
func (daemon *Daemon) DaemonJoinsCluster(clusterProvider cluster.Provider) {
439+
daemon.setClusterProvider(clusterProvider)
440+
}
441+
442+
// DaemonLeavesCluster informs the daemon has left the cluster
443+
func (daemon *Daemon) DaemonLeavesCluster() {
444+
// Daemon is in charge of removing the attachable networks with
445+
// connected containers when the node leaves the swarm
446+
daemon.clearAttachableNetworks()
447+
daemon.setClusterProvider(nil)
448+
}
449+
450+
// setClusterProvider sets a component for querying the current cluster state.
451+
func (daemon *Daemon) setClusterProvider(clusterProvider cluster.Provider) {
438452
daemon.clusterProvider = clusterProvider
439453
daemon.netController.SetClusterProvider(clusterProvider)
440454
}

daemon/network.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,31 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
468468
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
469469
return daemon.getAllNetworks()
470470
}
471+
472+
// clearAttachableNetworks removes the attachable networks
473+
// after disconnecting any connected container
474+
func (daemon *Daemon) clearAttachableNetworks() {
475+
for _, n := range daemon.GetNetworks() {
476+
if !n.Info().Attachable() {
477+
continue
478+
}
479+
for _, ep := range n.Endpoints() {
480+
epInfo := ep.Info()
481+
if epInfo == nil {
482+
continue
483+
}
484+
sb := epInfo.Sandbox()
485+
if sb == nil {
486+
continue
487+
}
488+
containerID := sb.ContainerID()
489+
if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil {
490+
logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v",
491+
containerID, n.Name(), err)
492+
}
493+
}
494+
if err := daemon.DeleteManagedNetwork(n.ID()); err != nil {
495+
logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err)
496+
}
497+
}
498+
}

integration-cli/docker_cli_swarm_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,33 @@ func (s *DockerSwarmSuite) TestOverlayAttachable(c *check.C) {
358358
c.Assert(strings.TrimSpace(out), checker.Equals, "true")
359359
}
360360

361+
func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *check.C) {
362+
d := s.AddDaemon(c, true, true)
363+
364+
// Create an attachable swarm network
365+
nwName := "attovl"
366+
out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", nwName)
367+
c.Assert(err, checker.IsNil, check.Commentf(out))
368+
369+
// Connect a container to the network
370+
out, err = d.Cmd("run", "-d", "--network", nwName, "--name", "c1", "busybox", "top")
371+
c.Assert(err, checker.IsNil, check.Commentf(out))
372+
373+
// Leave the swarm
374+
err = d.Leave(true)
375+
c.Assert(err, checker.IsNil)
376+
377+
// Check the container is disconnected
378+
out, err = d.Cmd("inspect", "c1", "--format", "{{.NetworkSettings.Networks."+nwName+"}}")
379+
c.Assert(err, checker.IsNil)
380+
c.Assert(strings.TrimSpace(out), checker.Equals, "<no value>")
381+
382+
// Check the network is gone
383+
out, err = d.Cmd("network", "ls", "--format", "{{.Name}}")
384+
c.Assert(err, checker.IsNil)
385+
c.Assert(out, checker.Not(checker.Contains), nwName)
386+
}
387+
361388
func (s *DockerSwarmSuite) TestSwarmRemoveInternalNetwork(c *check.C) {
362389
d := s.AddDaemon(c, true, true)
363390

0 commit comments

Comments
 (0)