Signed-off-by: Doug Davis <dug@us.ibm.com>
| ... | ... |
@@ -1,11 +1,12 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"text/tabwriter" |
| 6 | 7 |
"time" |
| 7 | 8 |
|
| 8 |
- "github.com/docker/docker/engine" |
|
| 9 |
+ "github.com/docker/docker/api/types" |
|
| 9 | 10 |
flag "github.com/docker/docker/pkg/mflag" |
| 10 | 11 |
"github.com/docker/docker/pkg/stringid" |
| 11 | 12 |
"github.com/docker/docker/pkg/units" |
| ... | ... |
@@ -20,16 +21,16 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
|
| 20 | 20 |
quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
|
| 21 | 21 |
noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
|
| 22 | 22 |
cmd.Require(flag.Exact, 1) |
| 23 |
- |
|
| 24 | 23 |
cmd.ParseFlags(args, true) |
| 25 | 24 |
|
| 26 |
- body, _, err := readBody(cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil))
|
|
| 25 |
+ rdr, _, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
|
|
| 27 | 26 |
if err != nil {
|
| 28 | 27 |
return err |
| 29 | 28 |
} |
| 30 | 29 |
|
| 31 |
- outs := engine.NewTable("Created", 0)
|
|
| 32 |
- if _, err := outs.ReadListFrom(body); err != nil {
|
|
| 30 |
+ history := []types.ImageHistory{}
|
|
| 31 |
+ err = json.NewDecoder(rdr).Decode(&history) |
|
| 32 |
+ if err != nil {
|
|
| 33 | 33 |
return err |
| 34 | 34 |
} |
| 35 | 35 |
|
| ... | ... |
@@ -38,30 +39,23 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
|
| 38 | 38 |
fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE") |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
- for _, out := range outs.Data {
|
|
| 42 |
- outID := out.Get("Id")
|
|
| 41 |
+ for _, entry := range history {
|
|
| 42 |
+ if *noTrunc {
|
|
| 43 |
+ fmt.Fprintf(w, entry.ID) |
|
| 44 |
+ } else {
|
|
| 45 |
+ fmt.Fprintf(w, stringid.TruncateID(entry.ID)) |
|
| 46 |
+ } |
|
| 43 | 47 |
if !*quiet {
|
| 44 |
- if *noTrunc {
|
|
| 45 |
- fmt.Fprintf(w, "%s\t", outID) |
|
| 46 |
- } else {
|
|
| 47 |
- fmt.Fprintf(w, "%s\t", stringid.TruncateID(outID)) |
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- fmt.Fprintf(w, "%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))))
|
|
| 48 |
+ fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0)))) |
|
| 51 | 49 |
|
| 52 | 50 |
if *noTrunc {
|
| 53 |
- fmt.Fprintf(w, "%s\t", out.Get("CreatedBy"))
|
|
| 54 |
- } else {
|
|
| 55 |
- fmt.Fprintf(w, "%s\t", utils.Trunc(out.Get("CreatedBy"), 45))
|
|
| 56 |
- } |
|
| 57 |
- fmt.Fprintf(w, "%s\n", units.HumanSize(float64(out.GetInt64("Size"))))
|
|
| 58 |
- } else {
|
|
| 59 |
- if *noTrunc {
|
|
| 60 |
- fmt.Fprintln(w, outID) |
|
| 51 |
+ fmt.Fprintf(w, "%s\t", entry.CreatedBy) |
|
| 61 | 52 |
} else {
|
| 62 |
- fmt.Fprintln(w, stringid.TruncateID(outID)) |
|
| 53 |
+ fmt.Fprintf(w, "%s\t", utils.Trunc(entry.CreatedBy, 45)) |
|
| 63 | 54 |
} |
| 55 |
+ fmt.Fprintf(w, "%s", units.HumanSize(float64(entry.Size))) |
|
| 64 | 56 |
} |
| 57 |
+ fmt.Fprintf(w, "\n") |
|
| 65 | 58 |
} |
| 66 | 59 |
w.Flush() |
| 67 | 60 |
return nil |
| ... | ... |
@@ -1,10 +1,11 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"net/url" |
| 6 | 7 |
|
| 7 |
- "github.com/docker/docker/engine" |
|
| 8 |
+ "github.com/docker/docker/api/types" |
|
| 8 | 9 |
flag "github.com/docker/docker/pkg/mflag" |
| 9 | 10 |
) |
| 10 | 11 |
|
| ... | ... |
@@ -18,7 +19,6 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
|
| 18 | 18 |
noprune = cmd.Bool([]string{"-no-prune"}, false, "Do not delete untagged parents")
|
| 19 | 19 |
) |
| 20 | 20 |
cmd.Require(flag.Min, 1) |
| 21 |
- |
|
| 22 | 21 |
cmd.ParseFlags(args, true) |
| 23 | 22 |
|
| 24 | 23 |
v := url.Values{}
|
| ... | ... |
@@ -31,22 +31,24 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
|
| 31 | 31 |
|
| 32 | 32 |
var encounteredError error |
| 33 | 33 |
for _, name := range cmd.Args() {
|
| 34 |
- body, _, err := readBody(cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil))
|
|
| 34 |
+ rdr, _, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil)
|
|
| 35 | 35 |
if err != nil {
|
| 36 | 36 |
fmt.Fprintf(cli.err, "%s\n", err) |
| 37 | 37 |
encounteredError = fmt.Errorf("Error: failed to remove one or more images")
|
| 38 | 38 |
} else {
|
| 39 |
- outs := engine.NewTable("Created", 0)
|
|
| 40 |
- if _, err := outs.ReadListFrom(body); err != nil {
|
|
| 39 |
+ dels := []types.ImageDelete{}
|
|
| 40 |
+ err = json.NewDecoder(rdr).Decode(&dels) |
|
| 41 |
+ if err != nil {
|
|
| 41 | 42 |
fmt.Fprintf(cli.err, "%s\n", err) |
| 42 | 43 |
encounteredError = fmt.Errorf("Error: failed to remove one or more images")
|
| 43 | 44 |
continue |
| 44 | 45 |
} |
| 45 |
- for _, out := range outs.Data {
|
|
| 46 |
- if out.Get("Deleted") != "" {
|
|
| 47 |
- fmt.Fprintf(cli.out, "Deleted: %s\n", out.Get("Deleted"))
|
|
| 46 |
+ |
|
| 47 |
+ for _, del := range dels {
|
|
| 48 |
+ if del.Deleted != "" {
|
|
| 49 |
+ fmt.Fprintf(cli.out, "Deleted: %s\n", del.Deleted) |
|
| 48 | 50 |
} else {
|
| 49 |
- fmt.Fprintf(cli.out, "Untagged: %s\n", out.Get("Untagged"))
|
|
| 51 |
+ fmt.Fprintf(cli.out, "Untagged: %s\n", del.Untagged) |
|
| 50 | 52 |
} |
| 51 | 53 |
} |
| 52 | 54 |
} |
| ... | ... |
@@ -41,3 +41,18 @@ type ContainerChange struct {
|
| 41 | 41 |
Kind int |
| 42 | 42 |
Path string |
| 43 | 43 |
} |
| 44 |
+ |
|
| 45 |
+// GET "/images/{name:.*}/history"
|
|
| 46 |
+type ImageHistory struct {
|
|
| 47 |
+ ID string `json:"Id"` |
|
| 48 |
+ Created int64 |
|
| 49 |
+ CreatedBy string |
|
| 50 |
+ Tags []string |
|
| 51 |
+ Size int64 |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// DELETE "/images/{name:.*}"
|
|
| 55 |
+type ImageDelete struct {
|
|
| 56 |
+ Untagged string `json:",omitempty"` |
|
| 57 |
+ Deleted string `json:",omitempty"` |
|
| 58 |
+} |
| ... | ... |
@@ -1,9 +1,11 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"strings" |
| 6 | 7 |
|
| 8 |
+ "github.com/docker/docker/api/types" |
|
| 7 | 9 |
"github.com/docker/docker/engine" |
| 8 | 10 |
"github.com/docker/docker/graph" |
| 9 | 11 |
"github.com/docker/docker/image" |
| ... | ... |
@@ -16,21 +18,22 @@ func (daemon *Daemon) ImageDelete(job *engine.Job) error {
|
| 16 | 16 |
if n := len(job.Args); n != 1 {
|
| 17 | 17 |
return fmt.Errorf("Usage: %s IMAGE", job.Name)
|
| 18 | 18 |
} |
| 19 |
- imgs := engine.NewTable("", 0)
|
|
| 20 |
- if err := daemon.DeleteImage(job.Eng, job.Args[0], imgs, true, job.GetenvBool("force"), job.GetenvBool("noprune")); err != nil {
|
|
| 19 |
+ |
|
| 20 |
+ list := []types.ImageDelete{}
|
|
| 21 |
+ if err := daemon.DeleteImage(job.Eng, job.Args[0], &list, true, job.GetenvBool("force"), job.GetenvBool("noprune")); err != nil {
|
|
| 21 | 22 |
return err |
| 22 | 23 |
} |
| 23 |
- if len(imgs.Data) == 0 {
|
|
| 24 |
+ if len(list) == 0 {
|
|
| 24 | 25 |
return fmt.Errorf("Conflict, %s wasn't deleted", job.Args[0])
|
| 25 | 26 |
} |
| 26 |
- if _, err := imgs.WriteListTo(job.Stdout); err != nil {
|
|
| 27 |
+ if err := json.NewEncoder(job.Stdout).Encode(list); err != nil {
|
|
| 27 | 28 |
return err |
| 28 | 29 |
} |
| 29 | 30 |
return nil |
| 30 | 31 |
} |
| 31 | 32 |
|
| 32 | 33 |
// FIXME: make this private and use the job instead |
| 33 |
-func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, imgs *engine.Table, first, force, noprune bool) error {
|
|
| 34 |
+func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, list *[]types.ImageDelete, first, force, noprune bool) error {
|
|
| 34 | 35 |
var ( |
| 35 | 36 |
repoName, tag string |
| 36 | 37 |
tags = []string{}
|
| ... | ... |
@@ -102,9 +105,9 @@ func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, imgs *engine. |
| 102 | 102 |
return err |
| 103 | 103 |
} |
| 104 | 104 |
if tagDeleted {
|
| 105 |
- out := &engine.Env{}
|
|
| 106 |
- out.Set("Untagged", utils.ImageReference(repoName, tag))
|
|
| 107 |
- imgs.Add(out) |
|
| 105 |
+ *list = append(*list, types.ImageDelete{
|
|
| 106 |
+ Untagged: utils.ImageReference(repoName, tag), |
|
| 107 |
+ }) |
|
| 108 | 108 |
eng.Job("log", "untag", img.ID, "").Run()
|
| 109 | 109 |
} |
| 110 | 110 |
} |
| ... | ... |
@@ -117,12 +120,12 @@ func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, imgs *engine. |
| 117 | 117 |
if err := daemon.Graph().Delete(img.ID); err != nil {
|
| 118 | 118 |
return err |
| 119 | 119 |
} |
| 120 |
- out := &engine.Env{}
|
|
| 121 |
- out.SetJson("Deleted", img.ID)
|
|
| 122 |
- imgs.Add(out) |
|
| 120 |
+ *list = append(*list, types.ImageDelete{
|
|
| 121 |
+ Deleted: img.ID, |
|
| 122 |
+ }) |
|
| 123 | 123 |
eng.Job("log", "delete", img.ID, "").Run()
|
| 124 | 124 |
if img.Parent != "" && !noprune {
|
| 125 |
- err := daemon.DeleteImage(eng, img.Parent, imgs, false, force, noprune) |
|
| 125 |
+ err := daemon.DeleteImage(eng, img.Parent, list, false, force, noprune) |
|
| 126 | 126 |
if first {
|
| 127 | 127 |
return err |
| 128 | 128 |
} |
| ... | ... |
@@ -1,9 +1,11 @@ |
| 1 | 1 |
package graph |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"strings" |
| 6 | 7 |
|
| 8 |
+ "github.com/docker/docker/api/types" |
|
| 7 | 9 |
"github.com/docker/docker/engine" |
| 8 | 10 |
"github.com/docker/docker/image" |
| 9 | 11 |
"github.com/docker/docker/utils" |
| ... | ... |
@@ -30,19 +32,22 @@ func (s *TagStore) CmdHistory(job *engine.Job) error {
|
| 30 | 30 |
} |
| 31 | 31 |
} |
| 32 | 32 |
|
| 33 |
- outs := engine.NewTable("Created", 0)
|
|
| 33 |
+ history := []types.ImageHistory{}
|
|
| 34 |
+ |
|
| 34 | 35 |
err = foundImage.WalkHistory(func(img *image.Image) error {
|
| 35 |
- out := &engine.Env{}
|
|
| 36 |
- out.SetJson("Id", img.ID)
|
|
| 37 |
- out.SetInt64("Created", img.Created.Unix())
|
|
| 38 |
- out.Set("CreatedBy", strings.Join(img.ContainerConfig.Cmd, " "))
|
|
| 39 |
- out.SetList("Tags", lookupMap[img.ID])
|
|
| 40 |
- out.SetInt64("Size", img.Size)
|
|
| 41 |
- outs.Add(out) |
|
| 36 |
+ history = append(history, types.ImageHistory{
|
|
| 37 |
+ ID: img.ID, |
|
| 38 |
+ Created: img.Created.Unix(), |
|
| 39 |
+ CreatedBy: strings.Join(img.ContainerConfig.Cmd, " "), |
|
| 40 |
+ Tags: lookupMap[img.ID], |
|
| 41 |
+ Size: img.Size, |
|
| 42 |
+ }) |
|
| 42 | 43 |
return nil |
| 43 | 44 |
}) |
| 44 |
- if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
| 45 |
+ |
|
| 46 |
+ if err = json.NewEncoder(job.Stdout).Encode(history); err != nil {
|
|
| 45 | 47 |
return err |
| 46 | 48 |
} |
| 49 |
+ |
|
| 47 | 50 |
return nil |
| 48 | 51 |
} |