Add format to the docker system df command

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
This commit is contained in:
Boaz Shuster 2017-03-02 14:05:48 +02:00
parent d37d03c9dc
commit a2273ea372
3 changed files with 123 additions and 14 deletions

View File

@ -45,15 +45,33 @@ func (ctx *DiskUsageContext) startSubsection(format string) (*template.Template,
return ctx.parseFormat() return ctx.parseFormat()
} }
func (ctx *DiskUsageContext) Write() { //
// NewDiskUsageFormat returns a format for rendering an DiskUsageContext
func NewDiskUsageFormat(source string) Format {
switch source {
case TableFormatKey:
format := defaultDiskUsageTableFormat
return Format(format)
case RawFormatKey:
format := `type: {{.Type}}
total: {{.TotalCount}}
active: {{.Active}}
size: {{.Size}}
reclaimable: {{.Reclaimable}}
`
return Format(format)
}
return Format(source)
}
func (ctx *DiskUsageContext) Write() (err error) {
if ctx.Verbose == false { if ctx.Verbose == false {
ctx.buffer = bytes.NewBufferString("") ctx.buffer = bytes.NewBufferString("")
ctx.Format = defaultDiskUsageTableFormat
ctx.preFormat() ctx.preFormat()
tmpl, err := ctx.parseFormat() tmpl, err := ctx.parseFormat()
if err != nil { if err != nil {
return return err
} }
err = ctx.contextFormat(tmpl, &diskUsageImagesContext{ err = ctx.contextFormat(tmpl, &diskUsageImagesContext{
@ -61,20 +79,20 @@ func (ctx *DiskUsageContext) Write() {
images: ctx.Images, images: ctx.Images,
}) })
if err != nil { if err != nil {
return return err
} }
err = ctx.contextFormat(tmpl, &diskUsageContainersContext{ err = ctx.contextFormat(tmpl, &diskUsageContainersContext{
containers: ctx.Containers, containers: ctx.Containers,
}) })
if err != nil { if err != nil {
return return err
} }
err = ctx.contextFormat(tmpl, &diskUsageVolumesContext{ err = ctx.contextFormat(tmpl, &diskUsageVolumesContext{
volumes: ctx.Volumes, volumes: ctx.Volumes,
}) })
if err != nil { if err != nil {
return return err
} }
diskUsageContainersCtx := diskUsageContainersContext{containers: []*types.Container{}} diskUsageContainersCtx := diskUsageContainersContext{containers: []*types.Container{}}
@ -87,7 +105,7 @@ func (ctx *DiskUsageContext) Write() {
} }
ctx.postFormat(tmpl, &diskUsageContainersCtx) ctx.postFormat(tmpl, &diskUsageContainersCtx)
return return err
} }
// First images // First images
@ -158,6 +176,7 @@ func (ctx *DiskUsageContext) Write() {
} }
} }
ctx.postFormat(tmpl, newVolumeContext()) ctx.postFormat(tmpl, newVolumeContext())
return
} }
type diskUsageImagesContext struct { type diskUsageImagesContext struct {

View File

@ -8,13 +8,17 @@ import (
) )
func TestDiskUsageContextFormatWrite(t *testing.T) { func TestDiskUsageContextFormatWrite(t *testing.T) {
// Check default output format (verbose and non-verbose mode) for table headers
cases := []struct { cases := []struct {
context DiskUsageContext context DiskUsageContext
expected string expected string
}{ }{
// Check default output format (verbose and non-verbose mode) for table headers
{ {
DiskUsageContext{Verbose: false}, DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table"),
},
Verbose: false},
`TYPE TOTAL ACTIVE SIZE RECLAIMABLE `TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 0 0 0B 0B Images 0 0 0B 0B
Containers 0 0 0B 0B Containers 0 0 0B 0B
@ -34,6 +38,77 @@ CONTAINER ID IMAGE COMMAND LOCAL VOLUMES
Local Volumes space usage: Local Volumes space usage:
VOLUME NAME LINKS SIZE VOLUME NAME LINKS SIZE
`,
},
// Errors
{
DiskUsageContext{
Context: Context{
Format: "{{InvalidFunction}}",
},
},
`Template parsing error: template: :1: function "InvalidFunction" not defined
`,
},
{
DiskUsageContext{
Context: Context{
Format: "{{nil}}",
},
},
`Template parsing error: template: :1:2: executing "" at <nil>: nil is not a command
`,
},
// Table Format
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table"),
},
},
`TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 0 0 0B 0B
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
`,
},
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}"),
},
},
`TYPE ACTIVE
Images 0
Containers 0
Local Volumes 0
`,
},
// Raw Format
{
DiskUsageContext{
Context: Context{
Format: NewDiskUsageFormat("raw"),
},
},
`type: Images
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Containers
total: 0
active: 0
size: 0B
reclaimable: 0B
type: Local Volumes
total: 0
active: 0
size: 0B
reclaimable: 0B
`, `,
}, },
} }
@ -41,7 +116,10 @@ VOLUME NAME LINKS SIZE
for _, testcase := range cases { for _, testcase := range cases {
out := bytes.NewBufferString("") out := bytes.NewBufferString("")
testcase.context.Output = out testcase.context.Output = out
testcase.context.Write() if err := testcase.context.Write(); err != nil {
assert.Equal(t, err.Error(), testcase.expected)
} else {
assert.Equal(t, out.String(), testcase.expected) assert.Equal(t, out.String(), testcase.expected)
} }
}
} }

View File

@ -1,6 +1,8 @@
package system package system
import ( import (
"errors"
"github.com/docker/docker/cli" "github.com/docker/docker/cli"
"github.com/docker/docker/cli/command" "github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/formatter" "github.com/docker/docker/cli/command/formatter"
@ -10,6 +12,7 @@ import (
type diskUsageOptions struct { type diskUsageOptions struct {
verbose bool verbose bool
format string
} }
// NewDiskUsageCommand creates a new cobra.Command for `docker df` // NewDiskUsageCommand creates a new cobra.Command for `docker df`
@ -29,19 +32,30 @@ func NewDiskUsageCommand(dockerCli *command.DockerCli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.BoolVarP(&opts.verbose, "verbose", "v", false, "Show detailed information on space usage") flags.BoolVarP(&opts.verbose, "verbose", "v", false, "Show detailed information on space usage")
flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template")
return cmd return cmd
} }
func runDiskUsage(dockerCli *command.DockerCli, opts diskUsageOptions) error { func runDiskUsage(dockerCli *command.DockerCli, 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()) du, err := dockerCli.Client().DiskUsage(context.Background())
if err != nil { if err != nil {
return err return err
} }
format := opts.format
if len(format) == 0 {
format = formatter.TableFormatKey
}
duCtx := formatter.DiskUsageContext{ duCtx := formatter.DiskUsageContext{
Context: formatter.Context{ Context: formatter.Context{
Output: dockerCli.Out(), Output: dockerCli.Out(),
Format: formatter.NewDiskUsageFormat(format),
}, },
LayersSize: du.LayersSize, LayersSize: du.LayersSize,
Images: du.Images, Images: du.Images,
@ -50,7 +64,5 @@ func runDiskUsage(dockerCli *command.DockerCli, opts diskUsageOptions) error {
Verbose: opts.verbose, Verbose: opts.verbose,
} }
duCtx.Write() return duCtx.Write()
return nil
} }