mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add format to the docker system df command
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
This commit is contained in:
parent
9518a71cef
commit
985a9c7047
4 changed files with 168 additions and 14 deletions
|
@ -45,15 +45,33 @@ func (ctx *DiskUsageContext) startSubsection(format string) (*template.Template,
|
|||
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 {
|
||||
ctx.buffer = bytes.NewBufferString("")
|
||||
ctx.Format = defaultDiskUsageTableFormat
|
||||
ctx.preFormat()
|
||||
|
||||
tmpl, err := ctx.parseFormat()
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctx.contextFormat(tmpl, &diskUsageImagesContext{
|
||||
|
@ -61,20 +79,20 @@ func (ctx *DiskUsageContext) Write() {
|
|||
images: ctx.Images,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
err = ctx.contextFormat(tmpl, &diskUsageContainersContext{
|
||||
containers: ctx.Containers,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
err = ctx.contextFormat(tmpl, &diskUsageVolumesContext{
|
||||
volumes: ctx.Volumes,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
diskUsageContainersCtx := diskUsageContainersContext{containers: []*types.Container{}}
|
||||
|
@ -87,7 +105,7 @@ func (ctx *DiskUsageContext) Write() {
|
|||
}
|
||||
ctx.postFormat(tmpl, &diskUsageContainersCtx)
|
||||
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// First images
|
||||
|
@ -158,6 +176,7 @@ func (ctx *DiskUsageContext) Write() {
|
|||
}
|
||||
}
|
||||
ctx.postFormat(tmpl, newVolumeContext())
|
||||
return
|
||||
}
|
||||
|
||||
type diskUsageImagesContext struct {
|
||||
|
|
|
@ -8,13 +8,17 @@ import (
|
|||
)
|
||||
|
||||
func TestDiskUsageContextFormatWrite(t *testing.T) {
|
||||
// Check default output format (verbose and non-verbose mode) for table headers
|
||||
cases := []struct {
|
||||
context DiskUsageContext
|
||||
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
|
||||
Images 0 0 0B 0B
|
||||
Containers 0 0 0B 0B
|
||||
|
@ -34,6 +38,77 @@ CONTAINER ID IMAGE COMMAND LOCAL VOLUMES
|
|||
Local Volumes space usage:
|
||||
|
||||
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 {
|
||||
out := bytes.NewBufferString("")
|
||||
testcase.context.Output = out
|
||||
testcase.context.Write()
|
||||
assert.Equal(t, out.String(), testcase.expected)
|
||||
if err := testcase.context.Write(); err != nil {
|
||||
assert.Equal(t, err.Error(), testcase.expected)
|
||||
} else {
|
||||
assert.Equal(t, out.String(), testcase.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/cli/command"
|
||||
"github.com/docker/docker/cli/command/formatter"
|
||||
|
@ -10,6 +12,7 @@ import (
|
|||
|
||||
type diskUsageOptions struct {
|
||||
verbose bool
|
||||
format string
|
||||
}
|
||||
|
||||
// NewDiskUsageCommand creates a new cobra.Command for `docker df`
|
||||
|
@ -29,19 +32,30 @@ func NewDiskUsageCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|||
flags := cmd.Flags()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
format := opts.format
|
||||
if len(format) == 0 {
|
||||
format = formatter.TableFormatKey
|
||||
}
|
||||
|
||||
duCtx := formatter.DiskUsageContext{
|
||||
Context: formatter.Context{
|
||||
Output: dockerCli.Out(),
|
||||
Format: formatter.NewDiskUsageFormat(format),
|
||||
},
|
||||
LayersSize: du.LayersSize,
|
||||
Images: du.Images,
|
||||
|
@ -50,7 +64,5 @@ func runDiskUsage(dockerCli *command.DockerCli, opts diskUsageOptions) error {
|
|||
Verbose: opts.verbose,
|
||||
}
|
||||
|
||||
duCtx.Write()
|
||||
|
||||
return nil
|
||||
return duCtx.Write()
|
||||
}
|
||||
|
|
|
@ -86,6 +86,51 @@ volumes or in systems where some images, containers, or volumes have very large
|
|||
filesystems with many files. You should also be careful not to run this command
|
||||
in systems where performance is critical.
|
||||
|
||||
## Format the output
|
||||
|
||||
The formatting option (`--format`) pretty prints the disk usage output
|
||||
using a Go template.
|
||||
|
||||
Valid placeholders for the Go template are listed below:
|
||||
|
||||
| Placeholder | Description |
|
||||
| -------------- | ------------------------------------------ |
|
||||
| `.Type` | `Images`, `Containers` and `Local Volumes` |
|
||||
| `.TotalCount` | Total number of items |
|
||||
| `.Active` | Number of active items |
|
||||
| `.Size` | Available size |
|
||||
| `.Reclaimable` | Reclaimable size |
|
||||
|
||||
When using the `--format` option, the `system df` command outputs
|
||||
the data exactly as the template declares or, when using the
|
||||
`table` directive, will include column headers as well.
|
||||
|
||||
The following example uses a template without headers and outputs the
|
||||
`Type` and `TotalCount` entries separated by a colon:
|
||||
|
||||
```bash
|
||||
$ docker system df --format "{{.Type}}: {{.TotalCount}}"
|
||||
|
||||
Images: 2
|
||||
Containers: 4
|
||||
Local Volumes: 1
|
||||
```
|
||||
|
||||
To list the disk usage with size and reclaimable size in a table format you
|
||||
can use:
|
||||
|
||||
```bash
|
||||
$ docker system df --format "table {{.Type}}\t{{.Size}}\t{{.Reclaimable}}"
|
||||
|
||||
TYPE SIZE RECLAIMABLE
|
||||
Images 2.547 GB 2.342 GB (91%)
|
||||
Containers 0 B 0 B
|
||||
Local Volumes 150.3 MB 150.3 MB (100%)
|
||||
<Paste>
|
||||
```
|
||||
|
||||
**Note** the format option is meaningless when verbose is true.
|
||||
|
||||
## Related commands
|
||||
* [system prune](system_prune.md)
|
||||
* [container prune](container_prune.md)
|
||||
|
|
Loading…
Reference in a new issue