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