launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/juju/constraints.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 9 "launchpad.net/gnuflag" 10 11 "launchpad.net/juju-core/cmd" 12 "launchpad.net/juju-core/constraints" 13 "launchpad.net/juju-core/juju" 14 "launchpad.net/juju-core/names" 15 "launchpad.net/juju-core/state/api/params" 16 ) 17 18 const getConstraintsDoc = ` 19 get-constraints returns a list of constraints that have been set on 20 the environment using juju set-constraints. You can also view constraints set 21 for a specific service by using juju get-constraints <service>. 22 23 See Also: 24 juju help constraints 25 juju help set-constraints 26 ` 27 28 const setConstraintsDoc = ` 29 set-constraints sets machine constraints on the system, which are used as the 30 default constraints for all new machines provisioned in the environment (unless 31 overridden). You can also set constraints on a specific service by using juju 32 set-constraints <service>. 33 34 Constraints set on a service are combined with environment constraints for 35 commands (such as juju deploy) that provision machines for services. Where 36 environment and service constraints overlap, the service constraints take 37 precedence. 38 39 Examples: 40 41 set-constraints mem=8G (all new machines in the environment must have at least 8GB of RAM) 42 set-constraints --service wordpress mem=4G (all new wordpress machines can ignore the 8G constraint above, and require only 4G) 43 44 See Also: 45 juju help constraints 46 juju help get-constraints 47 juju help deploy 48 juju help add-machine 49 juju help add-unit 50 ` 51 52 // GetConstraintsCommand shows the constraints for a service or environment. 53 type GetConstraintsCommand struct { 54 cmd.EnvCommandBase 55 ServiceName string 56 out cmd.Output 57 } 58 59 func (c *GetConstraintsCommand) Info() *cmd.Info { 60 return &cmd.Info{ 61 Name: "get-constraints", 62 Args: "[<service>]", 63 Purpose: "view constraints on the environment or a service", 64 Doc: getConstraintsDoc, 65 } 66 } 67 68 func formatConstraints(value interface{}) ([]byte, error) { 69 return []byte(value.(constraints.Value).String()), nil 70 } 71 72 func (c *GetConstraintsCommand) SetFlags(f *gnuflag.FlagSet) { 73 c.EnvCommandBase.SetFlags(f) 74 c.out.AddFlags(f, "constraints", map[string]cmd.Formatter{ 75 "constraints": formatConstraints, 76 "yaml": cmd.FormatYaml, 77 "json": cmd.FormatJson, 78 }) 79 } 80 81 func (c *GetConstraintsCommand) Init(args []string) error { 82 if len(args) > 0 { 83 if !names.IsService(args[0]) { 84 return fmt.Errorf("invalid service name %q", args[0]) 85 } 86 c.ServiceName, args = args[0], args[1:] 87 } 88 return cmd.CheckEmpty(args) 89 } 90 91 // getEnvironConstraints1dot16 uses direct DB access to get the Environment 92 // constraints against an API server running 1.16 or older (when GetEnvironmentConstraints 93 // was not available). This fallback can be removed when we no longer maintain 94 // 1.16 compatibility. 95 // This only does the GetEnvironmentConstraints portion of Run, since 96 // GetServiceConstraints was already implemented. 97 func (c *GetConstraintsCommand) getEnvironConstraints1dot16() (constraints.Value, error) { 98 conn, err := juju.NewConnFromName(c.EnvName) 99 if err != nil { 100 return constraints.Value{}, err 101 } 102 defer conn.Close() 103 return conn.State.EnvironConstraints() 104 } 105 106 func (c *GetConstraintsCommand) Run(ctx *cmd.Context) error { 107 apiclient, err := juju.NewAPIClientFromName(c.EnvName) 108 if err != nil { 109 return err 110 } 111 defer apiclient.Close() 112 113 var cons constraints.Value 114 if c.ServiceName == "" { 115 cons, err = apiclient.GetEnvironmentConstraints() 116 if params.IsCodeNotImplemented(err) { 117 logger.Infof("GetEnvironmentConstraints not supported by the API server, " + 118 "falling back to 1.16 compatibility mode (direct DB access)") 119 cons, err = c.getEnvironConstraints1dot16() 120 } 121 } else { 122 cons, err = apiclient.GetServiceConstraints(c.ServiceName) 123 } 124 if err != nil { 125 return err 126 } 127 return c.out.Write(ctx, cons) 128 } 129 130 // SetConstraintsCommand shows the constraints for a service or environment. 131 type SetConstraintsCommand struct { 132 cmd.EnvCommandBase 133 ServiceName string 134 Constraints constraints.Value 135 } 136 137 func (c *SetConstraintsCommand) Info() *cmd.Info { 138 return &cmd.Info{ 139 Name: "set-constraints", 140 Args: "[key=[value] ...]", 141 Purpose: "set constraints on the environment or a service", 142 Doc: setConstraintsDoc, 143 } 144 } 145 146 func (c *SetConstraintsCommand) SetFlags(f *gnuflag.FlagSet) { 147 c.EnvCommandBase.SetFlags(f) 148 f.StringVar(&c.ServiceName, "s", "", "set service constraints") 149 f.StringVar(&c.ServiceName, "service", "", "") 150 } 151 152 func (c *SetConstraintsCommand) Init(args []string) (err error) { 153 if c.ServiceName != "" && !names.IsService(c.ServiceName) { 154 return fmt.Errorf("invalid service name %q", c.ServiceName) 155 } 156 c.Constraints, err = constraints.Parse(args...) 157 return err 158 } 159 160 // setEnvironConstraints1dot16 uses direct DB access to get the Environment 161 // constraints against an API server running 1.16 or older (when SetEnvironmentConstraints 162 // was not available). This fallback can be removed when we no longer maintain 163 // 1.16 compatibility. 164 // This only does the SetEnvironmentConstraints portion of Run, since 165 // SetServiceConstraints was already implemented. 166 func (c *SetConstraintsCommand) setEnvironConstraints1dot16() error { 167 conn, err := juju.NewConnFromName(c.EnvName) 168 if err != nil { 169 return err 170 } 171 defer conn.Close() 172 return conn.State.SetEnvironConstraints(c.Constraints) 173 } 174 175 func (c *SetConstraintsCommand) Run(_ *cmd.Context) (err error) { 176 apiclient, err := juju.NewAPIClientFromName(c.EnvName) 177 if err != nil { 178 return err 179 } 180 defer apiclient.Close() 181 if c.ServiceName == "" { 182 err = apiclient.SetEnvironmentConstraints(c.Constraints) 183 if params.IsCodeNotImplemented(err) { 184 logger.Infof("SetEnvironmentConstraints not supported by the API server, " + 185 "falling back to 1.16 compatibility mode (direct DB access)") 186 err = c.setEnvironConstraints1dot16() 187 } 188 return err 189 } 190 return apiclient.SetServiceConstraints(c.ServiceName, c.Constraints) 191 }