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