1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Last step in removing engine.Tabel from api/client/*

Signed-off-by: Doug Davis <dug@us.ibm.com>
This commit is contained in:
Doug Davis 2015-04-03 17:39:06 -07:00
parent 2a79d54f4c
commit 065648a832
6 changed files with 258 additions and 131 deletions

View file

@ -1,13 +1,14 @@
package client package client
import ( import (
"encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/docker/docker/engine" "github.com/docker/docker/api/types"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers"
@ -18,26 +19,26 @@ import (
) )
// FIXME: --viz and --tree are deprecated. Remove them in a future version. // FIXME: --viz and --tree are deprecated. Remove them in a future version.
func (cli *DockerCli) WalkTree(noTrunc bool, images *engine.Table, byParent map[string]*engine.Table, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)) { func (cli *DockerCli) WalkTree(noTrunc bool, images []*types.Image, byParent map[string][]*types.Image, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *types.Image, prefix string)) {
length := images.Len() length := len(images)
if length > 1 { if length > 1 {
for index, image := range images.Data { for index, image := range images {
if index+1 == length { if index+1 == length {
printNode(cli, noTrunc, image, prefix+"└─") printNode(cli, noTrunc, image, prefix+"└─")
if subimages, exists := byParent[image.Get("Id")]; exists { if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
} }
} else { } else {
printNode(cli, noTrunc, image, prefix+"\u251C─") printNode(cli, noTrunc, image, prefix+"\u251C─")
if subimages, exists := byParent[image.Get("Id")]; exists { if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode) cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode)
} }
} }
} }
} else { } else {
for _, image := range images.Data { for _, image := range images {
printNode(cli, noTrunc, image, prefix+"└─") printNode(cli, noTrunc, image, prefix+"└─")
if subimages, exists := byParent[image.Get("Id")]; exists { if subimages, exists := byParent[image.ID]; exists {
cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode)
} }
} }
@ -45,41 +46,41 @@ func (cli *DockerCli) WalkTree(noTrunc bool, images *engine.Table, byParent map[
} }
// FIXME: --viz and --tree are deprecated. Remove them in a future version. // FIXME: --viz and --tree are deprecated. Remove them in a future version.
func (cli *DockerCli) printVizNode(noTrunc bool, image *engine.Env, prefix string) { func (cli *DockerCli) printVizNode(noTrunc bool, image *types.Image, prefix string) {
var ( var (
imageID string imageID string
parentID string parentID string
) )
if noTrunc { if noTrunc {
imageID = image.Get("Id") imageID = image.ID
parentID = image.Get("ParentId") parentID = image.ParentId
} else { } else {
imageID = stringid.TruncateID(image.Get("Id")) imageID = stringid.TruncateID(image.ID)
parentID = stringid.TruncateID(image.Get("ParentId")) parentID = stringid.TruncateID(image.ParentId)
} }
if parentID == "" { if parentID == "" {
fmt.Fprintf(cli.out, " base -> \"%s\" [style=invis]\n", imageID) fmt.Fprintf(cli.out, " base -> \"%s\" [style=invis]\n", imageID)
} else { } else {
fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID) fmt.Fprintf(cli.out, " \"%s\" -> \"%s\"\n", parentID, imageID)
} }
if image.GetList("RepoTags")[0] != "<none>:<none>" { if image.RepoTags[0] != "<none>:<none>" {
fmt.Fprintf(cli.out, " \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n", fmt.Fprintf(cli.out, " \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n",
imageID, imageID, strings.Join(image.GetList("RepoTags"), "\\n")) imageID, imageID, strings.Join(image.RepoTags, "\\n"))
} }
} }
// FIXME: --viz and --tree are deprecated. Remove them in a future version. // FIXME: --viz and --tree are deprecated. Remove them in a future version.
func (cli *DockerCli) printTreeNode(noTrunc bool, image *engine.Env, prefix string) { func (cli *DockerCli) printTreeNode(noTrunc bool, image *types.Image, prefix string) {
var imageID string var imageID string
if noTrunc { if noTrunc {
imageID = image.Get("Id") imageID = image.ID
} else { } else {
imageID = stringid.TruncateID(image.Get("Id")) imageID = stringid.TruncateID(image.ID)
} }
fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, units.HumanSize(float64(image.GetInt64("VirtualSize")))) fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, units.HumanSize(float64(image.VirtualSize)))
if image.GetList("RepoTags")[0] != "<none>:<none>" { if image.RepoTags[0] != "<none>:<none>" {
fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.GetList("RepoTags"), ", ")) fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.RepoTags, ", "))
} else { } else {
fmt.Fprint(cli.out, "\n") fmt.Fprint(cli.out, "\n")
} }
@ -101,7 +102,6 @@ func (cli *DockerCli) CmdImages(args ...string) error {
flFilter := opts.NewListOpts(nil) flFilter := opts.NewListOpts(nil)
cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided")
cmd.Require(flag.Max, 1) cmd.Require(flag.Max, 1)
cmd.ParseFlags(args, true) cmd.ParseFlags(args, true)
// Consolidate all filter flags, and sanity check them early. // Consolidate all filter flags, and sanity check them early.
@ -129,44 +129,44 @@ func (cli *DockerCli) CmdImages(args ...string) error {
v.Set("filters", filterJSON) v.Set("filters", filterJSON)
} }
body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, nil)) rdr, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil)
if err != nil { if err != nil {
return err return err
} }
outs := engine.NewTable("Created", 0) images := []types.Image{}
if _, err := outs.ReadListFrom(body); err != nil { err = json.NewDecoder(rdr).Decode(&images)
if err != nil {
return err return err
} }
var ( var (
printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string) printNode func(cli *DockerCli, noTrunc bool, image *types.Image, prefix string)
startImage *engine.Env startImage *types.Image
roots = engine.NewTable("Created", outs.Len()) roots = []*types.Image{}
byParent = make(map[string]*engine.Table) byParent = make(map[string][]*types.Image)
) )
for _, image := range outs.Data { for _, image := range images {
if image.Get("ParentId") == "" { if image.ParentId == "" {
roots.Add(image) roots = append(roots, &image)
} else { } else {
if children, exists := byParent[image.Get("ParentId")]; exists { if children, exists := byParent[image.ParentId]; exists {
children.Add(image) children = append(children, &image)
} else { } else {
byParent[image.Get("ParentId")] = engine.NewTable("Created", 1) byParent[image.ParentId] = []*types.Image{&image}
byParent[image.Get("ParentId")].Add(image)
} }
} }
if matchName != "" { if matchName != "" {
if matchName == image.Get("Id") || matchName == stringid.TruncateID(image.Get("Id")) { if matchName == image.ID || matchName == stringid.TruncateID(image.ID) {
startImage = image startImage = &image
} }
for _, repotag := range image.GetList("RepoTags") { for _, repotag := range image.RepoTags {
if repotag == matchName { if repotag == matchName {
startImage = image startImage = &image
} }
} }
} }
@ -180,8 +180,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
} }
if startImage != nil { if startImage != nil {
root := engine.NewTable("Created", 1) root := []*types.Image{startImage}
root.Add(startImage)
cli.WalkTree(*noTrunc, root, byParent, "", printNode) cli.WalkTree(*noTrunc, root, byParent, "", printNode)
} else if matchName == "" { } else if matchName == "" {
cli.WalkTree(*noTrunc, roots, byParent, "", printNode) cli.WalkTree(*noTrunc, roots, byParent, "", printNode)
@ -207,14 +206,14 @@ func (cli *DockerCli) CmdImages(args ...string) error {
v.Set("all", "1") v.Set("all", "1")
} }
body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, nil)) rdr, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil)
if err != nil { if err != nil {
return err return err
} }
outs := engine.NewTable("Created", 0) images := []types.Image{}
if _, err := outs.ReadListFrom(body); err != nil { err = json.NewDecoder(rdr).Decode(&images)
if err != nil {
return err return err
} }
@ -227,14 +226,14 @@ func (cli *DockerCli) CmdImages(args ...string) error {
} }
} }
for _, out := range outs.Data { for _, image := range images {
outID := out.Get("Id") ID := image.ID
if !*noTrunc { if !*noTrunc {
outID = stringid.TruncateID(outID) ID = stringid.TruncateID(ID)
} }
repoTags := out.GetList("RepoTags") repoTags := image.RepoTags
repoDigests := out.GetList("RepoDigests") repoDigests := image.RepoDigests
if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" { if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" {
// dangling image - clear out either repoTags or repoDigsts so we only show it once below // dangling image - clear out either repoTags or repoDigsts so we only show it once below
@ -256,12 +255,12 @@ func (cli *DockerCli) CmdImages(args ...string) error {
if !*quiet { if !*quiet {
if *showDigests { if *showDigests {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize")))) fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
} else { } else {
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize")))) fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize)))
} }
} else { } else {
fmt.Fprintln(w, outID) fmt.Fprintln(w, ID)
} }
} }
} }

View file

@ -1,6 +1,7 @@
package client package client
import ( import (
"encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"strconv" "strconv"
@ -9,7 +10,7 @@ import (
"time" "time"
"github.com/docker/docker/api" "github.com/docker/docker/api"
"github.com/docker/docker/engine" "github.com/docker/docker/api/types"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag" flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/parsers/filters" "github.com/docker/docker/pkg/parsers/filters"
@ -85,13 +86,14 @@ func (cli *DockerCli) CmdPs(args ...string) error {
v.Set("filters", filterJSON) v.Set("filters", filterJSON)
} }
body, _, err := readBody(cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)) rdr, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)
if err != nil { if err != nil {
return err return err
} }
outs := engine.NewTable("Created", 0) containers := []types.Container{}
if _, err := outs.ReadListFrom(body); err != nil { err = json.NewDecoder(rdr).Decode(&containers)
if err != nil {
return err return err
} }
@ -114,54 +116,50 @@ func (cli *DockerCli) CmdPs(args ...string) error {
return ss return ss
} }
for _, out := range outs.Data { for _, container := range containers {
outID := out.Get("Id") ID := container.ID
if !*noTrunc { if !*noTrunc {
outID = stringid.TruncateID(outID) ID = stringid.TruncateID(ID)
} }
if *quiet { if *quiet {
fmt.Fprintln(w, outID) fmt.Fprintln(w, ID)
continue continue
} }
var ( var (
outNames = stripNamePrefix(out.GetList("Names")) names = stripNamePrefix(container.Names)
outCommand = strconv.Quote(out.Get("Command")) command = strconv.Quote(container.Command)
ports = engine.NewTable("", 0)
) )
if !*noTrunc { if !*noTrunc {
outCommand = utils.Trunc(outCommand, 20) command = utils.Trunc(command, 20)
// only display the default name for the container with notrunc is passed // only display the default name for the container with notrunc is passed
for _, name := range outNames { for _, name := range names {
if len(strings.Split(name, "/")) == 1 { if len(strings.Split(name, "/")) == 1 {
outNames = []string{name} names = []string{name}
break break
} }
} }
} }
ports.ReadListFrom([]byte(out.Get("Ports"))) image := container.Image
image := out.Get("Image")
if image == "" { if image == "" {
image = "<no image>" image = "<no image>"
} }
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, image, outCommand, fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command,
units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))),
out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ",")) container.Status, api.NewDisplayablePorts(container.Ports), strings.Join(names, ","))
if *size { if *size {
if out.GetInt("SizeRootFs") > 0 { if container.SizeRootFs > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(out.GetInt64("SizeRw"))), units.HumanSize(float64(out.GetInt64("SizeRootFs")))) fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(container.SizeRw)), units.HumanSize(float64(container.SizeRootFs)))
} else { } else {
fmt.Fprintf(w, "%s\n", units.HumanSize(float64(out.GetInt64("SizeRw")))) fmt.Fprintf(w, "%s\n", units.HumanSize(float64(container.SizeRw)))
} }
continue continue

View file

@ -5,9 +5,11 @@ import (
"mime" "mime"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/engine" "github.com/docker/docker/engine"
"github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/version" "github.com/docker/docker/pkg/version"
@ -31,6 +33,7 @@ func ValidateHost(val string) (string, error) {
} }
// TODO remove, used on < 1.5 in getContainersJSON // TODO remove, used on < 1.5 in getContainersJSON
// TODO this can go away when we get rid of engine.table
func DisplayablePorts(ports *engine.Table) string { func DisplayablePorts(ports *engine.Table) string {
var ( var (
result = []string{} result = []string{}
@ -80,6 +83,61 @@ func DisplayablePorts(ports *engine.Table) string {
return strings.Join(result, ", ") return strings.Join(result, ", ")
} }
type ByPrivatePort []types.Port
func (r ByPrivatePort) Len() int { return len(r) }
func (r ByPrivatePort) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r ByPrivatePort) Less(i, j int) bool { return r[i].PrivatePort < r[j].PrivatePort }
// TODO Rename to DisplayablePorts (remove "New") when engine.Table goes away
func NewDisplayablePorts(ports []types.Port) string {
var (
result = []string{}
hostMappings = []string{}
firstInGroupMap map[string]int
lastInGroupMap map[string]int
)
firstInGroupMap = make(map[string]int)
lastInGroupMap = make(map[string]int)
sort.Sort(ByPrivatePort(ports))
for _, port := range ports {
var (
current = port.PrivatePort
portKey = port.Type
firstInGroup int
lastInGroup int
)
if port.IP != "" {
if port.PublicPort != current {
hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type))
continue
}
portKey = fmt.Sprintf("%s/%s", port.IP, port.Type)
}
firstInGroup = firstInGroupMap[portKey]
lastInGroup = lastInGroupMap[portKey]
if firstInGroup == 0 {
firstInGroupMap[portKey] = current
lastInGroupMap[portKey] = current
continue
}
if current == (lastInGroup + 1) {
lastInGroupMap[portKey] = current
continue
}
result = append(result, FormGroup(portKey, firstInGroup, lastInGroup))
firstInGroupMap[portKey] = current
lastInGroupMap[portKey] = current
}
for portKey, firstInGroup := range firstInGroupMap {
result = append(result, FormGroup(portKey, firstInGroup, lastInGroupMap[portKey]))
}
result = append(result, hostMappings...)
return strings.Join(result, ", ")
}
func FormGroup(key string, start, last int) string { func FormGroup(key string, start, last int) string {
var ( var (
group string group string

View file

@ -56,3 +56,36 @@ type ImageDelete struct {
Untagged string `json:",omitempty"` Untagged string `json:",omitempty"`
Deleted string `json:",omitempty"` Deleted string `json:",omitempty"`
} }
// GET "/images/json"
type Image struct {
ID string `json:"Id"`
ParentId string
RepoTags []string
RepoDigests []string
Created int
Size int
VirtualSize int
Labels map[string]string
}
// GET "/containers/json"
type Port struct {
IP string
PrivatePort int
PublicPort int
Type string
}
type Container struct {
ID string `json:"Id"`
Names []string `json:,omitempty"`
Image string `json:,omitempty"`
Command string `json:,omitempty"`
Created int `json:,omitempty"`
Ports []Port `json:,omitempty"`
SizeRw int `json:,omitempty"`
SizeRootFs int `json:,omitempty"`
Labels map[string]string `json:,omitempty"`
Status string `json:,omitempty"`
}

View file

@ -1,18 +1,21 @@
package daemon package daemon
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"sort"
"strconv" "strconv"
"strings" "strings"
"github.com/docker/docker/graph" "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/graphdb"
"github.com/docker/docker/utils"
"github.com/docker/docker/engine" "github.com/docker/docker/engine"
"github.com/docker/docker/graph"
"github.com/docker/docker/nat"
"github.com/docker/docker/pkg/graphdb"
"github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/parsers/filters" "github.com/docker/docker/pkg/parsers/filters"
"github.com/docker/docker/utils"
) )
// List returns an array of all containers registered in the daemon. // List returns an array of all containers registered in the daemon.
@ -20,6 +23,12 @@ func (daemon *Daemon) List() []*Container {
return daemon.containers.List() return daemon.containers.List()
} }
type ByCreated []types.Container
func (r ByCreated) Len() int { return len(r) }
func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
func (daemon *Daemon) Containers(job *engine.Job) error { func (daemon *Daemon) Containers(job *engine.Job) error {
var ( var (
foundBefore bool foundBefore bool
@ -32,7 +41,7 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
psFilters filters.Args psFilters filters.Args
filtExited []int filtExited []int
) )
outs := engine.NewTable("Created", 0) containers := []types.Container{}
psFilters, err := filters.FromParam(job.Getenv("filters")) psFilters, err := filters.FromParam(job.Getenv("filters"))
if err != nil { if err != nil {
@ -126,15 +135,16 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
return nil return nil
} }
displayed++ displayed++
out := &engine.Env{} newC := types.Container{
out.SetJson("Id", container.ID) ID: container.ID,
out.SetList("Names", names[container.ID]) Names: names[container.ID],
}
img := container.Config.Image img := container.Config.Image
_, tag := parsers.ParseRepositoryTag(container.Config.Image) _, tag := parsers.ParseRepositoryTag(container.Config.Image)
if tag == "" { if tag == "" {
img = utils.ImageReference(img, graph.DEFAULTTAG) img = utils.ImageReference(img, graph.DEFAULTTAG)
} }
out.SetJson("Image", img) newC.Image = img
if len(container.Args) > 0 { if len(container.Args) > 0 {
args := []string{} args := []string{}
for _, arg := range container.Args { for _, arg := range container.Args {
@ -146,24 +156,41 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
} }
argsAsString := strings.Join(args, " ") argsAsString := strings.Join(args, " ")
out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString)) newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString)
} else { } else {
out.Set("Command", fmt.Sprintf("\"%s\"", container.Path)) newC.Command = fmt.Sprintf("%s", container.Path)
} }
out.SetInt64("Created", container.Created.Unix()) newC.Created = int(container.Created.Unix())
out.Set("Status", container.State.String()) newC.Status = container.State.String()
str, err := container.NetworkSettings.PortMappingAPI().ToListString()
if err != nil { newC.Ports = []types.Port{}
return err for port, bindings := range container.NetworkSettings.Ports {
p, _ := nat.ParsePort(port.Port())
if len(bindings) == 0 {
newC.Ports = append(newC.Ports, types.Port{
PrivatePort: p,
Type: port.Proto(),
})
continue
} }
out.Set("Ports", str) for _, binding := range bindings {
h, _ := nat.ParsePort(binding.HostPort)
newC.Ports = append(newC.Ports, types.Port{
PrivatePort: p,
PublicPort: h,
Type: port.Proto(),
IP: binding.HostIp,
})
}
}
if size { if size {
sizeRw, sizeRootFs := container.GetSize() sizeRw, sizeRootFs := container.GetSize()
out.SetInt64("SizeRw", sizeRw) newC.SizeRw = int(sizeRw)
out.SetInt64("SizeRootFs", sizeRootFs) newC.SizeRootFs = int(sizeRootFs)
} }
out.SetJson("Labels", container.Config.Labels) newC.Labels = container.Config.Labels
outs.Add(out) containers = append(containers, newC)
return nil return nil
} }
@ -175,8 +202,8 @@ func (daemon *Daemon) Containers(job *engine.Job) error {
break break
} }
} }
outs.ReverseSort() sort.Sort(sort.Reverse(ByCreated(containers)))
if _, err := outs.WriteListTo(job.Stdout); err != nil { if err = json.NewEncoder(job.Stdout).Encode(containers); err != nil {
return err return err
} }
return nil return nil

View file

@ -1,11 +1,14 @@
package graph package graph
import ( import (
"encoding/json"
"fmt" "fmt"
"log" "log"
"path" "path"
"sort"
"strings" "strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/engine" "github.com/docker/docker/engine"
"github.com/docker/docker/image" "github.com/docker/docker/image"
"github.com/docker/docker/pkg/parsers/filters" "github.com/docker/docker/pkg/parsers/filters"
@ -17,6 +20,12 @@ var acceptedImageFilterTags = map[string]struct{}{
"label": {}, "label": {},
} }
type ByCreated []*types.Image
func (r ByCreated) Len() int { return len(r) }
func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
func (s *TagStore) CmdImages(job *engine.Job) error { func (s *TagStore) CmdImages(job *engine.Job) error {
var ( var (
allImages map[string]*image.Image allImages map[string]*image.Image
@ -53,7 +62,8 @@ func (s *TagStore) CmdImages(job *engine.Job) error {
if err != nil { if err != nil {
return err return err
} }
lookup := make(map[string]*engine.Env)
lookup := make(map[string]*types.Image)
s.Lock() s.Lock()
for repoName, repository := range s.Repositories { for repoName, repository := range s.Repositories {
if job.Getenv("filter") != "" { if job.Getenv("filter") != "" {
@ -69,12 +79,12 @@ func (s *TagStore) CmdImages(job *engine.Job) error {
continue continue
} }
if out, exists := lookup[id]; exists { if lImage, exists := lookup[id]; exists {
if filtTagged { if filtTagged {
if utils.DigestReference(ref) { if utils.DigestReference(ref) {
out.SetList("RepoDigests", append(out.GetList("RepoDigests"), imgRef)) lImage.RepoDigests = append(lImage.RepoDigests, imgRef)
} else { // Tag Ref. } else { // Tag Ref.
out.SetList("RepoTags", append(out.GetList("RepoTags"), imgRef)) lImage.RepoTags = append(lImage.RepoTags, imgRef)
} }
} }
} else { } else {
@ -84,23 +94,23 @@ func (s *TagStore) CmdImages(job *engine.Job) error {
continue continue
} }
if filtTagged { if filtTagged {
out := &engine.Env{} newImage := new(types.Image)
out.SetJson("ParentId", image.Parent) newImage.ParentId = image.Parent
out.SetJson("Id", image.ID) newImage.ID = image.ID
out.SetInt64("Created", image.Created.Unix()) newImage.Created = int(image.Created.Unix())
out.SetInt64("Size", image.Size) newImage.Size = int(image.Size)
out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size) newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size)
out.SetJson("Labels", image.ContainerConfig.Labels) newImage.Labels = image.ContainerConfig.Labels
if utils.DigestReference(ref) { if utils.DigestReference(ref) {
out.SetList("RepoTags", []string{}) newImage.RepoTags = []string{}
out.SetList("RepoDigests", []string{imgRef}) newImage.RepoDigests = []string{imgRef}
} else { } else {
out.SetList("RepoTags", []string{imgRef}) newImage.RepoTags = []string{imgRef}
out.SetList("RepoDigests", []string{}) newImage.RepoDigests = []string{}
} }
lookup[id] = out lookup[id] = newImage
} }
} }
@ -108,9 +118,9 @@ func (s *TagStore) CmdImages(job *engine.Job) error {
} }
s.Unlock() s.Unlock()
outs := engine.NewTable("Created", len(lookup)) images := []*types.Image{}
for _, value := range lookup { for _, value := range lookup {
outs.Add(value) images = append(images, value)
} }
// Display images which aren't part of a repository/tag // Display images which aren't part of a repository/tag
@ -119,21 +129,23 @@ func (s *TagStore) CmdImages(job *engine.Job) error {
if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) { if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
continue continue
} }
out := &engine.Env{} newImage := new(types.Image)
out.SetJson("ParentId", image.Parent) newImage.ParentId = image.Parent
out.SetList("RepoTags", []string{"<none>:<none>"}) newImage.RepoTags = []string{"<none>:<none>"}
out.SetList("RepoDigests", []string{"<none>@<none>"}) newImage.RepoDigests = []string{"<none>@<none>"}
out.SetJson("Id", image.ID) newImage.ID = image.ID
out.SetInt64("Created", image.Created.Unix()) newImage.Created = int(image.Created.Unix())
out.SetInt64("Size", image.Size) newImage.Size = int(image.Size)
out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size) newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size)
out.SetJson("Labels", image.ContainerConfig.Labels) newImage.Labels = image.ContainerConfig.Labels
outs.Add(out)
images = append(images, newImage)
} }
} }
outs.ReverseSort() sort.Sort(sort.Reverse(ByCreated(images)))
if _, err := outs.WriteListTo(job.Stdout); err != nil {
if err = json.NewEncoder(job.Stdout).Encode(images); err != nil {
return err return err
} }
return nil return nil