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 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 } inspectSearcher := func(name string) (interface{}, []byte, error) { i, err := cli.client.VolumeInspect(context.Background(), 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 for _, name := range cmd.Args() { if err := cli.client.VolumeRemove(context.Background(), 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 }