Merge pull request #1386 from tiborvass/18.09-df-verbose-format-raw

[18.09] system/df: allow -v with --format
This commit is contained in:
Andrew Hsu 2018-09-22 00:25:21 -07:00 committed by GitHub
commit 5ba5678898
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 53 deletions

View File

@ -15,6 +15,7 @@ const (
defaultBuildCacheTableFormat = "table {{.ID}}\t{{.Type}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}\t{{.Description}}"
cacheIDHeader = "CACHE ID"
cacheTypeHeader = "CACHE TYPE"
parentHeader = "PARENT"
lastUsedSinceHeader = "LAST USED"
usageCountHeader = "USAGE"
@ -36,10 +37,12 @@ func NewBuildCacheFormat(source string, quiet bool) Format {
}
format := `build_cache_id: {{.ID}}
parent_id: {{.Parent}}
type: {{.Type}}
build_cache_type: {{.CacheType}}
description: {{.Description}}
created_at: {{.CreatedSince}}
last_used_at: {{.LastUsedSince}}
created_at: {{.CreatedAt}}
created_since: {{.CreatedSince}}
last_used_at: {{.LastUsedAt}}
last_used_since: {{.LastUsedSince}}
usage_count: {{.UsageCount}}
in_use: {{.InUse}}
shared: {{.Shared}}
@ -95,7 +98,7 @@ func newBuildCacheContext() *buildCacheContext {
buildCacheCtx.header = buildCacheHeaderContext{
"ID": cacheIDHeader,
"Parent": parentHeader,
"Type": typeHeader,
"CacheType": cacheTypeHeader,
"Size": sizeHeader,
"CreatedSince": createdSinceHeader,
"LastUsedSince": lastUsedSinceHeader,
@ -129,7 +132,7 @@ func (c *buildCacheContext) Parent() string {
return c.v.Parent
}
func (c *buildCacheContext) Type() string {
func (c *buildCacheContext) CacheType() string {
return c.v.Type
}
@ -141,10 +144,21 @@ func (c *buildCacheContext) Size() string {
return units.HumanSizeWithPrecision(float64(c.v.Size), 3)
}
func (c *buildCacheContext) CreatedAt() string {
return c.v.CreatedAt.String()
}
func (c *buildCacheContext) CreatedSince() string {
return units.HumanDuration(time.Now().UTC().Sub(c.v.CreatedAt)) + " ago"
}
func (c *buildCacheContext) LastUsedAt() string {
if c.v.LastUsedAt == nil {
return ""
}
return c.v.LastUsedAt.String()
}
func (c *buildCacheContext) LastUsedSince() string {
if c.v.LastUsedAt == nil {
return ""

View File

@ -15,8 +15,8 @@ const (
defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}"
defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}}\t{{.Status}}\t{{.Names}}"
defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}"
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.CacheType}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
defaultDiskUsageTableFormat = "table {{.Type}}\t{{.TotalCount}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}"
defaultDiskUsageBuildCacheTableFormat = "table {{.ID}}\t{{.Type}}\t{{.Size}}\t{{.CreatedSince}}\t{{.LastUsedSince}}\t{{.UsageCount}}\t{{.Shared}}"
typeHeader = "TYPE"
totalHeader = "TOTAL"
@ -49,12 +49,25 @@ func (ctx *DiskUsageContext) startSubsection(format string) (*template.Template,
}
// NewDiskUsageFormat returns a format for rendering an DiskUsageContext
func NewDiskUsageFormat(source string) Format {
switch source {
case TableFormatKey:
format := defaultDiskUsageTableFormat
return Format(format)
case RawFormatKey:
func NewDiskUsageFormat(source string, verbose bool) Format {
switch {
case verbose && source == RawFormatKey:
format := `{{range .Images}}type: Image
` + NewImageFormat(source, false, true) + `
{{end -}}
{{range .Containers}}type: Container
` + NewContainerFormat(source, false, true) + `
{{end -}}
{{range .Volumes}}type: Volume
` + NewVolumeFormat(source, false) + `
{{end -}}
{{range .BuildCache}}type: Build Cache
` + NewBuildCacheFormat(source, false) + `
{{end -}}`
return format
case !verbose && source == TableFormatKey:
return Format(defaultDiskUsageTableFormat)
case !verbose && source == RawFormatKey:
format := `type: {{.Type}}
total: {{.TotalCount}}
active: {{.Active}}
@ -62,8 +75,9 @@ size: {{.Size}}
reclaimable: {{.Reclaimable}}
`
return Format(format)
}
default:
return Format(source)
}
}
func (ctx *DiskUsageContext) Write() (err error) {
@ -120,15 +134,23 @@ func (ctx *DiskUsageContext) Write() (err error) {
return err
}
// nolint: gocyclo
func (ctx *DiskUsageContext) verboseWrite() error {
// First images
tmpl, err := ctx.startSubsection(defaultDiskUsageImageTableFormat)
if err != nil {
return err
}
type diskUsageContext struct {
Images []*imageContext
Containers []*containerContext
Volumes []*volumeContext
BuildCache []*buildCacheContext
}
ctx.Output.Write([]byte("Images space usage:\n\n"))
func (ctx *DiskUsageContext) verboseWrite() error {
duc := &diskUsageContext{
Images: make([]*imageContext, 0, len(ctx.Images)),
Containers: make([]*containerContext, 0, len(ctx.Containers)),
Volumes: make([]*volumeContext, 0, len(ctx.Volumes)),
BuildCache: make([]*buildCacheContext, 0, len(ctx.BuildCache)),
}
trunc := ctx.Format.IsTable()
// First images
for _, i := range ctx.Images {
repo := "<none>"
tag := "<none>"
@ -144,57 +166,88 @@ func (ctx *DiskUsageContext) verboseWrite() error {
}
}
err := ctx.contextFormat(tmpl, &imageContext{
duc.Images = append(duc.Images, &imageContext{
repo: repo,
tag: tag,
trunc: true,
trunc: trunc,
i: *i,
})
}
// Now containers
for _, c := range ctx.Containers {
// Don't display the virtual size
c.SizeRootFs = 0
duc.Containers = append(duc.Containers, &containerContext{trunc: trunc, c: *c})
}
// And volumes
for _, v := range ctx.Volumes {
duc.Volumes = append(duc.Volumes, &volumeContext{v: *v})
}
// And build cache
buildCacheSort(ctx.BuildCache)
for _, v := range ctx.BuildCache {
duc.BuildCache = append(duc.BuildCache, &buildCacheContext{v: v, trunc: trunc})
}
if ctx.Format == TableFormatKey {
return ctx.verboseWriteTable(duc)
}
ctx.preFormat()
tmpl, err := ctx.parseFormat()
if err != nil {
return err
}
return tmpl.Execute(ctx.Output, duc)
}
func (ctx *DiskUsageContext) verboseWriteTable(duc *diskUsageContext) error {
tmpl, err := ctx.startSubsection(defaultDiskUsageImageTableFormat)
if err != nil {
return err
}
ctx.Output.Write([]byte("Images space usage:\n\n"))
for _, img := range duc.Images {
if err := ctx.contextFormat(tmpl, img); err != nil {
return err
}
}
ctx.postFormat(tmpl, newImageContext())
// Now containers
ctx.Output.Write([]byte("\nContainers space usage:\n\n"))
tmpl, err = ctx.startSubsection(defaultDiskUsageContainerTableFormat)
if err != nil {
return err
}
for _, c := range ctx.Containers {
// Don't display the virtual size
c.SizeRootFs = 0
err := ctx.contextFormat(tmpl, &containerContext{trunc: true, c: *c})
if err != nil {
ctx.Output.Write([]byte("\nContainers space usage:\n\n"))
for _, c := range duc.Containers {
if err := ctx.contextFormat(tmpl, c); err != nil {
return err
}
}
ctx.postFormat(tmpl, newContainerContext())
// And volumes
ctx.Output.Write([]byte("\nLocal Volumes space usage:\n\n"))
tmpl, err = ctx.startSubsection(defaultDiskUsageVolumeTableFormat)
if err != nil {
return err
}
for _, v := range ctx.Volumes {
if err := ctx.contextFormat(tmpl, &volumeContext{v: *v}); err != nil {
ctx.Output.Write([]byte("\nLocal Volumes space usage:\n\n"))
for _, v := range duc.Volumes {
if err := ctx.contextFormat(tmpl, v); err != nil {
return err
}
}
ctx.postFormat(tmpl, newVolumeContext())
// And build cache
fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize)))
tmpl, err = ctx.startSubsection(defaultDiskUsageBuildCacheTableFormat)
if err != nil {
return err
}
buildCacheSort(ctx.BuildCache)
for _, v := range ctx.BuildCache {
if err := ctx.contextFormat(tmpl, &buildCacheContext{v: v, trunc: true}); err != nil {
fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize)))
for _, v := range duc.BuildCache {
if err := ctx.contextFormat(tmpl, v); err != nil {
return err
}
}

View File

@ -18,7 +18,7 @@ func TestDiskUsageContextFormatWrite(t *testing.T) {
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table"),
Format: NewDiskUsageFormat("table", false),
},
Verbose: false},
`TYPE TOTAL ACTIVE SIZE RECLAIMABLE
@ -29,7 +29,7 @@ Build Cache 0 0 0B
`,
},
{
DiskUsageContext{Verbose: true},
DiskUsageContext{Verbose: true, Context: Context{Format: NewDiskUsageFormat("table", true)}},
`Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
@ -44,9 +44,17 @@ VOLUME NAME LINKS SIZE
Build cache usage: 0B
CACHE ID TYPE SIZE CREATED LAST USED USAGE SHARED
CACHE ID CACHE TYPE SIZE CREATED LAST USED USAGE SHARED
`,
},
{
DiskUsageContext{Verbose: true, Context: Context{Format: NewDiskUsageFormat("raw", true)}},
``,
},
{
DiskUsageContext{Verbose: true, Context: Context{Format: NewDiskUsageFormat("{{json .}}", true)}},
`{"Images":[],"Containers":[],"Volumes":[],"BuildCache":[]}`,
},
// Errors
{
DiskUsageContext{
@ -70,7 +78,7 @@ CACHE ID TYPE SIZE CREATED
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table"),
Format: NewDiskUsageFormat("table", false),
},
},
`TYPE TOTAL ACTIVE SIZE RECLAIMABLE
@ -83,7 +91,7 @@ Build Cache 0 0 0B
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}"),
Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}", false),
},
},
string(golden.Get(t, "disk-usage-context-write-custom.golden")),
@ -92,7 +100,7 @@ Build Cache 0 0 0B
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("raw"),
Format: NewDiskUsageFormat("raw", false),
},
},
string(golden.Get(t, "disk-usage-raw-format.golden")),

View File

@ -2,7 +2,6 @@ package system
import (
"context"
"errors"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -38,10 +37,6 @@ func newDiskUsageCommand(dockerCli command.Cli) *cobra.Command {
}
func runDiskUsage(dockerCli command.Cli, opts diskUsageOptions) error {
if opts.verbose && len(opts.format) != 0 {
return errors.New("the verbose and the format options conflict")
}
du, err := dockerCli.Client().DiskUsage(context.Background())
if err != nil {
return err
@ -62,7 +57,7 @@ func runDiskUsage(dockerCli command.Cli, opts diskUsageOptions) error {
duCtx := formatter.DiskUsageContext{
Context: formatter.Context{
Output: dockerCli.Out(),
Format: formatter.NewDiskUsageFormat(format),
Format: formatter.NewDiskUsageFormat(format, opts.verbose),
},
LayersSize: du.LayersSize,
BuilderSize: bsz,