mirror of https://github.com/docker/docs.git
				
				
				
			Migrate volume commands to cobra.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
		
							parent
							
								
									6bc3e23f65
								
							
						
					
					
						commit
						69264beb40
					
				|  | @ -60,6 +60,21 @@ func (cli *DockerCli) Initialize() error { | |||
| 	return cli.init() | ||||
| } | ||||
| 
 | ||||
| // Client returns the APIClient
 | ||||
| func (cli *DockerCli) Client() client.APIClient { | ||||
| 	return cli.client | ||||
| } | ||||
| 
 | ||||
| // Out returns the writer used for stdout
 | ||||
| func (cli *DockerCli) Out() io.Writer { | ||||
| 	return cli.out | ||||
| } | ||||
| 
 | ||||
| // Err returns the writer used for stderr
 | ||||
| func (cli *DockerCli) Err() io.Writer { | ||||
| 	return cli.err | ||||
| } | ||||
| 
 | ||||
| // CheckTtyInput checks if we are trying to attach to a container tty
 | ||||
| // from a non-tty client input stream, and if so, returns an error.
 | ||||
| func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error { | ||||
|  | @ -127,40 +142,13 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cliflags.Cl | |||
| 
 | ||||
| 	cli.init = func() error { | ||||
| 		clientFlags.PostParse() | ||||
| 		configFile, e := cliconfig.Load(cliconfig.ConfigDir()) | ||||
| 		if e != nil { | ||||
| 			fmt.Fprintf(cli.err, "WARNING: Error loading config file:%v\n", e) | ||||
| 		} | ||||
| 		if !configFile.ContainsAuth() { | ||||
| 			credentials.DetectDefaultStore(configFile) | ||||
| 		} | ||||
| 		cli.configFile = configFile | ||||
| 		cli.configFile = LoadDefaultConfigFile(err) | ||||
| 
 | ||||
| 		host, err := getServerHost(clientFlags.Common.Hosts, clientFlags.Common.TLSOptions) | ||||
| 		client, err := NewAPIClientFromFlags(clientFlags, cli.configFile) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		customHeaders := cli.configFile.HTTPHeaders | ||||
| 		if customHeaders == nil { | ||||
| 			customHeaders = map[string]string{} | ||||
| 		} | ||||
| 		customHeaders["User-Agent"] = clientUserAgent() | ||||
| 
 | ||||
| 		verStr := api.DefaultVersion | ||||
| 		if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { | ||||
| 			verStr = tmpStr | ||||
| 		} | ||||
| 
 | ||||
| 		httpClient, err := newHTTPClient(host, clientFlags.Common.TLSOptions) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		client, err := client.NewClient(host, verStr, httpClient, customHeaders) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		cli.client = client | ||||
| 
 | ||||
| 		if cli.in != nil { | ||||
|  | @ -176,6 +164,45 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, clientFlags *cliflags.Cl | |||
| 	return cli | ||||
| } | ||||
| 
 | ||||
| // LoadDefaultConfigFile attempts to load the default config file and returns
 | ||||
| // an initialized ConfigFile struct if none is found.
 | ||||
| func LoadDefaultConfigFile(err io.Writer) *configfile.ConfigFile { | ||||
| 	configFile, e := cliconfig.Load(cliconfig.ConfigDir()) | ||||
| 	if e != nil { | ||||
| 		fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e) | ||||
| 	} | ||||
| 	if !configFile.ContainsAuth() { | ||||
| 		credentials.DetectDefaultStore(configFile) | ||||
| 	} | ||||
| 	return configFile | ||||
| } | ||||
| 
 | ||||
| // NewAPIClientFromFlags creates a new APIClient from command line flags
 | ||||
| func NewAPIClientFromFlags(clientFlags *cliflags.ClientFlags, configFile *configfile.ConfigFile) (client.APIClient, error) { | ||||
| 	host, err := getServerHost(clientFlags.Common.Hosts, clientFlags.Common.TLSOptions) | ||||
| 	if err != nil { | ||||
| 		return &client.Client{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	customHeaders := configFile.HTTPHeaders | ||||
| 	if customHeaders == nil { | ||||
| 		customHeaders = map[string]string{} | ||||
| 	} | ||||
| 	customHeaders["User-Agent"] = clientUserAgent() | ||||
| 
 | ||||
| 	verStr := api.DefaultVersion | ||||
| 	if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { | ||||
| 		verStr = tmpStr | ||||
| 	} | ||||
| 
 | ||||
| 	httpClient, err := newHTTPClient(host, clientFlags.Common.TLSOptions) | ||||
| 	if err != nil { | ||||
| 		return &client.Client{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	return client.NewClient(host, verStr, httpClient, customHeaders) | ||||
| } | ||||
| 
 | ||||
| func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (host string, err error) { | ||||
| 	switch len(hosts) { | ||||
| 	case 0: | ||||
|  |  | |||
|  | @ -49,11 +49,6 @@ func (cli *DockerCli) Command(name string) func(...string) error { | |||
| 		"unpause":            cli.CmdUnpause, | ||||
| 		"update":             cli.CmdUpdate, | ||||
| 		"version":            cli.CmdVersion, | ||||
| 		"volume":             cli.CmdVolume, | ||||
| 		"volume create":      cli.CmdVolumeCreate, | ||||
| 		"volume inspect":     cli.CmdVolumeInspect, | ||||
| 		"volume ls":          cli.CmdVolumeLs, | ||||
| 		"volume rm":          cli.CmdVolumeRm, | ||||
| 		"wait":               cli.CmdWait, | ||||
| 	}[name] | ||||
| } | ||||
|  |  | |||
|  | @ -1,181 +0,0 @@ | |||
| package client | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| 	"text/tabwriter" | ||||
| 
 | ||||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	Cli "github.com/docker/docker/cli" | ||||
| 	"github.com/docker/docker/opts" | ||||
| 	flag "github.com/docker/docker/pkg/mflag" | ||||
| 	runconfigopts "github.com/docker/docker/runconfig/opts" | ||||
| 	"github.com/docker/engine-api/types" | ||||
| 	"github.com/docker/engine-api/types/filters" | ||||
| ) | ||||
| 
 | ||||
| // CmdVolume is the parent subcommand for all volume commands
 | ||||
| //
 | ||||
| // Usage: docker volume <COMMAND> <OPTS>
 | ||||
| func (cli *DockerCli) CmdVolume(args ...string) error { | ||||
| 	description := Cli.DockerCommands["volume"].Description + "\n\nCommands:\n" | ||||
| 	commands := [][]string{ | ||||
| 		{"create", "Create a volume"}, | ||||
| 		{"inspect", "Return low-level information on a volume"}, | ||||
| 		{"ls", "List volumes"}, | ||||
| 		{"rm", "Remove a volume"}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, cmd := range commands { | ||||
| 		description += fmt.Sprintf("  %-25.25s%s\n", cmd[0], cmd[1]) | ||||
| 	} | ||||
| 
 | ||||
| 	description += "\nRun 'docker volume COMMAND --help' for more information on a command" | ||||
| 	cmd := Cli.Subcmd("volume", []string{"[COMMAND]"}, description, false) | ||||
| 
 | ||||
| 	cmd.Require(flag.Exact, 0) | ||||
| 	err := cmd.ParseFlags(args, true) | ||||
| 	cmd.Usage() | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // CmdVolumeLs outputs a list of Docker volumes.
 | ||||
| //
 | ||||
| // Usage: docker volume ls [OPTIONS]
 | ||||
| func (cli *DockerCli) CmdVolumeLs(args ...string) error { | ||||
| 	cmd := Cli.Subcmd("volume ls", nil, "List volumes", true) | ||||
| 
 | ||||
| 	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display volume names") | ||||
| 	flFilter := opts.NewListOpts(nil) | ||||
| 	cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')") | ||||
| 
 | ||||
| 	cmd.Require(flag.Exact, 0) | ||||
| 	cmd.ParseFlags(args, true) | ||||
| 
 | ||||
| 	volFilterArgs := filters.NewArgs() | ||||
| 	for _, f := range flFilter.GetAll() { | ||||
| 		var err error | ||||
| 		volFilterArgs, err = filters.ParseFlag(f, volFilterArgs) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	volumes, err := cli.client.VolumeList(context.Background(), volFilterArgs) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) | ||||
| 	if !*quiet { | ||||
| 		for _, warn := range volumes.Warnings { | ||||
| 			fmt.Fprintln(cli.err, warn) | ||||
| 		} | ||||
| 		fmt.Fprintf(w, "DRIVER \tVOLUME NAME") | ||||
| 		fmt.Fprintf(w, "\n") | ||||
| 	} | ||||
| 
 | ||||
| 	sort.Sort(byVolumeName(volumes.Volumes)) | ||||
| 	for _, vol := range volumes.Volumes { | ||||
| 		if *quiet { | ||||
| 			fmt.Fprintln(w, vol.Name) | ||||
| 			continue | ||||
| 		} | ||||
| 		fmt.Fprintf(w, "%s\t%s\n", vol.Driver, vol.Name) | ||||
| 	} | ||||
| 	w.Flush() | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| type byVolumeName []*types.Volume | ||||
| 
 | ||||
| func (r byVolumeName) Len() int      { return len(r) } | ||||
| func (r byVolumeName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } | ||||
| func (r byVolumeName) Less(i, j int) bool { | ||||
| 	return r[i].Name < r[j].Name | ||||
| } | ||||
| 
 | ||||
| // CmdVolumeInspect displays low-level information on one or more volumes.
 | ||||
| //
 | ||||
| // Usage: docker volume inspect [OPTIONS] VOLUME [VOLUME...]
 | ||||
| func (cli *DockerCli) CmdVolumeInspect(args ...string) error { | ||||
| 	cmd := Cli.Subcmd("volume inspect", []string{"VOLUME [VOLUME...]"}, "Return low-level information on a volume", true) | ||||
| 	tmplStr := cmd.String([]string{"f", "-format"}, "", "Format the output using the given go template") | ||||
| 
 | ||||
| 	cmd.Require(flag.Min, 1) | ||||
| 	cmd.ParseFlags(args, true) | ||||
| 
 | ||||
| 	if err := cmd.Parse(args); err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	ctx := context.Background() | ||||
| 
 | ||||
| 	inspectSearcher := func(name string) (interface{}, []byte, error) { | ||||
| 		i, err := cli.client.VolumeInspect(ctx, name) | ||||
| 		return i, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return cli.inspectElements(*tmplStr, cmd.Args(), inspectSearcher) | ||||
| } | ||||
| 
 | ||||
| // CmdVolumeCreate creates a new volume.
 | ||||
| //
 | ||||
| // Usage: docker volume create [OPTIONS]
 | ||||
| func (cli *DockerCli) CmdVolumeCreate(args ...string) error { | ||||
| 	cmd := Cli.Subcmd("volume create", nil, "Create a volume", true) | ||||
| 	flDriver := cmd.String([]string{"d", "-driver"}, "local", "Specify volume driver name") | ||||
| 	flName := cmd.String([]string{"-name"}, "", "Specify volume name") | ||||
| 
 | ||||
| 	flDriverOpts := opts.NewMapOpts(nil, nil) | ||||
| 	cmd.Var(flDriverOpts, []string{"o", "-opt"}, "Set driver specific options") | ||||
| 
 | ||||
| 	flLabels := opts.NewListOpts(nil) | ||||
| 	cmd.Var(&flLabels, []string{"-label"}, "Set metadata for a volume") | ||||
| 
 | ||||
| 	cmd.Require(flag.Exact, 0) | ||||
| 	cmd.ParseFlags(args, true) | ||||
| 
 | ||||
| 	volReq := types.VolumeCreateRequest{ | ||||
| 		Driver:     *flDriver, | ||||
| 		DriverOpts: flDriverOpts.GetAll(), | ||||
| 		Name:       *flName, | ||||
| 		Labels:     runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()), | ||||
| 	} | ||||
| 
 | ||||
| 	vol, err := cli.client.VolumeCreate(context.Background(), volReq) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Fprintf(cli.out, "%s\n", vol.Name) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CmdVolumeRm removes one or more volumes.
 | ||||
| //
 | ||||
| // Usage: docker volume rm VOLUME [VOLUME...]
 | ||||
| func (cli *DockerCli) CmdVolumeRm(args ...string) error { | ||||
| 	cmd := Cli.Subcmd("volume rm", []string{"VOLUME [VOLUME...]"}, "Remove a volume", true) | ||||
| 	cmd.Require(flag.Min, 1) | ||||
| 	cmd.ParseFlags(args, true) | ||||
| 
 | ||||
| 	var status = 0 | ||||
| 
 | ||||
| 	ctx := context.Background() | ||||
| 
 | ||||
| 	for _, name := range cmd.Args() { | ||||
| 		if err := cli.client.VolumeRemove(ctx, name); err != nil { | ||||
| 			fmt.Fprintf(cli.err, "%s\n", err) | ||||
| 			status = 1 | ||||
| 			continue | ||||
| 		} | ||||
| 		fmt.Fprintf(cli.out, "%s\n", name) | ||||
| 	} | ||||
| 
 | ||||
| 	if status != 0 { | ||||
| 		return Cli.StatusError{StatusCode: status} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,22 @@ | |||
| package volume | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/spf13/cobra" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/client" | ||||
| ) | ||||
| 
 | ||||
| // NewVolumeCommand returns a cobra command for `volume` subcommands
 | ||||
| func NewVolumeCommand(dockerCli *client.DockerCli) *cobra.Command { | ||||
| 	cmd := &cobra.Command{ | ||||
| 		Use:   "volume", | ||||
| 		Short: "Manage Docker volumes", | ||||
| 	} | ||||
| 	cmd.AddCommand( | ||||
| 		newCreateCommand(dockerCli), | ||||
| 		newInspectCommand(dockerCli), | ||||
| 		newListCommand(dockerCli), | ||||
| 		newRemoveCommand(dockerCli), | ||||
| 	) | ||||
| 	return cmd | ||||
| } | ||||
|  | @ -0,0 +1,58 @@ | |||
| package volume | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/docker/opts" | ||||
| 	runconfigopts "github.com/docker/docker/runconfig/opts" | ||||
| 	"github.com/docker/engine-api/types" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| type createOptions struct { | ||||
| 	name       string | ||||
| 	driver     string | ||||
| 	driverOpts opts.MapOpts | ||||
| 	labels     []string | ||||
| } | ||||
| 
 | ||||
| func newCreateCommand(dockerCli *client.DockerCli) *cobra.Command { | ||||
| 	var opts createOptions | ||||
| 
 | ||||
| 	cmd := &cobra.Command{ | ||||
| 		Use:   "create", | ||||
| 		Short: "Create a volume", | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			return runCreate(dockerCli, opts) | ||||
| 		}, | ||||
| 	} | ||||
| 	flags := cmd.Flags() | ||||
| 	flags.StringVarP(&opts.driver, "driver", "d", "local", "Specify volume driver name") | ||||
| 	flags.StringVar(&opts.name, "name", "", "Specify volume name") | ||||
| 	flags.VarP(&opts.driverOpts, "opt", "o", "Set driver specific options") | ||||
| 	flags.StringSliceVar(&opts.labels, "label", []string{}, "Set metadata for a volume") | ||||
| 
 | ||||
| 	return cmd | ||||
| } | ||||
| 
 | ||||
| func runCreate(dockerCli *client.DockerCli, opts createOptions) error { | ||||
| 	client := dockerCli.Client() | ||||
| 
 | ||||
| 	volReq := types.VolumeCreateRequest{ | ||||
| 		Driver:     opts.driver, | ||||
| 		DriverOpts: opts.driverOpts.GetAll(), | ||||
| 		Name:       opts.name, | ||||
| 		Labels:     runconfigopts.ConvertKVStringsToMap(opts.labels), | ||||
| 	} | ||||
| 
 | ||||
| 	vol, err := client.VolumeCreate(context.Background(), volReq) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Fprintf(dockerCli.Out(), "%s\n", vol.Name) | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,46 @@ | |||
| package volume | ||||
| 
 | ||||
| import ( | ||||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/docker/api/client/inspect" | ||||
| 	"github.com/docker/docker/cli" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| type inspectOptions struct { | ||||
| 	format string | ||||
| 	names  []string | ||||
| } | ||||
| 
 | ||||
| func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command { | ||||
| 	var opts inspectOptions | ||||
| 
 | ||||
| 	cmd := &cobra.Command{ | ||||
| 		Use:   "inspect [OPTIONS] VOLUME [VOLUME...]", | ||||
| 		Short: "Return low-level information on a volume", | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			if err := cli.MinRequiredArgs(args, 1, cmd); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			opts.names = args | ||||
| 			return runInspect(dockerCli, opts) | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given go template") | ||||
| 
 | ||||
| 	return cmd | ||||
| } | ||||
| 
 | ||||
| func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error { | ||||
| 	client := dockerCli.Client() | ||||
| 
 | ||||
| 	getVolFunc := func(name string) (interface{}, []byte, error) { | ||||
| 		i, err := client.VolumeInspect(context.Background(), name) | ||||
| 		return i, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getVolFunc) | ||||
| } | ||||
|  | @ -0,0 +1,84 @@ | |||
| package volume | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| 	"text/tabwriter" | ||||
| 
 | ||||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/engine-api/types" | ||||
| 	"github.com/docker/engine-api/types/filters" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| type byVolumeName []*types.Volume | ||||
| 
 | ||||
| func (r byVolumeName) Len() int      { return len(r) } | ||||
| func (r byVolumeName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } | ||||
| func (r byVolumeName) Less(i, j int) bool { | ||||
| 	return r[i].Name < r[j].Name | ||||
| } | ||||
| 
 | ||||
| type listOptions struct { | ||||
| 	quiet  bool | ||||
| 	filter []string | ||||
| } | ||||
| 
 | ||||
| func newListCommand(dockerCli *client.DockerCli) *cobra.Command { | ||||
| 	var opts listOptions | ||||
| 
 | ||||
| 	cmd := &cobra.Command{ | ||||
| 		Use:     "ls", | ||||
| 		Aliases: []string{"list"}, | ||||
| 		Short:   "List volumes", | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			return runList(dockerCli, opts) | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	flags := cmd.Flags() | ||||
| 	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only display volume names") | ||||
| 	flags.StringSliceVarP(&opts.filter, "filter", "f", []string{}, "Provide filter values (i.e. 'dangling=true')") | ||||
| 
 | ||||
| 	return cmd | ||||
| } | ||||
| 
 | ||||
| func runList(dockerCli *client.DockerCli, opts listOptions) error { | ||||
| 	client := dockerCli.Client() | ||||
| 
 | ||||
| 	volFilterArgs := filters.NewArgs() | ||||
| 	for _, f := range opts.filter { | ||||
| 		var err error | ||||
| 		volFilterArgs, err = filters.ParseFlag(f, volFilterArgs) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	volumes, err := client.VolumeList(context.Background(), volFilterArgs) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) | ||||
| 	if !opts.quiet { | ||||
| 		for _, warn := range volumes.Warnings { | ||||
| 			fmt.Fprintln(dockerCli.Err(), warn) | ||||
| 		} | ||||
| 		fmt.Fprintf(w, "DRIVER \tVOLUME NAME") | ||||
| 		fmt.Fprintf(w, "\n") | ||||
| 	} | ||||
| 
 | ||||
| 	sort.Sort(byVolumeName(volumes.Volumes)) | ||||
| 	for _, vol := range volumes.Volumes { | ||||
| 		if opts.quiet { | ||||
| 			fmt.Fprintln(w, vol.Name) | ||||
| 			continue | ||||
| 		} | ||||
| 		fmt.Fprintf(w, "%s\t%s\n", vol.Driver, vol.Name) | ||||
| 	} | ||||
| 	w.Flush() | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,44 @@ | |||
| package volume | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"golang.org/x/net/context" | ||||
| 
 | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/docker/cli" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| func newRemoveCommand(dockerCli *client.DockerCli) *cobra.Command { | ||||
| 	return &cobra.Command{ | ||||
| 		Use:     "rm VOLUME [VOLUME]...", | ||||
| 		Aliases: []string{"remove"}, | ||||
| 		Short:   "Remove a volume", | ||||
| 		RunE: func(cmd *cobra.Command, args []string) error { | ||||
| 			if err := cli.MinRequiredArgs(args, 1, cmd); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			return runRemove(dockerCli, args) | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func runRemove(dockerCli *client.DockerCli, volumes []string) error { | ||||
| 	client := dockerCli.Client() | ||||
| 	var status = 0 | ||||
| 
 | ||||
| 	for _, name := range volumes { | ||||
| 		if err := client.VolumeRemove(context.Background(), name); err != nil { | ||||
| 			fmt.Fprintf(dockerCli.Err(), "%s\n", err) | ||||
| 			status = 1 | ||||
| 			continue | ||||
| 		} | ||||
| 		fmt.Fprintf(dockerCli.Err(), "%s\n", name) | ||||
| 	} | ||||
| 
 | ||||
| 	if status != 0 { | ||||
| 		return cli.StatusError{StatusCode: status} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,83 @@ | |||
| package cobraadaptor | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/docker/api/client/volume" | ||||
| 	"github.com/docker/docker/cli" | ||||
| 	cliflags "github.com/docker/docker/cli/flags" | ||||
| 	"github.com/docker/docker/pkg/term" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| // CobraAdaptor is an adaptor for supporting spf13/cobra commands in the
 | ||||
| // docker/cli framework
 | ||||
| type CobraAdaptor struct { | ||||
| 	rootCmd   *cobra.Command | ||||
| 	dockerCli *client.DockerCli | ||||
| } | ||||
| 
 | ||||
| // NewCobraAdaptor returns a new handler
 | ||||
| func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor { | ||||
| 	var rootCmd = &cobra.Command{ | ||||
| 		Use: "docker", | ||||
| 	} | ||||
| 	rootCmd.SetUsageTemplate(usageTemplate) | ||||
| 
 | ||||
| 	stdin, stdout, stderr := term.StdStreams() | ||||
| 	dockerCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) | ||||
| 
 | ||||
| 	rootCmd.AddCommand( | ||||
| 		volume.NewVolumeCommand(dockerCli), | ||||
| 	) | ||||
| 	return CobraAdaptor{ | ||||
| 		rootCmd:   rootCmd, | ||||
| 		dockerCli: dockerCli, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Usage returns the list of commands and their short usage string for
 | ||||
| // all top level cobra commands.
 | ||||
| func (c CobraAdaptor) Usage() []cli.Command { | ||||
| 	cmds := []cli.Command{} | ||||
| 	for _, cmd := range c.rootCmd.Commands() { | ||||
| 		cmds = append(cmds, cli.Command{Name: cmd.Use, Description: cmd.Short}) | ||||
| 	} | ||||
| 	return cmds | ||||
| } | ||||
| 
 | ||||
| func (c CobraAdaptor) run(cmd string, args []string) error { | ||||
| 	c.dockerCli.Initialize() | ||||
| 	// Prepend the command name to support normal cobra command delegation
 | ||||
| 	c.rootCmd.SetArgs(append([]string{cmd}, args...)) | ||||
| 	return c.rootCmd.Execute() | ||||
| } | ||||
| 
 | ||||
| // Command returns a cli command handler if one exists
 | ||||
| func (c CobraAdaptor) Command(name string) func(...string) error { | ||||
| 	for _, cmd := range c.rootCmd.Commands() { | ||||
| 		if cmd.Name() == name { | ||||
| 			return func(args ...string) error { | ||||
| 				return c.run(name, args) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| var usageTemplate = `Usage:  {{if .Runnable}}{{if .HasFlags}}{{appendIfNotPresent .UseLine "[OPTIONS]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasSubCommands}}{{ .CommandPath}} COMMAND {{end}}{{if gt .Aliases 0}} | ||||
| 
 | ||||
| Aliases: | ||||
|   {{.NameAndAliases}} | ||||
| {{end}}{{if .HasExample}} | ||||
| 
 | ||||
| Examples: | ||||
| {{ .Example }}{{end}}{{ if .HasLocalFlags}} | ||||
| 
 | ||||
| Options: | ||||
| {{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableSubCommands}} | ||||
| 
 | ||||
| Commands:{{range .Commands}}{{if .IsAvailableCommand}} | ||||
|   {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasSubCommands }} | ||||
| 
 | ||||
| Run '{{.CommandPath}} COMMAND --help' for more information on a command.{{end}} | ||||
| ` | ||||
|  | @ -0,0 +1,23 @@ | |||
| package cli | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| // MinRequiredArgs checks if the minimum number of args exists, and returns an
 | ||||
| // error if they do not.
 | ||||
| func MinRequiredArgs(args []string, min int, cmd *cobra.Command) error { | ||||
| 	if len(args) >= min { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return fmt.Errorf( | ||||
| 		"\"%s\" requires at least %d argument(s).\n\nUsage:  %s\n\n%s", | ||||
| 		cmd.CommandPath(), | ||||
| 		min, | ||||
| 		cmd.UseLine(), | ||||
| 		cmd.Short, | ||||
| 	) | ||||
| } | ||||
|  | @ -8,6 +8,7 @@ import ( | |||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/docker/api/client" | ||||
| 	"github.com/docker/docker/cli" | ||||
| 	"github.com/docker/docker/cli/cobraadaptor" | ||||
| 	cliflags "github.com/docker/docker/cli/flags" | ||||
| 	"github.com/docker/docker/cliconfig" | ||||
| 	"github.com/docker/docker/dockerversion" | ||||
|  | @ -31,6 +32,8 @@ func main() { | |||
| 
 | ||||
| 	flag.Merge(flag.CommandLine, clientFlags.FlagSet, commonFlags.FlagSet) | ||||
| 
 | ||||
| 	cobraAdaptor := cobraadaptor.NewCobraAdaptor(clientFlags) | ||||
| 
 | ||||
| 	flag.Usage = func() { | ||||
| 		fmt.Fprint(stdout, "Usage: docker [OPTIONS] COMMAND [arg...]\n       docker [ --help | -v | --version ]\n\n") | ||||
| 		fmt.Fprint(stdout, "A self-sufficient runtime for containers.\n\nOptions:\n") | ||||
|  | @ -40,8 +43,8 @@ func main() { | |||
| 
 | ||||
| 		help := "\nCommands:\n" | ||||
| 
 | ||||
| 		dockerCommands := sortCommands(cli.DockerCommandUsage) | ||||
| 		for _, cmd := range dockerCommands { | ||||
| 		dockerCommands := append(cli.DockerCommandUsage, cobraAdaptor.Usage()...) | ||||
| 		for _, cmd := range sortCommands(dockerCommands) { | ||||
| 			help += fmt.Sprintf("    %-10.10s%s\n", cmd.Name, cmd.Description) | ||||
| 		} | ||||
| 
 | ||||
|  | @ -65,7 +68,7 @@ func main() { | |||
| 
 | ||||
| 	clientCli := client.NewDockerCli(stdin, stdout, stderr, clientFlags) | ||||
| 
 | ||||
| 	c := cli.New(clientCli, NewDaemonProxy()) | ||||
| 	c := cli.New(clientCli, NewDaemonProxy(), cobraAdaptor) | ||||
| 	if err := c.Run(flag.Args()...); err != nil { | ||||
| 		if sterr, ok := err.(cli.StatusError); ok { | ||||
| 			if sterr.Status != "" { | ||||
|  |  | |||
|  | @ -163,6 +163,11 @@ func (opts *MapOpts) String() string { | |||
| 	return fmt.Sprintf("%v", map[string]string((opts.values))) | ||||
| } | ||||
| 
 | ||||
| // Type returns a string name for this Option type
 | ||||
| func (opts *MapOpts) Type() string { | ||||
| 	return "map" | ||||
| } | ||||
| 
 | ||||
| // NewMapOpts creates a new MapOpts with the specified map of values and a validator.
 | ||||
| func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts { | ||||
| 	if values == nil { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue