github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/uniter/runner/jujuc/relation-set.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc 5 6 import ( 7 "fmt" 8 "io" 9 "io/ioutil" 10 11 "github.com/juju/cmd" 12 "github.com/juju/errors" 13 "github.com/juju/utils/keyvalues" 14 goyaml "gopkg.in/yaml.v2" 15 "launchpad.net/gnuflag" 16 ) 17 18 const relationSetDoc = ` 19 "relation-set" writes the local unit's settings for some relation. 20 If no relation is specified then the current relation is used. The 21 setting values are not inspected and are stored as strings. Setting 22 an empty string causes the setting to be removed. Duplicate settings 23 are not allowed. 24 25 The --file option should be used when one or more key-value pairs are 26 too long to fit within the command length limit of the shell or 27 operating system. The file will contain a YAML map containing the 28 settings. Settings in the file will be overridden by any duplicate 29 key-value arguments. A value of "-" for the filename means <stdin>. 30 ` 31 32 // RelationSetCommand implements the relation-set command. 33 type RelationSetCommand struct { 34 cmd.CommandBase 35 ctx Context 36 RelationId int 37 relationIdProxy gnuflag.Value 38 Settings map[string]string 39 settingsFile cmd.FileVar 40 formatFlag string // deprecated 41 } 42 43 func NewRelationSetCommand(ctx Context) (cmd.Command, error) { 44 c := &RelationSetCommand{ctx: ctx} 45 46 rV, err := newRelationIdValue(ctx, &c.RelationId) 47 if err != nil { 48 return nil, errors.Trace(err) 49 } 50 c.relationIdProxy = rV 51 52 return c, nil 53 } 54 55 func (c *RelationSetCommand) Info() *cmd.Info { 56 return &cmd.Info{ 57 Name: "relation-set", 58 Args: "key=value [key=value ...]", 59 Purpose: "set relation settings", 60 Doc: relationSetDoc, 61 } 62 } 63 64 func (c *RelationSetCommand) SetFlags(f *gnuflag.FlagSet) { 65 f.Var(c.relationIdProxy, "r", "specify a relation by id") 66 f.Var(c.relationIdProxy, "relation", "") 67 68 c.settingsFile.SetStdin() 69 f.Var(&c.settingsFile, "file", "file containing key-value pairs") 70 71 f.StringVar(&c.formatFlag, "format", "", "deprecated format flag") 72 } 73 74 func (c *RelationSetCommand) Init(args []string) error { 75 if c.RelationId == -1 { 76 return errors.Errorf("no relation id specified") 77 } 78 79 // The overrides will be applied during Run when c.settingsFile is handled. 80 overrides, err := keyvalues.Parse(args, true) 81 if err != nil { 82 return errors.Trace(err) 83 } 84 c.Settings = overrides 85 return nil 86 } 87 88 func (c *RelationSetCommand) readSettings(in io.Reader) (map[string]string, error) { 89 data, err := ioutil.ReadAll(in) 90 if err != nil { 91 return nil, errors.Trace(err) 92 } 93 94 kvs := make(map[string]string) 95 if err := goyaml.Unmarshal(data, kvs); err != nil { 96 return nil, errors.Trace(err) 97 } 98 99 return kvs, nil 100 } 101 102 func (c *RelationSetCommand) handleSettingsFile(ctx *cmd.Context) error { 103 if c.settingsFile.Path == "" { 104 return nil 105 } 106 107 file, err := c.settingsFile.Open(ctx) 108 if err != nil { 109 return errors.Trace(err) 110 } 111 defer file.Close() 112 113 settings, err := c.readSettings(file) 114 if err != nil { 115 return errors.Trace(err) 116 } 117 118 overrides := c.Settings 119 for k, v := range overrides { 120 settings[k] = v 121 } 122 c.Settings = settings 123 return nil 124 } 125 126 func (c *RelationSetCommand) Run(ctx *cmd.Context) (err error) { 127 if c.formatFlag != "" { 128 fmt.Fprintf(ctx.Stderr, "--format flag deprecated for command %q", c.Info().Name) 129 } 130 if err := c.handleSettingsFile(ctx); err != nil { 131 return errors.Trace(err) 132 } 133 134 r, err := c.ctx.Relation(c.RelationId) 135 if err != nil { 136 return errors.Trace(err) 137 } 138 settings, err := r.Settings() 139 if err != nil { 140 return errors.Annotate(err, "cannot read relation settings") 141 } 142 for k, v := range c.Settings { 143 if v != "" { 144 settings.Set(k, v) 145 } else { 146 settings.Delete(k) 147 } 148 } 149 return nil 150 }