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