github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/juju/application/constraints.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application 5 6 import ( 7 "fmt" 8 "io" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/gnuflag" 13 "gopkg.in/juju/names.v2" 14 15 "github.com/juju/juju/api/application" 16 "github.com/juju/juju/cmd/juju/block" 17 "github.com/juju/juju/cmd/modelcmd" 18 "github.com/juju/juju/constraints" 19 ) 20 21 var usageGetConstraintsSummary = ` 22 Displays machine constraints for an application.`[1:] 23 24 var usageGetConstraintsDetails = ` 25 Shows machine constraints that have been set for an application with ` + "`juju set-\nconstraints`" + `. 26 By default, the model is the current model. 27 Application constraints are combined with model constraints, set with ` + 28 "`juju \nset-model-constraints`" + `, for commands (such as 'deploy') that provision 29 machines for applications. Where model and application constraints overlap, the 30 application constraints take precedence. 31 Constraints for a specific model can be viewed with ` + "`juju get-model-\nconstraints`" + `. 32 33 Examples: 34 juju get-constraints mysql 35 juju get-constraints -m mymodel apache2 36 37 See also: 38 set-constraints 39 get-model-constraints 40 set-model-constraints` 41 42 var usageSetConstraintsSummary = ` 43 Sets machine constraints for an application.`[1:] 44 45 // setConstraintsDoc is multi-line since we need to use ` to denote 46 // commands for ease in markdown. 47 var usageSetConstraintsDetails = ` 48 Sets constraints for an application, which are used for all new machines 49 provisioned for that application. They can be viewed with `[1:] + "`juju get-\nconstraints`" + `. 50 By default, the model is the current model. 51 Application constraints are combined with model constraints, set with ` + 52 "`juju \nset-model-constraints`" + `, for commands (such as 'juju deploy') that 53 provision machines for applications. Where model and application constraints 54 overlap, the application constraints take precedence. 55 Constraints for a specific model can be viewed with ` + "`juju get-model-\nconstraints`" + `. 56 This command requires that the application to have at least one unit. To apply 57 constraints to 58 the first unit set them at the model level or pass them as an argument 59 when deploying. 60 61 Examples: 62 juju set-constraints mysql mem=8G cores=4 63 juju set-constraints -m mymodel apache2 mem=8G arch=amd64 64 65 See also: 66 get-constraints 67 get-model-constraints 68 set-model-constraints` 69 70 // NewServiceGetConstraintsCommand returns a command which gets application constraints. 71 func NewServiceGetConstraintsCommand() cmd.Command { 72 return modelcmd.Wrap(&serviceGetConstraintsCommand{}) 73 } 74 75 type serviceConstraintsAPI interface { 76 Close() error 77 GetConstraints(string) (constraints.Value, error) 78 SetConstraints(string, constraints.Value) error 79 } 80 81 type serviceConstraintsCommand struct { 82 modelcmd.ModelCommandBase 83 ApplicationName string 84 out cmd.Output 85 api serviceConstraintsAPI 86 } 87 88 func (c *serviceConstraintsCommand) getAPI() (serviceConstraintsAPI, error) { 89 if c.api != nil { 90 return c.api, nil 91 } 92 root, err := c.NewAPIRoot() 93 if err != nil { 94 return nil, errors.Trace(err) 95 } 96 return application.NewClient(root), nil 97 } 98 99 type serviceGetConstraintsCommand struct { 100 serviceConstraintsCommand 101 } 102 103 func (c *serviceGetConstraintsCommand) Info() *cmd.Info { 104 return &cmd.Info{ 105 Name: "get-constraints", 106 Args: "<application>", 107 Purpose: usageGetConstraintsSummary, 108 Doc: usageGetConstraintsDetails, 109 } 110 } 111 112 func formatConstraints(writer io.Writer, value interface{}) error { 113 fmt.Fprint(writer, value.(constraints.Value).String()) 114 return nil 115 } 116 117 func (c *serviceGetConstraintsCommand) SetFlags(f *gnuflag.FlagSet) { 118 c.ModelCommandBase.SetFlags(f) 119 c.out.AddFlags(f, "constraints", map[string]cmd.Formatter{ 120 "constraints": formatConstraints, 121 "yaml": cmd.FormatYaml, 122 "json": cmd.FormatJson, 123 }) 124 } 125 126 func (c *serviceGetConstraintsCommand) Init(args []string) error { 127 if len(args) == 0 { 128 return errors.Errorf("no application name specified") 129 } 130 if !names.IsValidApplication(args[0]) { 131 return errors.Errorf("invalid application name %q", args[0]) 132 } 133 134 c.ApplicationName, args = args[0], args[1:] 135 return cmd.CheckEmpty(args) 136 } 137 138 func (c *serviceGetConstraintsCommand) Run(ctx *cmd.Context) error { 139 apiclient, err := c.getAPI() 140 if err != nil { 141 return err 142 } 143 defer apiclient.Close() 144 145 cons, err := apiclient.GetConstraints(c.ApplicationName) 146 if err != nil { 147 return err 148 } 149 return c.out.Write(ctx, cons) 150 } 151 152 type serviceSetConstraintsCommand struct { 153 serviceConstraintsCommand 154 Constraints constraints.Value 155 } 156 157 // NewServiceSetConstraintsCommand returns a command which sets application constraints. 158 func NewServiceSetConstraintsCommand() cmd.Command { 159 return modelcmd.Wrap(&serviceSetConstraintsCommand{}) 160 } 161 162 func (c *serviceSetConstraintsCommand) Info() *cmd.Info { 163 return &cmd.Info{ 164 Name: "set-constraints", 165 Args: "<application> <constraint>=<value> ...", 166 Purpose: usageSetConstraintsSummary, 167 Doc: usageSetConstraintsDetails, 168 } 169 } 170 171 func (c *serviceSetConstraintsCommand) Init(args []string) (err error) { 172 if len(args) == 0 { 173 return errors.Errorf("no application name specified") 174 } 175 if !names.IsValidApplication(args[0]) { 176 return errors.Errorf("invalid application name %q", args[0]) 177 } 178 179 c.ApplicationName, args = args[0], args[1:] 180 181 c.Constraints, err = constraints.Parse(args...) 182 return err 183 } 184 185 func (c *serviceSetConstraintsCommand) Run(_ *cmd.Context) (err error) { 186 apiclient, err := c.getAPI() 187 if err != nil { 188 return err 189 } 190 defer apiclient.Close() 191 192 err = apiclient.SetConstraints(c.ApplicationName, c.Constraints) 193 return block.ProcessBlockedError(err, block.BlockChange) 194 }