Browse code

Use spf13/cobra for docker commit

This fix is part of the effort to convert commands to spf13/cobra #23211.

Thif fix coverted command `docker commit` to use spf13/cobra

NOTE: `RequiresMinMaxArgs()` has been renamed to `RequiresRangeArgs()`.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

Yong Tang authored on 2016/06/06 23:57:44
Showing 7 changed files
... ...
@@ -3,7 +3,6 @@ package client
3 3
 // Command returns a cli command handler if one exists
4 4
 func (cli *DockerCli) Command(name string) func(...string) error {
5 5
 	return map[string]func(...string) error{
6
-		"commit":  cli.CmdCommit,
7 6
 		"cp":      cli.CmdCp,
8 7
 		"exec":    cli.CmdExec,
9 8
 		"info":    cli.CmdInfo,
10 9
deleted file mode 100644
... ...
@@ -1,62 +0,0 @@
1
-package client
2
-
3
-import (
4
-	"encoding/json"
5
-	"fmt"
6
-
7
-	"golang.org/x/net/context"
8
-
9
-	Cli "github.com/docker/docker/cli"
10
-	"github.com/docker/docker/opts"
11
-	flag "github.com/docker/docker/pkg/mflag"
12
-	"github.com/docker/engine-api/types"
13
-	"github.com/docker/engine-api/types/container"
14
-)
15
-
16
-// CmdCommit creates a new image from a container's changes.
17
-//
18
-// Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
19
-func (cli *DockerCli) CmdCommit(args ...string) error {
20
-	cmd := Cli.Subcmd("commit", []string{"CONTAINER [REPOSITORY[:TAG]]"}, Cli.DockerCommands["commit"].Description, true)
21
-	flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit")
22
-	flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
23
-	flAuthor := cmd.String([]string{"a", "-author"}, "", "Author (e.g., \"John Hannibal Smith <hannibal@a-team.com>\")")
24
-	flChanges := opts.NewListOpts(nil)
25
-	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
26
-	// FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
27
-	flConfig := cmd.String([]string{"#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
28
-	cmd.Require(flag.Max, 2)
29
-	cmd.Require(flag.Min, 1)
30
-
31
-	cmd.ParseFlags(args, true)
32
-
33
-	var (
34
-		name      = cmd.Arg(0)
35
-		reference = cmd.Arg(1)
36
-	)
37
-
38
-	var config *container.Config
39
-	if *flConfig != "" {
40
-		config = &container.Config{}
41
-		if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
42
-			return err
43
-		}
44
-	}
45
-
46
-	options := types.ContainerCommitOptions{
47
-		Reference: reference,
48
-		Comment:   *flComment,
49
-		Author:    *flAuthor,
50
-		Changes:   flChanges.GetAll(),
51
-		Pause:     *flPause,
52
-		Config:    config,
53
-	}
54
-
55
-	response, err := cli.client.ContainerCommit(context.Background(), name, options)
56
-	if err != nil {
57
-		return err
58
-	}
59
-
60
-	fmt.Fprintln(cli.out, response.ID)
61
-	return nil
62
-}
63 1
new file mode 100644
... ...
@@ -0,0 +1,93 @@
0
+package container
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+
6
+	"golang.org/x/net/context"
7
+
8
+	"github.com/docker/docker/api/client"
9
+	"github.com/docker/docker/cli"
10
+	dockeropts "github.com/docker/docker/opts"
11
+	"github.com/docker/engine-api/types"
12
+	containertypes "github.com/docker/engine-api/types/container"
13
+	"github.com/spf13/cobra"
14
+)
15
+
16
+type commitOptions struct {
17
+	container string
18
+	reference string
19
+
20
+	pause   bool
21
+	comment string
22
+	author  string
23
+	changes dockeropts.ListOpts
24
+	config  string
25
+}
26
+
27
+// NewCommitCommand creats a new cobra.Command for `docker commit`
28
+func NewCommitCommand(dockerCli *client.DockerCli) *cobra.Command {
29
+	var opts commitOptions
30
+
31
+	cmd := &cobra.Command{
32
+		Use:   "commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]",
33
+		Short: "Create a new image from a container's changes",
34
+		Args:  cli.RequiresRangeArgs(1, 2),
35
+		RunE: func(cmd *cobra.Command, args []string) error {
36
+			opts.container = args[0]
37
+			if len(args) > 1 {
38
+				opts.reference = args[1]
39
+			}
40
+			return runCommit(dockerCli, &opts)
41
+		},
42
+	}
43
+	cmd.SetFlagErrorFunc(flagErrorFunc)
44
+
45
+	flags := cmd.Flags()
46
+	flags.SetInterspersed(false)
47
+
48
+	flags.BoolVarP(&opts.pause, "pause", "p", true, "Pause container during commit")
49
+	flags.StringVarP(&opts.comment, "message", "m", "", "Commit message")
50
+	flags.StringVarP(&opts.author, "author", "a", "", "Author (e.g., \"John Hannibal Smith <hannibal@a-team.com>\")")
51
+
52
+	opts.changes = dockeropts.NewListOpts(nil)
53
+	flags.VarP(&opts.changes, "change", "c", "Apply Dockerfile instruction to the created image")
54
+
55
+	// FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
56
+	flags.StringVar(&opts.config, "run", "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands")
57
+	flags.MarkDeprecated("run", "it will be replaced with inline Dockerfile commands.")
58
+
59
+	return cmd
60
+}
61
+
62
+func runCommit(dockerCli *client.DockerCli, opts *commitOptions) error {
63
+	ctx := context.Background()
64
+
65
+	name := opts.container
66
+	reference := opts.reference
67
+
68
+	var config *containertypes.Config
69
+	if opts.config != "" {
70
+		config = &containertypes.Config{}
71
+		if err := json.Unmarshal([]byte(opts.config), config); err != nil {
72
+			return err
73
+		}
74
+	}
75
+
76
+	options := types.ContainerCommitOptions{
77
+		Reference: reference,
78
+		Comment:   opts.comment,
79
+		Author:    opts.author,
80
+		Changes:   opts.changes.GetAll(),
81
+		Pause:     opts.pause,
82
+		Config:    config,
83
+	}
84
+
85
+	response, err := dockerCli.Client().ContainerCommit(ctx, name, options)
86
+	if err != nil {
87
+		return err
88
+	}
89
+
90
+	fmt.Fprintln(dockerCli.Out(), response.ID)
91
+	return nil
92
+}
... ...
@@ -25,7 +25,7 @@ func NewPortCommand(dockerCli *client.DockerCli) *cobra.Command {
25 25
 	cmd := &cobra.Command{
26 26
 		Use:   "port CONTAINER [PRIVATE_PORT[/PROTO]]",
27 27
 		Short: "List port mappings or a specific mapping for the container",
28
-		Args:  cli.RequiresMinMaxArgs(1, 2),
28
+		Args:  cli.RequiresRangeArgs(1, 2),
29 29
 		RunE: func(cmd *cobra.Command, args []string) error {
30 30
 			opts.container = args[0]
31 31
 			if len(args) > 1 {
... ...
@@ -36,6 +36,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor {
36 36
 	rootCmd.SetOutput(stdout)
37 37
 	rootCmd.AddCommand(
38 38
 		container.NewAttachCommand(dockerCli),
39
+		container.NewCommitCommand(dockerCli),
39 40
 		container.NewCreateCommand(dockerCli),
40 41
 		container.NewDiffCommand(dockerCli),
41 42
 		container.NewExportCommand(dockerCli),
... ...
@@ -60,8 +60,8 @@ func RequiresMaxArgs(max int) cobra.PositionalArgs {
60 60
 	}
61 61
 }
62 62
 
63
-// RequiresMinMaxArgs returns an error if there is not at least min args and at most max args
64
-func RequiresMinMaxArgs(min int, max int) cobra.PositionalArgs {
63
+// RequiresRangeArgs returns an error if there is not at least min args and at most max args
64
+func RequiresRangeArgs(min int, max int) cobra.PositionalArgs {
65 65
 	return func(cmd *cobra.Command, args []string) error {
66 66
 		if len(args) >= min && len(args) <= max {
67 67
 			return nil
... ...
@@ -8,7 +8,6 @@ type Command struct {
8 8
 
9 9
 // DockerCommandUsage lists the top level docker commands and their short usage
10 10
 var DockerCommandUsage = []Command{
11
-	{"commit", "Create a new image from a container's changes"},
12 11
 	{"cp", "Copy files/folders between a container and the local filesystem"},
13 12
 	{"exec", "Run a command in a running container"},
14 13
 	{"info", "Display system-wide information"},