From 2b52d6e801dd888e1f5759448da025e0ddcffedd Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 24 Jan 2014 23:15:40 -0800 Subject: [PATCH] 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) }