From 8c1fae65d38b96fc5ebc040dec5afabe1ca49d03 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 1 Oct 2013 01:08:37 -0700 Subject: [PATCH] Convert links to upper case --- api.go | 23 +++++++++++++++++++++-- commands.go | 31 +++++++++++++++++++++++++------ links.go | 4 ++-- links_test.go | 16 ++++++++-------- server.go | 17 ++++++++++++++++- server_test.go | 4 ++-- sorter.go | 22 ++++++++++++++++++++++ 7 files changed, 96 insertions(+), 21 deletions(-) diff --git a/api.go b/api.go index 71b055e09..4ee1ddc81 100644 --- a/api.go +++ b/api.go @@ -135,6 +135,7 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r * return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) if err := srv.ContainerKill(name); err != nil { return err } @@ -147,6 +148,7 @@ func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) if err := srv.ContainerExport(name, w); err != nil { utils.Debugf("%s", err) @@ -557,6 +559,7 @@ func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) if err := srv.ContainerRestart(name, t); err != nil { return err } @@ -572,12 +575,18 @@ func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *ht return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) + removeVolume, err := getBoolParam(r.Form.Get("v")) if err != nil { return err } + removeLink, err := getBoolParam(r.Form.Get("link")) + if err != nil { + return err + } - if err := srv.ContainerDestroy(name, removeVolume); err != nil { + if err := srv.ContainerDestroy(name, removeVolume, removeLink); err != nil { return err } w.WriteHeader(http.StatusNoContent) @@ -625,7 +634,7 @@ func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r } var err error name := vars["name"] - name, err = url.QueryUnescape(name) + name = decodeName(name) if err != nil { return err } @@ -649,6 +658,7 @@ func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r * return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) if err := srv.ContainerStop(name, t); err != nil { return err @@ -662,6 +672,8 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r * return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) + status, err := srv.ContainerWait(name) if err != nil { return err @@ -721,6 +733,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r return fmt.Errorf("Missing parameter") } name := vars["name"] + name = decodeName(name) c, err := srv.ContainerInspect(name) if err != nil { @@ -1050,6 +1063,12 @@ func postContainerLink(srv *Server, version float64, w http.ResponseWriter, r *h return nil } + +func decodeName(name string) string { + s, _ := url.QueryUnescape(name) + return s +} + func createRouter(srv *Server, logging bool) (*mux.Router, error) { r := mux.NewRouter() diff --git a/commands.go b/commands.go index 4085236ea..0639f65ba 100644 --- a/commands.go +++ b/commands.go @@ -511,7 +511,8 @@ func (cli *DockerCli) CmdStop(args ...string) error { v.Set("t", strconv.Itoa(*nSeconds)) for _, name := range cmd.Args() { - _, _, err := cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil) + encName := cleanName(name) + _, _, err := cli.call("POST", "/containers/"+encName+"/stop?"+v.Encode(), nil) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) } else { @@ -536,6 +537,7 @@ func (cli *DockerCli) CmdRestart(args ...string) error { v.Set("t", strconv.Itoa(*nSeconds)) for _, name := range cmd.Args() { + name = cleanName(name) _, _, err := cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) @@ -558,8 +560,8 @@ func (cli *DockerCli) CmdStart(args ...string) error { var encounteredError error for _, name := range args { - name = strings.Replace(name, "/", "%252F", -1) - _, _, err := cli.call("POST", "/containers/"+name+"/start", nil) + encName := cleanName(name) + _, _, err := cli.call("POST", "/containers/"+encName+"/start", nil) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) encounteredError = fmt.Errorf("Error: failed to start one or more containers") @@ -581,6 +583,7 @@ func (cli *DockerCli) CmdInspect(args ...string) error { } fmt.Fprintf(cli.out, "[") for i, name := range args { + name = cleanName(name) if i > 0 { fmt.Fprintf(cli.out, ",") } @@ -742,6 +745,8 @@ func (cli *DockerCli) CmdHistory(args ...string) error { func (cli *DockerCli) CmdRm(args ...string) error { cmd := Subcmd("rm", "[OPTIONS] CONTAINER [CONTAINER...]", "Remove one or more containers") v := cmd.Bool("v", false, "Remove the volumes associated to the container") + link := cmd.Bool("link", false, "Remove the specified link and not the underlying container") + if err := cmd.Parse(args); err != nil { return nil } @@ -753,7 +758,11 @@ func (cli *DockerCli) CmdRm(args ...string) error { if *v { val.Set("v", "1") } + if *link { + val.Set("link", "1") + } for _, name := range cmd.Args() { + name = cleanName(name) _, _, err := cli.call("DELETE", "/containers/"+name+"?"+val.Encode(), nil) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) @@ -776,6 +785,7 @@ func (cli *DockerCli) CmdKill(args ...string) error { } for _, name := range args { + name = cleanName(name) _, _, err := cli.call("POST", "/containers/"+name+"/kill", nil) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) @@ -1134,6 +1144,9 @@ func (cli *DockerCli) CmdLs(args ...string) error { fmt.Fprintf(w, "NAME\tID\tIMAGE") fmt.Fprintf(w, "\n") + sortLinks(links, func(i, j APILink) bool { + return len(i.Path) < len(j.Path) + }) for _, link := range links { fmt.Fprintf(w, "%s\t%s\t%s", link.Path, link.ContainerID, link.Image) fmt.Fprintf(w, "\n") @@ -1281,8 +1294,9 @@ func (cli *DockerCli) CmdLogs(args ...string) error { cmd.Usage() return nil } + name := cleanName(cmd.Arg(0)) - if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err); err != nil { + if err := cli.hijack("POST", "/containers/"+name+"/attach?logs=1&stdout=1&stderr=1", false, nil, cli.out, cli.err); err != nil { return err } return nil @@ -1297,8 +1311,9 @@ func (cli *DockerCli) CmdAttach(args ...string) error { cmd.Usage() return nil } - - body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil) + name := cmd.Arg(0) + name = cleanName(name) + body, _, err := cli.call("GET", "/containers/"+name+"/json", nil) if err != nil { return err } @@ -1972,6 +1987,10 @@ func getExitCode(cli *DockerCli, containerId string) (int, error) { return c.State.ExitCode, nil } +func cleanName(name string) string { + return strings.Replace(name, "/", "%252F", -1) +} + func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string) *DockerCli { var ( isTerminal = false diff --git a/links.go b/links.go index b51cfc502..bcd6fe6a1 100644 --- a/links.go +++ b/links.go @@ -51,7 +51,7 @@ func (l *Link) Alias() string { func (l *Link) ToEnv() []string { env := []string{} - alias := l.Alias() + alias := strings.ToUpper(l.Alias()) if p := l.getDefaultPort(); p != nil { env = append(env, fmt.Sprintf("%s_PORT=%s://%s:%s", alias, p.Proto(), l.ChildIP, p.Port())) @@ -59,7 +59,7 @@ func (l *Link) ToEnv() []string { // Load exposed ports into the environment for _, p := range l.Ports { - env = append(env, fmt.Sprintf("%s_PORT_%s_%s=%s://%s:%s", alias, p.Port(), p.Proto(), p.Proto(), l.ChildIP, p.Port())) + env = append(env, fmt.Sprintf("%s_PORT_%s_%s=%s://%s:%s", alias, p.Port(), strings.ToUpper(p.Proto()), p.Proto(), l.ChildIP, p.Port())) } // Load the linked container's name into the environment diff --git a/links_test.go b/links_test.go index 6ece93b93..64608e15c 100644 --- a/links_test.go +++ b/links_test.go @@ -89,16 +89,16 @@ func TestLinkEnv(t *testing.T) { } env[parts[0]] = parts[1] } - if env["docker_PORT"] != "tcp://172.0.17.2:6379" { - t.Fatalf("Expected tcp://172.0.17.2:6379, got %s", env["docker_PORT"]) + if env["DOCKER_PORT"] != "tcp://172.0.17.2:6379" { + t.Fatalf("Expected tcp://172.0.17.2:6379, got %s", env["DOCKER_PORT"]) } - if env["docker_PORT_6379_tcp"] != "tcp://172.0.17.2:6379" { - t.Fatalf("Expected tcp://172.0.17.2:6379, got %s", env["docker_PORT_6379_tcp"]) + if env["DOCKER_PORT_6379_TCP"] != "tcp://172.0.17.2:6379" { + t.Fatalf("Expected tcp://172.0.17.2:6379, got %s", env["DOCKER_PORT_6379_TCP"]) } - if env["docker_NAME"] != "/db/docker" { - t.Fatalf("Expected /db/docker, got %s", env["docker_NAME"]) + if env["DOCKER_NAME"] != "/db/docker" { + t.Fatalf("Expected /db/docker, got %s", env["DOCKER_NAME"]) } - if env["docker_ENV_PASSWORD"] != "gordon" { - t.Fatalf("Expected gordon, got %s", env["docker_ENV_PASSWORD"]) + if env["DOCKER_ENV_PASSWORD"] != "gordon" { + t.Fatalf("Expected gordon, got %s", env["DOCKER_ENV_PASSWORD"]) } } diff --git a/server.go b/server.go index 457e1ef63..a708376c3 100644 --- a/server.go +++ b/server.go @@ -962,7 +962,22 @@ func (srv *Server) ContainerRestart(name string, t int) error { return nil } -func (srv *Server) ContainerDestroy(name string, removeVolume bool) error { +func (srv *Server) ContainerDestroy(name string, removeVolume, removeLink bool) error { + if removeLink { + parent, _ := path.Split(name) + p := srv.runtime.containerGraph.Get(parent) + parentContainer := srv.runtime.Get(p.ID()) + if parentContainer != nil && parentContainer.activeLinks != nil { + if link, exists := parentContainer.activeLinks[name]; exists { + link.Disable() + } + } + + if err := srv.runtime.containerGraph.Delete(name); err != nil { + return err + } + return nil + } if container := srv.runtime.Get(name); container != nil { if container.State.Running { return fmt.Errorf("Impossible to remove a running container, please stop it first") diff --git a/server_test.go b/server_test.go index 3691e3437..a0d8dacfc 100644 --- a/server_test.go +++ b/server_test.go @@ -98,7 +98,7 @@ func TestCreateRm(t *testing.T) { t.Errorf("Expected 1 container, %v found", len(runtime.List())) } - if err = srv.ContainerDestroy(id, true); err != nil { + if err = srv.ContainerDestroy(id, true, false); err != nil { t.Fatal(err) } @@ -175,7 +175,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { } // FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty") - if err = srv.ContainerDestroy(id, true); err != nil { + if err = srv.ContainerDestroy(id, true, false); err != nil { t.Fatal(err) } diff --git a/sorter.go b/sorter.go index d4331eaf1..ad931ebcb 100644 --- a/sorter.go +++ b/sorter.go @@ -81,3 +81,25 @@ 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) +}