github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/action/list.go (about)

     1  // Copyright 2014, 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package action
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"strings"
    10  
    11  	"github.com/juju/cmd"
    12  	errors "github.com/juju/errors"
    13  	"github.com/juju/gnuflag"
    14  	"github.com/juju/utils"
    15  	"gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/apiserver/params"
    18  	"github.com/juju/juju/cmd/modelcmd"
    19  	"github.com/juju/juju/cmd/output"
    20  )
    21  
    22  func NewListCommand() cmd.Command {
    23  	return modelcmd.Wrap(&listCommand{})
    24  }
    25  
    26  // listCommand lists actions defined by the charm of a given service.
    27  type listCommand struct {
    28  	ActionCommandBase
    29  	applicationTag names.ApplicationTag
    30  	fullSchema     bool
    31  	out            cmd.Output
    32  }
    33  
    34  const listDoc = `
    35  List the actions available to run on the target application, with a short
    36  description.  To show the full schema for the actions, use --schema.
    37  
    38  For more information, see also the 'run-action' command, which executes actions.
    39  `
    40  
    41  // Set up the output.
    42  func (c *listCommand) SetFlags(f *gnuflag.FlagSet) {
    43  	c.ActionCommandBase.SetFlags(f)
    44  	c.out.AddFlags(f, "tabular", map[string]cmd.Formatter{
    45  		"yaml":    cmd.FormatYaml,
    46  		"json":    cmd.FormatJson,
    47  		"tabular": c.printTabular,
    48  	})
    49  	f.BoolVar(&c.fullSchema, "schema", false, "Display the full action schema")
    50  }
    51  
    52  func (c *listCommand) Info() *cmd.Info {
    53  	return &cmd.Info{
    54  		Name:    "actions",
    55  		Args:    "<application name>",
    56  		Purpose: "List actions defined for a service.",
    57  		Doc:     listDoc,
    58  		Aliases: []string{"list-actions"},
    59  	}
    60  }
    61  
    62  // Init validates the service name and any other options.
    63  func (c *listCommand) Init(args []string) error {
    64  	if c.out.Name() == "tabular" && c.fullSchema {
    65  		return errors.New("full schema not compatible with tabular output")
    66  	}
    67  	switch len(args) {
    68  	case 0:
    69  		return errors.New("no application name specified")
    70  	case 1:
    71  		svcName := args[0]
    72  		if !names.IsValidApplication(svcName) {
    73  			return errors.Errorf("invalid application name %q", svcName)
    74  		}
    75  		c.applicationTag = names.NewApplicationTag(svcName)
    76  		return nil
    77  	default:
    78  		return cmd.CheckEmpty(args[1:])
    79  	}
    80  }
    81  
    82  // Run grabs the Actions spec from the api.  It then sets up a sensible
    83  // output format for the map.
    84  func (c *listCommand) Run(ctx *cmd.Context) error {
    85  	api, err := c.NewActionAPIClient()
    86  	if err != nil {
    87  		return err
    88  	}
    89  	defer api.Close()
    90  
    91  	actions, err := api.ApplicationCharmActions(params.Entity{c.applicationTag.String()})
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	if c.fullSchema {
    97  		verboseSpecs := make(map[string]interface{})
    98  		for k, v := range actions {
    99  			verboseSpecs[k] = v.Params
   100  		}
   101  
   102  		return c.out.Write(ctx, verboseSpecs)
   103  	}
   104  
   105  	shortOutput := make(map[string]string)
   106  	var sortedNames []string
   107  	for name, action := range actions {
   108  		shortOutput[name] = action.Description
   109  		if shortOutput[name] == "" {
   110  			shortOutput[name] = "No description"
   111  		}
   112  		sortedNames = append(sortedNames, name)
   113  	}
   114  	utils.SortStringsNaturally(sortedNames)
   115  
   116  	var output interface{}
   117  	switch c.out.Name() {
   118  	case "yaml", "json":
   119  		output = shortOutput
   120  	default:
   121  		if len(sortedNames) == 0 {
   122  			ctx.Infof("No actions defined for %s.", c.applicationTag.Id())
   123  			return nil
   124  		}
   125  		var list []listOutput
   126  		for _, name := range sortedNames {
   127  			list = append(list, listOutput{name, shortOutput[name]})
   128  		}
   129  		output = list
   130  	}
   131  
   132  	return c.out.Write(ctx, output)
   133  }
   134  
   135  type listOutput struct {
   136  	action      string
   137  	description string
   138  }
   139  
   140  // printTabular prints the list of actions in tabular format
   141  func (c *listCommand) printTabular(writer io.Writer, value interface{}) error {
   142  	list, ok := value.([]listOutput)
   143  	if !ok {
   144  		return errors.New("unexpected value")
   145  	}
   146  
   147  	tw := output.TabWriter(writer)
   148  	fmt.Fprintf(tw, "%s\t%s\n", "ACTION", "DESCRIPTION")
   149  	for _, value := range list {
   150  		fmt.Fprintf(tw, "%s\t%s\n", value.action, strings.TrimSpace(value.description))
   151  	}
   152  	tw.Flush()
   153  	return nil
   154  }