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  }