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