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  }