From 2b52d6e801dd888e1f5759448da025e0ddcffedd Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 24 Jan 2014 23:15:40 -0800 Subject: [PATCH 1/3] Remove api_params.go Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api.go | 69 ++++++++++++++++-------------- api_params.go | 43 ------------------- commands.go | 95 +++++++++++++++++++++++------------------ integration/api_test.go | 68 +++++++++++++++-------------- 4 files changed, 127 insertions(+), 148 deletions(-) delete mode 100644 api_params.go diff --git a/api.go b/api.go index 0a7f7abea7..ba8646599d 100644 --- a/api.go +++ b/api.go @@ -89,18 +89,10 @@ func httpError(w http.ResponseWriter, err error) { } } -func writeJSON(w http.ResponseWriter, code int, v interface{}) error { - b, err := json.Marshal(v) - - if err != nil { - return err - } - +func writeJSON(w http.ResponseWriter, code int, v engine.Env) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - w.Write(b) - - return nil + return v.Encode(w) } func getBoolParam(value string) (bool, error) { @@ -352,12 +344,15 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req if err := parseForm(r); err != nil { return err } - config := &Config{} + var ( + config = &Config{} + env engine.Env + job = srv.Eng.Job("commit", r.Form.Get("container")) + ) if err := json.NewDecoder(r.Body).Decode(config); err != nil && err != io.EOF { utils.Errorf("%s", err) } - job := srv.Eng.Job("commit", r.Form.Get("container")) job.Setenv("repo", r.Form.Get("repo")) job.Setenv("tag", r.Form.Get("tag")) job.Setenv("author", r.Form.Get("author")) @@ -369,8 +364,8 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req if err := job.Run(); err != nil { return err } - - return writeJSON(w, http.StatusCreated, &APIID{id}) + env.Set("Id", id) + return writeJSON(w, http.StatusCreated, env) } // Creates an image from Pull or from Import @@ -555,15 +550,19 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r if err := parseForm(r); err != nil { return nil } - out := &APIRun{} - job := srv.Eng.Job("create", r.Form.Get("name")) + var ( + out engine.Env + job = srv.Eng.Job("create", r.Form.Get("name")) + outWarnings []string + outId string + warnings = bytes.NewBuffer(nil) + ) if err := job.DecodeEnv(r.Body); err != nil { return err } // Read container ID from the first line of stdout - job.Stdout.AddString(&out.ID) + job.Stdout.AddString(&outId) // Read warnings from stderr - warnings := &bytes.Buffer{} job.Stderr.Add(warnings) if err := job.Run(); err != nil { return err @@ -571,8 +570,10 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r // Parse warnings from stderr scanner := bufio.NewScanner(warnings) for scanner.Scan() { - out.Warnings = append(out.Warnings, scanner.Text()) + outWarnings = append(outWarnings, scanner.Text()) } + out.Set("Id", outId) + out.SetList("Warnings", outWarnings) return writeJSON(w, http.StatusCreated, out) } @@ -664,18 +665,22 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r * if vars == nil { return fmt.Errorf("Missing parameter") } - job := srv.Eng.Job("wait", vars["name"]) - var statusStr string - job.Stdout.AddString(&statusStr) + var ( + env engine.Env + status string + job = srv.Eng.Job("wait", vars["name"]) + ) + job.Stdout.AddString(&status) if err := job.Run(); err != nil { return err } // Parse a 16-bit encoded integer to map typical unix exit status. - status, err := strconv.ParseInt(statusStr, 10, 16) + _, err := strconv.ParseInt(status, 10, 16) if err != nil { return err } - return writeJSON(w, http.StatusOK, &APIWait{StatusCode: int(status)}) + env.Set("StatusCode", status) + return writeJSON(w, http.StatusOK, env) } func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { @@ -874,24 +879,24 @@ func postContainersCopy(srv *Server, version float64, w http.ResponseWriter, r * return fmt.Errorf("Missing parameter") } - copyData := &APICopy{} - contentType := r.Header.Get("Content-Type") - if contentType == "application/json" { - if err := json.NewDecoder(r.Body).Decode(copyData); err != nil { + var copyData engine.Env + + if contentType := r.Header.Get("Content-Type"); contentType == "application/json" { + if err := copyData.Decode(r.Body); err != nil { return err } } else { return fmt.Errorf("Content-Type not supported: %s", contentType) } - if copyData.Resource == "" { + if copyData.Get("Resource") == "" { return fmt.Errorf("Path cannot be empty") } - if copyData.Resource[0] == '/' { - copyData.Resource = copyData.Resource[1:] + if copyData.Get("Resource")[0] == '/' { + copyData.Set("Resource", copyData.Get("Resource")[1:]) } - job := srv.Eng.Job("container_copy", vars["name"], copyData.Resource) + job := srv.Eng.Job("container_copy", vars["name"], copyData.Get("Resource")) job.Stdout.Add(w) if err := job.Run(); err != nil { utils.Errorf("%s", err.Error()) diff --git a/api_params.go b/api_params.go deleted file mode 100644 index fb5ad6f388..0000000000 --- a/api_params.go +++ /dev/null @@ -1,43 +0,0 @@ -package docker - -type ( - APITop struct { - Titles []string - Processes [][]string - } - - APIRmi struct { - Deleted string `json:",omitempty"` - Untagged string `json:",omitempty"` - } - - APIID struct { - ID string `json:"Id"` - } - - APIRun struct { - ID string `json:"Id"` - Warnings []string `json:",omitempty"` - } - - APIPort struct { - PrivatePort int64 - PublicPort int64 - Type string - IP string - } - - APIWait struct { - StatusCode int - } - - APIImageConfig struct { - ID string `json:"Id"` - *Config - } - - APICopy struct { - Resource string - HostPath string - } -) diff --git a/commands.go b/commands.go index ff7691c916..1428a769d0 100644 --- a/commands.go +++ b/commands.go @@ -755,18 +755,21 @@ func (cli *DockerCli) CmdTop(args ...string) error { val.Set("ps_args", strings.Join(cmd.Args()[1:], " ")) } - body, _, err := readBody(cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, false)) + stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, false) if err != nil { return err } - procs := APITop{} - err = json.Unmarshal(body, &procs) - if err != nil { + var procs engine.Env + if err := procs.Decode(stream); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - fmt.Fprintln(w, strings.Join(procs.Titles, "\t")) - for _, proc := range procs.Processes { + fmt.Fprintln(w, strings.Join(procs.GetList("Titles"), "\t")) + processes := [][]string{} + if err := procs.GetJson("Processes", &processes); err != nil { + return err + } + for _, proc := range processes { fmt.Fprintln(w, strings.Join(proc, "\t")) } w.Flush() @@ -1451,25 +1454,25 @@ func (cli *DockerCli) CmdCommit(args ...string) error { v.Set("tag", tag) v.Set("comment", *flComment) v.Set("author", *flAuthor) - var config *Config + var ( + config *Config + env engine.Env + ) if *flConfig != "" { config = &Config{} if err := json.Unmarshal([]byte(*flConfig), config); err != nil { return err } } - body, _, err := readBody(cli.call("POST", "/commit?"+v.Encode(), config, false)) + stream, _, err := cli.call("POST", "/commit?"+v.Encode(), config, false) if err != nil { return err } - - apiID := &APIID{} - err = json.Unmarshal(body, apiID) - if err != nil { + if err := env.Decode(stream); err != nil { return err } - fmt.Fprintf(cli.out, "%s\n", apiID.ID) + fmt.Fprintf(cli.out, "%s\n", env.Get("ID")) return nil } @@ -1989,7 +1992,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { } //create the container - body, statusCode, err := readBody(cli.call("POST", "/containers/create?"+containerValues.Encode(), config, false)) + stream, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), config, false) //if image not found try to pull it if statusCode == 404 { _, tag := utils.ParseRepositoryTag(config.Image) @@ -2026,30 +2029,30 @@ func (cli *DockerCli) CmdRun(args ...string) error { if err = cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.err, map[string][]string{"X-Registry-Auth": registryAuthHeader}); err != nil { return err } - if body, _, err = readBody(cli.call("POST", "/containers/create?"+containerValues.Encode(), config, false)); err != nil { + if stream, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), config, false); err != nil { return err } } else if err != nil { return err } - var runResult APIRun - if err := json.Unmarshal(body, &runResult); err != nil { + var runResult engine.Env + if err := runResult.Decode(stream); err != nil { return err } - for _, warning := range runResult.Warnings { + for _, warning := range runResult.GetList("Warnings") { fmt.Fprintf(cli.err, "WARNING: %s\n", warning) } if len(hostConfig.ContainerIDFile) > 0 { - if _, err = containerIDFile.Write([]byte(runResult.ID)); err != nil { + if _, err = containerIDFile.Write([]byte(runResult.Get("Id"))); err != nil { return fmt.Errorf("failed to write the container ID to the file: %s", err) } } if sigProxy { - sigc := cli.forwardAllSignals(runResult.ID) + sigc := cli.forwardAllSignals(runResult.Get("Id")) defer utils.StopCatch(sigc) } @@ -2063,7 +2066,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { waitDisplayId = make(chan struct{}) go func() { defer close(waitDisplayId) - fmt.Fprintf(cli.out, "%s\n", runResult.ID) + fmt.Fprintf(cli.out, "%s\n", runResult.Get("Id")) }() } @@ -2105,7 +2108,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { } errCh = utils.Go(func() error { - return cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked) + return cli.hijack("POST", "/containers/"+runResult.Get("Id")+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked) }) } else { close(hijacked) @@ -2127,12 +2130,12 @@ func (cli *DockerCli) CmdRun(args ...string) error { } //start the container - if _, _, err = readBody(cli.call("POST", "/containers/"+runResult.ID+"/start", hostConfig, false)); err != nil { + if _, _, err = readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/start", hostConfig, false)); err != nil { return err } if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminal { - if err := cli.monitorTtySize(runResult.ID); err != nil { + if err := cli.monitorTtySize(runResult.Get("Id")); err != nil { utils.Errorf("Error monitoring TTY size: %s\n", err) } } @@ -2157,26 +2160,26 @@ func (cli *DockerCli) CmdRun(args ...string) error { if autoRemove { // Autoremove: wait for the container to finish, retrieve // the exit code and remove the container - if _, _, err := readBody(cli.call("POST", "/containers/"+runResult.ID+"/wait", nil, false)); err != nil { + if _, _, err := readBody(cli.call("POST", "/containers/"+runResult.Get("Id")+"/wait", nil, false)); err != nil { return err } - if _, status, err = getExitCode(cli, runResult.ID); err != nil { + if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil { return err } - if _, _, err := readBody(cli.call("DELETE", "/containers/"+runResult.ID+"?v=1", nil, false)); err != nil { + if _, _, err := readBody(cli.call("DELETE", "/containers/"+runResult.Get("Id")+"?v=1", nil, false)); err != nil { return err } } else { if !config.Tty { // In non-tty mode, we can't dettach, so we know we need to wait. - if status, err = waitForExit(cli, runResult.ID); err != nil { + if status, err = waitForExit(cli, runResult.Get("Id")); err != nil { return err } } else { // In TTY mode, there is a race. If the process dies too slowly, the state can be update after the getExitCode call // and result in a wrong exit code. // No Autoremove: Simply retrieve the exit code - if _, status, err = getExitCode(cli, runResult.ID); err != nil { + if _, status, err = getExitCode(cli, runResult.Get("Id")); err != nil { return err } } @@ -2198,15 +2201,15 @@ func (cli *DockerCli) CmdCp(args ...string) error { return nil } - var copyData APICopy + var copyData engine.Env info := strings.Split(cmd.Arg(0), ":") if len(info) != 2 { return fmt.Errorf("Error: Path not specified") } - copyData.Resource = info[1] - copyData.HostPath = cmd.Arg(1) + copyData.Set("Resource", info[1]) + copyData.Set("HostPath", cmd.Arg(1)) stream, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", copyData, false) if stream != nil { @@ -2217,7 +2220,7 @@ func (cli *DockerCli) CmdCp(args ...string) error { } if statusCode == 200 { - if err := archive.Untar(stream, copyData.HostPath, nil); err != nil { + if err := archive.Untar(stream, copyData.Get("HostPath"), nil); err != nil { return err } } @@ -2260,13 +2263,21 @@ func (cli *DockerCli) CmdLoad(args ...string) error { } func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) { - var params io.Reader + params := bytes.NewBuffer(nil) if data != nil { - buf, err := json.Marshal(data) - if err != nil { - return nil, -1, err + if env, ok := data.(engine.Env); ok { + if err := env.Encode(params); err != nil { + return nil, -1, err + } + } else { + buf, err := json.Marshal(data) + if err != nil { + return nil, -1, err + } + if _, err := params.Write(buf); err != nil { + return nil, -1, err + } } - params = bytes.NewBuffer(buf) } // fixme: refactor client to support redirect re := regexp.MustCompile("/+") @@ -2569,16 +2580,16 @@ func (cli *DockerCli) LoadConfigFile() (err error) { } func waitForExit(cli *DockerCli, containerId string) (int, error) { - body, _, err := readBody(cli.call("POST", "/containers/"+containerId+"/wait", nil, false)) + stream, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil, false) if err != nil { return -1, err } - var out APIWait - if err := json.Unmarshal(body, &out); err != nil { + var out engine.Env + if err := out.Decode(stream); err != nil { return -1, err } - return out.StatusCode, nil + return out.GetInt("StatusCode"), nil } // getExitCode perform an inspect on the container. It returns diff --git a/integration/api_test.go b/integration/api_test.go index 95cae47e15..b9ff079cb1 100644 --- a/integration/api_test.go +++ b/integration/api_test.go @@ -485,26 +485,29 @@ func TestGetContainersTop(t *testing.T) { t.Fatal(err) } assertHttpNotError(r, t) - procs := docker.APITop{} - if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil { + var procs engine.Env + if err := procs.Decode(r.Body); err != nil { t.Fatal(err) } - if len(procs.Titles) != 11 { - t.Fatalf("Expected 11 titles, found %d.", len(procs.Titles)) + if len(procs.GetList("Titles")) != 11 { + t.Fatalf("Expected 11 titles, found %d.", len(procs.GetList("Titles"))) } - if procs.Titles[0] != "USER" || procs.Titles[10] != "COMMAND" { - t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.Titles[0], procs.Titles[10]) + if procs.GetList("Titles")[0] != "USER" || procs.GetList("Titles")[10] != "COMMAND" { + t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.GetList("Titles")[0], procs.GetList("Titles")[10]) } - - if len(procs.Processes) != 2 { - t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes)) + processes := [][]string{} + if err := procs.GetJson("Processes", &processes); err != nil { + t.Fatal(err) } - if procs.Processes[0][10] != "/bin/sh -c cat" { - t.Fatalf("Expected `/bin/sh -c cat`, found %s.", procs.Processes[0][10]) + if len(processes) != 2 { + t.Fatalf("Expected 2 processes, found %d.", len(processes)) } - if procs.Processes[1][10] != "/bin/sh -c cat" { - t.Fatalf("Expected `/bin/sh -c cat`, found %s.", procs.Processes[1][10]) + if processes[0][10] != "/bin/sh -c cat" { + t.Fatalf("Expected `/bin/sh -c cat`, found %s.", processes[0][10]) + } + if processes[1][10] != "/bin/sh -c cat" { + t.Fatalf("Expected `/bin/sh -c cat`, found %s.", processes[1][10]) } } @@ -570,11 +573,11 @@ func TestPostCommit(t *testing.T) { t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code) } - apiID := &docker.APIID{} - if err := json.Unmarshal(r.Body.Bytes(), apiID); err != nil { + var env engine.Env + if err := env.Decode(r.Body); err != nil { t.Fatal(err) } - if _, err := srv.ImageInspect(apiID.ID); err != nil { + if _, err := srv.ImageInspect(env.Get("Id")); err != nil { t.Fatalf("The image has not been committed") } } @@ -607,11 +610,11 @@ func TestPostContainersCreate(t *testing.T) { t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code) } - apiRun := &docker.APIRun{} - if err := json.Unmarshal(r.Body.Bytes(), apiRun); err != nil { + var apiRun engine.Env + if err := apiRun.Decode(r.Body); err != nil { t.Fatal(err) } - containerID := apiRun.ID + containerID := apiRun.Get("Id") containerAssertExists(eng, containerID, t) containerRun(eng, containerID, t) @@ -863,12 +866,12 @@ func TestPostContainersWait(t *testing.T) { t.Fatal(err) } assertHttpNotError(r, t) - apiWait := &docker.APIWait{} - if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil { + var apiWait engine.Env + if err := apiWait.Decode(r.Body); err != nil { t.Fatal(err) } - if apiWait.StatusCode != 0 { - t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.StatusCode) + if apiWait.GetInt("StatusCode") != 0 { + t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.GetInt("StatusCode")) } }) @@ -1160,12 +1163,12 @@ func TestDeleteImages(t *testing.T) { t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) } - var outs []docker.APIRmi - if err := json.Unmarshal(r2.Body.Bytes(), &outs); err != nil { + outs := engine.NewTable("Created", 0) + if _, err := outs.ReadListFrom(r2.Body.Bytes()); err != nil { t.Fatal(err) } - if len(outs) != 1 { - t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs)) + if len(outs.Data) != 1 { + t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs.Data)) } images = getImages(eng, t, false, "") @@ -1190,14 +1193,17 @@ func TestPostContainersCopy(t *testing.T) { containerRun(eng, containerID, t) r := httptest.NewRecorder() - copyData := docker.APICopy{HostPath: ".", Resource: "/test.txt"} - jsonData, err := json.Marshal(copyData) - if err != nil { + var copyData engine.Env + copyData.Set("Resource", "/test.txt") + copyData.Set("HostPath", ".") + + jsonData := bytes.NewBuffer(nil) + if err := copyData.Encode(jsonData); err != nil { t.Fatal(err) } - req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", bytes.NewReader(jsonData)) + req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", jsonData) if err != nil { t.Fatal(err) } From 24086fa75dff1ebb56dfb8fbf2c80fdfd5be0e8a Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 28 Jan 2014 00:27:02 +0000 Subject: [PATCH 2/3] job.error\* now return engine.StatusErr Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- engine/job.go | 10 +- server.go | 446 +++++++++++++++++--------------------------------- 2 files changed, 154 insertions(+), 302 deletions(-) diff --git a/engine/job.go b/engine/job.go index c2eadccc1b..782bb02171 100644 --- a/engine/job.go +++ b/engine/job.go @@ -188,10 +188,12 @@ func (job *Job) Printf(format string, args ...interface{}) (n int, err error) { return fmt.Fprintf(job.Stdout, format, args...) } -func (job *Job) Errorf(format string, args ...interface{}) (n int, err error) { - return fmt.Fprintf(job.Stderr, format, args...) +func (job *Job) Errorf(format string, args ...interface{}) Status { + fmt.Fprintf(job.Stderr, format, args...) + return StatusErr } -func (job *Job) Error(err error) (int, error) { - return fmt.Fprintf(job.Stderr, "%s", err) +func (job *Job) Error(err error) Status { + fmt.Fprintf(job.Stderr, "%s", err) + return StatusErr } diff --git a/server.go b/server.go index 90a8bb3ed8..6eeca79d90 100644 --- a/server.go +++ b/server.go @@ -44,8 +44,7 @@ func jobInitApi(job *engine.Job) engine.Status { job.Logf("Creating server") srv, err := NewServer(job.Eng, DaemonConfigFromJob(job)) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if srv.runtime.config.Pidfile != "" { job.Logf("Creating pidfile") @@ -106,8 +105,7 @@ func jobInitApi(job *engine.Job) engine.Status { "auth": srv.Auth, } { if err := job.Eng.Register(name, handler); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } return engine.StatusOK @@ -130,8 +128,7 @@ func (srv *Server) ListenAndServe(job *engine.Job) engine.Status { for i := 0; i < len(protoAddrs); i += 1 { err := <-chErrors if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } @@ -199,8 +196,7 @@ func (srv *Server) ContainerKill(job *engine.Job) engine.Status { } if n := len(job.Args); n < 1 || n > 2 { - job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name) } name := job.Args[0] var sig uint64 @@ -211,8 +207,7 @@ func (srv *Server) ContainerKill(job *engine.Job) engine.Status { // The largest legal signal is 31, so let's parse on 5 bits sig, err = strconv.ParseUint(job.Args[1], 10, 5) if err != nil { - job.Errorf("Invalid signal: %s", job.Args[1]) - return engine.StatusErr + return job.Errorf("Invalid signal: %s", job.Args[1]) } } } @@ -220,21 +215,18 @@ func (srv *Server) ContainerKill(job *engine.Job) engine.Status { // If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait()) if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL { if err := container.Kill(); err != nil { - job.Errorf("Cannot kill container %s: %s", name, err) - return engine.StatusErr + return job.Errorf("Cannot kill container %s: %s", name, err) } srv.LogEvent("kill", container.ID, srv.runtime.repositories.ImageName(container.Image)) } else { // Otherwise, just send the requested signal if err := container.kill(int(sig)); err != nil { - job.Errorf("Cannot kill container %s: %s", name, err) - return engine.StatusErr + return job.Errorf("Cannot kill container %s: %s", name, err) } // FIXME: Add event for signals } } else { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } return engine.StatusOK } @@ -244,8 +236,7 @@ func (srv *Server) Auth(job *engine.Job) engine.Status { job.GetenvJson("authConfig", authConfig) status, err := auth.Login(authConfig, srv.HTTPRequestFactory(nil)) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } job.Printf("%s\n", status) return engine.StatusOK @@ -253,8 +244,7 @@ func (srv *Server) Auth(job *engine.Job) engine.Status { func (srv *Server) Events(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s FROM", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s FROM", job.Name) } var ( @@ -304,8 +294,7 @@ func (srv *Server) Events(job *engine.Job) engine.Status { continue } if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } return engine.StatusOK @@ -313,28 +302,24 @@ func (srv *Server) Events(job *engine.Job) engine.Status { func (srv *Server) ContainerExport(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s container_id", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s container_id", job.Name) } name := job.Args[0] if container := srv.runtime.Get(name); container != nil { data, err := container.Export() if err != nil { - job.Errorf("%s: %s", name, err) - return engine.StatusErr + return job.Errorf("%s: %s", name, err) } // Stream the entire contents of the container (basically a volatile snapshot) if _, err := io.Copy(job.Stdout, data); err != nil { - job.Errorf("%s: %s", name, err) - return engine.StatusErr + return job.Errorf("%s: %s", name, err) } // FIXME: factor job-specific LogEvent to engine.Job.Run() srv.LogEvent("export", container.ID, srv.runtime.repositories.ImageName(container.Image)) return engine.StatusOK } - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } // ImageExport exports all images with the given tag. All versions @@ -344,15 +329,13 @@ func (srv *Server) ContainerExport(job *engine.Job) engine.Status { // out is the writer where the images are written to. func (srv *Server) ImageExport(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER\n", job.Name) } name := job.Args[0] // get image json tempdir, err := ioutil.TempDir("", "docker-export-") if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer os.RemoveAll(tempdir) @@ -360,20 +343,17 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status { rootRepo, err := srv.runtime.repositories.Get(name) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if rootRepo != nil { for _, id := range rootRepo { image, err := srv.ImageInspect(id) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if err := srv.exportImage(image, tempdir); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } @@ -383,30 +363,25 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status { rootRepoJson, _ := json.Marshal(rootRepoMap) if err := ioutil.WriteFile(path.Join(tempdir, "repositories"), rootRepoJson, os.ModeAppend); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } else { image, err := srv.ImageInspect(name) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if err := srv.exportImage(image, tempdir); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } fs, err := archive.Tar(tempdir, archive.Uncompressed) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if _, err := io.Copy(job.Stdout, fs); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } @@ -468,8 +443,7 @@ func (srv *Server) exportImage(image *Image, tempdir string) error { func (srv *Server) Build(job *engine.Job) engine.Status { if len(job.Args) != 0 { - job.Errorf("Usage: %s\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s\n", job.Name) } var ( remoteURL = job.Getenv("remote") @@ -494,38 +468,32 @@ func (srv *Server) Build(job *engine.Job) engine.Status { } root, err := ioutil.TempDir("", "docker-build-git") if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer os.RemoveAll(root) if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil { - job.Errorf("Error trying to use git: %s (%s)", err, output) - return engine.StatusErr + return job.Errorf("Error trying to use git: %s (%s)", err, output) } c, err := archive.Tar(root, archive.Uncompressed) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } context = c } else if utils.IsURL(remoteURL) { f, err := utils.Download(remoteURL) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer f.Body.Close() dockerFile, err := ioutil.ReadAll(f.Body) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } c, err := MkBuildContext(string(dockerFile), nil) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } context = c } @@ -543,8 +511,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status { !suppressOutput, !noCache, rm, job.Stdout, sf, authConfig, configFile) id, err := b.Build(context) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if repoName != "" { srv.runtime.repositories.Set(repoName, tag, id, false) @@ -557,8 +524,7 @@ func (srv *Server) Build(job *engine.Job) engine.Status { func (srv *Server) ImageLoad(job *engine.Job) engine.Status { tmpImageDir, err := ioutil.TempDir("", "docker-import-") if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer os.RemoveAll(tmpImageDir) @@ -569,40 +535,33 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status { tarFile, err := os.Create(repoTarFile) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if _, err := io.Copy(tarFile, job.Stdin); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } tarFile.Close() repoFile, err := os.Open(repoTarFile) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if err := os.Mkdir(repoDir, os.ModeDir); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if err := archive.Untar(repoFile, repoDir, nil); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } dirs, err := ioutil.ReadDir(repoDir) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } for _, d := range dirs { if d.IsDir() { if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } } @@ -611,21 +570,18 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status { if err == nil { repositories := map[string]Repository{} if err := json.Unmarshal(repositoriesJson, &repositories); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } for imageName, tagMap := range repositories { for tag, address := range tagMap { if err := srv.runtime.repositories.Set(imageName, tag, address, true); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } } } else if !os.IsNotExist(err) { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK @@ -669,8 +625,7 @@ func (srv *Server) recursiveLoad(address, tmpImageDir string) error { func (srv *Server) ImagesSearch(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 { - job.Errorf("Usage: %s TERM", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s TERM", job.Name) } var ( term = job.Args[0] @@ -682,13 +637,11 @@ func (srv *Server) ImagesSearch(job *engine.Job) engine.Status { r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), auth.IndexServerAddress()) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } results, err := r.SearchRepositories(term) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } outs := engine.NewTable("star_count", 0) for _, result := range results.Results { @@ -698,16 +651,14 @@ func (srv *Server) ImagesSearch(job *engine.Job) engine.Status { } outs.ReverseSort() if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } func (srv *Server) ImageInsert(job *engine.Job) engine.Status { if len(job.Args) != 3 { - job.Errorf("Usage: %s IMAGE URL PATH\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE URL PATH\n", job.Name) } var ( @@ -721,32 +672,27 @@ func (srv *Server) ImageInsert(job *engine.Job) engine.Status { out := utils.NewWriteFlusher(job.Stdout) img, err := srv.runtime.repositories.LookupImage(name) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } file, err := utils.Download(url) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer file.Body.Close() config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.sysInfo) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } c, _, err := srv.runtime.Create(config, "") if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf, false, utils.TruncateID(img.ID), "Downloading"), path); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } // FIXME: Handle custom repo, tag comment, author img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil) @@ -772,8 +718,7 @@ func (srv *Server) ImagesViz(job *engine.Job) engine.Status { for _, image := range images { parentImage, err = image.GetParent() if err != nil { - job.Errorf("Error while getting parent image: %v", err) - return engine.StatusErr + return job.Errorf("Error while getting parent image: %v", err) } if parentImage != nil { job.Stdout.Write([]byte(" \"" + parentImage.ID + "\" -> \"" + image.ID + "\"\n")) @@ -808,8 +753,7 @@ func (srv *Server) Images(job *engine.Job) engine.Status { allImages, err = srv.runtime.graph.Heads() } if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } lookup := make(map[string]*engine.Env) for name, repository := range srv.runtime.repositories.Repositories { @@ -863,8 +807,7 @@ func (srv *Server) Images(job *engine.Job) engine.Status { outs.ReverseSort() if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } @@ -907,22 +850,19 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { v.Set("InitSha1", utils.INITSHA1) v.Set("InitPath", initPath) if _, err := v.WriteTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } func (srv *Server) ImageHistory(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 { - job.Errorf("Usage: %s IMAGE", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE", job.Name) } name := job.Args[0] image, err := srv.runtime.repositories.LookupImage(name) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } lookupMap := make(map[string][]string) @@ -949,16 +889,14 @@ func (srv *Server) ImageHistory(job *engine.Job) engine.Status { }) outs.ReverseSort() if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } func (srv *Server) ContainerTop(job *engine.Job) engine.Status { if len(job.Args) != 1 && len(job.Args) != 2 { - job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name) - return engine.StatusErr + return job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name) } var ( name = job.Args[0] @@ -971,18 +909,15 @@ func (srv *Server) ContainerTop(job *engine.Job) engine.Status { if container := srv.runtime.Get(name); container != nil { if !container.State.IsRunning() { - job.Errorf("Container %s is not running", name) - return engine.StatusErr + return job.Errorf("Container %s is not running", name) } pids, err := srv.runtime.execDriver.GetPidsForContainer(container.ID) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } output, err := exec.Command("ps", psArgs).Output() if err != nil { - job.Errorf("Error running ps: %s", err) - return engine.StatusErr + return job.Errorf("Error running ps: %s", err) } lines := strings.Split(string(output), "\n") @@ -997,8 +932,7 @@ func (srv *Server) ContainerTop(job *engine.Job) engine.Status { } } if pidIndex == -1 { - job.Errorf("Couldn't find PID field in ps output") - return engine.StatusErr + return job.Errorf("Couldn't find PID field in ps output") } processes := [][]string{} @@ -1009,8 +943,7 @@ func (srv *Server) ContainerTop(job *engine.Job) engine.Status { fields := strings.Fields(line) p, err := strconv.Atoi(fields[pidIndex]) if err != nil { - job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) - return engine.StatusErr + return job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) } for _, pid := range pids { @@ -1028,38 +961,32 @@ func (srv *Server) ContainerTop(job *engine.Job) engine.Status { return engine.StatusOK } - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } func (srv *Server) ContainerChanges(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 { - job.Errorf("Usage: %s CONTAINER", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER", job.Name) } name := job.Args[0] if container := srv.runtime.Get(name); container != nil { outs := engine.NewTable("", 0) changes, err := container.Changes() if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } for _, change := range changes { out := &engine.Env{} if err := out.Import(change); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } outs.Add(out) } if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } else { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } return engine.StatusOK } @@ -1108,8 +1035,7 @@ func (srv *Server) Containers(job *engine.Job) engine.Status { out.Set("Status", container.State.String()) str, err := container.NetworkSettings.PortMappingAPI().ToListString() if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } out.Set("Ports", str) if size { @@ -1121,34 +1047,29 @@ func (srv *Server) Containers(job *engine.Job) engine.Status { } outs.ReverseSort() if _, err := outs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } func (srv *Server) ContainerCommit(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name) } name := job.Args[0] container := srv.runtime.Get(name) if container == nil { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } var config Config if err := job.GetenvJson("config", &config); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } job.Printf("%s\n", img.ID) return engine.StatusOK @@ -1156,16 +1077,14 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status { func (srv *Server) ImageTag(job *engine.Job) engine.Status { if len(job.Args) != 2 && len(job.Args) != 3 { - job.Errorf("Usage: %s IMAGE REPOSITORY [TAG]\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE REPOSITORY [TAG]\n", job.Name) } var tag string if len(job.Args) == 3 { tag = job.Args[2] } if err := srv.runtime.repositories.Set(job.Args[1], tag, job.Args[0], job.GetenvBool("force")); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } @@ -1402,8 +1321,7 @@ func (srv *Server) poolRemove(kind, key string) error { func (srv *Server) ImagePull(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 && n != 2 { - job.Errorf("Usage: %s IMAGE [TAG]", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE [TAG]", job.Name) } var ( localName = job.Args[0] @@ -1427,22 +1345,19 @@ func (srv *Server) ImagePull(job *engine.Job) engine.Status { <-c return engine.StatusOK } - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer srv.poolRemove("pull", localName+":"+tag) // Resolve the Repository name from fqn to endpoint + name endpoint, remoteName, err := registry.ResolveRepositoryName(localName) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if endpoint == auth.IndexServerAddress() { @@ -1451,8 +1366,7 @@ func (srv *Server) ImagePull(job *engine.Job) engine.Status { } if err = srv.pullRepository(r, job.Stdout, localName, remoteName, tag, sf, job.GetenvBool("parallel")); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK @@ -1621,8 +1535,7 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgID, // FIXME: Allow to interrupt current push when new push of same image is done. func (srv *Server) ImagePush(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 { - job.Errorf("Usage: %s IMAGE", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE", job.Name) } var ( localName = job.Args[0] @@ -1634,23 +1547,20 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status { job.GetenvJson("authConfig", authConfig) job.GetenvJson("metaHeaders", metaHeaders) if _, err := srv.poolAdd("push", localName); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } defer srv.poolRemove("push", localName) // Resolve the Repository name from fqn to endpoint + name endpoint, remoteName, err := registry.ResolveRepositoryName(localName) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } img, err := srv.runtime.graph.Get(localName) r, err2 := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint) if err2 != nil { - job.Error(err2) - return engine.StatusErr + return job.Error(err2) } if err != nil { @@ -1659,28 +1569,24 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status { // If it fails, try to get the repository if localRepo, exists := srv.runtime.repositories.Repositories[localName]; exists { if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, sf); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } - job.Error(err) - return engine.StatusErr + return job.Error(err) } var token []string job.Stdout.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName)) if _, err := srv.pushImage(r, job.Stdout, remoteName, img.ID, endpoint, token, sf); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } func (srv *Server) ImageImport(job *engine.Job) engine.Status { if n := len(job.Args); n != 2 && n != 3 { - job.Errorf("Usage: %s SRC REPO [TAG]", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s SRC REPO [TAG]", job.Name) } var ( src = job.Args[0] @@ -1699,8 +1605,7 @@ func (srv *Server) ImageImport(job *engine.Job) engine.Status { } else { u, err := url.Parse(src) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if u.Scheme == "" { u.Scheme = "http" @@ -1712,21 +1617,18 @@ func (srv *Server) ImageImport(job *engine.Job) engine.Status { // If curl is not available, fallback to http.Get() resp, err = utils.Download(u.String()) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), job.Stdout, sf, true, "", "Importing") } img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } // Optionally register the image at REPO/TAG if repo != "" { if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } } job.Stdout.Write(sf.FormatStatus("", img.ID)) @@ -1738,13 +1640,11 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status { if len(job.Args) == 1 { name = job.Args[0] } else if len(job.Args) > 1 { - job.Printf("Usage: %s", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s", job.Name) } config := ContainerConfigFromJob(job) if config.Memory != 0 && config.Memory < 524288 { - job.Errorf("Minimum memory limit allowed is 512k") - return engine.StatusErr + return job.Errorf("Minimum memory limit allowed is 512k") } if config.Memory > 0 && !srv.runtime.sysInfo.MemoryLimit { job.Errorf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n") @@ -1771,11 +1671,9 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status { if tag == "" { tag = DEFAULTTAG } - job.Errorf("No such image: %s (tag: %s)", config.Image, tag) - return engine.StatusErr + return job.Errorf("No such image: %s (tag: %s)", config.Image, tag) } - job.Error(err) - return engine.StatusErr + return job.Error(err) } if !container.Config.NetworkDisabled && srv.runtime.sysInfo.IPv4ForwardingDisabled { job.Errorf("WARNING: IPv4 forwarding is disabled.\n") @@ -1788,15 +1686,14 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status { job.Printf("%s\n", container.ID) } for _, warning := range buildWarnings { - job.Errorf("%s\n", warning) + return job.Errorf("%s\n", warning) } return engine.StatusOK } func (srv *Server) ContainerRestart(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER\n", job.Name) } var ( name = job.Args[0] @@ -1807,22 +1704,18 @@ func (srv *Server) ContainerRestart(job *engine.Job) engine.Status { } if container := srv.runtime.Get(name); container != nil { if err := container.Restart(int(t)); err != nil { - job.Errorf("Cannot restart container %s: %s\n", name, err) - return engine.StatusErr + return job.Errorf("Cannot restart container %s: %s\n", name, err) } srv.LogEvent("restart", container.ID, srv.runtime.repositories.ImageName(container.Image)) } else { - job.Errorf("No such container: %s\n", name) - return engine.StatusErr + return job.Errorf("No such container: %s\n", name) } return engine.StatusOK - } func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Not enough arguments. Usage: %s CONTAINER\n", job.Name) } name := job.Args[0] removeVolume := job.GetenvBool("removeVolume") @@ -1832,23 +1725,19 @@ func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { if removeLink { if container == nil { - job.Errorf("No such link: %s", name) - return engine.StatusErr + return job.Errorf("No such link: %s", name) } name, err := getFullName(name) if err != nil { job.Error(err) - return engine.StatusErr } parent, n := path.Split(name) if parent == "/" { - job.Errorf("Conflict, cannot remove the default name of the container") - return engine.StatusErr + return job.Errorf("Conflict, cannot remove the default name of the container") } pe := srv.runtime.containerGraph.Get(parent) if pe == nil { - job.Errorf("Cannot get parent %s for name %s", parent, name) - return engine.StatusErr + return job.Errorf("Cannot get parent %s for name %s", parent, name) } parentContainer := srv.runtime.Get(pe.ID()) @@ -1861,16 +1750,14 @@ func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { } if err := srv.runtime.containerGraph.Delete(name); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } if container != nil { if container.State.IsRunning() { - job.Errorf("Impossible to remove a running container, please stop it first") - return engine.StatusErr + return job.Errorf("Impossible to remove a running container, please stop it first") } volumes := make(map[string]struct{}) @@ -1895,8 +1782,7 @@ func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { volumes[volumeId] = struct{}{} } if err := srv.runtime.Destroy(container); err != nil { - job.Errorf("Cannot destroy container %s: %s", name, err) - return engine.StatusErr + return job.Errorf("Cannot destroy container %s: %s", name, err) } srv.LogEvent("destroy", container.ID, srv.runtime.repositories.ImageName(container.Image)) @@ -1916,14 +1802,12 @@ func (srv *Server) ContainerDestroy(job *engine.Job) engine.Status { continue } if err := srv.runtime.volumes.Delete(volumeId); err != nil { - job.Errorf("Error calling volumes.Delete(%q): %v", volumeId, err) - return engine.StatusErr + return job.Errorf("Error calling volumes.Delete(%q): %v", volumeId, err) } } } } else { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } return engine.StatusOK } @@ -2075,22 +1959,18 @@ func (srv *Server) DeleteImage(name string, autoPrune bool) (*engine.Table, erro func (srv *Server) ImageDelete(job *engine.Job) engine.Status { if n := len(job.Args); n != 1 { - job.Errorf("Usage: %s IMAGE", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s IMAGE", job.Name) } imgs, err := srv.DeleteImage(job.Args[0], job.GetenvBool("autoPrune")) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if len(imgs.Data) == 0 { - job.Errorf("Conflict, %s wasn't deleted", job.Args[0]) - return engine.StatusErr + return job.Errorf("Conflict, %s wasn't deleted", job.Args[0]) } if _, err := imgs.WriteListTo(job.Stdout); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } @@ -2180,16 +2060,14 @@ func (srv *Server) RegisterLinks(container *Container, hostConfig *HostConfig) e func (srv *Server) ContainerStart(job *engine.Job) engine.Status { if len(job.Args) < 1 { - job.Errorf("Usage: %s container_id", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s container_id", job.Name) } name := job.Args[0] runtime := srv.runtime container := runtime.Get(name) if container == nil { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } // If no environment was set, then no hostconfig was passed. if len(job.Environ()) > 0 { @@ -2205,8 +2083,7 @@ func (srv *Server) ContainerStart(job *engine.Job) engine.Status { // refuse to bind mount "/" to the container if source == "/" { - job.Errorf("Invalid bind mount '%s' : source can't be '/'", bind) - return engine.StatusErr + return job.Errorf("Invalid bind mount '%s' : source can't be '/'", bind) } // ensure the source exists on the host @@ -2214,22 +2091,19 @@ func (srv *Server) ContainerStart(job *engine.Job) engine.Status { if err != nil && os.IsNotExist(err) { err = os.MkdirAll(source, 0755) if err != nil { - job.Errorf("Could not create local directory '%s' for bind mount: %s!", source, err.Error()) - return engine.StatusErr + return job.Errorf("Could not create local directory '%s' for bind mount: %s!", source, err.Error()) } } } // Register any links from the host config before starting the container if err := srv.RegisterLinks(container, hostConfig); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } container.hostConfig = hostConfig container.ToDisk() } if err := container.Start(); err != nil { - job.Errorf("Cannot start container %s: %s", name, err) - return engine.StatusErr + return job.Errorf("Cannot start container %s: %s", name, err) } srv.LogEvent("start", container.ID, runtime.repositories.ImageName(container.Image)) @@ -2238,8 +2112,7 @@ func (srv *Server) ContainerStart(job *engine.Job) engine.Status { func (srv *Server) ContainerStop(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER\n", job.Name) } var ( name = job.Args[0] @@ -2250,21 +2123,18 @@ func (srv *Server) ContainerStop(job *engine.Job) engine.Status { } if container := srv.runtime.Get(name); container != nil { if err := container.Stop(int(t)); err != nil { - job.Errorf("Cannot stop container %s: %s\n", name, err) - return engine.StatusErr + return job.Errorf("Cannot stop container %s: %s\n", name, err) } srv.LogEvent("stop", container.ID, srv.runtime.repositories.ImageName(container.Image)) } else { - job.Errorf("No such container: %s\n", name) - return engine.StatusErr + return job.Errorf("No such container: %s\n", name) } return engine.StatusOK } func (srv *Server) ContainerWait(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s", job.Name) } name := job.Args[0] if container := srv.runtime.Get(name); container != nil { @@ -2272,41 +2142,34 @@ func (srv *Server) ContainerWait(job *engine.Job) engine.Status { job.Printf("%d\n", status) return engine.StatusOK } - job.Errorf("%s: no such container: %s", job.Name, name) - return engine.StatusErr + return job.Errorf("%s: no such container: %s", job.Name, name) } func (srv *Server) ContainerResize(job *engine.Job) engine.Status { if len(job.Args) != 3 { - job.Errorf("Not enough arguments. Usage: %s CONTAINER HEIGHT WIDTH\n", job.Name) - return engine.StatusErr + return job.Errorf("Not enough arguments. Usage: %s CONTAINER HEIGHT WIDTH\n", job.Name) } name := job.Args[0] height, err := strconv.Atoi(job.Args[1]) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } width, err := strconv.Atoi(job.Args[2]) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if container := srv.runtime.Get(name); container != nil { if err := container.Resize(height, width); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } func (srv *Server) ContainerAttach(job *engine.Job) engine.Status { if len(job.Args) != 1 { - job.Errorf("Usage: %s CONTAINER\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER\n", job.Name) } var ( @@ -2320,8 +2183,7 @@ func (srv *Server) ContainerAttach(job *engine.Job) engine.Status { container := srv.runtime.Get(name) if container == nil { - job.Errorf("No such container: %s", name) - return engine.StatusErr + return job.Errorf("No such container: %s", name) } //logs @@ -2372,8 +2234,7 @@ func (srv *Server) ContainerAttach(job *engine.Job) engine.Status { //stream if stream { if container.State.IsGhost() { - job.Errorf("Impossible to attach to a ghost container") - return engine.StatusErr + return job.Errorf("Impossible to attach to a ghost container") } var ( @@ -2427,8 +2288,7 @@ func (srv *Server) ImageInspect(name string) (*Image, error) { func (srv *Server) JobInspect(job *engine.Job) engine.Status { // TODO: deprecate KIND/conflict if n := len(job.Args); n != 2 { - job.Errorf("Usage: %s CONTAINER|IMAGE KIND", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER|IMAGE KIND", job.Name) } var ( name = job.Args[0] @@ -2440,35 +2300,30 @@ func (srv *Server) JobInspect(job *engine.Job) engine.Status { ) if conflict && image != nil && container != nil { - job.Errorf("Conflict between containers and images") - return engine.StatusErr + return job.Errorf("Conflict between containers and images") } switch kind { case "image": if errImage != nil { - job.Error(errImage) - return engine.StatusErr + return job.Error(errImage) } object = image case "container": if errContainer != nil { - job.Error(errContainer) - return engine.StatusErr + return job.Error(errContainer) } object = &struct { *Container HostConfig *HostConfig }{container, container.hostConfig} default: - job.Errorf("Unknown kind: %s", kind) - return engine.StatusErr + return job.Errorf("Unknown kind: %s", kind) } b, err := json.Marshal(object) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } job.Stdout.Write(b) return engine.StatusOK @@ -2476,8 +2331,7 @@ func (srv *Server) JobInspect(job *engine.Job) engine.Status { func (srv *Server) ContainerCopy(job *engine.Job) engine.Status { if len(job.Args) != 2 { - job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name) - return engine.StatusErr + return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name) } var ( @@ -2489,19 +2343,15 @@ func (srv *Server) ContainerCopy(job *engine.Job) engine.Status { data, err := container.Copy(resource) if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if _, err := io.Copy(job.Stdout, data); err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } return engine.StatusOK } - job.Errorf("No such container: %s", name) - return engine.StatusErr - + return job.Errorf("No such container: %s", name) } func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) { From 8fbdb7b59eba078bf24546686e005cc86a60e493 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 28 Jan 2014 03:26:24 +0000 Subject: [PATCH 3/3] add setSubEnv and getSubEnv Docker-DCO-1.1-Signed-off-by: Victor Vieux (github: vieux) --- api.go | 18 +++++++----------- engine/env.go | 22 ++++++++++++++++++++++ engine/job.go | 8 ++++++++ server.go | 3 +-- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/api.go b/api.go index ba8646599d..4d294667ac 100644 --- a/api.go +++ b/api.go @@ -345,11 +345,11 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req return err } var ( - config = &Config{} + config engine.Env env engine.Env job = srv.Eng.Job("commit", r.Form.Get("container")) ) - if err := json.NewDecoder(r.Body).Decode(config); err != nil && err != io.EOF { + if err := config.Import(r.Body); err != nil { utils.Errorf("%s", err) } @@ -357,7 +357,7 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req job.Setenv("tag", r.Form.Get("tag")) job.Setenv("author", r.Form.Get("author")) job.Setenv("comment", r.Form.Get("comment")) - job.SetenvJson("config", config) + job.SetenvSubEnv("config", &config) var id string job.Stdout.AddString(&id) @@ -704,18 +704,14 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r return fmt.Errorf("Missing parameter") } - // TODO: replace the buffer by job.AddEnv() var ( job = srv.Eng.Job("inspect", vars["name"], "container") - buffer = bytes.NewBuffer(nil) - c Container + c, err = job.Stdout.AddEnv() ) - job.Stdout.Add(buffer) - if err := job.Run(); err != nil { + if err != nil { return err } - - if err := json.Unmarshal(buffer.Bytes(), &c); err != nil { + if err = job.Run(); err != nil { return err } @@ -742,7 +738,7 @@ func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") - if !c.Config.Tty && version >= 1.6 { + if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version >= 1.6 { errStream = utils.NewStdWriter(outStream, utils.Stderr) outStream = utils.NewStdWriter(outStream, utils.Stdout) } else { diff --git a/engine/env.go b/engine/env.go index d6ca4ec07b..ce8c34bb24 100644 --- a/engine/env.go +++ b/engine/env.go @@ -86,6 +86,28 @@ func (env *Env) GetList(key string) []string { return l } +func (env *Env) GetSubEnv(key string) *Env { + sval := env.Get(key) + if sval == "" { + return nil + } + buf := bytes.NewBufferString(sval) + var sub Env + if err := sub.Decode(buf); err != nil { + return nil + } + return &sub +} + +func (env *Env) SetSubEnv(key string, sub *Env) error { + var buf bytes.Buffer + if err := sub.Encode(&buf); err != nil { + return err + } + env.Set(key, string(buf.Bytes())) + return nil +} + func (env *Env) GetJson(key string, iface interface{}) error { sval := env.Get(key) if sval == "" { diff --git a/engine/job.go b/engine/job.go index 782bb02171..1f35ac85ff 100644 --- a/engine/job.go +++ b/engine/job.go @@ -118,6 +118,14 @@ func (job *Job) SetenvBool(key string, value bool) { job.env.SetBool(key, value) } +func (job *Job) GetenvSubEnv(key string) *Env { + return job.env.GetSubEnv(key) +} + +func (job *Job) SetenvSubEnv(key string, value *Env) error { + return job.env.SetSubEnv(key, value) +} + func (job *Job) GetenvInt64(key string) int64 { return job.env.GetInt64(key) } diff --git a/server.go b/server.go index 6eeca79d90..d8195f3de0 100644 --- a/server.go +++ b/server.go @@ -1656,8 +1656,7 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status { } resolvConf, err := utils.GetResolvConf() if err != nil { - job.Error(err) - return engine.StatusErr + return job.Error(err) } if !config.NetworkDisabled && len(config.Dns) == 0 && len(srv.runtime.config.Dns) == 0 && utils.CheckLocalDns(resolvConf) { job.Errorf("WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v\n", defaultDns)