launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/api/provisioner/provisioner_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner_test 5 6 import ( 7 gc "launchpad.net/gocheck" 8 stdtesting "testing" 9 10 "launchpad.net/juju-core/constraints" 11 "launchpad.net/juju-core/errors" 12 "launchpad.net/juju-core/instance" 13 "launchpad.net/juju-core/juju/testing" 14 "launchpad.net/juju-core/state" 15 "launchpad.net/juju-core/state/api" 16 commontesting "launchpad.net/juju-core/state/api/common/testing" 17 "launchpad.net/juju-core/state/api/params" 18 "launchpad.net/juju-core/state/api/provisioner" 19 statetesting "launchpad.net/juju-core/state/testing" 20 coretesting "launchpad.net/juju-core/testing" 21 jc "launchpad.net/juju-core/testing/checkers" 22 "launchpad.net/juju-core/tools" 23 "launchpad.net/juju-core/utils" 24 "launchpad.net/juju-core/version" 25 ) 26 27 func TestAll(t *stdtesting.T) { 28 coretesting.MgoTestPackage(t) 29 } 30 31 type provisionerSuite struct { 32 testing.JujuConnSuite 33 *commontesting.EnvironWatcherTest 34 35 st *api.State 36 machine *state.Machine 37 38 provisioner *provisioner.State 39 } 40 41 var _ = gc.Suite(&provisionerSuite{}) 42 43 func (s *provisionerSuite) SetUpTest(c *gc.C) { 44 s.JujuConnSuite.SetUpTest(c) 45 46 var err error 47 s.machine, err = s.State.AddMachine("quantal", state.JobManageEnviron) 48 c.Assert(err, gc.IsNil) 49 password, err := utils.RandomPassword() 50 c.Assert(err, gc.IsNil) 51 err = s.machine.SetPassword(password) 52 c.Assert(err, gc.IsNil) 53 err = s.machine.SetProvisioned("i-manager", "fake_nonce", nil) 54 c.Assert(err, gc.IsNil) 55 s.st = s.OpenAPIAsMachine(c, s.machine.Tag(), password, "fake_nonce") 56 c.Assert(s.st, gc.NotNil) 57 58 // Create the provisioner API facade. 59 s.provisioner = s.st.Provisioner() 60 c.Assert(s.provisioner, gc.NotNil) 61 62 s.EnvironWatcherTest = commontesting.NewEnvironWatcherTest(s.provisioner, s.State, s.BackingState, commontesting.HasSecrets) 63 } 64 65 func (s *provisionerSuite) TestMachineTagAndId(c *gc.C) { 66 apiMachine, err := s.provisioner.Machine("machine-42") 67 c.Assert(err, gc.ErrorMatches, "machine 42 not found") 68 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 69 c.Assert(apiMachine, gc.IsNil) 70 71 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 72 c.Assert(err, gc.IsNil) 73 c.Assert(apiMachine.Tag(), gc.Equals, s.machine.Tag()) 74 c.Assert(apiMachine.Id(), gc.Equals, s.machine.Id()) 75 } 76 77 func (s *provisionerSuite) TestGetSetStatus(c *gc.C) { 78 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 79 c.Assert(err, gc.IsNil) 80 81 status, info, err := apiMachine.Status() 82 c.Assert(err, gc.IsNil) 83 c.Assert(status, gc.Equals, params.StatusPending) 84 c.Assert(info, gc.Equals, "") 85 86 err = apiMachine.SetStatus(params.StatusStarted, "blah") 87 c.Assert(err, gc.IsNil) 88 89 status, info, err = apiMachine.Status() 90 c.Assert(err, gc.IsNil) 91 c.Assert(status, gc.Equals, params.StatusStarted) 92 c.Assert(info, gc.Equals, "blah") 93 } 94 95 func (s *provisionerSuite) TestEnsureDeadAndRemove(c *gc.C) { 96 // Create a fresh machine to test the complete scenario. 97 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 98 c.Assert(err, gc.IsNil) 99 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 100 101 apiMachine, err := s.provisioner.Machine(otherMachine.Tag()) 102 c.Assert(err, gc.IsNil) 103 104 err = apiMachine.Remove() 105 c.Assert(err, gc.ErrorMatches, `cannot remove entity "machine-1": still alive`) 106 err = apiMachine.EnsureDead() 107 c.Assert(err, gc.IsNil) 108 109 err = otherMachine.Refresh() 110 c.Assert(err, gc.IsNil) 111 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 112 113 err = apiMachine.EnsureDead() 114 c.Assert(err, gc.IsNil) 115 err = otherMachine.Refresh() 116 c.Assert(err, gc.IsNil) 117 c.Assert(otherMachine.Life(), gc.Equals, state.Dead) 118 119 err = apiMachine.Remove() 120 c.Assert(err, gc.IsNil) 121 err = otherMachine.Refresh() 122 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) 123 124 err = apiMachine.EnsureDead() 125 c.Assert(err, gc.ErrorMatches, "machine 1 not found") 126 c.Assert(err, jc.Satisfies, params.IsCodeNotFound) 127 128 // Now try to EnsureDead machine 0 - should fail. 129 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 130 c.Assert(err, gc.IsNil) 131 err = apiMachine.EnsureDead() 132 c.Assert(err, gc.ErrorMatches, "machine 0 is required by the environment") 133 } 134 135 func (s *provisionerSuite) TestRefreshAndLife(c *gc.C) { 136 // Create a fresh machine to test the complete scenario. 137 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 138 c.Assert(err, gc.IsNil) 139 c.Assert(otherMachine.Life(), gc.Equals, state.Alive) 140 141 apiMachine, err := s.provisioner.Machine(otherMachine.Tag()) 142 c.Assert(err, gc.IsNil) 143 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 144 145 err = apiMachine.EnsureDead() 146 c.Assert(err, gc.IsNil) 147 c.Assert(apiMachine.Life(), gc.Equals, params.Alive) 148 149 err = apiMachine.Refresh() 150 c.Assert(err, gc.IsNil) 151 c.Assert(apiMachine.Life(), gc.Equals, params.Dead) 152 } 153 154 func (s *provisionerSuite) TestSetProvisionedAndInstanceId(c *gc.C) { 155 // Create a fresh machine, since machine 0 is already provisioned. 156 notProvisionedMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 157 c.Assert(err, gc.IsNil) 158 159 apiMachine, err := s.provisioner.Machine(notProvisionedMachine.Tag()) 160 c.Assert(err, gc.IsNil) 161 162 instanceId, err := apiMachine.InstanceId() 163 c.Assert(err, jc.Satisfies, params.IsCodeNotProvisioned) 164 c.Assert(err, gc.ErrorMatches, "machine 1 is not provisioned") 165 c.Assert(instanceId, gc.Equals, instance.Id("")) 166 167 hwChars := instance.MustParseHardware("cpu-cores=123", "mem=4G") 168 err = apiMachine.SetProvisioned("i-will", "fake_nonce", &hwChars) 169 c.Assert(err, gc.IsNil) 170 171 instanceId, err = apiMachine.InstanceId() 172 c.Assert(err, gc.IsNil) 173 c.Assert(instanceId, gc.Equals, instance.Id("i-will")) 174 175 // Try it again - should fail. 176 err = apiMachine.SetProvisioned("i-wont", "fake", nil) 177 c.Assert(err, gc.ErrorMatches, `cannot set instance data for machine "1": already set`) 178 179 // Now try to get machine 0's instance id. 180 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 181 c.Assert(err, gc.IsNil) 182 instanceId, err = apiMachine.InstanceId() 183 c.Assert(err, gc.IsNil) 184 c.Assert(instanceId, gc.Equals, instance.Id("i-manager")) 185 } 186 187 func (s *provisionerSuite) TestSeries(c *gc.C) { 188 // Create a fresh machine with different series. 189 foobarMachine, err := s.State.AddMachine("foobar", state.JobHostUnits) 190 c.Assert(err, gc.IsNil) 191 192 apiMachine, err := s.provisioner.Machine(foobarMachine.Tag()) 193 c.Assert(err, gc.IsNil) 194 series, err := apiMachine.Series() 195 c.Assert(err, gc.IsNil) 196 c.Assert(series, gc.Equals, "foobar") 197 198 // Now try machine 0. 199 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 200 c.Assert(err, gc.IsNil) 201 series, err = apiMachine.Series() 202 c.Assert(err, gc.IsNil) 203 c.Assert(series, gc.Equals, "quantal") 204 } 205 206 func (s *provisionerSuite) TestConstraints(c *gc.C) { 207 // Create a fresh machine with some constraints. 208 template := state.MachineTemplate{ 209 Series: "quantal", 210 Jobs: []state.MachineJob{state.JobHostUnits}, 211 Constraints: constraints.MustParse("cpu-cores=12", "mem=8G"), 212 } 213 consMachine, err := s.State.AddOneMachine(template) 214 c.Assert(err, gc.IsNil) 215 216 apiMachine, err := s.provisioner.Machine(consMachine.Tag()) 217 c.Assert(err, gc.IsNil) 218 cons, err := apiMachine.Constraints() 219 c.Assert(err, gc.IsNil) 220 c.Assert(cons, gc.DeepEquals, template.Constraints) 221 222 // Now try machine 0. 223 apiMachine, err = s.provisioner.Machine(s.machine.Tag()) 224 c.Assert(err, gc.IsNil) 225 cons, err = apiMachine.Constraints() 226 c.Assert(err, gc.IsNil) 227 c.Assert(cons, gc.DeepEquals, constraints.Value{}) 228 } 229 230 func (s *provisionerSuite) TestWatchContainers(c *gc.C) { 231 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 232 c.Assert(err, gc.IsNil) 233 234 // Add one LXC container. 235 template := state.MachineTemplate{ 236 Series: "quantal", 237 Jobs: []state.MachineJob{state.JobHostUnits}, 238 } 239 container, err := s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 240 c.Assert(err, gc.IsNil) 241 242 w, err := apiMachine.WatchContainers(instance.LXC) 243 c.Assert(err, gc.IsNil) 244 defer statetesting.AssertStop(c, w) 245 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 246 247 // Initial event. 248 wc.AssertChange(container.Id()) 249 250 // Change something other than the containers and make sure it's 251 // not detected. 252 err = apiMachine.SetStatus(params.StatusStarted, "not really") 253 c.Assert(err, gc.IsNil) 254 wc.AssertNoChange() 255 256 // Add a KVM container and make sure it's not detected. 257 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.KVM) 258 c.Assert(err, gc.IsNil) 259 wc.AssertNoChange() 260 261 // Add another LXC container and make sure it's detected. 262 container, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 263 c.Assert(err, gc.IsNil) 264 wc.AssertChange(container.Id()) 265 266 statetesting.AssertStop(c, w) 267 wc.AssertClosed() 268 } 269 270 func (s *provisionerSuite) TestWatchContainersAcceptsSupportedContainers(c *gc.C) { 271 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 272 c.Assert(err, gc.IsNil) 273 274 for _, ctype := range instance.ContainerTypes { 275 w, err := apiMachine.WatchContainers(ctype) 276 c.Assert(w, gc.NotNil) 277 c.Assert(err, gc.IsNil) 278 } 279 } 280 281 func (s *provisionerSuite) TestWatchContainersErrors(c *gc.C) { 282 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 283 c.Assert(err, gc.IsNil) 284 285 _, err = apiMachine.WatchContainers(instance.NONE) 286 c.Assert(err, gc.ErrorMatches, `unsupported container type "none"`) 287 288 _, err = apiMachine.WatchContainers("") 289 c.Assert(err, gc.ErrorMatches, "container type must be specified") 290 } 291 292 func (s *provisionerSuite) TestWatchEnvironMachines(c *gc.C) { 293 w, err := s.provisioner.WatchEnvironMachines() 294 c.Assert(err, gc.IsNil) 295 defer statetesting.AssertStop(c, w) 296 wc := statetesting.NewStringsWatcherC(c, s.BackingState, w) 297 298 // Initial event. 299 wc.AssertChange(s.machine.Id()) 300 301 // Add another 2 machines make sure they are detected. 302 otherMachine, err := s.State.AddMachine("quantal", state.JobHostUnits) 303 c.Assert(err, gc.IsNil) 304 otherMachine, err = s.State.AddMachine("quantal", state.JobHostUnits) 305 c.Assert(err, gc.IsNil) 306 wc.AssertChange("1", "2") 307 308 // Change the lifecycle of last machine. 309 err = otherMachine.EnsureDead() 310 c.Assert(err, gc.IsNil) 311 wc.AssertChange("2") 312 313 // Add a container and make sure it's not detected. 314 template := state.MachineTemplate{ 315 Series: "quantal", 316 Jobs: []state.MachineJob{state.JobHostUnits}, 317 } 318 _, err = s.State.AddMachineInsideMachine(template, s.machine.Id(), instance.LXC) 319 c.Assert(err, gc.IsNil) 320 wc.AssertNoChange() 321 322 statetesting.AssertStop(c, w) 323 wc.AssertClosed() 324 } 325 326 func (s *provisionerSuite) TestStateAddresses(c *gc.C) { 327 err := s.machine.SetAddresses([]instance.Address{ 328 instance.NewAddress("0.1.2.3"), 329 }) 330 c.Assert(err, gc.IsNil) 331 332 stateAddresses, err := s.State.Addresses() 333 c.Assert(err, gc.IsNil) 334 335 addresses, err := s.provisioner.StateAddresses() 336 c.Assert(err, gc.IsNil) 337 c.Assert(addresses, gc.DeepEquals, stateAddresses) 338 } 339 340 func (s *provisionerSuite) TestAPIAddresses(c *gc.C) { 341 err := s.machine.SetAddresses([]instance.Address{ 342 instance.NewAddress("0.1.2.3"), 343 }) 344 c.Assert(err, gc.IsNil) 345 346 apiAddresses, err := s.State.APIAddresses() 347 c.Assert(err, gc.IsNil) 348 349 addresses, err := s.provisioner.APIAddresses() 350 c.Assert(err, gc.IsNil) 351 c.Assert(addresses, gc.DeepEquals, apiAddresses) 352 } 353 354 func (s *provisionerSuite) TestContainerConfig(c *gc.C) { 355 result, err := s.provisioner.ContainerConfig() 356 c.Assert(err, gc.IsNil) 357 c.Assert(result.ProviderType, gc.Equals, "dummy") 358 c.Assert(result.AuthorizedKeys, gc.Equals, coretesting.FakeAuthKeys) 359 c.Assert(result.SSLHostnameVerification, jc.IsTrue) 360 c.Assert(result.SyslogPort, gc.Equals, 2345) 361 } 362 363 func (s *provisionerSuite) TestCACert(c *gc.C) { 364 caCert, err := s.provisioner.CACert() 365 c.Assert(err, gc.IsNil) 366 c.Assert(caCert, gc.DeepEquals, s.State.CACert()) 367 } 368 369 func (s *provisionerSuite) TestToolsWrongMachine(c *gc.C) { 370 tools, err := s.provisioner.Tools("42") 371 c.Assert(err, gc.ErrorMatches, "permission denied") 372 c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized) 373 c.Assert(tools, gc.IsNil) 374 } 375 376 func (s *provisionerSuite) TestTools(c *gc.C) { 377 cur := version.Current 378 curTools := &tools.Tools{Version: cur, URL: ""} 379 curTools.Version.Minor++ 380 s.machine.SetAgentVersion(cur) 381 // Provisioner.Tools returns the *desired* set of tools, not the 382 // currently running set. We want to be upgraded to cur.Version 383 stateTools, err := s.provisioner.Tools(s.machine.Tag()) 384 c.Assert(err, gc.IsNil) 385 c.Assert(stateTools.Version, gc.Equals, cur) 386 c.Assert(stateTools.URL, gc.Not(gc.Equals), "") 387 } 388 389 func (s *provisionerSuite) TestSetSupportedContainers(c *gc.C) { 390 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 391 c.Assert(err, gc.IsNil) 392 err = apiMachine.SetSupportedContainers(instance.LXC, instance.KVM) 393 c.Assert(err, gc.IsNil) 394 395 err = s.machine.Refresh() 396 c.Assert(err, gc.IsNil) 397 containers, ok := s.machine.SupportedContainers() 398 c.Assert(ok, jc.IsTrue) 399 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{instance.LXC, instance.KVM}) 400 } 401 402 func (s *provisionerSuite) TestSupportsNoContainers(c *gc.C) { 403 apiMachine, err := s.provisioner.Machine(s.machine.Tag()) 404 c.Assert(err, gc.IsNil) 405 err = apiMachine.SupportsNoContainers() 406 c.Assert(err, gc.IsNil) 407 408 err = s.machine.Refresh() 409 c.Assert(err, gc.IsNil) 410 containers, ok := s.machine.SupportedContainers() 411 c.Assert(ok, jc.IsTrue) 412 c.Assert(containers, gc.DeepEquals, []instance.ContainerType{}) 413 }