From 3f6e3a0885124a00c7f915af8f9181e6a275d828 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Mon, 27 Jun 2016 18:48:11 -0700 Subject: [PATCH] Fix docker rename with linked containers This fix tries to address issue raised in #23973 where the `docker rename` does not update namedIndex and linkIndex, thus resulting in failures when the linked containers are referenced later on. This fix updates the namedIndex and linkIndex during the `docker rename` and fixes the issue. An integration test has been added to cover the changes in this fix. This fix fixes #23973. Signed-off-by: Yong Tang --- daemon/rename.go | 24 +++++++++++++++++++++++ integration-cli/docker_cli_rename_test.go | 12 ++++++++++++ 2 files changed, 36 insertions(+) diff --git a/daemon/rename.go b/daemon/rename.go index e92dfda861..ffb7715f23 100644 --- a/daemon/rename.go +++ b/daemon/rename.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/Sirupsen/logrus" + dockercontainer "github.com/docker/docker/container" "github.com/docker/libnetwork" ) @@ -40,10 +41,23 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { container.Lock() defer container.Unlock() + links := map[string]*dockercontainer.Container{} + for k, v := range daemon.linkIndex.children(container) { + if !strings.HasPrefix(k, oldName) { + return fmt.Errorf("Linked container %s does not match parent %s", k, oldName) + } + links[strings.TrimPrefix(k, oldName)] = v + } + if newName, err = daemon.reserveName(container.ID, newName); err != nil { return fmt.Errorf("Error when allocating new name: %v", err) } + for k, v := range links { + daemon.nameIndex.Reserve(newName+k, v.ID) + daemon.linkIndex.link(container, v, newName+k) + } + container.Name = newName container.NetworkSettings.IsAnonymousEndpoint = false @@ -52,10 +66,20 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { container.Name = oldName container.NetworkSettings.IsAnonymousEndpoint = oldIsAnonymousEndpoint daemon.reserveName(container.ID, oldName) + for k, v := range links { + daemon.nameIndex.Reserve(oldName+k, v.ID) + daemon.linkIndex.link(container, v, oldName+k) + daemon.linkIndex.unlink(newName+k, v, container) + daemon.nameIndex.Release(newName + k) + } daemon.releaseName(newName) } }() + for k, v := range links { + daemon.linkIndex.unlink(oldName+k, v, container) + daemon.nameIndex.Release(oldName + k) + } daemon.releaseName(oldName) if err = container.ToDisk(); err != nil { return err diff --git a/integration-cli/docker_cli_rename_test.go b/integration-cli/docker_cli_rename_test.go index 6d61c08cf6..1ba620a5e1 100644 --- a/integration-cli/docker_cli_rename_test.go +++ b/integration-cli/docker_cli_rename_test.go @@ -121,3 +121,15 @@ func (s *DockerSuite) TestRenameContainerWithSameName(c *check.C) { c.Assert(err, checker.NotNil, check.Commentf("Renaming a container with the same name should have failed")) c.Assert(out, checker.Contains, "Renaming a container with the same name", check.Commentf("%v", err)) } + +// Test case for #23973 +func (s *DockerSuite) TestRenameContainerWithLinkedContainer(c *check.C) { + testRequires(c, DaemonIsLinux) + + db1, _ := dockerCmd(c, "run", "--name", "db1", "-d", "busybox", "top") + dockerCmd(c, "run", "--name", "app1", "-d", "--link", "db1:/mysql", "busybox", "top") + dockerCmd(c, "rename", "app1", "app2") + out, _, err := dockerCmdWithError("inspect", "--format='{{ .Id }}'", "app2/mysql") + c.Assert(err, checker.IsNil) + c.Assert(strings.TrimSpace(out), checker.Equals, strings.TrimSpace(db1)) +}