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