github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/storage/list.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storage 5 6 import ( 7 "io" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 "github.com/juju/gnuflag" 12 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/cmd/modelcmd" 15 ) 16 17 // NewListCommand returns a command for listing storage instances. 18 func NewListCommand() cmd.Command { 19 cmd := &listCommand{} 20 cmd.newAPIFunc = func() (StorageListAPI, error) { 21 return cmd.NewStorageAPI() 22 } 23 return modelcmd.Wrap(cmd) 24 } 25 26 const listCommandDoc = ` 27 List information about storage instances. 28 ` 29 30 // listCommand returns storage instances. 31 type listCommand struct { 32 StorageCommandBase 33 out cmd.Output 34 ids []string 35 filesystem bool 36 volume bool 37 newAPIFunc func() (StorageListAPI, error) 38 } 39 40 // Init implements Command.Init. 41 func (c *listCommand) Init(args []string) (err error) { 42 c.ids = args 43 return nil 44 } 45 46 // Info implements Command.Info. 47 func (c *listCommand) Info() *cmd.Info { 48 return &cmd.Info{ 49 Name: "storage", 50 Args: "<machineID> ...", 51 Purpose: "Lists storage details.", 52 Doc: listCommandDoc, 53 Aliases: []string{"list-storage"}, 54 } 55 } 56 57 // SetFlags implements Command.SetFlags. 58 func (c *listCommand) SetFlags(f *gnuflag.FlagSet) { 59 c.StorageCommandBase.SetFlags(f) 60 c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{ 61 "yaml": cmd.FormatYaml, 62 "json": cmd.FormatJson, 63 "tabular": formatListTabular, 64 }) 65 f.BoolVar(&c.filesystem, "filesystem", false, "List filesystem storage") 66 f.BoolVar(&c.volume, "volume", false, "List volume storage") 67 } 68 69 // Run implements Command.Run. 70 func (c *listCommand) Run(ctx *cmd.Context) (err error) { 71 api, err := c.newAPIFunc() 72 if err != nil { 73 return err 74 } 75 defer api.Close() 76 77 var output interface{} 78 if c.filesystem { 79 output, err = c.generateListFilesystemsOutput(ctx, api) 80 } else if c.volume { 81 output, err = c.generateListVolumeOutput(ctx, api) 82 } else { 83 output, err = c.generateListOutput(ctx, api) 84 } 85 if err != nil { 86 return err 87 } 88 if output == nil && c.out.Name() == "tabular" { 89 ctx.Infof("No storage to display.") 90 return nil 91 } 92 return c.out.Write(ctx, output) 93 } 94 95 // StorageAPI defines the API methods that the storage commands use. 96 type StorageListAPI interface { 97 Close() error 98 ListStorageDetails() ([]params.StorageDetails, error) 99 ListFilesystems(machines []string) ([]params.FilesystemDetailsListResult, error) 100 ListVolumes(machines []string) ([]params.VolumeDetailsListResult, error) 101 } 102 103 // generateListOutput returns a map of storage details 104 func (c *listCommand) generateListOutput(ctx *cmd.Context, api StorageListAPI) (output interface{}, err error) { 105 106 results, err := api.ListStorageDetails() 107 if err != nil { 108 return nil, err 109 } 110 if len(results) == 0 { 111 return nil, nil 112 } 113 details, err := formatStorageDetails(results) 114 if err != nil { 115 return nil, err 116 } 117 switch c.out.Name() { 118 case "yaml", "json": 119 output = map[string]map[string]StorageInfo{"storage": details} 120 default: 121 output = details 122 } 123 return output, nil 124 } 125 126 func formatListTabular(writer io.Writer, value interface{}) error { 127 switch value := value.(type) { 128 case map[string]StorageInfo: 129 return formatStorageListTabular(writer, value) 130 131 case map[string]FilesystemInfo: 132 return formatFilesystemListTabular(writer, value) 133 134 case map[string]VolumeInfo: 135 return formatVolumeListTabular(writer, value) 136 137 default: 138 return errors.Errorf("unexpected value of type %T", value) 139 } 140 }