github.com/jandre/docker@v1.7.0/integration-cli/docker_cli_links_test.go (about)

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