github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/state-set.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujuc 5 6 import ( 7 "fmt" 8 9 "github.com/juju/cmd/v3" 10 "github.com/juju/errors" 11 "github.com/juju/gnuflag" 12 "github.com/juju/utils/v3/keyvalues" 13 14 jujucmd "github.com/juju/juju/cmd" 15 "github.com/juju/juju/core/quota" 16 ) 17 18 // StateSetCommand implements the state-set command. 19 type StateSetCommand struct { 20 cmd.CommandBase 21 ctx Context 22 StateValues map[string]string 23 keyValueFile cmd.FileVar 24 } 25 26 // NewStateSetCommand returns a state-set command. 27 func NewStateSetCommand(ctx Context) (cmd.Command, error) { 28 return &StateSetCommand{ctx: ctx}, nil 29 } 30 31 // Info returns information about the Command. 32 // Info implements part of the cmd.Command interface. 33 func (c *StateSetCommand) Info() *cmd.Info { 34 doc := ` 35 state-set sets the value of the server side state specified by key. 36 37 The --file option should be used when one or more key-value pairs 38 are too long to fit within the command length limit of the shell 39 or operating system. The file will contain a YAML map containing 40 the settings as strings. Settings in the file will be overridden 41 by any duplicate key-value arguments. A value of "-" for the filename 42 means <stdin>. 43 44 The following fixed size limits apply: 45 - Length of stored keys cannot exceed %d bytes. 46 - Length of stored values cannot exceed %d bytes. 47 48 See also: 49 state-delete 50 state-get 51 ` 52 return jujucmd.Info(&cmd.Info{ 53 Name: "state-set", 54 Args: "key=value [key=value ...]", 55 Purpose: "set server-side-state values", 56 Doc: fmt.Sprintf( 57 doc, 58 quota.MaxCharmStateKeySize, 59 quota.MaxCharmStateValueSize, 60 ), 61 }) 62 } 63 64 // SetFlags adds command specific flags to the flag set. 65 // SetFlags implements part of the cmd.Command interface. 66 func (c *StateSetCommand) SetFlags(f *gnuflag.FlagSet) { 67 c.keyValueFile.SetStdin() 68 f.Var(&c.keyValueFile, "file", "file containing key-value pairs") 69 } 70 71 // Init initializes the Command before running. 72 // Init implements part of the cmd.Command interface. 73 func (c *StateSetCommand) Init(args []string) error { 74 if args == nil { 75 return nil 76 } 77 78 // The overrides will be applied during Run when c.keyValueFile is handled. 79 overrides, err := keyvalues.Parse(args, true) 80 if err != nil { 81 return errors.Trace(err) 82 } 83 c.StateValues = overrides 84 return nil 85 } 86 87 // Run will execute the Command as directed by the options and positional 88 // arguments passed to Init. 89 // Run implements part of the cmd.Command interface. 90 func (c *StateSetCommand) Run(ctx *cmd.Context) error { 91 if err := c.handleKeyValueFile(ctx); err != nil { 92 return errors.Trace(err) 93 } 94 95 for k, v := range c.StateValues { 96 if err := c.ctx.SetCharmStateValue(k, v); err != nil { 97 return err 98 } 99 } 100 return nil 101 } 102 103 func (c *StateSetCommand) handleKeyValueFile(ctx *cmd.Context) error { 104 if c.keyValueFile.Path == "" { 105 return nil 106 } 107 108 file, err := c.keyValueFile.Open(ctx) 109 if err != nil { 110 return errors.Trace(err) 111 } 112 defer func() { _ = file.Close() }() 113 114 kvs, err := readSettings(file) 115 if err != nil { 116 return errors.Trace(err) 117 } 118 119 overrides := c.StateValues 120 for k, v := range overrides { 121 kvs[k] = v 122 } 123 c.StateValues = kvs 124 return nil 125 }