diff --git a/daemon/daemon.go b/daemon/daemon.go index 70f4a7b21b576757655c7817a3d8592b10b8ee11..e64da1cde99ad8a97ec0ffa977e06b8f028f03c0 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -686,14 +686,14 @@ func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error { if hostConfig != nil && hostConfig.Links != nil { for _, l := range hostConfig.Links { - parts, err := parsers.PartParser("name:alias", l) + name, alias, err := parsers.ParseLink(l) if err != nil { return err } - child, err := daemon.Get(parts["name"]) + child, err := daemon.Get(name) if err != nil { //An error from daemon.Get() means this name could not be found - return fmt.Errorf("Could not get container for %s", parts["name"]) + return fmt.Errorf("Could not get container for %s", name) } for child.hostConfig.NetworkMode.IsContainer() { parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2) @@ -705,7 +705,7 @@ func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig. if child.hostConfig.NetworkMode.IsHost() { return runconfig.ErrConflictHostNetworkAndLinks } - if err := daemon.RegisterLink(container, child, parts["alias"]); err != nil { + if err := daemon.RegisterLink(container, child, alias); err != nil { return err } } diff --git a/docs/man/docker-create.1.md b/docs/man/docker-create.1.md index 18a6f870dc7c9b1d921d29d34b10f74b985b1d17..02958e55eddb5bd65ccf77fd9856b70a8be28a18 100644 --- a/docs/man/docker-create.1.md +++ b/docs/man/docker-create.1.md @@ -137,7 +137,8 @@ two memory nodes. Read labels from a file. Delimit each label with an EOL. **--link**=[] - Add link to another container in the form of :alias + Add link to another container in the form of :alias or just + in which case the alias will match the name. **--lxc-conf**=[] (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" diff --git a/docs/man/docker-run.1.md b/docs/man/docker-run.1.md index 6e533ec6f24f2463124f612e41f78f6ad2e1788d..57bda2b65b1aa614d75f0cfb836789e0cd560ff2 100644 --- a/docs/man/docker-run.1.md +++ b/docs/man/docker-run.1.md @@ -238,7 +238,8 @@ ENTRYPOINT. Read in a line delimited file of labels **--link**=[] - Add link to another container in the form of :alias + Add link to another container in the form of :alias or just +in which case the alias will match the name If the operator uses **--link** when starting the new client container, then the client diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 30e2f80d0bd53818d5928c9b542bd09721a9e858..c0a88fb73756969d5d083affaf6dd1726bf2fad8 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -2138,6 +2138,12 @@ Guide. The `--link` flag will link the container named `/redis` into the newly created container with the alias `redis`. The new container can access the network and environment of the `redis` container via environment variables. +The `--link` flag will also just accept the form `` in which case +the alias will match the name. For instance, you could have written the previous +example as: + + $ docker run --link redis --name console ubuntu bash + The `--name` flag will assign the name `console` to the newly created container. diff --git a/docs/sources/reference/run.md b/docs/sources/reference/run.md index aafa34dfc8dc983a32bb7b5533885cb5b45c2bf8..fdc905fe44fa494ca07cefd21151143464532417 100644 --- a/docs/sources/reference/run.md +++ b/docs/sources/reference/run.md @@ -942,7 +942,7 @@ or override the Dockerfile's exposed defaults: Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. (e.g., `-p 1234-1236:1234-1236/tcp`) (use 'docker port' to see the actual mapping) - --link="" : Add link to another container (:alias) + --link="" : Add link to another container (:alias or ) As mentioned previously, `EXPOSE` (and `--expose`) makes ports available **in** a container for incoming connections. The port number on the diff --git a/docs/sources/userguide/dockerlinks.md b/docs/sources/userguide/dockerlinks.md index 8a20388463cfdda9c6c9cf6bfff119f4ba600b85..2b7d30cd44fba60a02cbc49955891da22107ed84 100644 --- a/docs/sources/userguide/dockerlinks.md +++ b/docs/sources/userguide/dockerlinks.md @@ -114,7 +114,7 @@ You can also use `docker inspect` to return the container's name. $ docker inspect -f "{{ .Name }}" aed84ee21bde /web -> **Note:** +> **Note:** > Container names have to be unique. That means you can only call > one container `web`. If you want to re-use a container name you must delete > the old container (with `docker rm`) before you can create a new @@ -151,6 +151,14 @@ earlier. The `--link` flag takes the form: Where `name` is the name of the container we're linking to and `alias` is an alias for the link name. You'll see how that alias gets used shortly. +The `--link` flag also takes the form: + + --link + +In which case the alias will match the name. You could have written the previous +example as: + + $ docker run -d -P --name web --link db training/webapp python app.py Next, inspect your linked containers with `docker inspect`: diff --git a/integration-cli/docker_cli_links_test.go b/integration-cli/docker_cli_links_test.go index 6bb173c10cc2000fd65b97de9dff9ba9ef21d0ca..56932163eac5fb8b4e78e13c11758a4151075493 100644 --- a/integration-cli/docker_cli_links_test.go +++ b/integration-cli/docker_cli_links_test.go @@ -15,7 +15,6 @@ import ( ) func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) { - runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts") out, _, _, err := runCommandWithStdoutStderr(runCmd) if err != nil { @@ -331,3 +330,23 @@ func (s *DockerSuite) TestLinksEnvs(c *check.C) { c.Fatalf("Incorrect output: %s", out) } } + +func (s *DockerSuite) TestLinkShortDefinition(c *check.C) { + runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "shortlinkdef", "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + c.Assert(err, check.IsNil) + + cid := strings.TrimSpace(out) + c.Assert(waitRun(cid), check.IsNil) + + runCmd = exec.Command(dockerBinary, "run", "-d", "--name", "link2", "--link", "shortlinkdef", "busybox", "top") + out, _, err = runCommandWithOutput(runCmd) + c.Assert(err, check.IsNil) + + cid2 := strings.TrimSpace(out) + c.Assert(waitRun(cid2), check.IsNil) + + links, err := inspectFieldJSON(cid2, "HostConfig.Links") + c.Assert(err, check.IsNil) + c.Assert(links, check.Equals, "[\"/shortlinkdef:/link2/shortlinkdef\"]") +} diff --git a/opts/opts.go b/opts/opts.go index 3801596631649c869e4c25741403c5b3267329a9..c330c27a5de72a0fb2badd277b502bfb7fe00820 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -196,7 +196,7 @@ func ValidateAttach(val string) (string, error) { } func ValidateLink(val string) (string, error) { - if _, err := parsers.PartParser("name:alias", val); err != nil { + if _, _, err := parsers.ParseLink(val); err != nil { return val, err } return val, nil diff --git a/pkg/parsers/parsers.go b/pkg/parsers/parsers.go index 59e294dc2255b42cb68da93d4ccd0cd685db7760..5049613ac5f6e325bb13852c59f58fe9c5eac791 100644 --- a/pkg/parsers/parsers.go +++ b/pkg/parsers/parsers.go @@ -135,3 +135,17 @@ func ParsePortRange(ports string) (uint64, uint64, error) { } return start, end, nil } + +func ParseLink(val string) (string, string, error) { + if val == "" { + return "", "", fmt.Errorf("empty string specified for links") + } + arr := strings.Split(val, ":") + if len(arr) > 2 { + return "", "", fmt.Errorf("bad format for links: %s", val) + } + if len(arr) == 1 { + return val, val, nil + } + return arr[0], arr[1], nil +} diff --git a/pkg/parsers/parsers_test.go b/pkg/parsers/parsers_test.go index bc9a1e943c2ed4bcb263e34b1c6e58f4c9640889..89f4ae023aeed3f686aafd3a7f8e326e369ec762 100644 --- a/pkg/parsers/parsers_test.go +++ b/pkg/parsers/parsers_test.go @@ -123,3 +123,35 @@ func TestParsePortRangeIncorrectStartRange(t *testing.T) { t.Fatalf("Expecting error 'Invalid range specified for the Port' but received %s.", err) } } + +func TestParseLink(t *testing.T) { + name, alias, err := ParseLink("name:alias") + if err != nil { + t.Fatalf("Expected not to error out on a valid name:alias format but got: %v", err) + } + if name != "name" { + t.Fatalf("Link name should have been name, got %s instead", name) + } + if alias != "alias" { + t.Fatalf("Link alias should have been alias, got %s instead", alias) + } + // short format definition + name, alias, err = ParseLink("name") + if err != nil { + t.Fatalf("Expected not to error out on a valid name only format but got: %v", err) + } + if name != "name" { + t.Fatalf("Link name should have been name, got %s instead", name) + } + if alias != "name" { + t.Fatalf("Link alias should have been name, got %s instead", alias) + } + // empty string link definition is not allowed + if _, _, err := ParseLink(""); err == nil || !strings.Contains(err.Error(), "empty string specified for links") { + t.Fatalf("Expected error 'empty string specified for links' but got: %v", err) + } + // more than two colons are not allowed + if _, _, err := ParseLink("link:alias:wrong"); err == nil || !strings.Contains(err.Error(), "bad format for links: link:alias:wrong") { + t.Fatalf("Expected error 'bad format for links: link:alias:wrong' but got: %v", err) + } +} diff --git a/runconfig/config_test.go b/runconfig/config_test.go index 87fc6c6aaca34e9c4ed5907e6e0f9a34a6d0ac83..8b1a49f11b07431c8470b01d9e87e1b0a03759ad 100644 --- a/runconfig/config_test.go +++ b/runconfig/config_test.go @@ -45,13 +45,6 @@ func TestParseRunLinks(t *testing.T) { if _, hostConfig := mustParse(t, ""); len(hostConfig.Links) != 0 { t.Fatalf("Error parsing links. No link expected, received: %v", hostConfig.Links) } - - if _, _, err := parse(t, "--link a"); err == nil { - t.Fatalf("Error parsing links. `--link a` should be an error but is not") - } - if _, _, err := parse(t, "--link"); err == nil { - t.Fatalf("Error parsing links. `--link` should be an error but is not") - } } func TestParseRunAttach(t *testing.T) {