github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/runner/jujuc/action-set.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/gnuflag"
    12  	"gopkg.in/juju/charm.v6"
    13  
    14  	jujucmd "github.com/juju/juju/cmd"
    15  )
    16  
    17  var keyRule = charm.GetActionNameRule()
    18  
    19  // ActionSetCommand implements the action-set command.
    20  type ActionSetCommand struct {
    21  	cmd.CommandBase
    22  	ctx  Context
    23  	args [][]string
    24  }
    25  
    26  // NewActionSetCommand returns a new ActionSetCommand with the given context.
    27  func NewActionSetCommand(ctx Context) (cmd.Command, error) {
    28  	return &ActionSetCommand{ctx: ctx}, nil
    29  }
    30  
    31  // Info returns the content for --help.
    32  func (c *ActionSetCommand) Info() *cmd.Info {
    33  	doc := `
    34  action-set adds the given values to the results map of the Action.  This map
    35  is returned to the user after the completion of the Action.  Keys must start
    36  and end with lowercase alphanumeric, and contain only lowercase alphanumeric,
    37  hyphens and periods.
    38  
    39  Example usage:
    40   action-set outfile.size=10G
    41   action-set foo.bar=2
    42   action-set foo.baz.val=3
    43   action-set foo.bar.zab=4
    44   action-set foo.baz=1
    45  
    46   will yield:
    47  
    48   outfile:
    49     size: "10G"
    50   foo:
    51     bar:
    52       zab: "4"
    53     baz: "1"
    54  `
    55  	return jujucmd.Info(&cmd.Info{
    56  		Name:    "action-set",
    57  		Args:    "<key>=<value> [<key>=<value> ...]",
    58  		Purpose: "set action results",
    59  		Doc:     doc,
    60  	})
    61  }
    62  
    63  // SetFlags handles known option flags.
    64  func (c *ActionSetCommand) SetFlags(f *gnuflag.FlagSet) {
    65  	// TODO(binary132): add cmd.Input type as in cmd.Output for YAML piping.
    66  }
    67  
    68  // Init accepts maps in the form of key=value, key.key2.keyN....=value
    69  func (c *ActionSetCommand) Init(args []string) error {
    70  	c.args = make([][]string, 0)
    71  	for _, arg := range args {
    72  		thisArg := strings.SplitN(arg, "=", 2)
    73  		if len(thisArg) != 2 {
    74  			return fmt.Errorf("argument %q must be of the form key...=value", arg)
    75  		}
    76  		keySlice := strings.Split(thisArg[0], ".")
    77  		// check each key for validity
    78  		for _, key := range keySlice {
    79  			if valid := keyRule.MatchString(key); !valid {
    80  				return fmt.Errorf("key %q must start and end with lowercase alphanumeric, and contain only lowercase alphanumeric, hyphens and periods", key)
    81  			}
    82  		}
    83  		// [key, key, key, key, value]
    84  		c.args = append(c.args, append(keySlice, thisArg[1]))
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  // Run adds the given <key list>/<value> pairs, such as foo.bar=baz to the
    91  // existing map of results for the Action.
    92  func (c *ActionSetCommand) Run(ctx *cmd.Context) error {
    93  	for _, argSlice := range c.args {
    94  		valueIndex := len(argSlice) - 1
    95  		keys := argSlice[:valueIndex]
    96  		value := argSlice[valueIndex]
    97  		err := c.ctx.UpdateActionResults(keys, value)
    98  		if err != nil {
    99  			return err
   100  		}
   101  	}
   102  
   103  	return nil
   104  }