Improved 'docker layers': sort by added date, -l to show only N most recent

This commit is contained in:
Solomon Hykes 2013-01-20 14:13:25 -08:00
Родитель f154ebf744
Коммит bf46593505
1 изменённых файлов: 57 добавлений и 15 удалений

Просмотреть файл

@ -18,10 +18,10 @@ import (
"crypto/sha256" "crypto/sha256"
"bytes" "bytes"
"text/tabwriter" "text/tabwriter"
"sort"
) )
func (docker *Docker) CmdHelp(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (docker *Docker) CmdHelp(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
log.Printf("Help %s\n", args)
if len(args) == 0 { if len(args) == 0 {
fmt.Fprintf(stdout, "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n") fmt.Fprintf(stdout, "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n")
for _, cmd := range [][]interface{}{ for _, cmd := range [][]interface{}{
@ -52,6 +52,7 @@ func (docker *Docker) CmdHelp(stdin io.ReadCloser, stdout io.Writer, args ...str
func (docker *Docker) CmdLayers(stdin io.ReadCloser, stdout io.Writer, args ...string) error { func (docker *Docker) CmdLayers(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
flags := Subcmd(stdout, "layers", "[OPTIONS] [NAME]", "Show available filesystem layers") flags := Subcmd(stdout, "layers", "[OPTIONS] [NAME]", "Show available filesystem layers")
quiet := flags.Bool("q", false, "Quiet mode") quiet := flags.Bool("q", false, "Quiet mode")
limit := flags.Int("l", 0, "Only show the N most recent versions of each layer")
flags.Parse(args) flags.Parse(args)
if flags.NArg() > 1 { if flags.NArg() > 1 {
flags.Usage() flags.Usage()
@ -61,22 +62,31 @@ func (docker *Docker) CmdLayers(stdin io.ReadCloser, stdout io.Writer, args ...s
if flags.NArg() == 1 { if flags.NArg() == 1 {
nameFilter = flags.Arg(0) nameFilter = flags.Arg(0)
} }
if *quiet { var names []string
for id, layer := range docker.layers { for name := range docker.layersByName {
if nameFilter != "" && nameFilter != layer.Name { names = append(names, name)
continue }
} sort.Strings(names)
stdout.Write([]byte(id+ "\n")) w := tabwriter.NewWriter(stdout, 20, 1, 3, ' ', 0)
} if (!*quiet) {
} else {
w := tabwriter.NewWriter(stdout, 20, 1, 3, ' ', 0)
fmt.Fprintf(w, "ID\tNAME\tSIZE\tADDED\tSOURCE\n") fmt.Fprintf(w, "ID\tNAME\tSIZE\tADDED\tSOURCE\n")
for _, layer := range docker.layers { }
if nameFilter != "" && nameFilter != layer.Name { for _, name := range names {
continue if nameFilter != "" && nameFilter != name {
} continue
fmt.Fprintf(w, "%s\t%s\t%.1fM\t%s ago\t%s\n", layer.Id, layer.Name, float32(layer.Size) / 1024 / 1024, humanDuration(time.Now().Sub(layer.Added)), layer.Source)
} }
for idx, layer := range *docker.layersByName[name] {
if *limit > 0 && idx >= *limit {
break
}
if !*quiet {
fmt.Fprintf(w, "%s\t%s\t%.1fM\t%s ago\t%s\n", layer.Id, layer.Name, float32(layer.Size) / 1024 / 1024, humanDuration(time.Now().Sub(layer.Added)), layer.Source)
} else {
stdout.Write([]byte(layer.Id + "\n"))
}
}
}
if (!*quiet) {
w.Flush() w.Flush()
} }
return nil return nil
@ -124,12 +134,42 @@ func (docker *Docker) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...s
} }
// ByDate wraps an array of layers so they can be sorted by date (most recent first)
type ByDate []*Layer
func (l *ByDate) Len() int {
return len(*l)
}
func (l *ByDate) Less(i, j int) bool {
layers := *l
return layers[j].Added.Before(layers[i].Added)
}
func (l *ByDate) Swap(i, j int) {
layers := *l
tmp := layers[i]
layers[i] = layers[j]
layers[j] = tmp
}
func (l *ByDate) Add(layer *Layer) {
*l = append(*l, layer)
sort.Sort(l)
}
func (docker *Docker) addLayer(name string, source string, size uint) Layer { func (docker *Docker) addLayer(name string, source string, size uint) Layer {
if size == 0 { if size == 0 {
size = uint(rand.Int31n(142 * 1024 * 1024)) size = uint(rand.Int31n(142 * 1024 * 1024))
} }
layer := Layer{Id: randomId(), Name: name, Source: source, Added: time.Now(), Size: size} layer := Layer{Id: randomId(), Name: name, Source: source, Added: time.Now(), Size: size}
docker.layers[layer.Id] = layer docker.layers[layer.Id] = layer
if _, exists := docker.layersByName[layer.Name]; !exists {
docker.layersByName[layer.Name] = new(ByDate)
}
docker.layersByName[layer.Name].Add(&layer)
return layer return layer
} }
@ -275,6 +315,7 @@ func main() {
func New() *Docker { func New() *Docker {
return &Docker{ return &Docker{
layers: make(map[string]Layer), layers: make(map[string]Layer),
layersByName: make(map[string]*ByDate),
containers: make(map[string]Container), containers: make(map[string]Container),
} }
} }
@ -346,6 +387,7 @@ func Go(f func() error) chan error {
type Docker struct { type Docker struct {
layers map[string]Layer layers map[string]Layer
layersByName map[string]*ByDate
containers map[string]Container containers map[string]Container
} }