diff --git a/components/engine/api.go b/components/engine/api.go index 178ef4d353..638e78a713 100644 --- a/components/engine/api.go +++ b/components/engine/api.go @@ -6,7 +6,6 @@ import ( "encoding/json" "fmt" "github.com/dotcloud/docker/auth" - "github.com/dotcloud/docker/gograph" "github.com/dotcloud/docker/utils" "github.com/gorilla/mux" "io" @@ -522,8 +521,12 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http } func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if err := parseForm(r); err != nil { + return nil + } config := &Config{} out := &APIRun{} + name := r.Form.Get("name") if err := json.NewDecoder(r.Body).Decode(config); err != nil { return err @@ -539,7 +542,7 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r config.Dns = defaultDns } - id, warnings, err := srv.ContainerCreate(config) + id, warnings, err := srv.ContainerCreate(config, name) if err != nil { return err } @@ -649,6 +652,10 @@ func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r return fmt.Errorf("Missing parameter") } name := vars["name"] + // Register any links from the host config before starting the container + if err := srv.RegisterLinks(name, hostConfig); err != nil { + return err + } if err := srv.ContainerStart(name, hostConfig); err != nil { return err } @@ -1019,73 +1026,6 @@ func makeHttpHandler(srv *Server, logging bool, localMethod string, localRoute s } } -func getContainersLinks(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if err := parseForm(r); err != nil { - return err - } - - runtime := srv.runtime - all, err := getBoolParam(r.Form.Get("all")) - if err != nil { - return err - } - - out := []APILink{} - err = runtime.containerGraph.Walk("/", func(p string, e *gograph.Entity) error { - if container := runtime.Get(e.ID()); container != nil { - if !all && strings.Contains(p, container.ID) { - return nil - } - out = append(out, APILink{ - Path: p, - ContainerID: container.ID, - Image: runtime.repositories.ImageName(container.Image), - }) - } - return nil - }, -1) - - if err != nil { - return err - } - return writeJSON(w, http.StatusOK, out) -} - -func postContainerLink(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if vars == nil { - return fmt.Errorf("Missing parameter") - } - values := make(map[string]string) - if matchesContentType(r.Header.Get("Content-Type"), "application/json") && r.Body != nil { - defer r.Body.Close() - - dec := json.NewDecoder(r.Body) - if err := dec.Decode(&values); err != nil { - return err - } - } else { - return fmt.Errorf("Invalid json body") - } - currentName := values["currentName"] - newName := values["newName"] - - if currentName == "" { - return fmt.Errorf("currentName cannot be empty") - } - if newName == "" { - return fmt.Errorf("newName cannot be empty") - } - - if err := srv.runtime.RenameLink(currentName, newName); err != nil { - if strings.HasSuffix(err.Error(), "name are not unique") { - return fmt.Errorf("Conflict, %s already exists", newName) - } - return err - } - - return nil -} - func createRouter(srv *Server, logging bool) (*mux.Router, error) { r := mux.NewRouter() @@ -1106,7 +1046,6 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) { "/containers/{name:.*}/json": getContainersByName, "/containers/{name:.*}/top": getContainersTop, "/containers/{name:.*}/attach/ws": wsContainersAttach, - "/containers/links": getContainersLinks, }, "POST": { "/auth": postAuth, @@ -1125,7 +1064,6 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) { "/containers/{name:.*}/resize": postContainersResize, "/containers/{name:.*}/attach": postContainersAttach, "/containers/{name:.*}/copy": postContainersCopy, - "/containers/link": postContainerLink, }, "DELETE": { "/containers/{name:.*}": deleteContainers, diff --git a/components/engine/api_params.go b/components/engine/api_params.go index 5242d02221..40738f9fe9 100644 --- a/components/engine/api_params.go +++ b/components/engine/api_params.go @@ -121,9 +121,3 @@ type APICopy struct { Resource string HostPath string } - -type APILink struct { - Path string - ContainerID string - Image string -} diff --git a/components/engine/api_test.go b/components/engine/api_test.go index 94a19a1362..34c89f8294 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -352,7 +352,7 @@ func TestGetContainersJSON(t *testing.T) { container, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "test"}, - }) + }, "") if err != nil { t.Fatal(err) } @@ -391,6 +391,7 @@ func TestGetContainersExport(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, }, + "", ) if err != nil { t.Fatal(err) @@ -441,6 +442,7 @@ func TestGetContainersChanges(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/rm", "/etc/passwd"}, }, + "", ) if err != nil { t.Fatal(err) @@ -485,6 +487,7 @@ func TestGetContainersTop(t *testing.T) { Cmd: []string{"/bin/sh", "-c", "cat"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -566,6 +569,7 @@ func TestGetContainersByName(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "test"}, }, + "", ) if err != nil { t.Fatal(err) @@ -597,6 +601,7 @@ func TestPostCommit(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, }, + "", ) if err != nil { t.Fatal(err) @@ -692,6 +697,7 @@ func TestPostContainersKill(t *testing.T) { Cmd: []string{"/bin/cat"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -734,6 +740,7 @@ func TestPostContainersRestart(t *testing.T) { Cmd: []string{"/bin/top"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -788,6 +795,7 @@ func TestPostContainersStart(t *testing.T) { Cmd: []string{"/bin/cat"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -840,6 +848,7 @@ func TestPostContainersStop(t *testing.T) { Cmd: []string{"/bin/top"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -887,6 +896,7 @@ func TestPostContainersWait(t *testing.T) { Cmd: []string{"/bin/sleep", "1"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -929,6 +939,7 @@ func TestPostContainersAttach(t *testing.T) { Cmd: []string{"/bin/cat"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -1018,6 +1029,7 @@ func TestPostContainersAttachStderr(t *testing.T) { Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"}, OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -1107,7 +1119,7 @@ func TestDeleteContainers(t *testing.T) { container, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, - }) + }, "") if err != nil { t.Fatal(err) } @@ -1299,6 +1311,7 @@ func TestPostContainersCopy(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test.txt"}, }, + "", ) if err != nil { t.Fatal(err) diff --git a/components/engine/buildfile.go b/components/engine/buildfile.go index a41443a965..effad01ef0 100644 --- a/components/engine/buildfile.go +++ b/components/engine/buildfile.go @@ -335,7 +335,7 @@ func (b *buildFile) CmdAdd(args string) error { b.config.Image = b.image // Create the container and start it - container, _, err := b.runtime.Create(b.config) + container, _, err := b.runtime.Create(b.config, "") if err != nil { return err } @@ -370,7 +370,7 @@ func (b *buildFile) run() (string, error) { b.config.Image = b.image // Create the container and start it - c, _, err := b.runtime.Create(b.config) + c, _, err := b.runtime.Create(b.config, "") if err != nil { return "", err } @@ -433,7 +433,7 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { } } - container, _, err := b.runtime.Create(b.config) + container, _, err := b.runtime.Create(b.config, "") if err != nil { return err } diff --git a/components/engine/commands.go b/components/engine/commands.go index ef265429ab..31d201f6cb 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -91,7 +91,6 @@ func (cli *DockerCli) CmdHelp(args ...string) error { {"insert", "Insert a file in an image"}, {"inspect", "Return low-level information on a container"}, {"kill", "Kill a running container"}, - {"link", "Link the container with a new name"}, {"login", "Register or Login to the docker registry server"}, {"logs", "Fetch the logs of a container"}, {"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"}, @@ -1163,12 +1162,15 @@ func (cli *DockerCli) CmdPs(args ...string) error { if !*noTrunc { out.ID = utils.TruncateID(out.ID) } + + // Remove the leading / from the names + for i := 0; i < len(out.Names); i++ { + out.Names[i] = out.Names[i][1:] + } + if !*quiet { if !*noTrunc { out.Command = utils.Trunc(out.Command, 20) - for i := 0; i < len(out.Names); i++ { - out.Names[i] = utils.Trunc(out.Names[i], 10) - } } fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, displayablePorts(out.Ports), strings.Join(out.Names, ",")) if *size { @@ -1191,27 +1193,6 @@ func (cli *DockerCli) CmdPs(args ...string) error { return nil } -func (cli *DockerCli) CmdLink(args ...string) error { - cmd := Subcmd("link", "CURRENT_NAME NEW_NAME", "Link the container with a new name") - if err := cmd.Parse(args); err != nil { - return nil - } - if cmd.NArg() != 2 { - cmd.Usage() - return nil - } - body := map[string]string{ - "currentName": cmd.Arg(0), - "newName": cmd.Arg(1), - } - - _, _, err := cli.call("POST", "/containers/link", body) - if err != nil { - return err - } - return nil -} - func (cli *DockerCli) CmdCommit(args ...string) error { cmd := Subcmd("commit", "[OPTIONS] CONTAINER [REPOSITORY [TAG]]", "Create a new image from a container's changes") flComment := cmd.String("m", "", "Commit message") @@ -1535,6 +1516,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { flSigProxy := cmd.Lookup("sig-proxy") sigProxy, _ := strconv.ParseBool(flSigProxy.Value.String()) + flName := cmd.Lookup("name") var containerIDFile *os.File if len(hostConfig.ContainerIDFile) > 0 { @@ -1547,9 +1529,14 @@ func (cli *DockerCli) CmdRun(args ...string) error { } defer containerIDFile.Close() } + containerValues := url.Values{} + name := flName.Value.String() + if name != "" { + containerValues.Set("name", name) + } //create the container - body, statusCode, err := cli.call("POST", "/containers/create", config) + body, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), config) //if image not found try to pull it if statusCode == 404 { _, tag := utils.ParseRepositoryTag(config.Image) @@ -1590,7 +1577,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { if err != nil { return err } - body, _, err = cli.call("POST", "/containers/create", config) + body, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), config) if err != nil { return err } diff --git a/components/engine/container.go b/components/engine/container.go index 9ee91a4c50..ce0ce479a3 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -44,6 +44,7 @@ type Container struct { ResolvConfPath string HostnamePath string HostsPath string + Name string cmd *exec.Cmd stdout *utils.WriteBroadcaster @@ -167,6 +168,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, flPrivileged := cmd.Bool("privileged", false, "Give extended privileges to this container") flAutoRemove := cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)") flSigProxy := cmd.Bool("sig-proxy", false, "Proxify all received signal to the process (even in non-tty mode)") + cmd.String("name", "", "Assign a name to the container") if capabilities != nil && *flMemory > 0 && !capabilities.MemoryLimit { //fmt.Fprintf(stdout, "WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n") @@ -199,7 +201,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, cmd.Var(&flLxcOpts, "lxc-conf", "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"") var flLinks utils.ListOpts - cmd.Var(&flLinks, "link", "Add link to another container (containerid:alias)") + cmd.Var(&flLinks, "link", "Add link to another container (name:alias)") if err := cmd.Parse(args); err != nil { return nil, nil, cmd, err @@ -858,7 +860,7 @@ func (container *Container) Start(hostConfig *HostConfig) (err error) { // Init any links between the parent and children runtime := container.runtime - children, err := runtime.Children(fmt.Sprintf("/%s", container.ID)) + children, err := runtime.Children(container.Name) if err != nil { return err } diff --git a/components/engine/container_test.go b/components/engine/container_test.go index b8f1f0c8e7..262d6fcb1d 100644 --- a/components/engine/container_test.go +++ b/components/engine/container_test.go @@ -23,6 +23,7 @@ func TestIDFormat(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sh", "-c", "echo hello world"}, }, + "", ) if err != nil { t.Fatal(err) @@ -393,6 +394,7 @@ func TestOutput(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foobar"}, }, + "", ) if err != nil { t.Fatal(err) @@ -415,6 +417,7 @@ func TestContainerNetwork(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"ping", "-c", "1", "127.0.0.1"}, }, + "", ) if err != nil { t.Fatal(err) @@ -438,6 +441,7 @@ func TestKillDifferentUser(t *testing.T) { OpenStdin: true, User: "daemon", }, + "", ) if err != nil { t.Fatal(err) @@ -492,7 +496,7 @@ func TestCreateVolume(t *testing.T) { if err != nil { t.Fatal(err) } - c, _, err := runtime.Create(config) + c, _, err := runtime.Create(config, "") if err != nil { t.Fatal(err) } @@ -511,6 +515,7 @@ func TestKill(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"sleep", "2"}, }, + "", ) if err != nil { t.Fatal(err) @@ -554,7 +559,7 @@ func TestExitCode(t *testing.T) { trueContainer, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/true", ""}, - }) + }, "") if err != nil { t.Fatal(err) } @@ -569,7 +574,7 @@ func TestExitCode(t *testing.T) { falseContainer, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/false", ""}, - }) + }, "") if err != nil { t.Fatal(err) } @@ -589,6 +594,7 @@ func TestRestart(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foobar"}, }, + "", ) if err != nil { t.Fatal(err) @@ -621,6 +627,7 @@ func TestRestartStdin(t *testing.T) { OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -697,6 +704,7 @@ func TestUser(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, }, + "", ) if err != nil { t.Fatal(err) @@ -717,6 +725,7 @@ func TestUser(t *testing.T) { User: "root", }, + "", ) if err != nil { t.Fatal(err) @@ -737,6 +746,7 @@ func TestUser(t *testing.T) { User: "0", }, + "", ) if err != nil || container.State.ExitCode != 0 { t.Fatal(err) @@ -757,6 +767,7 @@ func TestUser(t *testing.T) { User: "1", }, + "", ) if err != nil { t.Fatal(err) @@ -779,6 +790,7 @@ func TestUser(t *testing.T) { User: "daemon", }, + "", ) if err != nil { t.Fatal(err) @@ -799,6 +811,7 @@ func TestUser(t *testing.T) { User: "unknownuser", }, + "", ) if err != nil { t.Fatal(err) @@ -818,6 +831,7 @@ func TestMultipleContainers(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"sleep", "2"}, }, + "", ) if err != nil { t.Fatal(err) @@ -828,6 +842,7 @@ func TestMultipleContainers(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"sleep", "2"}, }, + "", ) if err != nil { t.Fatal(err) @@ -874,6 +889,7 @@ func TestStdin(t *testing.T) { OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -919,6 +935,7 @@ func TestTty(t *testing.T) { OpenStdin: true, }, + "", ) if err != nil { t.Fatal(err) @@ -962,6 +979,7 @@ func TestEnv(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"env"}, }, + "", ) if err != nil { t.Fatal(err) @@ -1013,6 +1031,7 @@ func TestEntrypoint(t *testing.T) { Entrypoint: []string{"/bin/echo"}, Cmd: []string{"-n", "foobar"}, }, + "", ) if err != nil { t.Fatal(err) @@ -1035,6 +1054,7 @@ func TestEntrypointNoCmd(t *testing.T) { Image: GetTestImage(runtime).ID, Entrypoint: []string{"/bin/echo", "foobar"}, }, + "", ) if err != nil { t.Fatal(err) @@ -1089,6 +1109,7 @@ func TestLXCConfig(t *testing.T) { Memory: int64(mem), CpuShares: int64(cpu), }, + "", ) if err != nil { t.Fatal(err) @@ -1111,6 +1132,7 @@ func TestCustomLxcConfig(t *testing.T) { Hostname: "foobar", }, + "", ) if err != nil { t.Fatal(err) @@ -1140,6 +1162,7 @@ func BenchmarkRunSequencial(b *testing.B) { Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foo"}, }, + "", ) if err != nil { b.Fatal(err) @@ -1172,6 +1195,7 @@ func BenchmarkRunParallel(b *testing.B) { Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foo"}, }, + "", ) if err != nil { complete <- err @@ -1324,6 +1348,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) { Cmd: []string{"/bin/echo", "-n", "foobar"}, Volumes: map[string]struct{}{"/test": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1343,6 +1368,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) { Cmd: []string{"/bin/echo", "-n", "foobar"}, VolumesFrom: container.ID, }, + "", ) if err != nil { t.Fatal(err) @@ -1378,6 +1404,7 @@ func TestRestartWithVolumes(t *testing.T) { Cmd: []string{"echo", "-n", "foobar"}, Volumes: map[string]struct{}{"/test": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1421,6 +1448,7 @@ func TestVolumesFromWithVolumes(t *testing.T) { Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"}, Volumes: map[string]struct{}{"/test": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1450,6 +1478,7 @@ func TestVolumesFromWithVolumes(t *testing.T) { VolumesFrom: container.ID, Volumes: map[string]struct{}{"/test": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1484,7 +1513,7 @@ func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) { if err != nil { t.Fatal(err) } - c, _, err := runtime.Create(config) + c, _, err := runtime.Create(config, "") if err != nil { t.Fatal(err) } @@ -1555,6 +1584,7 @@ func TestMultipleVolumesFrom(t *testing.T) { Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"}, Volumes: map[string]struct{}{"/test": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1583,6 +1613,7 @@ func TestMultipleVolumesFrom(t *testing.T) { Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"}, Volumes: map[string]struct{}{"/other": {}}, }, + "", ) if err != nil { t.Fatal(err) @@ -1603,7 +1634,7 @@ func TestMultipleVolumesFrom(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/echo", "-n", "foobar"}, VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","), - }) + }, "") if err != nil { t.Fatal(err) diff --git a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst index 4a743a75ac..4d844c7a9a 100644 --- a/components/engine/docs/sources/api/docker_remote_api_v1.6.rst +++ b/components/engine/docs/sources/api/docker_remote_api_v1.6.rst @@ -151,6 +151,7 @@ Create a container } :jsonparam config: the container's configuration + :query name: container name to use :statuscode 201: no error :statuscode 404: no such container :statuscode 406: impossible to attach (container not running) diff --git a/components/engine/docs/sources/commandline/cli.rst b/components/engine/docs/sources/commandline/cli.rst index 4ced41894a..0badcd67c1 100644 --- a/components/engine/docs/sources/commandline/cli.rst +++ b/components/engine/docs/sources/commandline/cli.rst @@ -403,33 +403,6 @@ Insert file from github Kill a running container -.. _cli_link: - -``link`` --------- - -:: - - Usage: docker link CURRENT_NAME NEW_NAME - - Link a container to a new name. - - -Examples: -~~~~~~~~~ - -.. code-block:: bash - - $ docker link /59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc /redis - $ docker ls - NAME ID IMAGE - /redis 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest - /59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc 59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc crosbymichael/redis:latest - - -This will create a new link for the existing name ``/59669e088202c2ebe150b4346cb3301562d073b51261176a354a74e8f618bfbc`` -with the new name ``/redis`` so that we can new reference the same container under the new name ``/redis``. - .. _cli_login: ``login`` @@ -604,7 +577,8 @@ network communication. -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" -sig-proxy=false: Proxify all received signal to the process (even in non-tty mode) -expose=[]: Expose a port from the container without publishing it to your host - -link="": Add link to another container (containerid:alias) + -link="": Add link to another container (name:alias) + -name="": Assign the specified name to the container. If no name is specific docker will generate a random name Examples -------- @@ -680,12 +654,20 @@ without publishing the port to the host system's interfaces. .. code-block:: bash - docker run -link /redis:redis ubuntu bash + docker run -name console -t -i ubuntu bash + +This will create and run a new container with the container name +being ``console``. + +.. code-block:: bash + + docker run -link /redis:redis -name console ubuntu bash 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. +environment variables. The ``-name`` flag will assign the name ``console`` +to the newly created container. .. _cli_search: diff --git a/components/engine/docs/sources/examples/linking_into_redis.rst b/components/engine/docs/sources/examples/linking_into_redis.rst index 70a83b4333..4e0e612ba4 100644 --- a/components/engine/docs/sources/examples/linking_into_redis.rst +++ b/components/engine/docs/sources/examples/linking_into_redis.rst @@ -54,26 +54,14 @@ Run the redis container .. code-block:: bash - docker run -d -e PASSWORD=docker crosbymichael/redis --requirepass docker + docker run -d -e PASSWORD=docker -name redis crosbymichael/redis --requirepass=docker -This will run our redis container using the default port of 6379 and using -as password to secure our service. Next we will link the redis container to -a new name using ``docker link``. - - -Linking an existing container ------------------------------ - -Docker will automatically create an initial link with the container's id but -because the is long and not very user friendly we can link the container with -a new name. - -.. code-block:: bash - - docker link /39588b6a45100ef5b328b2c302ea085624f29e6cbab70f88be04793af02cec89 /redis - -Now we can reference our running redis service using the friendly name ``/redis``. -We can issue all the commands that you would expect; start, stop, attach, using the new name. +This will run our redis container using the default port of 6379 and using docker +as password to secure our service. By specifying the ``-name`` flag on run +we will assign the name ``redis`` to this container. +We can issue all the commands that you would expect; start, stop, attach, using the name. +The name also allows us to link other containers into this one. If you do not specify a +name on docker run, docker will automatically generate a name for your container. Linking redis as a child ------------------------ @@ -90,12 +78,12 @@ Now lets start our web application with a link into redis. .. code-block:: bash - docker run -t -i -link /redis:db ubuntu bash + docker run -t -i -link /redis:db -name webapp ubuntu bash root@4c01db0b339c:/# env HOSTNAME=4c01db0b339c - DB_NAME=/4c01db0b339cf19958731255a796ee072040a652f51652a4ade190ab8c27006f/db + DB_NAME=/webapp/db TERM=xterm DB_PORT=tcp://172.17.0.8:6379 DB_PORT_6379_TCP=tcp://172.17.0.8:6379 @@ -118,7 +106,7 @@ network and environment information from the child. .. code-block:: bash # The name of the child container - DB_NAME=/4c01db0b339cf19958731255a796ee072040a652f51652a4ade190ab8c27006f/db + DB_NAME=/webapp/db # The default protocol, ip, and port of the service running in the container DB_PORT=tcp://172.17.0.8:6379 # A specific protocol, ip, and port of various services @@ -129,4 +117,4 @@ network and environment information from the child. Accessing the network information along with the environment of the child container allows us to easily connect to the redis service on the specific ip and port and use the password -specified in the environment. +specified in the environment. diff --git a/components/engine/gograph/gograph.go b/components/engine/gograph/gograph.go index caec3bffa2..ff0b854064 100644 --- a/components/engine/gograph/gograph.go +++ b/components/engine/gograph/gograph.go @@ -132,6 +132,11 @@ func (db *Database) Set(fullPath, id string) (*Entity, error) { return e, nil } +// Return true if a name already exists in the database +func (db *Database) Exists(name string) bool { + return db.Get(name) != nil +} + func (db *Database) setEdge(parentPath, name string, e *Entity) error { parent, err := db.get(parentPath) if err != nil { @@ -189,14 +194,22 @@ func (db *Database) get(name string) (*Entity, error) { // The key will be the full path of the entity func (db *Database) List(name string, depth int) Entities { out := Entities{} - for c := range db.children(name, depth) { + e, err := db.get(name) + if err != nil { + return out + } + for c := range db.children(e, name, depth) { out[c.FullPath] = c.Entity } return out } func (db *Database) Walk(name string, walkFunc WalkFunc, depth int) error { - for c := range db.children(name, depth) { + e, err := db.get(name) + if err != nil { + return err + } + for c := range db.children(e, name, depth) { if err := walkFunc(c.FullPath, c.Entity); err != nil { return err } @@ -327,10 +340,9 @@ type WalkMeta struct { Edge *Edge } -func (db *Database) children(name string, depth int) <-chan WalkMeta { +func (db *Database) children(e *Entity, name string, depth int) <-chan WalkMeta { out := make(chan WalkMeta) - e, err := db.get(name) - if err != nil { + if e == nil { close(out) return out } @@ -370,7 +382,7 @@ func (db *Database) children(name string, depth int) <-chan WalkMeta { if depth != -1 { nDepth -= 1 } - sc := db.children(meta.FullPath, nDepth) + sc := db.children(child, meta.FullPath, nDepth) for c := range sc { out <- c } diff --git a/components/engine/gograph/gograph_test.go b/components/engine/gograph/gograph_test.go index 57077e9f36..7107ef55ea 100644 --- a/components/engine/gograph/gograph_test.go +++ b/components/engine/gograph/gograph_test.go @@ -28,6 +28,7 @@ func TestNewDatabase(t *testing.T) { if db == nil { t.Fatal("Database should not be nil") } + db.Close() defer destroyTestDb(dbpath) } @@ -465,3 +466,26 @@ func TestRefPaths(t *testing.T) { t.Fatalf("Expected reference count to be 2, got %d", len(refs)) } } + +func TestExistsTrue(t *testing.T) { + db, dbpath := newTestDb(t) + defer destroyTestDb(dbpath) + + db.Set("/testing", "1") + + if !db.Exists("/testing") { + t.Fatalf("/tesing should exist") + } +} + +func TestExistsFalse(t *testing.T) { + db, dbpath := newTestDb(t) + defer destroyTestDb(dbpath) + + db.Set("toerhe", "1") + + if db.Exists("/testing") { + t.Fatalf("/tesing should not exist") + } + +} diff --git a/components/engine/links.go b/components/engine/links.go index 9b3d0b8886..f1087ec34a 100644 --- a/components/engine/links.go +++ b/components/engine/links.go @@ -54,7 +54,7 @@ func (l *Link) ToEnv() []string { alias := strings.ToUpper(l.Alias()) if p := l.getDefaultPort(); p != nil { - env = append(env, fmt.Sprintf("%s_PORT=%s:%s", alias, l.ChildIP, p.Port())) + env = append(env, fmt.Sprintf("%s_PORT=%s://%s:%s", alias, p.Proto(), l.ChildIP, p.Port())) } // Load exposed ports into the environment diff --git a/components/engine/links_test.go b/components/engine/links_test.go index 0865732890..4371248fb1 100644 --- a/components/engine/links_test.go +++ b/components/engine/links_test.go @@ -89,7 +89,7 @@ func TestLinkEnv(t *testing.T) { } env[parts[0]] = parts[1] } - if env["DOCKER_PORT"] != "172.0.17.2:6379" { + if env["DOCKER_PORT"] != "tcp://172.0.17.2:6379" { t.Fatalf("Expected 172.0.17.2:6379, got %s", env["DOCKER_PORT"]) } if env["DOCKER_PORT_6379_TCP"] != "tcp://172.0.17.2:6379" { diff --git a/components/engine/names-generator/names-generator.go b/components/engine/namesgenerator/names-generator.go similarity index 100% rename from components/engine/names-generator/names-generator.go rename to components/engine/namesgenerator/names-generator.go diff --git a/components/engine/names-generator/names-generator_test.go b/components/engine/namesgenerator/names-generator_test.go similarity index 100% rename from components/engine/names-generator/names-generator_test.go rename to components/engine/namesgenerator/names-generator_test.go diff --git a/components/engine/runtime.go b/components/engine/runtime.go index 58c2007f7b..e5c535f9fc 100644 --- a/components/engine/runtime.go +++ b/components/engine/runtime.go @@ -265,7 +265,10 @@ func (runtime *Runtime) restore() error { // Any containers that are left over do not exist in the graph for _, container := range containers { // Try to set the default name for a container if it exists prior to links - if _, err := runtime.containerGraph.Set(fmt.Sprintf("/%s", container.ID), container.ID); err != nil { + name := generateRandomName(runtime) + container.Name = name + + if _, err := runtime.containerGraph.Set(name, container.ID); err != nil { utils.Debugf("Setting default id - %s", err) } register(container) @@ -306,8 +309,8 @@ func (runtime *Runtime) UpdateCapabilities(quiet bool) { } } -// Create creates a new container from the given configuration. -func (runtime *Runtime) Create(config *Config) (*Container, []string, error) { +// Create creates a new container from the given configuration with a given name. +func (runtime *Runtime) Create(config *Config, name string) (*Container, []string, error) { // Lookup image img, err := runtime.repositories.LookupImage(config.Image) if err != nil { @@ -345,8 +348,15 @@ func (runtime *Runtime) Create(config *Config) (*Container, []string, error) { // Generate id id := GenerateID() - // Set the default enitity in the graph - if _, err := runtime.containerGraph.Set(fmt.Sprintf("/%s", id), id); err != nil { + if name == "" { + name = generateRandomName(runtime) + } + if name[0] != '/' { + name = "/" + name + } + + // Set the enitity in the graph using the default name specified + if _, err := runtime.containerGraph.Set(name, id); err != nil { return nil, nil, err } @@ -378,6 +388,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, []string, error) { NetworkSettings: &NetworkSettings{}, // FIXME: do we need to store this in the container? SysInitPath: sysInitPath, + Name: name, } container.root = runtime.containerRoot(container.ID) // Step 1: create the container directory. @@ -483,16 +494,7 @@ func (runtime *Runtime) Commit(container *Container, repository, tag, comment, a return img, nil } -// Strip the leading slash from the name to look up if it -// is a truncated id -// Prepend the slash back after finding the name func (runtime *Runtime) getFullName(name string) string { - if name[0] == '/' { - name = name[1:] - } - if id, err := runtime.idIndex.Get(name); err == nil { - name = id - } if name[0] != '/' { name = "/" + name } @@ -500,9 +502,7 @@ func (runtime *Runtime) getFullName(name string) string { } func (runtime *Runtime) GetByName(name string) (*Container, error) { - name = runtime.getFullName(name) - - entity := runtime.containerGraph.Get(name) + entity := runtime.containerGraph.Get(runtime.getFullName(name)) if entity == nil { return nil, fmt.Errorf("Could not find entity for %s", name) } @@ -514,6 +514,7 @@ func (runtime *Runtime) GetByName(name string) (*Container, error) { } func (runtime *Runtime) Children(name string) (map[string]*Container, error) { + name = runtime.getFullName(name) children := make(map[string]*Container) err := runtime.containerGraph.Walk(name, func(p string, e *gograph.Entity) error { @@ -531,44 +532,13 @@ func (runtime *Runtime) Children(name string) (map[string]*Container, error) { return children, nil } -func (runtime *Runtime) RenameLink(oldName, newName string) error { - oldName = runtime.getFullName(oldName) - - entity := runtime.containerGraph.Get(oldName) - if entity == nil { - return fmt.Errorf("Could not find entity for %s", oldName) - } - - if newName[0] != '/' { - newName = "/" + newName - } - - // This is not rename but adding a new link for the default name - // Strip the leading '/' - if entity.ID() == oldName[1:] { - _, err := runtime.containerGraph.Set(newName, entity.ID()) +func (runtime *Runtime) RegisterLink(parent, child *Container, alias string) error { + fullName := path.Join(parent.Name, alias) + if !runtime.containerGraph.Exists(fullName) { + _, err := runtime.containerGraph.Set(fullName, child.ID) return err } - return runtime.containerGraph.Rename(oldName, newName) -} - -func (runtime *Runtime) Link(parentName, childName, alias string) error { - if id, err := runtime.idIndex.Get(parentName); err == nil { - parentName = id - } - parent := runtime.containerGraph.Get(parentName) - if parent == nil { - return fmt.Errorf("Could not get container for %s", parentName) - } - if id, err := runtime.idIndex.Get(childName); err == nil { - childName = id - } - child := runtime.containerGraph.Get(childName) - if child == nil { - return fmt.Errorf("Could not get container for %s", childName) - } - _, err := runtime.containerGraph.Set(path.Join(parentName, alias), child.ID()) - return err + return nil } // FIXME: harmonize with NewGraph() diff --git a/components/engine/runtime_test.go b/components/engine/runtime_test.go index 085e5be1a3..c7cea75616 100644 --- a/components/engine/runtime_test.go +++ b/components/engine/runtime_test.go @@ -197,6 +197,7 @@ func TestRuntimeCreate(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, + "", ) if err != nil { t.Fatal(err) @@ -234,7 +235,7 @@ func TestRuntimeCreate(t *testing.T) { } // Make sure create with bad parameters returns an error - if _, _, err = runtime.Create(&Config{Image: GetTestImage(runtime).ID}); err == nil { + if _, _, err = runtime.Create(&Config{Image: GetTestImage(runtime).ID}, ""); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is missing") } @@ -243,6 +244,7 @@ func TestRuntimeCreate(t *testing.T) { Image: GetTestImage(runtime).ID, Cmd: []string{}, }, + "", ); err == nil { t.Fatal("Builder.Create should throw an error when Cmd is empty") } @@ -252,7 +254,7 @@ func TestRuntimeCreate(t *testing.T) { Cmd: []string{"/bin/ls"}, PortSpecs: []string{"80"}, } - container, _, err = runtime.Create(config) + container, _, err = runtime.Create(config, "") _, err = runtime.Commit(container, "testrepo", "testtag", "", "", config) if err != nil { @@ -267,7 +269,7 @@ func TestDestroy(t *testing.T) { container, _, err := runtime.Create(&Config{ Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, - }) + }, "") if err != nil { t.Fatal(err) } @@ -361,7 +363,7 @@ func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container, Cmd: []string{"sh", "-c", cmd}, PortSpecs: []string{fmt.Sprintf("%s/%s", strPort, proto)}, ExposedPorts: ep, - }) + }, "") if err != nil { nuke(runtime) t.Fatal(err) @@ -573,6 +575,9 @@ func TestReloadContainerLinks(t *testing.T) { h1 := &HostConfig{} // Add a link to container 2 h1.Links = []string{"/" + container2.ID + ":first"} + if err := runtime1.RegisterLink(container1, container2, "first"); err != nil { + t.Fatal(err) + } if err := container1.Start(h1); err != nil { t.Fatal(err) } @@ -620,7 +625,7 @@ func TestReloadContainerLinks(t *testing.T) { t.Logf("Number of links: %d", runtime2.containerGraph.Refs("0")) // Verify that the link is still registered in the runtime - entity := runtime2.containerGraph.Get(fmt.Sprintf("/%s", container1.ID)) + entity := runtime2.containerGraph.Get(container1.Name) if entity == nil { t.Fatal("Entity should not be nil") } @@ -636,13 +641,17 @@ func TestDefaultContainerName(t *testing.T) { t.Fatal(err) } - shortId, _, err := srv.ContainerCreate(config) + shortId, _, err := srv.ContainerCreate(config, "some_name") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) containerID := container.ID + if container.Name != "/some_name" { + t.Fatalf("Expect /some_name got %s", container.Name) + } + paths := runtime.containerGraph.RefPaths(containerID) if paths == nil || len(paths) == 0 { t.Fatalf("Could not find edges for %s", containerID) @@ -654,12 +663,12 @@ func TestDefaultContainerName(t *testing.T) { if edge.EntityID != containerID { t.Fatalf("Expected %s got %s", containerID, edge.EntityID) } - if edge.Name != containerID { - t.Fatalf("Expected %s got %s", containerID, edge.Name) + if edge.Name != "some_name" { + t.Fatalf("Expected some_name got %s", edge.Name) } } -func TestDefaultContainerRename(t *testing.T) { +func TestRandomContainerName(t *testing.T) { runtime := mkRuntime(t) defer nuke(runtime) srv := &Server{runtime: runtime} @@ -669,24 +678,30 @@ func TestDefaultContainerRename(t *testing.T) { t.Fatal(err) } - shortId, _, err := srv.ContainerCreate(config) + shortId, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) containerID := container.ID - if err := runtime.RenameLink(fmt.Sprintf("/%s", containerID), "/webapp"); err != nil { - t.Fatal(err) + if container.Name == "" { + t.Fatalf("Expected not empty container name") } - webapp, err := runtime.GetByName("/webapp") - if err != nil { - t.Fatal(err) + paths := runtime.containerGraph.RefPaths(containerID) + if paths == nil || len(paths) == 0 { + t.Fatalf("Could not find edges for %s", containerID) } - - if webapp.ID != container.ID { - t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) + edge := paths[0] + if edge.ParentID != "0" { + t.Fatalf("Expected engine got %s", edge.ParentID) + } + if edge.EntityID != containerID { + t.Fatalf("Expected %s got %s", containerID, edge.EntityID) + } + if edge.Name == "" { + t.Fatalf("Expected not empty container name") } } @@ -700,16 +715,12 @@ func TestLinkChildContainer(t *testing.T) { t.Fatal(err) } - shortId, _, err := srv.ContainerCreate(config) + shortId, _, err := srv.ContainerCreate(config, "/webapp") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) - if err := runtime.RenameLink(fmt.Sprintf("/%s", container.ID), "/webapp"); err != nil { - t.Fatal(err) - } - webapp, err := runtime.GetByName("/webapp") if err != nil { t.Fatal(err) @@ -724,17 +735,14 @@ func TestLinkChildContainer(t *testing.T) { t.Fatal(err) } - shortId, _, err = srv.ContainerCreate(config) + shortId, _, err = srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } childContainer := runtime.Get(shortId) - if err := runtime.RenameLink(fmt.Sprintf("/%s", childContainer.ID), "/db"); err != nil { - t.Fatal(err) - } - if err := runtime.Link("/webapp", "/db", "db"); err != nil { + if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } @@ -758,16 +766,12 @@ func TestGetAllChildren(t *testing.T) { t.Fatal(err) } - shortId, _, err := srv.ContainerCreate(config) + shortId, _, err := srv.ContainerCreate(config, "/webapp") if err != nil { t.Fatal(err) } container := runtime.Get(shortId) - if err := runtime.RenameLink(fmt.Sprintf("/%s", container.ID), "/webapp"); err != nil { - t.Fatal(err) - } - webapp, err := runtime.GetByName("/webapp") if err != nil { t.Fatal(err) @@ -782,17 +786,14 @@ func TestGetAllChildren(t *testing.T) { t.Fatal(err) } - shortId, _, err = srv.ContainerCreate(config) + shortId, _, err = srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } childContainer := runtime.Get(shortId) - if err := runtime.RenameLink(fmt.Sprintf("/%s", childContainer.ID), "/db"); err != nil { - t.Fatal(err) - } - if err := runtime.Link("/webapp", "/db", "db"); err != nil { + if err := runtime.RegisterLink(webapp, childContainer, "db"); err != nil { t.Fatal(err) } diff --git a/components/engine/server.go b/components/engine/server.go index d1bbe1bfe3..6cbb6db340 100644 --- a/components/engine/server.go +++ b/components/engine/server.go @@ -156,7 +156,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils. return "", err } - c, _, err := srv.runtime.Create(config) + c, _, err := srv.runtime.Create(config, "") if err != nil { return "", err } @@ -937,7 +937,7 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write return nil } -func (srv *Server) ContainerCreate(config *Config) (string, []string, error) { +func (srv *Server) ContainerCreate(config *Config, name string) (string, []string, error) { if config.Memory != 0 && config.Memory < 524288 { return "", nil, fmt.Errorf("Memory limit must be given in bytes (minimum 524288 bytes)") } @@ -949,7 +949,7 @@ func (srv *Server) ContainerCreate(config *Config) (string, []string, error) { if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit { config.MemorySwap = -1 } - container, buildWarnings, err := srv.runtime.Create(config) + container, buildWarnings, err := srv.runtime.Create(config, name) if err != nil { if srv.runtime.graph.IsNotExist(err) { @@ -1209,13 +1209,12 @@ func (srv *Server) ImageGetCached(imgID string, config *Config) (*Image, error) return nil, nil } -func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { +func (srv *Server) RegisterLinks(name string, hostConfig *HostConfig) error { runtime := srv.runtime container := runtime.Get(name) if container == nil { return fmt.Errorf("No such container: %s", name) } - // Register links if hostConfig != nil && hostConfig.Links != nil { for _, l := range hostConfig.Links { @@ -1223,16 +1222,28 @@ func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { if err != nil { return err } - - childName := parts["name"] - if childName[0] != '/' { - childName = "/" + childName + child, err := srv.runtime.GetByName(parts["name"]) + if err != nil { + return err } - if err := runtime.Link(fmt.Sprintf("/%s", container.ID), childName, parts["alias"]); err != nil { + if child == nil { + return fmt.Errorf("Could not get container for %s", parts["name"]) + } + + if err := runtime.RegisterLink(container, child, parts["alias"]); err != nil { return err } } } + return nil +} + +func (srv *Server) ContainerStart(name string, hostConfig *HostConfig) error { + runtime := srv.runtime + container := runtime.Get(name) + if container == nil { + return fmt.Errorf("No such container: %s", name) + } if err := container.Start(hostConfig); err != nil { return fmt.Errorf("Error starting container %s: %s", name, err) diff --git a/components/engine/server_test.go b/components/engine/server_test.go index ef7b1a9106..7a8ea4e41c 100644 --- a/components/engine/server_test.go +++ b/components/engine/server_test.go @@ -89,7 +89,7 @@ func TestCreateRm(t *testing.T) { t.Fatal(err) } - id, _, err := srv.ContainerCreate(config) + id, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } @@ -119,7 +119,7 @@ func TestCreateRmVolumes(t *testing.T) { t.Fatal(err) } - id, _, err := srv.ContainerCreate(config) + id, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } @@ -158,7 +158,7 @@ func TestCommit(t *testing.T) { t.Fatal(err) } - id, _, err := srv.ContainerCreate(config) + id, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } @@ -179,7 +179,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { t.Fatal(err) } - id, _, err := srv.ContainerCreate(config) + id, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } @@ -231,6 +231,7 @@ func TestRunWithTooLowMemoryLimit(t *testing.T) { CpuShares: 1000, Cmd: []string{"/bin/cat"}, }, + "", ); err == nil { t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!") } @@ -397,7 +398,7 @@ func TestRmi(t *testing.T) { t.Fatal(err) } - containerID, _, err := srv.ContainerCreate(config) + containerID, _, err := srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } @@ -418,7 +419,7 @@ func TestRmi(t *testing.T) { t.Fatal(err) } - containerID, _, err = srv.ContainerCreate(config) + containerID, _, err = srv.ContainerCreate(config, "") if err != nil { t.Fatal(err) } diff --git a/components/engine/sorter.go b/components/engine/sorter.go index ad931ebcb1..d4331eaf1f 100644 --- a/components/engine/sorter.go +++ b/components/engine/sorter.go @@ -81,25 +81,3 @@ func sortContainers(containers []*Container, predicate func(i, j *Container) boo s := &containerSorter{containers, predicate} sort.Sort(s) } - -type apiLinkSorter struct { - links []APILink - by func(i, j APILink) bool -} - -func (s *apiLinkSorter) Len() int { - return len(s.links) -} - -func (s *apiLinkSorter) Swap(i, j int) { - s.links[i], s.links[j] = s.links[j], s.links[i] -} - -func (s *apiLinkSorter) Less(i, j int) bool { - return s.by(s.links[i], s.links[j]) -} - -func sortLinks(links []APILink, predicate func(i, j APILink) bool) { - s := &apiLinkSorter{links, predicate} - sort.Sort(s) -} diff --git a/components/engine/utils.go b/components/engine/utils.go index 6da1c0aee6..cffee05615 100644 --- a/components/engine/utils.go +++ b/components/engine/utils.go @@ -2,6 +2,7 @@ package docker import ( "fmt" + "github.com/dotcloud/docker/namesgenerator" "github.com/dotcloud/docker/utils" "strconv" "strings" @@ -289,3 +290,20 @@ func migratePortMappings(config *Config) error { func parseLink(rawLink string) (map[string]string, error) { return utils.PartParser("name:alias", rawLink) } + +type checker struct { + runtime *Runtime +} + +func (c *checker) Exists(name string) bool { + return c.runtime.containerGraph.Exists("/" + name) +} + +// Generate a random and unique name +func generateRandomName(runtime *Runtime) string { + n, err := namesgenerator.GenerateRandomName(&checker{runtime}) + if err != nil { + panic(err) + } + return n +} diff --git a/components/engine/utils_test.go b/components/engine/utils_test.go index 917c4c1591..439cf0a7d1 100644 --- a/components/engine/utils_test.go +++ b/components/engine/utils_test.go @@ -129,7 +129,7 @@ func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, *HostConf if config.Image == "_" { config.Image = GetTestImage(r).ID } - c, _, err := r.Create(config) + c, _, err := r.Create(config, "") if err != nil { return nil, nil, err }