github.com/goern/docker@v1.9.0-rc1/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.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.IPAddress") 193 if err != nil { 194 c.Fatal(err) 195 } 196 content, err = readContainerFileWithExec(id, "/etc/hosts") 197 if err != nil { 198 c.Fatal(err, string(content)) 199 } 200 if ip := getIP(content, "one"); ip != realIP { 201 c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip) 202 } 203 if ip := getIP(content, "onetwo"); ip != realIP { 204 c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip) 205 } 206 } 207 208 func (s *DockerSuite) TestLinksEnvs(c *check.C) { 209 testRequires(c, DaemonIsLinux) 210 dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top") 211 out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env") 212 if !strings.Contains(out, "FIRST_ENV_e1=\n") || 213 !strings.Contains(out, "FIRST_ENV_e2=v2") || 214 !strings.Contains(out, "FIRST_ENV_e3=v3=v3") { 215 c.Fatalf("Incorrect output: %s", out) 216 } 217 } 218 219 func (s *DockerSuite) TestLinkShortDefinition(c *check.C) { 220 testRequires(c, DaemonIsLinux) 221 out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top") 222 223 cid := strings.TrimSpace(out) 224 c.Assert(waitRun(cid), check.IsNil) 225 226 out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top") 227 228 cid2 := strings.TrimSpace(out) 229 c.Assert(waitRun(cid2), check.IsNil) 230 231 links, err := inspectFieldJSON(cid2, "HostConfig.Links") 232 c.Assert(err, check.IsNil) 233 c.Assert(links, check.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]") 234 } 235 236 func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) { 237 testRequires(c, DaemonIsLinux, NotUserNamespace) 238 dockerCmd(c, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top") 239 out, _, err := dockerCmdWithError("run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true") 240 if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior") { 241 c.Fatalf("Running container linking to a container with --net host should have failed: %s", out) 242 } 243 } 244 245 func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) { 246 testRequires(c, DaemonIsLinux, NotUserNamespace) 247 out, _ := dockerCmd(c, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts") 248 if !strings.HasPrefix(out, "-") { 249 c.Errorf("/etc/hosts should be a regular file") 250 } 251 }