Browse code

Merge pull request #31800 from ripcurld0/checkpoint_ls

Use formatter in docker checkpoint ls

Victor Vieux authored on 2017/04/01 07:54:22
Showing 3 changed files
... ...
@@ -1,14 +1,12 @@
1 1
 package checkpoint
2 2
 
3 3
 import (
4
-	"fmt"
5
-	"text/tabwriter"
6
-
7 4
 	"golang.org/x/net/context"
8 5
 
9 6
 	"github.com/docker/docker/api/types"
10 7
 	"github.com/docker/docker/cli"
11 8
 	"github.com/docker/docker/cli/command"
9
+	"github.com/docker/docker/cli/command/formatter"
12 10
 	"github.com/spf13/cobra"
13 11
 )
14 12
 
... ...
@@ -48,15 +46,9 @@ func runList(dockerCli *command.DockerCli, container string, opts listOptions) e
48 48
 		return err
49 49
 	}
50 50
 
51
-	w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0)
52
-	fmt.Fprintf(w, "CHECKPOINT NAME")
53
-	fmt.Fprintf(w, "\n")
54
-
55
-	for _, checkpoint := range checkpoints {
56
-		fmt.Fprintf(w, "%s\t", checkpoint.Name)
57
-		fmt.Fprint(w, "\n")
51
+	cpCtx := formatter.Context{
52
+		Output: dockerCli.Out(),
53
+		Format: formatter.NewCheckpointFormat(formatter.TableFormatKey),
58 54
 	}
59
-
60
-	w.Flush()
61
-	return nil
55
+	return formatter.CheckpointWrite(cpCtx, checkpoints)
62 56
 }
63 57
new file mode 100644
... ...
@@ -0,0 +1,52 @@
0
+package formatter
1
+
2
+import "github.com/docker/docker/api/types"
3
+
4
+const (
5
+	defaultCheckpointFormat = "table {{.Name}}"
6
+
7
+	checkpointNameHeader = "CHECKPOINT NAME"
8
+)
9
+
10
+// NewCheckpointFormat returns a format for use with a checkpoint Context
11
+func NewCheckpointFormat(source string) Format {
12
+	switch source {
13
+	case TableFormatKey:
14
+		return defaultCheckpointFormat
15
+	}
16
+	return Format(source)
17
+}
18
+
19
+// CheckpointWrite writes formatted checkpoints using the Context
20
+func CheckpointWrite(ctx Context, checkpoints []types.Checkpoint) error {
21
+	render := func(format func(subContext subContext) error) error {
22
+		for _, checkpoint := range checkpoints {
23
+			if err := format(&checkpointContext{c: checkpoint}); err != nil {
24
+				return err
25
+			}
26
+		}
27
+		return nil
28
+	}
29
+	return ctx.Write(newCheckpointContext(), render)
30
+}
31
+
32
+type checkpointContext struct {
33
+	HeaderContext
34
+	c types.Checkpoint
35
+}
36
+
37
+func newCheckpointContext() *checkpointContext {
38
+	cpCtx := checkpointContext{}
39
+	cpCtx.header = volumeHeaderContext{
40
+		"Name": checkpointNameHeader,
41
+	}
42
+	return &cpCtx
43
+}
44
+
45
+func (c *checkpointContext) MarshalJSON() ([]byte, error) {
46
+	return marshalJSON(c)
47
+}
48
+
49
+func (c *checkpointContext) Name() string {
50
+	return c.c.Name
51
+}
0 52
new file mode 100644
... ...
@@ -0,0 +1,55 @@
0
+package formatter
1
+
2
+import (
3
+	"bytes"
4
+	"testing"
5
+
6
+	"github.com/docker/docker/api/types"
7
+	"github.com/stretchr/testify/assert"
8
+)
9
+
10
+func TestCheckpointContextFormatWrite(t *testing.T) {
11
+	cases := []struct {
12
+		context  Context
13
+		expected string
14
+	}{
15
+		{
16
+			Context{Format: NewCheckpointFormat(defaultCheckpointFormat)},
17
+			`CHECKPOINT NAME
18
+checkpoint-1
19
+checkpoint-2
20
+checkpoint-3
21
+`,
22
+		},
23
+		{
24
+			Context{Format: NewCheckpointFormat("{{.Name}}")},
25
+			`checkpoint-1
26
+checkpoint-2
27
+checkpoint-3
28
+`,
29
+		},
30
+		{
31
+			Context{Format: NewCheckpointFormat("{{.Name}}:")},
32
+			`checkpoint-1:
33
+checkpoint-2:
34
+checkpoint-3:
35
+`,
36
+		},
37
+	}
38
+
39
+	checkpoints := []types.Checkpoint{
40
+		{"checkpoint-1"},
41
+		{"checkpoint-2"},
42
+		{"checkpoint-3"},
43
+	}
44
+	for _, testcase := range cases {
45
+		out := bytes.NewBufferString("")
46
+		testcase.context.Output = out
47
+		err := CheckpointWrite(testcase.context, checkpoints)
48
+		if err != nil {
49
+			assert.Error(t, err, testcase.expected)
50
+		} else {
51
+			assert.Equal(t, out.String(), testcase.expected)
52
+		}
53
+	}
54
+}