github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/spaces_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state_test 5 6 import ( 7 "fmt" 8 "net" 9 "strings" 10 11 "github.com/juju/errors" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/network" 16 "github.com/juju/juju/state" 17 ) 18 19 type SpacesSuite struct { 20 ConnSuite 21 } 22 23 var _ = gc.Suite(&SpacesSuite{}) 24 25 func (s *SpacesSuite) addSubnets(c *gc.C, CIDRs []string) { 26 s.addSubnetsForState(c, CIDRs, s.State) 27 } 28 29 func (s *SpacesSuite) addSubnetsForState(c *gc.C, CIDRs []string, st *state.State) { 30 if len(CIDRs) == 0 { 31 return 32 } 33 for _, info := range s.makeSubnetInfosForCIDRs(c, CIDRs) { 34 _, err := st.AddSubnet(info) 35 c.Assert(err, jc.ErrorIsNil) 36 } 37 } 38 39 func (s *SpacesSuite) makeSubnetInfosForCIDRs(c *gc.C, CIDRs []string) []state.SubnetInfo { 40 infos := make([]state.SubnetInfo, len(CIDRs)) 41 for i, cidr := range CIDRs { 42 ip, ipNet, err := net.ParseCIDR(cidr) 43 c.Assert(err, jc.ErrorIsNil) 44 45 // Generate the high IP address from the CIDR 46 // First create a copy of the low IP address 47 highIp := ip 48 49 // By default we always get 16 bytes for each IP address. We want to 50 // reduce this to 4 if we were provided an IPv4 address. 51 if ip.To4() != nil { 52 highIp = ip.To4() 53 ip = ip.To4() 54 } 55 56 // To generate a high IP address we bitwise not each byte of the subnet 57 // mask and OR it to the low IP address. 58 for j, b := range ipNet.Mask { 59 if j < len(ip) { 60 highIp[j] |= ^b 61 } 62 } 63 64 infos[i] = state.SubnetInfo{ 65 CIDR: cidr, 66 VLANTag: 79, 67 AllocatableIPLow: ip.String(), 68 AllocatableIPHigh: highIp.String(), 69 AvailabilityZone: "AvailabilityZone", 70 } 71 72 } 73 return infos 74 } 75 76 type addSpaceArgs struct { 77 Name string 78 ProviderId network.Id 79 SubnetCIDRs []string 80 IsPublic bool 81 ForState *state.State 82 } 83 84 func (s *SpacesSuite) addSpaceWithSubnets(c *gc.C, args addSpaceArgs) (*state.Space, error) { 85 if args.ForState == nil { 86 args.ForState = s.State 87 } 88 s.addSubnetsForState(c, args.SubnetCIDRs, args.ForState) 89 return args.ForState.AddSpace(args.Name, args.ProviderId, args.SubnetCIDRs, args.IsPublic) 90 } 91 92 func (s *SpacesSuite) assertSpaceNotFound(c *gc.C, name string) { 93 s.assertSpaceNotFoundForState(c, name, s.State) 94 } 95 96 func (s *SpacesSuite) assertSpaceNotFoundForState(c *gc.C, name string, st *state.State) { 97 _, err := st.Space(name) 98 s.assertSpaceNotFoundError(c, err, name) 99 } 100 101 func (s *SpacesSuite) assertSpaceNotFoundError(c *gc.C, err error, name string) { 102 c.Assert(err, gc.ErrorMatches, fmt.Sprintf("space %q not found", name)) 103 104 c.Assert(err, jc.Satisfies, errors.IsNotFound) 105 } 106 107 func (s *SpacesSuite) assertSpaceMatchesArgs(c *gc.C, space *state.Space, args addSpaceArgs) { 108 c.Assert(space.Name(), gc.Equals, args.Name) 109 c.Assert(space.ProviderId(), gc.Equals, args.ProviderId) 110 111 actualSubnets, err := space.Subnets() 112 c.Assert(err, jc.ErrorIsNil) 113 actualSubnetIds := make([]string, len(actualSubnets)) 114 for i, subnet := range actualSubnets { 115 actualSubnetIds[i] = subnet.CIDR() 116 } 117 c.Assert(actualSubnetIds, jc.SameContents, args.SubnetCIDRs) 118 c.Assert(state.SpaceDoc(space).IsPublic, gc.Equals, args.IsPublic) 119 120 c.Assert(space.Life(), gc.Equals, state.Alive) 121 c.Assert(strings.HasSuffix(space.ID(), args.Name), jc.IsTrue) 122 c.Assert(space.String(), gc.Equals, args.Name) 123 } 124 125 func (s *SpacesSuite) TestAddSpaceWithNoSubnetsAndEmptyProviderId(c *gc.C) { 126 args := addSpaceArgs{ 127 Name: "my-space", 128 ProviderId: "", 129 SubnetCIDRs: nil, 130 } 131 space, err := s.addSpaceWithSubnets(c, args) 132 c.Assert(err, jc.ErrorIsNil) 133 s.assertSpaceMatchesArgs(c, space, args) 134 135 } 136 137 func (s *SpacesSuite) TestAddSpaceWithNoSubnetsAndNonEmptyProviderId(c *gc.C) { 138 args := addSpaceArgs{ 139 Name: "my-space", 140 ProviderId: network.Id("my provider id"), 141 SubnetCIDRs: nil, 142 } 143 space, err := s.addSpaceWithSubnets(c, args) 144 c.Assert(err, jc.ErrorIsNil) 145 s.assertSpaceMatchesArgs(c, space, args) 146 } 147 148 func (s *SpacesSuite) TestAddSpaceWithOneIPv4SubnetAndEmptyProviderId(c *gc.C) { 149 args := addSpaceArgs{ 150 Name: "my-space", 151 ProviderId: "", 152 SubnetCIDRs: []string{"1.1.1.0/24"}, 153 } 154 space, err := s.addSpaceWithSubnets(c, args) 155 c.Assert(err, jc.ErrorIsNil) 156 s.assertSpaceMatchesArgs(c, space, args) 157 } 158 159 func (s *SpacesSuite) TestAddSpaceWithOneIPv4SubnetAndNonEmptyProviderId(c *gc.C) { 160 args := addSpaceArgs{ 161 Name: "my-space", 162 ProviderId: network.Id("some id"), 163 SubnetCIDRs: []string{"1.1.1.0/24"}, 164 } 165 space, err := s.addSpaceWithSubnets(c, args) 166 c.Assert(err, jc.ErrorIsNil) 167 s.assertSpaceMatchesArgs(c, space, args) 168 } 169 170 func (s *SpacesSuite) TestAddSpaceWithOneIPv6SubnetAndEmptyProviderId(c *gc.C) { 171 args := addSpaceArgs{ 172 Name: "my-space", 173 ProviderId: "", 174 SubnetCIDRs: []string{"fc00:123::/64"}, 175 } 176 space, err := s.addSpaceWithSubnets(c, args) 177 c.Assert(err, jc.ErrorIsNil) 178 s.assertSpaceMatchesArgs(c, space, args) 179 } 180 181 func (s *SpacesSuite) TestAddSpaceWithOneIPv6SubnetAndNonEmptyProviderId(c *gc.C) { 182 args := addSpaceArgs{ 183 Name: "my-space", 184 ProviderId: network.Id("provider id"), 185 SubnetCIDRs: []string{"fc00:123::/64"}, 186 } 187 space, err := s.addSpaceWithSubnets(c, args) 188 c.Assert(err, jc.ErrorIsNil) 189 s.assertSpaceMatchesArgs(c, space, args) 190 } 191 192 func (s *SpacesSuite) TestAddSpaceWithOneIPv4AndOneIPv6SubnetAndEmptyProviderId(c *gc.C) { 193 args := addSpaceArgs{ 194 Name: "my-space", 195 ProviderId: "", 196 SubnetCIDRs: []string{"1.1.1.0/24", "fc00::123/64"}, 197 } 198 space, err := s.addSpaceWithSubnets(c, args) 199 c.Assert(err, jc.ErrorIsNil) 200 s.assertSpaceMatchesArgs(c, space, args) 201 } 202 203 func (s *SpacesSuite) TestAddSpaceWithOneIPv4AndOneIPv6SubnetAndNonEmptyProviderId(c *gc.C) { 204 args := addSpaceArgs{ 205 Name: "my-space", 206 ProviderId: network.Id("foo bar"), 207 SubnetCIDRs: []string{"1.1.1.0/24", "fc00::123/64"}, 208 } 209 space, err := s.addSpaceWithSubnets(c, args) 210 c.Assert(err, jc.ErrorIsNil) 211 s.assertSpaceMatchesArgs(c, space, args) 212 } 213 214 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv4SubnetsAndEmptyProviderId(c *gc.C) { 215 args := addSpaceArgs{ 216 Name: "my-space", 217 ProviderId: "", 218 SubnetCIDRs: []string{"1.1.1.0/24", "1.2.2.0/24"}, 219 } 220 space, err := s.addSpaceWithSubnets(c, args) 221 c.Assert(err, jc.ErrorIsNil) 222 s.assertSpaceMatchesArgs(c, space, args) 223 } 224 225 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv4SubnetsAndNonEmptyProviderId(c *gc.C) { 226 args := addSpaceArgs{ 227 Name: "my-space", 228 ProviderId: network.Id("My Provider ID"), 229 SubnetCIDRs: []string{"1.1.1.0/24", "1.2.2.0/24"}, 230 } 231 space, err := s.addSpaceWithSubnets(c, args) 232 c.Assert(err, jc.ErrorIsNil) 233 s.assertSpaceMatchesArgs(c, space, args) 234 } 235 236 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv6SubnetsAndEmptyProviderId(c *gc.C) { 237 args := addSpaceArgs{ 238 Name: "my-space", 239 ProviderId: "", 240 SubnetCIDRs: []string{"fc00:123::/64", "fc00:321::/64"}, 241 } 242 space, err := s.addSpaceWithSubnets(c, args) 243 c.Assert(err, jc.ErrorIsNil) 244 s.assertSpaceMatchesArgs(c, space, args) 245 } 246 247 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv6SubnetsAndNonEmptyProviderId(c *gc.C) { 248 args := addSpaceArgs{ 249 Name: "my-space", 250 ProviderId: network.Id("My Provider ID"), 251 SubnetCIDRs: []string{"fc00:123::/64", "fc00:321::/64"}, 252 } 253 space, err := s.addSpaceWithSubnets(c, args) 254 255 c.Assert(err, jc.ErrorIsNil) 256 s.assertSpaceMatchesArgs(c, space, args) 257 } 258 259 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv4AndIPv6SubnetsAndEmptyProviderId(c *gc.C) { 260 args := addSpaceArgs{ 261 Name: "my-space", 262 ProviderId: "", 263 SubnetCIDRs: []string{"fc00:123::/64", "2.2.2.0/20", "fc00:321::/64", "1.1.1.0/24"}, 264 } 265 space, err := s.addSpaceWithSubnets(c, args) 266 267 c.Assert(err, jc.ErrorIsNil) 268 s.assertSpaceMatchesArgs(c, space, args) 269 270 } 271 272 func (s *SpacesSuite) TestAddSpaceWithMultipleIPv4AndIPv6SubnetsAndNonEmptyProviderId(c *gc.C) { 273 args := addSpaceArgs{ 274 Name: "my-space", 275 ProviderId: network.Id("My Provider ID"), 276 SubnetCIDRs: []string{"fc00:123::/64", "2.2.2.0/20", "fc00:321::/64", "1.1.1.0/24"}, 277 } 278 space, err := s.addSpaceWithSubnets(c, args) 279 c.Assert(err, jc.ErrorIsNil) 280 s.assertSpaceMatchesArgs(c, space, args) 281 } 282 283 func (s *SpacesSuite) addTwoSpacesReturnSecond(c *gc.C, args1, args2 addSpaceArgs) (*state.Space, error) { 284 space1, err := s.addSpaceWithSubnets(c, args1) 285 286 c.Assert(err, jc.ErrorIsNil) 287 s.assertSpaceMatchesArgs(c, space1, args1) 288 289 return s.addSpaceWithSubnets(c, args2) 290 } 291 292 func (s *SpacesSuite) TestAddTwoSpacesWithDifferentNamesButSameProviderIdFailsInSameModel(c *gc.C) { 293 args1 := addSpaceArgs{ 294 Name: "my-space", 295 ProviderId: network.Id("provider id"), 296 } 297 args2 := args1 298 args2.Name = "different" 299 300 _, err := s.addTwoSpacesReturnSecond(c, args1, args2) 301 s.assertProviderIdNotUniqueErrorForArgs(c, err, args2) 302 } 303 304 func (s *SpacesSuite) assertProviderIdNotUniqueErrorForArgs(c *gc.C, err error, args addSpaceArgs) { 305 expectedError := fmt.Sprintf("adding space %q: ProviderId %q not unique", args.Name, args.ProviderId) 306 c.Assert(err, gc.ErrorMatches, expectedError) 307 } 308 309 func (s *SpacesSuite) TestAddTwoSpacesWithDifferentNamesButSameProviderIdSucceedsInDifferentModels(c *gc.C) { 310 args1 := addSpaceArgs{ 311 Name: "my-space", 312 ProviderId: network.Id("provider id"), 313 ForState: s.State, 314 } 315 args2 := args1 316 args2.Name = "different" 317 args2.ForState = s.NewStateForModelNamed(c, "other") 318 319 space2, err := s.addTwoSpacesReturnSecond(c, args1, args2) 320 321 c.Assert(err, jc.ErrorIsNil) 322 s.assertSpaceMatchesArgs(c, space2, args2) 323 } 324 325 func (s *SpacesSuite) TestAddTwoSpacesWithDifferentNamesAndEmptyProviderIdSucceedsInSameModel(c *gc.C) { 326 args1 := addSpaceArgs{ 327 Name: "my-space", 328 ProviderId: "", 329 } 330 args2 := args1 331 args2.Name = "different" 332 333 space2, err := s.addTwoSpacesReturnSecond(c, args1, args2) 334 c.Assert(err, jc.ErrorIsNil) 335 s.assertSpaceMatchesArgs(c, space2, args2) 336 } 337 338 func (s *SpacesSuite) TestAddTwoSpacesWithDifferentNamesAndEmptyProviderIdSucceedsInDifferentModels(c *gc.C) { 339 args1 := addSpaceArgs{ 340 Name: "my-space", 341 ProviderId: "", 342 ForState: s.State, 343 } 344 args2 := args1 345 args2.Name = "different" 346 args2.ForState = s.NewStateForModelNamed(c, "other") 347 348 space2, err := s.addTwoSpacesReturnSecond(c, args1, args2) 349 350 c.Assert(err, jc.ErrorIsNil) 351 s.assertSpaceMatchesArgs(c, space2, args2) 352 } 353 354 func (s *SpacesSuite) TestAddTwoSpacesWithSameNamesAndEmptyProviderIdsFailsInSameModel(c *gc.C) { 355 args := addSpaceArgs{ 356 Name: "my-space", 357 ProviderId: "", 358 } 359 360 _, err := s.addTwoSpacesReturnSecond(c, args, args) 361 s.assertSpaceAlreadyExistsErrorForArgs(c, err, args) 362 } 363 364 func (s *SpacesSuite) assertSpaceAlreadyExistsErrorForArgs(c *gc.C, err error, args addSpaceArgs) { 365 expectedError := fmt.Sprintf("adding space %q: space %q already exists", args.Name, args.Name) 366 c.Assert(err, gc.ErrorMatches, expectedError) 367 c.Assert(err, jc.Satisfies, errors.IsAlreadyExists) 368 } 369 370 func (s *SpacesSuite) TestAddTwoSpacesWithSameNamesAndProviderIdsFailsInTheSameModel(c *gc.C) { 371 args := addSpaceArgs{ 372 Name: "my-space", 373 ProviderId: network.Id("does not matter if not empty"), 374 } 375 376 _, err := s.addTwoSpacesReturnSecond(c, args, args) 377 s.assertSpaceAlreadyExistsErrorForArgs(c, err, args) 378 } 379 380 func (s *SpacesSuite) TestAddTwoSpacesWithSameNamesAndEmptyProviderIdsSuccedsInDifferentModels(c *gc.C) { 381 args1 := addSpaceArgs{ 382 Name: "my-space", 383 ProviderId: "", 384 ForState: s.State, 385 } 386 args2 := args1 387 args2.ForState = s.NewStateForModelNamed(c, "other") 388 389 space2, err := s.addTwoSpacesReturnSecond(c, args1, args2) 390 c.Assert(err, jc.ErrorIsNil) 391 s.assertSpaceMatchesArgs(c, space2, args2) 392 } 393 394 func (s *SpacesSuite) TestAddTwoSpacesWithSameNamesAndProviderIdsSuccedsInDifferentModels(c *gc.C) { 395 args1 := addSpaceArgs{ 396 Name: "my-space", 397 ProviderId: network.Id("same provider id"), 398 ForState: s.State, 399 } 400 args2 := args1 401 args2.ForState = s.NewStateForModelNamed(c, "other") 402 403 space2, err := s.addTwoSpacesReturnSecond(c, args1, args2) 404 c.Assert(err, jc.ErrorIsNil) 405 s.assertSpaceMatchesArgs(c, space2, args2) 406 } 407 408 func (s *SpacesSuite) TestAddSpaceWhenSubnetNotFound(c *gc.C) { 409 name := "my-space" 410 subnets := []string{"1.1.1.0/24"} 411 isPublic := false 412 413 _, err := s.State.AddSpace(name, "", subnets, isPublic) 414 c.Assert(err, gc.ErrorMatches, `adding space "my-space": subnet "1.1.1.0/24" not found`) 415 s.assertSpaceNotFound(c, name) 416 } 417 418 func (s *SpacesSuite) TestAddSpaceWithNonEmptyProviderIdAndInvalidNameFails(c *gc.C) { 419 args := addSpaceArgs{ 420 Name: "-bad name-", 421 ProviderId: network.Id("My Provider ID"), 422 } 423 _, err := s.addSpaceWithSubnets(c, args) 424 s.assertInvalidSpaceNameErrorAndWasNotAdded(c, err, args.Name) 425 } 426 427 func (s *SpacesSuite) assertInvalidSpaceNameErrorAndWasNotAdded(c *gc.C, err error, name string) { 428 expectedError := fmt.Sprintf("adding space %q: invalid space name", name) 429 c.Assert(err, gc.ErrorMatches, expectedError) 430 s.assertSpaceNotFound(c, name) 431 } 432 433 func (s *SpacesSuite) TestAddSpaceWithEmptyProviderIdAndInvalidNameFails(c *gc.C) { 434 args := addSpaceArgs{ 435 Name: "-bad name-", 436 ProviderId: "", 437 } 438 _, err := s.addSpaceWithSubnets(c, args) 439 s.assertInvalidSpaceNameErrorAndWasNotAdded(c, err, args.Name) 440 } 441 442 func (s *SpacesSuite) TestAddSpaceWithEmptyNameAndProviderIdFails(c *gc.C) { 443 args := addSpaceArgs{ 444 Name: "", 445 ProviderId: "", 446 } 447 _, err := s.addSpaceWithSubnets(c, args) 448 s.assertInvalidSpaceNameErrorAndWasNotAdded(c, err, args.Name) 449 } 450 451 func (s *SpacesSuite) TestAddSpaceWithEmptyNameAndNonEmptyProviderIdFails(c *gc.C) { 452 args := addSpaceArgs{ 453 Name: "", 454 ProviderId: network.Id("doesn't matter"), 455 } 456 _, err := s.addSpaceWithSubnets(c, args) 457 s.assertInvalidSpaceNameErrorAndWasNotAdded(c, err, args.Name) 458 } 459 460 func (s *SpacesSuite) TestSubnetsReturnsExpectedSubnets(c *gc.C) { 461 args := addSpaceArgs{ 462 Name: "my-space", 463 SubnetCIDRs: []string{"1.1.1.0/24", "2.1.1.0/24", "3.1.1.0/24", "4.1.1.0/24", "5.1.1.0/24"}, 464 } 465 space, err := s.addSpaceWithSubnets(c, args) 466 c.Assert(err, jc.ErrorIsNil) 467 468 expected := []*state.Subnet{} 469 for _, cidr := range args.SubnetCIDRs { 470 subnet, err := s.State.Subnet(cidr) 471 c.Assert(err, jc.ErrorIsNil) 472 expected = append(expected, subnet) 473 } 474 actual, err := space.Subnets() 475 c.Assert(err, jc.ErrorIsNil) 476 c.Assert(actual, jc.DeepEquals, expected) 477 } 478 479 func (s *SpacesSuite) TestAllSpaces(c *gc.C) { 480 spaces, err := s.State.AllSpaces() 481 c.Assert(err, jc.ErrorIsNil) 482 c.Assert(spaces, jc.DeepEquals, []*state.Space{}) 483 484 subnets := []string{"1.1.1.0/24", "2.1.1.0/24", "3.1.1.0/24"} 485 isPublic := false 486 s.addSubnets(c, subnets) 487 488 first, err := s.State.AddSpace("first", "", []string{"1.1.1.0/24"}, isPublic) 489 c.Assert(err, jc.ErrorIsNil) 490 second, err := s.State.AddSpace("second", "", []string{"2.1.1.0/24"}, isPublic) 491 c.Assert(err, jc.ErrorIsNil) 492 third, err := s.State.AddSpace("third", "", []string{"3.1.1.0/24"}, isPublic) 493 c.Assert(err, jc.ErrorIsNil) 494 495 actual, err := s.State.AllSpaces() 496 c.Assert(err, jc.ErrorIsNil) 497 c.Assert(actual, jc.SameContents, []*state.Space{first, second, third}) 498 } 499 500 func (s *SpacesSuite) TestEnsureDeadSetsLifeToDeadWhenAlive(c *gc.C) { 501 space := s.addAliveSpace(c, "alive") 502 503 s.ensureDeadAndAssertLifeIsDead(c, space) 504 s.refreshAndAssertSpaceLifeIs(c, space, state.Dead) 505 } 506 507 func (s *SpacesSuite) addAliveSpace(c *gc.C, name string) *state.Space { 508 space, err := s.State.AddSpace(name, "", nil, false) 509 c.Assert(err, jc.ErrorIsNil) 510 c.Assert(space.Life(), gc.Equals, state.Alive) 511 return space 512 } 513 514 func (s *SpacesSuite) ensureDeadAndAssertLifeIsDead(c *gc.C, space *state.Space) { 515 err := space.EnsureDead() 516 c.Assert(err, jc.ErrorIsNil) 517 c.Assert(space.Life(), gc.Equals, state.Dead) 518 } 519 520 func (s *SpacesSuite) refreshAndAssertSpaceLifeIs(c *gc.C, space *state.Space, expectedLife state.Life) { 521 err := space.Refresh() 522 c.Assert(err, jc.ErrorIsNil) 523 c.Assert(space.Life(), gc.Equals, expectedLife) 524 } 525 526 func (s *SpacesSuite) TestEnsureDeadSetsLifeToDeadWhenNotAlive(c *gc.C) { 527 space := s.addAliveSpace(c, "soon-dead") 528 s.ensureDeadAndAssertLifeIsDead(c, space) 529 530 s.ensureDeadAndAssertLifeIsDead(c, space) 531 } 532 533 func (s *SpacesSuite) TestRemoveFailsIfStillAlive(c *gc.C) { 534 space := s.addAliveSpace(c, "still-alive") 535 536 err := space.Remove() 537 c.Assert(err, gc.ErrorMatches, `cannot remove space "still-alive": space is not dead`) 538 539 s.refreshAndAssertSpaceLifeIs(c, space, state.Alive) 540 } 541 542 func (s *SpacesSuite) TestRemoveSucceedsWhenSpaceIsNotAlive(c *gc.C) { 543 space := s.addAliveSpace(c, "not-alive-soon") 544 s.ensureDeadAndAssertLifeIsDead(c, space) 545 546 s.removeSpaceAndAssertNotFound(c, space) 547 } 548 549 func (s *SpacesSuite) removeSpaceAndAssertNotFound(c *gc.C, space *state.Space) { 550 err := space.Remove() 551 c.Assert(err, jc.ErrorIsNil) 552 s.assertSpaceNotFound(c, space.Name()) 553 } 554 555 func (s *SpacesSuite) TestRemoveSucceedsWhenCalledTwice(c *gc.C) { 556 space := s.addAliveSpace(c, "twice-deleted") 557 s.ensureDeadAndAssertLifeIsDead(c, space) 558 s.removeSpaceAndAssertNotFound(c, space) 559 560 err := space.Remove() 561 c.Assert(err, gc.ErrorMatches, `cannot remove space "twice-deleted": not found or not dead`) 562 } 563 564 func (s *SpacesSuite) TestRefreshUpdatesStaleDocData(c *gc.C) { 565 space := s.addAliveSpace(c, "original") 566 spaceCopy, err := s.State.Space(space.Name()) 567 c.Assert(err, jc.ErrorIsNil) 568 569 s.ensureDeadAndAssertLifeIsDead(c, space) 570 c.Assert(spaceCopy.Life(), gc.Equals, state.Alive) 571 572 err = spaceCopy.Refresh() 573 c.Assert(err, jc.ErrorIsNil) 574 c.Assert(spaceCopy.Life(), gc.Equals, state.Dead) 575 } 576 577 func (s *SpacesSuite) TestRefreshFailsWithNotFoundWhenRemoved(c *gc.C) { 578 space := s.addAliveSpace(c, "soon-removed") 579 s.ensureDeadAndAssertLifeIsDead(c, space) 580 s.removeSpaceAndAssertNotFound(c, space) 581 582 err := space.Refresh() 583 s.assertSpaceNotFoundError(c, err, "soon-removed") 584 }