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