github.com/tsuna/docker@v1.7.0-rc3/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 }