github.com/damirazo/docker@v1.9.0/integration-cli/docker_cli_links_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/go-check/check"
    10  )
    11  
    12  func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) {
    13  	testRequires(c, DaemonIsLinux)
    14  	_, exitCode, err := dockerCmdWithError("run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
    15  
    16  	if exitCode == 0 {
    17  		c.Fatal("run ping did not fail")
    18  	} else if exitCode != 1 {
    19  		c.Fatalf("run ping failed with errors: %v", err)
    20  	}
    21  
    22  }
    23  
    24  // Test for appropriate error when calling --link with an invalid target container
    25  func (s *DockerSuite) TestLinksInvalidContainerTarget(c *check.C) {
    26  	testRequires(c, DaemonIsLinux)
    27  	out, _, err := dockerCmdWithError("run", "--link", "bogus:alias", "busybox", "true")
    28  
    29  	if err == nil {
    30  		c.Fatal("an invalid container target should produce an error")
    31  	}
    32  	if !strings.Contains(out, "Could not get container") {
    33  		c.Fatalf("error output expected 'Could not get container', but got %q instead; err: %v", out, err)
    34  	}
    35  
    36  }
    37  
    38  func (s *DockerSuite) TestLinksPingLinkedContainers(c *check.C) {
    39  	testRequires(c, DaemonIsLinux)
    40  	dockerCmd(c, "run", "-d", "--name", "container1", "--hostname", "fred", "busybox", "top")
    41  	dockerCmd(c, "run", "-d", "--name", "container2", "--hostname", "wilma", "busybox", "top")
    42  
    43  	runArgs := []string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c"}
    44  	pingCmd := "ping -c 1 %s -W 1 && ping -c 1 %s -W 1"
    45  
    46  	// test ping by alias, ping by name, and ping by hostname
    47  	// 1. Ping by alias
    48  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
    49  	// 2. Ping by container name
    50  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
    51  	// 3. Ping by hostname
    52  	dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
    53  
    54  }
    55  
    56  func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
    57  	testRequires(c, DaemonIsLinux)
    58  	out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
    59  	idA := strings.TrimSpace(out)
    60  	out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
    61  	idB := strings.TrimSpace(out)
    62  	dockerCmd(c, "rename", "container1", "container_new")
    63  	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")
    64  	dockerCmd(c, "kill", idA)
    65  	dockerCmd(c, "kill", idB)
    66  
    67  }
    68  
    69  func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
    70  	testRequires(c, DaemonIsLinux)
    71  	var (
    72  		expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
    73  		result   []string
    74  	)
    75  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
    76  	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
    77  	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
    78  	links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
    79  	if err != nil {
    80  		c.Fatal(err)
    81  	}
    82  
    83  	err = unmarshalJSON([]byte(links), &result)
    84  	if err != nil {
    85  		c.Fatal(err)
    86  	}
    87  
    88  	output := convertSliceOfStringsToMap(result)
    89  
    90  	equal := reflect.DeepEqual(output, expected)
    91  
    92  	if !equal {
    93  		c.Fatalf("Links %s, expected %s", result, expected)
    94  	}
    95  }
    96  
    97  func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
    98  	testRequires(c, DaemonIsLinux)
    99  	var (
   100  		expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
   101  		result   []string
   102  	)
   103  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
   104  	dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
   105  	dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
   106  	links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
   107  	if err != nil {
   108  		c.Fatal(err)
   109  	}
   110  
   111  	err = unmarshalJSON([]byte(links), &result)
   112  	if err != nil {
   113  		c.Fatal(err)
   114  	}
   115  
   116  	output := convertSliceOfStringsToMap(result)
   117  
   118  	equal := reflect.DeepEqual(output, expected)
   119  
   120  	if !equal {
   121  		c.Fatalf("Links %s, but expected %s", result, expected)
   122  	}
   123  
   124  }
   125  
   126  func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) {
   127  	testRequires(c, DaemonIsLinux)
   128  	dockerCmd(c, "create", "--name=first", "busybox", "top")
   129  	dockerCmd(c, "create", "--name=second", "--link=first:first", "busybox", "top")
   130  	dockerCmd(c, "start", "first")
   131  
   132  }
   133  
   134  func (s *DockerSuite) TestLinksHostsFilesInject(c *check.C) {
   135  	testRequires(c, DaemonIsLinux)
   136  	testRequires(c, SameHostDaemon, ExecSupport)
   137  
   138  	out, _ := dockerCmd(c, "run", "-itd", "--name", "one", "busybox", "top")
   139  	idOne := strings.TrimSpace(out)
   140  
   141  	out, _ = dockerCmd(c, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top")
   142  	idTwo := strings.TrimSpace(out)
   143  
   144  	c.Assert(waitRun(idTwo), check.IsNil)
   145  
   146  	contentOne, err := readContainerFileWithExec(idOne, "/etc/hosts")
   147  	if err != nil {
   148  		c.Fatal(err, string(contentOne))
   149  	}
   150  
   151  	contentTwo, err := readContainerFileWithExec(idTwo, "/etc/hosts")
   152  	if err != nil {
   153  		c.Fatal(err, string(contentTwo))
   154  	}
   155  
   156  	if !strings.Contains(string(contentTwo), "onetwo") {
   157  		c.Fatal("Host is not present in updated hosts file", string(contentTwo))
   158  	}
   159  
   160  }
   161  
   162  func (s *DockerSuite) TestLinksUpdateOnRestart(c *check.C) {
   163  	testRequires(c, DaemonIsLinux)
   164  	testRequires(c, SameHostDaemon, ExecSupport)
   165  	dockerCmd(c, "run", "-d", "--name", "one", "busybox", "top")
   166  	out, _ := dockerCmd(c, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top")
   167  	id := strings.TrimSpace(string(out))
   168  
   169  	realIP, err := inspectField("one", "NetworkSettings.Networks.bridge.IPAddress")
   170  	if err != nil {
   171  		c.Fatal(err)
   172  	}
   173  	content, err := readContainerFileWithExec(id, "/etc/hosts")
   174  	if err != nil {
   175  		c.Fatal(err, string(content))
   176  	}
   177  	getIP := func(hosts []byte, hostname string) string {
   178  		re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
   179  		matches := re.FindSubmatch(hosts)
   180  		if matches == nil {
   181  			c.Fatalf("Hostname %s have no matches in hosts", hostname)
   182  		}
   183  		return string(matches[1])
   184  	}
   185  	if ip := getIP(content, "one"); ip != realIP {
   186  		c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
   187  	}
   188  	if ip := getIP(content, "onetwo"); ip != realIP {
   189  		c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
   190  	}
   191  	dockerCmd(c, "restart", "one")
   192  	realIP, err = inspectField("one", "NetworkSettings.Networks.bridge.IPAddress")
   193  	c.Assert(err, check.IsNil)
   194  
   195  	content, err = readContainerFileWithExec(id, "/etc/hosts")
   196  	if err != nil {
   197  		c.Fatal(err, string(content))
   198  	}
   199  	if ip := getIP(content, "one"); ip != realIP {
   200  		c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
   201  	}
   202  	if ip := getIP(content, "onetwo"); ip != realIP {
   203  		c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
   204  	}
   205  }
   206  
   207  func (s *DockerSuite) TestLinksEnvs(c *check.C) {
   208  	testRequires(c, DaemonIsLinux)
   209  	dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top")
   210  	out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env")
   211  	if !strings.Contains(out, "FIRST_ENV_e1=\n") ||
   212  		!strings.Contains(out, "FIRST_ENV_e2=v2") ||
   213  		!strings.Contains(out, "FIRST_ENV_e3=v3=v3") {
   214  		c.Fatalf("Incorrect output: %s", out)
   215  	}
   216  }
   217  
   218  func (s *DockerSuite) TestLinkShortDefinition(c *check.C) {
   219  	testRequires(c, DaemonIsLinux)
   220  	out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top")
   221  
   222  	cid := strings.TrimSpace(out)
   223  	c.Assert(waitRun(cid), check.IsNil)
   224  
   225  	out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top")
   226  
   227  	cid2 := strings.TrimSpace(out)
   228  	c.Assert(waitRun(cid2), check.IsNil)
   229  
   230  	links, err := inspectFieldJSON(cid2, "HostConfig.Links")
   231  	c.Assert(err, check.IsNil)
   232  	c.Assert(links, check.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]")
   233  }
   234  
   235  func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
   236  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   237  	dockerCmd(c, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top")
   238  	out, _, err := dockerCmdWithError("run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true")
   239  	if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior") {
   240  		c.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
   241  	}
   242  }
   243  
   244  func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
   245  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   246  	out, _ := dockerCmd(c, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
   247  	if !strings.HasPrefix(out, "-") {
   248  		c.Errorf("/etc/hosts should be a regular file")
   249  	}
   250  }