github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/cmd/juju/addunit.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  
    10  	"launchpad.net/gnuflag"
    11  
    12  	"launchpad.net/juju-core/cmd"
    13  	"launchpad.net/juju-core/juju"
    14  )
    15  
    16  // UnitCommandBase provides support for commands which deploy units. It handles the parsing
    17  // and validation of --to and --num-units arguments.
    18  type UnitCommandBase struct {
    19  	ToMachineSpec string
    20  	NumUnits      int
    21  }
    22  
    23  func (c *UnitCommandBase) SetFlags(f *gnuflag.FlagSet) {
    24  	f.IntVar(&c.NumUnits, "num-units", 1, "")
    25  	f.StringVar(&c.ToMachineSpec, "to", "", "the machine or container to deploy the unit in, bypasses constraints")
    26  }
    27  
    28  func (c *UnitCommandBase) Init(args []string) error {
    29  	if c.NumUnits < 1 {
    30  		return errors.New("--num-units must be a positive integer")
    31  	}
    32  	if c.ToMachineSpec != "" {
    33  		if c.NumUnits > 1 {
    34  			return errors.New("cannot use --num-units > 1 with --to")
    35  		}
    36  		if !cmd.IsMachineOrNewContainer(c.ToMachineSpec) {
    37  			return fmt.Errorf("invalid --to parameter %q", c.ToMachineSpec)
    38  		}
    39  	}
    40  	return nil
    41  }
    42  
    43  // AddUnitCommand is responsible adding additional units to a service.
    44  type AddUnitCommand struct {
    45  	cmd.EnvCommandBase
    46  	UnitCommandBase
    47  	ServiceName string
    48  }
    49  
    50  const addUnitDoc = `
    51  Adding units to an existing service is a way to scale out an environment by
    52  deploying more instances of a service.  Add-unit must be called on services that
    53  have already been deployed via juju deploy.  
    54  
    55  By default, services are deployed to newly provisioned machines.  Alternatively,
    56  service units can be added to a specific existing machine using the --to
    57  argument.
    58  
    59  Examples:
    60   juju add-unit mysql -n 5          (Add 5 mysql units on 5 new machines)
    61   juju add-unit mysql --to 23       (Add a mysql unit to machine 23)
    62   juju add-unit mysql --to 24/lxc/3 (Add unit to lxc container 3 on host machine 24)
    63   juju add-unit mysql --to lxc:25   (Add unit to a new lxc container on host machine 25)
    64  `
    65  
    66  func (c *AddUnitCommand) Info() *cmd.Info {
    67  	return &cmd.Info{
    68  		Name:    "add-unit",
    69  		Args:    "<service name>",
    70  		Purpose: "add one or more units of an already-deployed service",
    71  		Doc:     addUnitDoc,
    72  	}
    73  }
    74  
    75  func (c *AddUnitCommand) SetFlags(f *gnuflag.FlagSet) {
    76  	c.EnvCommandBase.SetFlags(f)
    77  	c.UnitCommandBase.SetFlags(f)
    78  	f.IntVar(&c.NumUnits, "n", 1, "number of service units to add")
    79  }
    80  
    81  func (c *AddUnitCommand) Init(args []string) error {
    82  	switch len(args) {
    83  	case 1:
    84  		c.ServiceName = args[0]
    85  	case 0:
    86  		return errors.New("no service specified")
    87  	}
    88  	if err := cmd.CheckEmpty(args[1:]); err != nil {
    89  		return err
    90  	}
    91  	return c.UnitCommandBase.Init(args)
    92  }
    93  
    94  // Run connects to the environment specified on the command line
    95  // and calls AddServiceUnits for the given service.
    96  func (c *AddUnitCommand) Run(_ *cmd.Context) error {
    97  	apiclient, err := juju.NewAPIClientFromName(c.EnvName)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	defer apiclient.Close()
   102  
   103  	_, err = apiclient.AddServiceUnits(c.ServiceName, c.NumUnits, c.ToMachineSpec)
   104  	return err
   105  }