github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/juju/application/addunit_test.go (about)

     1  // Copyright 2012-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package application_test
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/cmd/juju/application"
    16  	"github.com/juju/juju/environs/config"
    17  	"github.com/juju/juju/instance"
    18  	"github.com/juju/juju/testing"
    19  )
    20  
    21  type AddUnitSuite struct {
    22  	testing.FakeJujuXDGDataHomeSuite
    23  	fake *fakeServiceAddUnitAPI
    24  }
    25  
    26  type fakeServiceAddUnitAPI struct {
    27  	envType     string
    28  	application string
    29  	numUnits    int
    30  	placement   []*instance.Placement
    31  	err         error
    32  }
    33  
    34  func (f *fakeServiceAddUnitAPI) Close() error {
    35  	return nil
    36  }
    37  
    38  func (f *fakeServiceAddUnitAPI) ModelUUID() string {
    39  	return "fake-uuid"
    40  }
    41  
    42  func (f *fakeServiceAddUnitAPI) AddUnits(application string, numUnits int, placement []*instance.Placement) ([]string, error) {
    43  	if f.err != nil {
    44  		return nil, f.err
    45  	}
    46  	if application != f.application {
    47  		return nil, errors.NotFoundf("application %q", application)
    48  	}
    49  
    50  	f.numUnits += numUnits
    51  	f.placement = placement
    52  	return nil, nil
    53  }
    54  
    55  func (f *fakeServiceAddUnitAPI) ModelGet() (map[string]interface{}, error) {
    56  	cfg, err := config.New(config.UseDefaults, map[string]interface{}{
    57  		"type": f.envType,
    58  		"name": "dummy",
    59  	})
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	return cfg.AllAttrs(), nil
    65  }
    66  
    67  func (s *AddUnitSuite) SetUpTest(c *gc.C) {
    68  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    69  	s.fake = &fakeServiceAddUnitAPI{application: "some-application-name", numUnits: 1, envType: "dummy"}
    70  }
    71  
    72  var _ = gc.Suite(&AddUnitSuite{})
    73  
    74  var initAddUnitErrorTests = []struct {
    75  	args []string
    76  	err  string
    77  }{
    78  	{
    79  		args: []string{"some-application-name", "-n", "0"},
    80  		err:  `--num-units must be a positive integer`,
    81  	}, {
    82  		args: []string{},
    83  		err:  `no application specified`,
    84  	}, {
    85  		args: []string{"some-application-name", "--to", "1,#:foo"},
    86  		err:  `invalid --to parameter "#:foo"`,
    87  	},
    88  }
    89  
    90  func (s *AddUnitSuite) TestInitErrors(c *gc.C) {
    91  	for i, t := range initAddUnitErrorTests {
    92  		c.Logf("test %d", i)
    93  		err := testing.InitCommand(application.NewAddUnitCommandForTest(s.fake), t.args)
    94  		c.Check(err, gc.ErrorMatches, t.err)
    95  	}
    96  }
    97  
    98  func (s *AddUnitSuite) runAddUnit(c *gc.C, args ...string) error {
    99  	_, err := testing.RunCommand(c, application.NewAddUnitCommandForTest(s.fake), args...)
   100  	return err
   101  }
   102  
   103  func (s *AddUnitSuite) TestAddUnit(c *gc.C) {
   104  	err := s.runAddUnit(c, "some-application-name")
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	c.Assert(s.fake.numUnits, gc.Equals, 2)
   107  
   108  	err = s.runAddUnit(c, "--num-units", "2", "some-application-name")
   109  	c.Assert(err, jc.ErrorIsNil)
   110  	c.Assert(s.fake.numUnits, gc.Equals, 4)
   111  }
   112  
   113  func (s *AddUnitSuite) TestAddUnitWithPlacement(c *gc.C) {
   114  	err := s.runAddUnit(c, "some-application-name")
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	c.Assert(s.fake.numUnits, gc.Equals, 2)
   117  
   118  	err = s.runAddUnit(c, "--num-units", "2", "--to", "123,lxd:1,1/lxd/2,foo", "some-application-name")
   119  	c.Assert(err, jc.ErrorIsNil)
   120  	c.Assert(s.fake.numUnits, gc.Equals, 4)
   121  	c.Assert(s.fake.placement, jc.DeepEquals, []*instance.Placement{
   122  		{"#", "123"},
   123  		{"lxd", "1"},
   124  		{"#", "1/lxd/2"},
   125  		{"fake-uuid", "foo"},
   126  	})
   127  }
   128  
   129  func (s *AddUnitSuite) TestBlockAddUnit(c *gc.C) {
   130  	// Block operation
   131  	s.fake.err = common.OperationBlockedError("TestBlockAddUnit")
   132  	s.runAddUnit(c, "some-application-name")
   133  
   134  	// msg is logged
   135  	stripped := strings.Replace(c.GetTestLog(), "\n", "", -1)
   136  	c.Check(stripped, gc.Matches, ".*TestBlockAddUnit.*")
   137  }
   138  
   139  func (s *AddUnitSuite) TestUnauthorizedMentionsJujuGrant(c *gc.C) {
   140  	s.fake.err = &params.Error{
   141  		Message: "permission denied",
   142  		Code:    params.CodeUnauthorized,
   143  	}
   144  	ctx, _ := testing.RunCommand(c, application.NewAddUnitCommandForTest(s.fake), "some-application-name")
   145  	errString := strings.Replace(testing.Stderr(ctx), "\n", " ", -1)
   146  	c.Assert(errString, gc.Matches, `.*juju grant.*`)
   147  }
   148  
   149  func (s *AddUnitSuite) TestForceMachine(c *gc.C) {
   150  	err := s.runAddUnit(c, "some-application-name", "--to", "3")
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	c.Assert(s.fake.numUnits, gc.Equals, 2)
   153  	c.Assert(s.fake.placement[0].Directive, gc.Equals, "3")
   154  
   155  	err = s.runAddUnit(c, "some-application-name", "--to", "23")
   156  	c.Assert(err, jc.ErrorIsNil)
   157  	c.Assert(s.fake.numUnits, gc.Equals, 3)
   158  	c.Assert(s.fake.placement[0].Directive, gc.Equals, "23")
   159  }
   160  
   161  func (s *AddUnitSuite) TestForceMachineNewContainer(c *gc.C) {
   162  	err := s.runAddUnit(c, "some-application-name", "--to", "lxd:1")
   163  	c.Assert(err, jc.ErrorIsNil)
   164  	c.Assert(s.fake.numUnits, gc.Equals, 2)
   165  	c.Assert(s.fake.placement[0].Directive, gc.Equals, "1")
   166  	c.Assert(s.fake.placement[0].Scope, gc.Equals, "lxd")
   167  }
   168  
   169  func (s *AddUnitSuite) TestNameChecks(c *gc.C) {
   170  	assertMachineOrNewContainer := func(s string, expect bool) {
   171  		c.Logf("%s -> %v", s, expect)
   172  		c.Assert(application.IsMachineOrNewContainer(s), gc.Equals, expect)
   173  	}
   174  	assertMachineOrNewContainer("0", true)
   175  	assertMachineOrNewContainer("00", false)
   176  	assertMachineOrNewContainer("1", true)
   177  	assertMachineOrNewContainer("0/lxd/0", true)
   178  	assertMachineOrNewContainer("lxd:0", true)
   179  	assertMachineOrNewContainer("lxd:lxd:0", false)
   180  	assertMachineOrNewContainer("kvm:0/lxd/1", true)
   181  	assertMachineOrNewContainer("lxd:", false)
   182  	assertMachineOrNewContainer(":lxd", false)
   183  	assertMachineOrNewContainer("0/lxd/", false)
   184  	assertMachineOrNewContainer("0/lxd", false)
   185  	assertMachineOrNewContainer("kvm:0/lxd", false)
   186  	assertMachineOrNewContainer("0/lxd/01", false)
   187  	assertMachineOrNewContainer("0/lxd/10", true)
   188  	assertMachineOrNewContainer("0/kvm/4", true)
   189  }