integration-cli/docker_cli_links_test.go
53f38a14
 package main
 
 import (
fb42e847
 	"encoding/json"
606c71d4
 	"fmt"
 	"regexp"
d30e5149
 	"sort"
5579bec4
 	"strings"
ea3afdad
 
33968e6c
 	"github.com/docker/docker/integration-cli/checker"
74900edb
 	"github.com/docker/docker/runconfig"
ea3afdad
 	"github.com/go-check/check"
53f38a14
 )
 
dc944ea7
 func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
693ba98c
 	_, exitCode, err := dockerCmdWithError("run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
53f38a14
 
97b9223a
 	// run ping failed with error
 	c.Assert(exitCode, checker.Equals, 1, check.Commentf("error: %v", err))
53f38a14
 }
 
6217f294
 // Test for appropriate error when calling --link with an invalid target container
dc944ea7
 func (s *DockerSuite) TestLinksInvalidContainerTarget(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
693ba98c
 	out, _, err := dockerCmdWithError("run", "--link", "bogus:alias", "busybox", "true")
6217f294
 
97b9223a
 	// an invalid container target should produce an error
 	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
 	// an invalid container target should produce an error
ebcb7d6b
 	c.Assert(out, checker.Contains, "could not get container")
6217f294
 }
 
dc944ea7
 func (s *DockerSuite) TestLinksPingLinkedContainers(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
3a3f800f
 	// Test with the three different ways of specifying the default network on Linux
 	testLinkPingOnNetwork(c, "")
 	testLinkPingOnNetwork(c, "default")
 	testLinkPingOnNetwork(c, "bridge")
 }
 
 func testLinkPingOnNetwork(c *check.C, network string) {
 	var postArgs []string
 	if network != "" {
 		postArgs = append(postArgs, []string{"--net", network}...)
 	}
 	postArgs = append(postArgs, []string{"busybox", "top"}...)
 	runArgs1 := append([]string{"run", "-d", "--name", "container1", "--hostname", "fred"}, postArgs...)
 	runArgs2 := append([]string{"run", "-d", "--name", "container2", "--hostname", "wilma"}, postArgs...)
 
 	// Run the two named containers
 	dockerCmd(c, runArgs1...)
 	dockerCmd(c, runArgs2...)
 
 	postArgs = []string{}
 	if network != "" {
 		postArgs = append(postArgs, []string{"--net", network}...)
 	}
 	postArgs = append(postArgs, []string{"busybox", "sh", "-c"}...)
16aa64dc
 
3a3f800f
 	// Format a run for a container which links to the other two
 	runArgs := append([]string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2"}, postArgs...)
16aa64dc
 	pingCmd := "ping -c 1 %s -W 1 && ping -c 1 %s -W 1"
3c984a6d
 
16aa64dc
 	// test ping by alias, ping by name, and ping by hostname
 	// 1. Ping by alias
dc944ea7
 	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
16aa64dc
 	// 2. Ping by container name
dc944ea7
 	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
16aa64dc
 	// 3. Ping by hostname
dc944ea7
 	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
16aa64dc
 
3a3f800f
 	// Clean for next round
 	dockerCmd(c, "rm", "-f", "container1")
 	dockerCmd(c, "rm", "-f", "container2")
53f38a14
 }
7cc27b20
 
dc944ea7
 func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
dc944ea7
 	out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
475c6531
 	idA := strings.TrimSpace(out)
dc944ea7
 	out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
475c6531
 	idB := strings.TrimSpace(out)
dc944ea7
 	dockerCmd(c, "rename", "container1", "container_new")
 	dockerCmd(c, "run", "--rm", "--link", "container_new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
 	dockerCmd(c, "kill", idA)
 	dockerCmd(c, "kill", idB)
21a809d9
 
 }
 
dc944ea7
 func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
dc944ea7
 	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
 	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
 	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
62a856e9
 	links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
68bb56a4
 
d30e5149
 	var result []string
fb42e847
 	err := json.Unmarshal([]byte(links), &result)
97b9223a
 	c.Assert(err, checker.IsNil)
68bb56a4
 
d30e5149
 	var expected = []string{
 		"/container1:/testinspectlink/alias1",
 		"/container2:/testinspectlink/alias2",
 	}
 	sort.Strings(result)
 	c.Assert(result, checker.DeepEquals, expected)
08182da5
 }
 
dc944ea7
 func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
d30e5149
 
dc944ea7
 	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
 	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
 	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
62a856e9
 	links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
d0cbc54f
 
d30e5149
 	var result []string
fb42e847
 	err := json.Unmarshal([]byte(links), &result)
97b9223a
 	c.Assert(err, checker.IsNil)
d0cbc54f
 
d30e5149
 	var expected = []string{
 		"/container1:/testinspectlink/alias1",
 		"/container2:/testinspectlink/alias2",
 	}
 	sort.Strings(result)
 	c.Assert(result, checker.DeepEquals, expected)
08182da5
 }
b83fc07d
 
dc944ea7
 func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
eef6eda7
 	dockerCmd(c, "create", "--name=first", "busybox", "top")
 	dockerCmd(c, "create", "--name=second", "--link=first:first", "busybox", "top")
 	dockerCmd(c, "start", "first")
 
