diff --git a/api/client/commands.go b/api/client/commands.go index 4e8259914f..c13540497a 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -3,7 +3,6 @@ package client // Command returns a cli command handler if one exists func (cli *DockerCli) Command(name string) func(...string) error { return map[string]func(...string) error{ - "commit": cli.CmdCommit, "cp": cli.CmdCp, "exec": cli.CmdExec, "info": cli.CmdInfo, diff --git a/api/client/commit.go b/api/client/commit.go deleted file mode 100644 index 4a985a43a4..0000000000 --- a/api/client/commit.go +++ /dev/null @@ -1,62 +0,0 @@ -package client - -import ( - "encoding/json" - "fmt" - - "golang.org/x/net/context" - - Cli "github.com/docker/docker/cli" - "github.com/docker/docker/opts" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/engine-api/types" - "github.com/docker/engine-api/types/container" -) - -// CmdCommit creates a new image from a container's changes. -// -// Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] -func (cli *DockerCli) CmdCommit(args ...string) error { - cmd := Cli.Subcmd("commit", []string{"CONTAINER [REPOSITORY[:TAG]]"}, Cli.DockerCommands["commit"].Description, true) - flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit") - flComment := cmd.String([]string{"m", "-message"}, "", "Commit message") - flAuthor := cmd.String([]string{"a", "-author"}, "", "Author (e.g., \"John Hannibal Smith \")") - flChanges := opts.NewListOpts(nil) - cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") - // FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands. - flConfig := cmd.String([]string{"#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands") - cmd.Require(flag.Max, 2) - cmd.Require(flag.Min, 1) - - cmd.ParseFlags(args, true) - - var ( - name = cmd.Arg(0) - reference = cmd.Arg(1) - ) - - var config *container.Config - if *flConfig != "" { - config = &container.Config{} - if err := json.Unmarshal([]byte(*flConfig), config); err != nil { - return err - } - } - - options := types.ContainerCommitOptions{ - Reference: reference, - Comment: *flComment, - Author: *flAuthor, - Changes: flChanges.GetAll(), - Pause: *flPause, - Config: config, - } - - response, err := cli.client.ContainerCommit(context.Background(), name, options) - if err != nil { - return err - } - - fmt.Fprintln(cli.out, response.ID) - return nil -} diff --git a/api/client/container/commit.go b/api/client/container/commit.go new file mode 100644 index 0000000000..ddbe61a87b --- /dev/null +++ b/api/client/container/commit.go @@ -0,0 +1,93 @@ +package container + +import ( + "encoding/json" + "fmt" + + "golang.org/x/net/context" + + "github.com/docker/docker/api/client" + "github.com/docker/docker/cli" + dockeropts "github.com/docker/docker/opts" + "github.com/docker/engine-api/types" + containertypes "github.com/docker/engine-api/types/container" + "github.com/spf13/cobra" +) + +type commitOptions struct { + container string + reference string + + pause bool + comment string + author string + changes dockeropts.ListOpts + config string +} + +// NewCommitCommand creats a new cobra.Command for `docker commit` +func NewCommitCommand(dockerCli *client.DockerCli) *cobra.Command { + var opts commitOptions + + cmd := &cobra.Command{ + Use: "commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]", + Short: "Create a new image from a container's changes", + Args: cli.RequiresRangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + opts.container = args[0] + if len(args) > 1 { + opts.reference = args[1] + } + return runCommit(dockerCli, &opts) + }, + } + cmd.SetFlagErrorFunc(flagErrorFunc) + + flags := cmd.Flags() + flags.SetInterspersed(false) + + flags.BoolVarP(&opts.pause, "pause", "p", true, "Pause container during commit") + flags.StringVarP(&opts.comment, "message", "m", "", "Commit message") + flags.StringVarP(&opts.author, "author", "a", "", "Author (e.g., \"John Hannibal Smith \")") + + opts.changes = dockeropts.NewListOpts(nil) + flags.VarP(&opts.changes, "change", "c", "Apply Dockerfile instruction to the created image") + + // FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands. + flags.StringVar(&opts.config, "run", "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands") + flags.MarkDeprecated("run", "it will be replaced with inline Dockerfile commands.") + + return cmd +} + +func runCommit(dockerCli *client.DockerCli, opts *commitOptions) error { + ctx := context.Background() + + name := opts.container + reference := opts.reference + + var config *containertypes.Config + if opts.config != "" { + config = &containertypes.Config{} + if err := json.Unmarshal([]byte(opts.config), config); err != nil { + return err + } + } + + options := types.ContainerCommitOptions{ + Reference: reference, + Comment: opts.comment, + Author: opts.author, + Changes: opts.changes.GetAll(), + Pause: opts.pause, + Config: config, + } + + response, err := dockerCli.Client().ContainerCommit(ctx, name, options) + if err != nil { + return err + } + + fmt.Fprintln(dockerCli.Out(), response.ID) + return nil +} diff --git a/api/client/container/port.go b/api/client/container/port.go index 71b78598a1..3594eb0c8d 100644 --- a/api/client/container/port.go +++ b/api/client/container/port.go @@ -25,7 +25,7 @@ func NewPortCommand(dockerCli *client.DockerCli) *cobra.Command { cmd := &cobra.Command{ Use: "port CONTAINER [PRIVATE_PORT[/PROTO]]", Short: "List port mappings or a specific mapping for the container", - Args: cli.RequiresMinMaxArgs(1, 2), + Args: cli.RequiresRangeArgs(1, 2), RunE: func(cmd *cobra.Command, args []string) error { opts.container = args[0] if len(args) > 1 { diff --git a/cli/cobraadaptor/adaptor.go b/cli/cobraadaptor/adaptor.go index 11b821cc44..4d4ca433ba 100644 --- a/cli/cobraadaptor/adaptor.go +++ b/cli/cobraadaptor/adaptor.go @@ -36,6 +36,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { rootCmd.SetOutput(stdout) rootCmd.AddCommand( container.NewAttachCommand(dockerCli), + container.NewCommitCommand(dockerCli), container.NewCreateCommand(dockerCli), container.NewDiffCommand(dockerCli), container.NewExportCommand(dockerCli), diff --git a/cli/required.go b/cli/required.go index 0c08e64f1a..9276a5740a 100644 --- a/cli/required.go +++ b/cli/required.go @@ -60,8 +60,8 @@ func RequiresMaxArgs(max int) cobra.PositionalArgs { } } -// RequiresMinMaxArgs returns an error if there is not at least min args and at most max args -func RequiresMinMaxArgs(min int, max int) cobra.PositionalArgs { +// RequiresRangeArgs returns an error if there is not at least min args and at most max args +func RequiresRangeArgs(min int, max int) cobra.PositionalArgs { return func(cmd *cobra.Command, args []string) error { if len(args) >= min && len(args) <= max { return nil diff --git a/cli/usage.go b/cli/usage.go index e9debf3be7..32b3442653 100644 --- a/cli/usage.go +++ b/cli/usage.go @@ -8,7 +8,6 @@ type Command struct { // DockerCommandUsage lists the top level docker commands and their short usage var DockerCommandUsage = []Command{ - {"commit", "Create a new image from a container's changes"}, {"cp", "Copy files/folders between a container and the local filesystem"}, {"exec", "Run a command in a running container"}, {"info", "Display system-wide information"},