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