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  }