diff --git a/command/checkpoint/list.go b/command/checkpoint/list.go index daf8349993..20e7d6d73a 100644 --- a/command/checkpoint/list.go +++ b/command/checkpoint/list.go @@ -1,14 +1,12 @@ package checkpoint import ( - "fmt" - "text/tabwriter" - "golang.org/x/net/context" "github.com/docker/docker/api/types" "github.com/docker/docker/cli" "github.com/docker/docker/cli/command" + "github.com/docker/docker/cli/command/formatter" "github.com/spf13/cobra" ) @@ -48,15 +46,9 @@ func runList(dockerCli *command.DockerCli, container string, opts listOptions) e return err } - w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) - fmt.Fprintf(w, "CHECKPOINT NAME") - fmt.Fprintf(w, "\n") - - for _, checkpoint := range checkpoints { - fmt.Fprintf(w, "%s\t", checkpoint.Name) - fmt.Fprint(w, "\n") + cpCtx := formatter.Context{ + Output: dockerCli.Out(), + Format: formatter.NewCheckpointFormat(formatter.TableFormatKey), } - - w.Flush() - return nil + return formatter.CheckpointWrite(cpCtx, checkpoints) } diff --git a/command/formatter/checkpoint.go b/command/formatter/checkpoint.go new file mode 100644 index 0000000000..041fcafb7d --- /dev/null +++ b/command/formatter/checkpoint.go @@ -0,0 +1,52 @@ +package formatter + +import "github.com/docker/docker/api/types" + +const ( + defaultCheckpointFormat = "table {{.Name}}" + + checkpointNameHeader = "CHECKPOINT NAME" +) + +// NewCheckpointFormat returns a format for use with a checkpoint Context +func NewCheckpointFormat(source string) Format { + switch source { + case TableFormatKey: + return defaultCheckpointFormat + } + return Format(source) +} + +// CheckpointWrite writes formatted checkpoints using the Context +func CheckpointWrite(ctx Context, checkpoints []types.Checkpoint) error { + render := func(format func(subContext subContext) error) error { + for _, checkpoint := range checkpoints { + if err := format(&checkpointContext{c: checkpoint}); err != nil { + return err + } + } + return nil + } + return ctx.Write(newCheckpointContext(), render) +} + +type checkpointContext struct { + HeaderContext + c types.Checkpoint +} + +func newCheckpointContext() *checkpointContext { + cpCtx := checkpointContext{} + cpCtx.header = volumeHeaderContext{ + "Name": checkpointNameHeader, + } + return &cpCtx +} + +func (c *checkpointContext) MarshalJSON() ([]byte, error) { + return marshalJSON(c) +} + +func (c *checkpointContext) Name() string { + return c.c.Name +} diff --git a/command/formatter/checkpoint_test.go b/command/formatter/checkpoint_test.go new file mode 100644 index 0000000000..e88c4d0132 --- /dev/null +++ b/command/formatter/checkpoint_test.go @@ -0,0 +1,55 @@ +package formatter + +import ( + "bytes" + "testing" + + "github.com/docker/docker/api/types" + "github.com/stretchr/testify/assert" +) + +func TestCheckpointContextFormatWrite(t *testing.T) { + cases := []struct { + context Context + expected string + }{ + { + Context{Format: NewCheckpointFormat(defaultCheckpointFormat)}, + `CHECKPOINT NAME +checkpoint-1 +checkpoint-2 +checkpoint-3 +`, + }, + { + Context{Format: NewCheckpointFormat("{{.Name}}")}, + `checkpoint-1 +checkpoint-2 +checkpoint-3 +`, + }, + { + Context{Format: NewCheckpointFormat("{{.Name}}:")}, + `checkpoint-1: +checkpoint-2: +checkpoint-3: +`, + }, + } + + checkpoints := []types.Checkpoint{ + {"checkpoint-1"}, + {"checkpoint-2"}, + {"checkpoint-3"}, + } + for _, testcase := range cases { + out := bytes.NewBufferString("") + testcase.context.Output = out + err := CheckpointWrite(testcase.context, checkpoints) + if err != nil { + assert.Error(t, err, testcase.expected) + } else { + assert.Equal(t, out.String(), testcase.expected) + } + } +}