b83fc07d
 }
68bc8de1
 
dc944ea7
 func (s *DockerSuite) TestLinksHostsFilesInject(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
dc944ea7
 	testRequires(c, SameHostDaemon, ExecSupport)
68bc8de1
 
eef6eda7
 	out, _ := dockerCmd(c, "run", "-itd", "--name", "one", "busybox", "top")
68bc8de1
 	idOne := strings.TrimSpace(out)
 
eef6eda7
 	out, _ = dockerCmd(c, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top")
68bc8de1
 	idTwo := strings.TrimSpace(out)
 
97b9223a
 	c.Assert(waitRun(idTwo), checker.IsNil)
68bc8de1
 
ecbb0e62
 	readContainerFileWithExec(c, idOne, "/etc/hosts")
 	contentTwo := readContainerFileWithExec(c, idTwo, "/etc/hosts")
97b9223a
 	// Host is not present in updated hosts file
 	c.Assert(string(contentTwo), checker.Contains, "onetwo")
68bc8de1
 }
6743be44
 
dc944ea7
 func (s *DockerSuite) TestLinksUpdateOnRestart(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
dc944ea7
 	testRequires(c, SameHostDaemon, ExecSupport)
eef6eda7
 	dockerCmd(c, "run", "-d", "--name", "one", "busybox", "top")
 	out, _ := dockerCmd(c, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top")
606c71d4
 	id := strings.TrimSpace(string(out))
 
62a856e9
 	realIP := inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
ecbb0e62
 	content := readContainerFileWithExec(c, id, "/etc/hosts")
97b9223a
 
606c71d4
 	getIP := func(hosts []byte, hostname string) string {
 		re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
 		matches := re.FindSubmatch(hosts)
97b9223a
 		c.Assert(matches, checker.NotNil, check.Commentf("Hostname %s have no matches in hosts", hostname))
606c71d4
 		return string(matches[1])
 	}
97b9223a
 	ip := getIP(content, "one")
 	c.Assert(ip, checker.Equals, realIP)
 
 	ip = getIP(content, "onetwo")
 	c.Assert(ip, checker.Equals, realIP)
 
eef6eda7
 	dockerCmd(c, "restart", "one")
62a856e9
 	realIP = inspectField(c, "one", "NetworkSettings.Networks.bridge.IPAddress")
97b9223a
 
ecbb0e62
 	content = readContainerFileWithExec(c, id, "/etc/hosts")
97b9223a
 	ip = getIP(content, "one")
 	c.Assert(ip, checker.Equals, realIP)
 
 	ip = getIP(content, "onetwo")
 	c.Assert(ip, checker.Equals, realIP)
606c71d4
 }
bc149be6
 
 func (s *DockerSuite) TestLinksEnvs(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
eef6eda7
 	dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top")
 	out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env")
97b9223a
 	c.Assert(out, checker.Contains, "FIRST_ENV_e1=\n")
 	c.Assert(out, checker.Contains, "FIRST_ENV_e2=v2")
 	c.Assert(out, checker.Contains, "FIRST_ENV_e3=v3=v3")
bc149be6
 }
c6e6223e
 
 func (s *DockerSuite) TestLinkShortDefinition(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
eef6eda7
 	out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top")
c6e6223e
 
 	cid := strings.TrimSpace(out)
97b9223a
 	c.Assert(waitRun(cid), checker.IsNil)
c6e6223e
 
eef6eda7
 	out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top")
c6e6223e
 
 	cid2 := strings.TrimSpace(out)
97b9223a
 	c.Assert(waitRun(cid2), checker.IsNil)
c6e6223e
 
62a856e9
 	links := inspectFieldJSON(c, cid2, "HostConfig.Links")
97b9223a
 	c.Assert(links, checker.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]")
c6e6223e
 }
4fccf8ad
 
 func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
ea3afdad
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
4fccf8ad
 	dockerCmd(c, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top")
 	out, _, err := dockerCmdWithError("run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true")
97b9223a
 
 	// Running container linking to a container with --net host should have failed
 	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
 	// Running container linking to a container with --net host should have failed
74900edb
 	c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetworkAndLinks.Error())
4fccf8ad
 }
 
 func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
ea3afdad
 	testRequires(c, DaemonIsLinux, NotUserNamespace)
4fccf8ad
 	out, _ := dockerCmd(c, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
97b9223a
 	// /etc/hosts should be a regular file
 	c.Assert(out, checker.Matches, "^-.+\n")
4fccf8ad
 }
332d95fd
 
 func (s *DockerSuite) TestLinksMultipleWithSameName(c *check.C) {
473a32ba
 	testRequires(c, DaemonIsLinux)
332d95fd
 	dockerCmd(c, "run", "-d", "--name=upstream-a", "busybox", "top")
 	dockerCmd(c, "run", "-d", "--name=upstream-b", "busybox", "top")
 	dockerCmd(c, "run", "--link", "upstream-a:upstream", "--link", "upstream-b:upstream", "busybox", "sh", "-c", "ping -c 1 upstream")
 }