github.com/iamlotus/docker@v1.8.1/integration-cli/docker_cli_links_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "github.com/go-check/check" 6 "reflect" 7 "regexp" 8 "strings" 9 "time" 10 ) 11 12 func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) { 13 14 _, exitCode, err := dockerCmdWithError(c, "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 27 out, _, err := dockerCmdWithError(c, "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 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 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 var ( 71 expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}} 72 result []string 73 ) 74 dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top") 75 dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top") 76 dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top") 77 links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links") 78 if err != nil { 79 c.Fatal(err) 80 } 81 82 err = unmarshalJSON([]byte(links), &result) 83 if err != nil { 84 c.Fatal(err) 85 } 86 87 output := convertSliceOfStringsToMap(result) 88 89 equal := reflect.DeepEqual(output, expected) 90 91 if !equal { 92 c.Fatalf("Links %s, expected %s", result, expected) 93 } 94 } 95 96 func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) { 97 var ( 98 expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}} 99 result []string 100 ) 101 dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top") 102 dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top") 103 dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true") 104 links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links") 105 if err != nil { 106 c.Fatal(err) 107 } 108 109 err = unmarshalJSON([]byte(links), &result) 110 if err != nil { 111 c.Fatal(err) 112 } 113 114 output := convertSliceOfStringsToMap(result) 115 116 equal := reflect.DeepEqual(output, expected) 117 118 if !equal { 119 c.Fatalf("Links %s, but expected %s", result, expected) 120 } 121 122 } 123 124 func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) { 125 126 dockerCmd(c, "create", "--name=first", "busybox", "top") 127 dockerCmd(c, "create", "--name=second", "--link=first:first", "busybox", "top") 128 dockerCmd(c, "start", "first") 129 130 } 131 132 func (s *DockerSuite) TestLinksHostsFilesInject(c *check.C) { 133 testRequires(c, SameHostDaemon, ExecSupport) 134 135 out, _ := dockerCmd(c, "run", "-itd", "--name", "one", "busybox", "top") 136 idOne := strings.TrimSpace(out) 137 138 out, _ = dockerCmd(c, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top") 139 idTwo := strings.TrimSpace(out) 140 141 time.Sleep(1 * time.Second) 142 143 contentOne, err := readContainerFileWithExec(idOne, "/etc/hosts") 144 if err != nil { 145 c.Fatal(err, string(contentOne)) 146 } 147 148 contentTwo, err := readContainerFileWithExec(idTwo, "/etc/hosts") 149 if err != nil { 150 c.Fatal(err, string(contentTwo)) 151 } 152 153 if !strings.Contains(string(contentTwo), "onetwo") { 154 c.Fatal("Host is not present in updated hosts file", string(contentTwo)) 155 } 156 157 } 158 159 func (s *DockerSuite) TestLinksUpdateOnRestart(c *check.C) { 160 testRequires(c, SameHostDaemon, ExecSupport) 161 dockerCmd(c, "run", "-d", "--name", "one", "busybox", "top") 162 out, _ := dockerCmd(c, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top") 163 id := strings.TrimSpace(string(out)) 164 165 realIP, err := inspectField("one", "NetworkSettings.IPAddress") 166 if err != nil { 167 c.Fatal(err) 168 } 169 content, err := readContainerFileWithExec(id, "/etc/hosts") 170 if err != nil { 171 c.Fatal(err, string(content)) 172 } 173 getIP := func(hosts []byte, hostname string) string { 174 re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname))) 175 matches := re.FindSubmatch(hosts) 176 if matches == nil { 177 c.Fatalf("Hostname %s have no matches in hosts", hostname) 178 } 179 return string(matches[1]) 180 } 181 if ip := getIP(content, "one"); ip != realIP { 182 c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip) 183 } 184 if ip := getIP(content, "onetwo"); ip != realIP { 185 c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip) 186 } 187 dockerCmd(c, "restart", "one") 188 realIP, err = inspectField("one", "NetworkSettings.IPAddress") 189 if err != nil { 190 c.Fatal(err) 191 } 192 content, err = readContainerFileWithExec(id, "/etc/hosts") 193 if err != nil { 194 c.Fatal(err, string(content)) 195 } 196 if ip := getIP(content, "one"); ip != realIP { 197 c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip) 198 } 199 if ip := getIP(content, "onetwo"); ip != realIP { 200 c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip) 201 } 202 } 203 204 func (s *DockerSuite) TestLinksEnvs(c *check.C) { 205 dockerCmd(c, "run", "-d", "-e", "e1=", "-e", "e2=v2", "-e", "e3=v3=v3", "--name=first", "busybox", "top") 206 out, _ := dockerCmd(c, "run", "--name=second", "--link=first:first", "busybox", "env") 207 if !strings.Contains(out, "FIRST_ENV_e1=\n") || 208 !strings.Contains(out, "FIRST_ENV_e2=v2") || 209 !strings.Contains(out, "FIRST_ENV_e3=v3=v3") { 210 c.Fatalf("Incorrect output: %s", out) 211 } 212 } 213 214 func (s *DockerSuite) TestLinkShortDefinition(c *check.C) { 215 out, _ := dockerCmd(c, "run", "-d", "--name", "shortlinkdef", "busybox", "top") 216 217 cid := strings.TrimSpace(out) 218 c.Assert(waitRun(cid), check.IsNil) 219 220 out, _ = dockerCmd(c, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top") 221 222 cid2 := strings.TrimSpace(out) 223 c.Assert(waitRun(cid2), check.IsNil) 224 225 links, err := inspectFieldJSON(cid2, "HostConfig.Links") 226 c.Assert(err, check.IsNil) 227 c.Assert(links, check.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]") 228 }