github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/machine/add_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machine_test 5 6 import ( 7 "strconv" 8 9 "github.com/juju/cmd" 10 "github.com/juju/errors" 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/common" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/cmd/juju/machine" 17 "github.com/juju/juju/environs/manual" 18 "github.com/juju/juju/provider/dummy" 19 "github.com/juju/juju/state/multiwatcher" 20 "github.com/juju/juju/storage" 21 "github.com/juju/juju/testing" 22 ) 23 24 type AddMachineSuite struct { 25 testing.FakeJujuXDGDataHomeSuite 26 fakeAddMachine *fakeAddMachineAPI 27 fakeMachineManager *fakeMachineManagerAPI 28 } 29 30 var _ = gc.Suite(&AddMachineSuite{}) 31 32 func (s *AddMachineSuite) SetUpTest(c *gc.C) { 33 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 34 s.fakeAddMachine = &fakeAddMachineAPI{} 35 s.fakeMachineManager = &fakeMachineManagerAPI{} 36 } 37 38 func (s *AddMachineSuite) TestInit(c *gc.C) { 39 for i, test := range []struct { 40 args []string 41 series string 42 constraints string 43 placement string 44 count int 45 errorString string 46 }{ 47 { 48 count: 1, 49 }, { 50 args: []string{"--series", "some-series"}, 51 count: 1, 52 series: "some-series", 53 }, { 54 args: []string{"-n", "2"}, 55 count: 2, 56 }, { 57 args: []string{"lxd"}, 58 count: 1, 59 placement: "lxd:", 60 }, { 61 args: []string{"lxd", "-n", "2"}, 62 count: 2, 63 placement: "lxd:", 64 }, { 65 args: []string{"lxd:4"}, 66 count: 1, 67 placement: "lxd:4", 68 }, { 69 args: []string{"ssh:user@10.10.0.3"}, 70 count: 1, 71 placement: "ssh:user@10.10.0.3", 72 }, { 73 args: []string{"zone=us-east-1a"}, 74 count: 1, 75 placement: "model-uuid:zone=us-east-1a", 76 }, { 77 args: []string{"anything-here"}, 78 count: 1, 79 placement: "model-uuid:anything-here", 80 }, { 81 args: []string{"anything", "else"}, 82 errorString: `unrecognized args: \["else"\]`, 83 }, { 84 args: []string{"something:special"}, 85 count: 1, 86 placement: "something:special", 87 }, 88 } { 89 c.Logf("test %d", i) 90 wrappedCommand, addCmd := machine.NewAddCommandForTest(s.fakeAddMachine, s.fakeAddMachine, s.fakeMachineManager) 91 err := testing.InitCommand(wrappedCommand, test.args) 92 if test.errorString == "" { 93 c.Check(err, jc.ErrorIsNil) 94 c.Check(addCmd.Series, gc.Equals, test.series) 95 c.Check(addCmd.Constraints.String(), gc.Equals, test.constraints) 96 if addCmd.Placement != nil { 97 c.Check(addCmd.Placement.String(), gc.Equals, test.placement) 98 } else { 99 c.Check("", gc.Equals, test.placement) 100 } 101 c.Check(addCmd.NumMachines, gc.Equals, test.count) 102 } else { 103 c.Check(err, gc.ErrorMatches, test.errorString) 104 } 105 } 106 } 107 108 func (s *AddMachineSuite) run(c *gc.C, args ...string) (*cmd.Context, error) { 109 add, _ := machine.NewAddCommandForTest(s.fakeAddMachine, s.fakeAddMachine, s.fakeMachineManager) 110 return testing.RunCommand(c, add, args...) 111 } 112 113 func (s *AddMachineSuite) TestAddMachine(c *gc.C) { 114 context, err := s.run(c) 115 c.Assert(err, jc.ErrorIsNil) 116 c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n") 117 118 c.Assert(s.fakeAddMachine.args, gc.HasLen, 1) 119 param := s.fakeAddMachine.args[0] 120 c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{ 121 multiwatcher.JobHostUnits, 122 }) 123 } 124 125 func (s *AddMachineSuite) TestSSHPlacement(c *gc.C) { 126 s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) { 127 return "42", nil 128 }) 129 context, err := s.run(c, "ssh:10.1.2.3") 130 c.Assert(err, jc.ErrorIsNil) 131 c.Assert(testing.Stderr(context), gc.Equals, "created machine 42\n") 132 } 133 134 func (s *AddMachineSuite) TestSSHPlacementError(c *gc.C) { 135 s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) { 136 return "", errors.New("failed to initialize warp core") 137 }) 138 context, err := s.run(c, "ssh:10.1.2.3") 139 c.Assert(err, gc.ErrorMatches, "failed to initialize warp core") 140 c.Assert(testing.Stderr(context), gc.Equals, "") 141 } 142 143 func (s *AddMachineSuite) TestParamsPassedOn(c *gc.C) { 144 _, err := s.run(c, "--constraints", "mem=8G", "--series=special", "zone=nz") 145 c.Assert(err, jc.ErrorIsNil) 146 c.Assert(s.fakeAddMachine.args, gc.HasLen, 1) 147 param := s.fakeAddMachine.args[0] 148 c.Assert(param.Placement.String(), gc.Equals, "fake-uuid:zone=nz") 149 c.Assert(param.Series, gc.Equals, "special") 150 c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M") 151 } 152 153 func (s *AddMachineSuite) TestParamsPassedOnNTimes(c *gc.C) { 154 _, err := s.run(c, "-n", "3", "--constraints", "mem=8G", "--series=special") 155 c.Assert(err, jc.ErrorIsNil) 156 c.Assert(s.fakeAddMachine.args, gc.HasLen, 3) 157 param := s.fakeAddMachine.args[0] 158 c.Assert(param.Series, gc.Equals, "special") 159 c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M") 160 c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[1]) 161 c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[2]) 162 } 163 164 func (s *AddMachineSuite) TestAddThreeMachinesWithTwoFailures(c *gc.C) { 165 s.fakeAddMachine.successOrder = []bool{true, false, false} 166 expectedOutput := `created machine 0 167 failed to create 2 machines 168 ` 169 context, err := s.run(c, "-n", "3") 170 c.Assert(err, gc.ErrorMatches, "something went wrong, something went wrong") 171 c.Assert(testing.Stderr(context), gc.Equals, expectedOutput) 172 } 173 174 func (s *AddMachineSuite) TestBlockedError(c *gc.C) { 175 s.fakeAddMachine.addError = common.OperationBlockedError("TestBlockedError") 176 _, err := s.run(c) 177 testing.AssertOperationWasBlocked(c, err, ".*TestBlockedError.*") 178 } 179 180 func (s *AddMachineSuite) TestAddMachineWithDisks(c *gc.C) { 181 s.fakeMachineManager.apiVersion = 1 182 _, err := s.run(c, "--disks", "2,1G", "--disks", "2G") 183 c.Assert(err, jc.ErrorIsNil) 184 c.Assert(s.fakeAddMachine.args, gc.HasLen, 0) 185 c.Assert(s.fakeMachineManager.args, gc.HasLen, 1) 186 param := s.fakeMachineManager.args[0] 187 c.Assert(param.Disks, gc.DeepEquals, []storage.Constraints{ 188 {Size: 1024, Count: 2}, 189 {Size: 2048, Count: 1}, 190 }) 191 } 192 193 func (s *AddMachineSuite) TestAddMachineWithDisksUnsupported(c *gc.C) { 194 _, err := s.run(c, "--disks", "2,1G", "--disks", "2G") 195 c.Assert(err, gc.ErrorMatches, "cannot add machines with disks: not supported by the API server") 196 } 197 198 type fakeAddMachineAPI struct { 199 successOrder []bool 200 currentOp int 201 args []params.AddMachineParams 202 addError error 203 providerType string 204 } 205 206 func (f *fakeAddMachineAPI) Close() error { 207 return nil 208 } 209 210 func (f *fakeAddMachineAPI) ModelUUID() (string, bool) { 211 return "fake-uuid", true 212 } 213 214 func (f *fakeAddMachineAPI) AddMachines(args []params.AddMachineParams) ([]params.AddMachinesResult, error) { 215 if f.addError != nil { 216 return nil, f.addError 217 } 218 results := []params.AddMachinesResult{} 219 for i := range args { 220 f.args = append(f.args, args[i]) 221 if i >= len(f.successOrder) || f.successOrder[i] { 222 results = append(results, params.AddMachinesResult{ 223 Machine: strconv.Itoa(i), 224 Error: nil, 225 }) 226 } else { 227 results = append(results, params.AddMachinesResult{ 228 Machine: string(i), 229 Error: ¶ms.Error{Message: "something went wrong", Code: "1"}, 230 }) 231 } 232 f.currentOp++ 233 } 234 return results, nil 235 } 236 237 func (f *fakeAddMachineAPI) ForceDestroyMachines(machines ...string) error { 238 return errors.NotImplementedf("ForceDestroyMachines") 239 } 240 241 func (f *fakeAddMachineAPI) ProvisioningScript(params.ProvisioningScriptParams) (script string, err error) { 242 return "", errors.NotImplementedf("ProvisioningScript") 243 } 244 245 func (f *fakeAddMachineAPI) ModelGet() (map[string]interface{}, error) { 246 providerType := "dummy" 247 if f.providerType != "" { 248 providerType = f.providerType 249 } 250 return dummy.SampleConfig().Merge(map[string]interface{}{ 251 "type": providerType, 252 }), nil 253 } 254 255 type fakeMachineManagerAPI struct { 256 apiVersion int 257 fakeAddMachineAPI 258 } 259 260 func (f *fakeMachineManagerAPI) BestAPIVersion() int { 261 return f.apiVersion 262 }