OLD | NEW |
1 // Copyright 2012, 2013 Canonical Ltd. | 1 // Copyright 2012, 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package state_test | 4 package state_test |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 "net/url" | 8 "net/url" |
9 "strconv" | 9 "strconv" |
10 "strings" | 10 "strings" |
11 "time" | 11 "time" |
12 | 12 |
13 "labix.org/v2/mgo/bson" | 13 "labix.org/v2/mgo/bson" |
14 gc "launchpad.net/gocheck" | 14 gc "launchpad.net/gocheck" |
15 | 15 |
16 "launchpad.net/juju-core/agent/tools" | 16 "launchpad.net/juju-core/agent/tools" |
17 "launchpad.net/juju-core/charm" | 17 "launchpad.net/juju-core/charm" |
18 "launchpad.net/juju-core/constraints" | 18 "launchpad.net/juju-core/constraints" |
19 "launchpad.net/juju-core/environs/config" | 19 "launchpad.net/juju-core/environs/config" |
20 "launchpad.net/juju-core/errors" | 20 "launchpad.net/juju-core/errors" |
21 "launchpad.net/juju-core/instance" | 21 "launchpad.net/juju-core/instance" |
| 22 "launchpad.net/juju-core/names" |
22 "launchpad.net/juju-core/state" | 23 "launchpad.net/juju-core/state" |
23 "launchpad.net/juju-core/state/api/params" | 24 "launchpad.net/juju-core/state/api/params" |
24 statetesting "launchpad.net/juju-core/state/testing" | 25 statetesting "launchpad.net/juju-core/state/testing" |
25 "launchpad.net/juju-core/testing" | 26 "launchpad.net/juju-core/testing" |
26 jc "launchpad.net/juju-core/testing/checkers" | 27 jc "launchpad.net/juju-core/testing/checkers" |
27 "launchpad.net/juju-core/version" | 28 "launchpad.net/juju-core/version" |
28 ) | 29 ) |
29 | 30 |
30 type D []bson.DocElem | 31 type D []bson.DocElem |
31 | 32 |
(...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 c.Assert(e2.PasswordValid("bar"), gc.Equals, true) | 1291 c.Assert(e2.PasswordValid("bar"), gc.Equals, true) |
1291 | 1292 |
1292 if le, ok := e.(lifer); ok { | 1293 if le, ok := e.(lifer); ok { |
1293 testWhenDying(c, le, noErr, deadErr, func() error { | 1294 testWhenDying(c, le, noErr, deadErr, func() error { |
1294 return e.SetPassword("arble") | 1295 return e.SetPassword("arble") |
1295 }) | 1296 }) |
1296 } | 1297 } |
1297 } | 1298 } |
1298 | 1299 |
1299 type entity interface { | 1300 type entity interface { |
1300 » lifer | 1301 » state.Entity |
1301 » state.TaggedAuthenticator | 1302 » state.Lifer |
1302 » SetMongoPassword(password string) error | 1303 » state.Authenticator |
| 1304 » state.MongoPassworder |
1303 } | 1305 } |
1304 | 1306 |
1305 func testSetMongoPassword(c *gc.C, getEntity func(st *state.State) (entity, erro
r)) { | 1307 func testSetMongoPassword(c *gc.C, getEntity func(st *state.State) (entity, erro
r)) { |
1306 info := state.TestingStateInfo() | 1308 info := state.TestingStateInfo() |
1307 st, err := state.Open(info, state.TestingDialOpts()) | 1309 st, err := state.Open(info, state.TestingDialOpts()) |
1308 c.Assert(err, gc.IsNil) | 1310 c.Assert(err, gc.IsNil) |
1309 defer st.Close() | 1311 defer st.Close() |
1310 // Turn on fully-authenticated mode. | 1312 // Turn on fully-authenticated mode. |
1311 err = st.SetAdminMongoPassword("admin-secret") | 1313 err = st.SetAdminMongoPassword("admin-secret") |
1312 c.Assert(err, gc.IsNil) | 1314 c.Assert(err, gc.IsNil) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1378 | 1380 |
1379 // Check that removing the password is idempotent. | 1381 // Check that removing the password is idempotent. |
1380 err = s.State.SetAdminMongoPassword("") | 1382 err = s.State.SetAdminMongoPassword("") |
1381 c.Assert(err, gc.IsNil) | 1383 c.Assert(err, gc.IsNil) |
1382 | 1384 |
1383 info.Password = "" | 1385 info.Password = "" |
1384 err = tryOpenState(info) | 1386 err = tryOpenState(info) |
1385 c.Assert(err, gc.IsNil) | 1387 c.Assert(err, gc.IsNil) |
1386 } | 1388 } |
1387 | 1389 |
1388 func (s *StateSuite) testEntity(c *gc.C, getEntity func(string) (state.Tagger, e
rror)) { | 1390 var findEntityTests = []struct { |
1389 » bad := []string{"", "machine", "-foo", "foo-", "---", "machine-bad", "un
it-123", "unit-foo", "service-", "service-foo/bar", "environment-foo"} | 1391 » tag string |
1390 » for i, name := range bad { | 1392 » err string |
1391 » » c.Logf("test %d. entity %q", i, name) | 1393 }{{ |
1392 » » e, err := getEntity(name) | 1394 » tag: "", |
1393 » » c.Check(e, gc.IsNil) | 1395 » err: `"" is not a valid tag`, |
1394 » » c.Assert(err, gc.ErrorMatches, `".*" is not a valid( [a-z]+)? ta
g`) | 1396 }, { |
1395 » } | 1397 » tag: "machine", |
| 1398 » err: `"machine" is not a valid tag`, |
| 1399 }, { |
| 1400 » tag: "-foo", |
| 1401 » err: `"-foo" is not a valid tag`, |
| 1402 }, { |
| 1403 » tag: "foo-", |
| 1404 » err: `"foo-" is not a valid tag`, |
| 1405 }, { |
| 1406 » tag: "---", |
| 1407 » err: `"---" is not a valid tag`, |
| 1408 }, { |
| 1409 » tag: "machine-bad", |
| 1410 » err: `"machine-bad" is not a valid machine tag`, |
| 1411 }, { |
| 1412 » tag: "unit-123", |
| 1413 » err: `"unit-123" is not a valid unit tag`, |
| 1414 }, { |
| 1415 » tag: "unit-foo", |
| 1416 » err: `"unit-foo" is not a valid unit tag`, |
| 1417 }, { |
| 1418 » tag: "service-", |
| 1419 » err: `"service-" is not a valid service tag`, |
| 1420 }, { |
| 1421 » tag: "service-foo/bar", |
| 1422 » err: `"service-foo/bar" is not a valid service tag`, |
| 1423 }, { |
| 1424 » tag: "environment-foo", |
| 1425 » err: `"environment-foo" is not a valid environment tag`, |
| 1426 }, { |
| 1427 » tag: "machine-1234", |
| 1428 » err: `machine 1234 not found`, |
| 1429 }, { |
| 1430 » tag: "unit-foo-654", |
| 1431 » err: `unit "foo/654" not found`, |
| 1432 }, { |
| 1433 » tag: "unit-foo-bar-654", |
| 1434 » err: `unit "foo-bar/654" not found`, |
| 1435 }, { |
| 1436 » tag: "machine-0", |
| 1437 }, { |
| 1438 » tag: "service-ser-vice2", |
| 1439 }, { |
| 1440 » tag: "unit-ser-vice2-0", |
| 1441 }, { |
| 1442 » tag: "user-arble", |
| 1443 }, { |
| 1444 » tag: "environment-test-name", |
| 1445 }} |
1396 | 1446 |
1397 » e, err := getEntity("machine-1234") | 1447 var entityTypes = map[string]interface{}{ |
1398 » c.Check(e, gc.IsNil) | 1448 » names.UserTagKind: (*state.User)(nil), |
1399 » c.Assert(err, gc.ErrorMatches, `machine 1234 not found`) | 1449 » names.EnvironTagKind: (*state.Environment)(nil), |
1400 » c.Assert(err, jc.Satisfies, errors.IsNotFoundError) | 1450 » names.ServiceTagKind: (*state.Service)(nil), |
| 1451 » names.UnitTagKind: (*state.Unit)(nil), |
| 1452 » names.MachineTagKind: (*state.Machine)(nil), |
| 1453 } |
1401 | 1454 |
1402 » e, err = getEntity("unit-foo-654") | 1455 func (s *StateSuite) TestFindEntity(c *gc.C) { |
1403 » c.Check(e, gc.IsNil) | 1456 » _, err := s.State.AddMachine("series", state.JobHostUnits) |
1404 » c.Assert(err, gc.ErrorMatches, `unit "foo/654" not found`) | 1457 » c.Assert(err, gc.IsNil) |
1405 » c.Assert(err, jc.Satisfies, errors.IsNotFoundError) | 1458 » svc, err := s.State.AddService("ser-vice2", s.AddTestingCharm(c, "mysql"
)) |
1406 | 1459 » c.Assert(err, gc.IsNil) |
1407 » e, err = getEntity("unit-foo-bar-654") | 1460 » _, err = svc.AddUnit() |
1408 » c.Check(e, gc.IsNil) | 1461 » c.Assert(err, gc.IsNil) |
1409 » c.Assert(err, gc.ErrorMatches, `unit "foo-bar/654" not found`) | 1462 » _, err = s.State.AddUser("arble", "pass") |
1410 » c.Assert(err, jc.Satisfies, errors.IsNotFoundError) | |
1411 | |
1412 » m, err := s.State.AddMachine("series", state.JobHostUnits) | |
1413 c.Assert(err, gc.IsNil) | 1463 c.Assert(err, gc.IsNil) |
1414 | 1464 |
1415 » e, err = getEntity(m.Tag()) | 1465 » for i, test := range findEntityTests { |
1416 » c.Assert(err, gc.IsNil) | 1466 » » c.Logf("test %d: %q", i, test.tag) |
1417 » c.Assert(e, gc.FitsTypeOf, m) | 1467 » » e, err := s.State.FindEntity(test.tag) |
1418 » c.Assert(e.Tag(), gc.Equals, m.Tag()) | 1468 » » if test.err != "" { |
1419 | 1469 » » » c.Assert(err, gc.ErrorMatches, test.err) |
1420 » svc, err := s.State.AddService("ser-vice2", s.AddTestingCharm(c, "mysql"
)) | 1470 » » } else { |
1421 » c.Assert(err, gc.IsNil) | 1471 » » » c.Assert(err, gc.IsNil) |
1422 » u, err := svc.AddUnit() | 1472 » » » kind, err := names.TagKind(test.tag) |
1423 » c.Assert(err, gc.IsNil) | 1473 » » » c.Assert(err, gc.IsNil) |
1424 | 1474 » » » c.Assert(e, gc.FitsTypeOf, entityTypes[kind]) |
1425 » e, err = getEntity(u.Tag()) | 1475 » » » c.Assert(e.Tag(), gc.Equals, test.tag) |
1426 » c.Assert(err, gc.IsNil) | |
1427 » c.Assert(e, gc.FitsTypeOf, u) | |
1428 » c.Assert(e.Tag(), gc.Equals, u.Tag()) | |
1429 | |
1430 » m.Destroy() | |
1431 » svc.Destroy() | |
1432 } | |
1433 | |
1434 func (s *StateSuite) TestAuthenticator(c *gc.C) { | |
1435 » getEntity := func(tag string) (state.Tagger, error) { | |
1436 » » e, err := s.State.Authenticator(tag) | |
1437 » » if err != nil { | |
1438 » » » return nil, err | |
1439 } | 1476 } |
1440 return e, nil | |
1441 } | 1477 } |
1442 s.testEntity(c, getEntity) | |
1443 e, err := getEntity("user-arble") | |
1444 c.Check(e, gc.IsNil) | |
1445 c.Assert(err, gc.ErrorMatches, `user "arble" not found`) | |
1446 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) | |
1447 | |
1448 user, err := s.State.AddUser("arble", "pass") | |
1449 c.Assert(err, gc.IsNil) | |
1450 | |
1451 e, err = getEntity(user.Tag()) | |
1452 c.Assert(err, gc.IsNil) | |
1453 c.Assert(e, gc.FitsTypeOf, user) | |
1454 c.Assert(e.Tag(), gc.Equals, user.Tag()) | |
1455 | |
1456 cfg, err := s.State.EnvironConfig() | |
1457 c.Assert(err, gc.IsNil) | |
1458 _, err = getEntity("environment-" + cfg.Name()) | |
1459 c.Assert( | |
1460 err, | |
1461 gc.ErrorMatches, | |
1462 `entity "environment-.*" does not support authentication`, | |
1463 ) | |
1464 } | |
1465 | |
1466 func (s *StateSuite) TestAgentEntity(c *gc.C) { | |
1467 machine, err := s.State.AddMachine("series", state.JobHostUnits) | |
1468 c.Assert(err, gc.IsNil) | |
1469 user, err := s.State.AddUser("arble", "pass") | |
1470 c.Assert(err, gc.IsNil) | |
1471 | |
1472 entity, err := s.State.AgentEntity(machine.Tag()) | |
1473 c.Assert(err, gc.IsNil) | |
1474 c.Assert(entity.Tag(), gc.Equals, machine.Tag()) | |
1475 | |
1476 entity, err = s.State.AgentEntity(user.Tag()) | |
1477 c.Assert(err, gc.ErrorMatches, `"user-arble" does not support agent oper
ations`) | |
1478 c.Assert(entity, gc.IsNil) | |
1479 | |
1480 entity, err = s.State.AgentEntity("machine-99") | |
1481 c.Assert(err, jc.Satisfies, errors.IsNotFoundError) | |
1482 c.Assert(entity, gc.IsNil) | |
1483 } | |
1484 | |
1485 func (s *StateSuite) TestAnnotator(c *gc.C) { | |
1486 getEntity := func(tag string) (state.Tagger, error) { | |
1487 e, err := s.State.Annotator(tag) | |
1488 if err != nil { | |
1489 return nil, err | |
1490 } | |
1491 return e, nil | |
1492 } | |
1493 s.testEntity(c, getEntity) | |
1494 svc, err := s.State.AddService("ser-vice1", s.AddTestingCharm(c, "dummy"
)) | |
1495 c.Assert(err, gc.IsNil) | |
1496 | |
1497 service, err := getEntity(svc.Tag()) | |
1498 c.Assert(err, gc.IsNil) | |
1499 c.Assert(service, gc.FitsTypeOf, svc) | |
1500 c.Assert(service.Tag(), gc.Equals, svc.Tag()) | |
1501 | |
1502 cfg, err := s.State.EnvironConfig() | |
1503 c.Assert(err, gc.IsNil) | |
1504 e, err := getEntity("environment-" + cfg.Name()) | |
1505 c.Assert(err, gc.IsNil) | |
1506 env, err := s.State.Environment() | |
1507 c.Assert(err, gc.IsNil) | |
1508 c.Assert(e, gc.FitsTypeOf, env) | |
1509 c.Assert(e.Tag(), gc.Equals, env.Tag()) | |
1510 | |
1511 user, err := s.State.AddUser("arble", "pass") | |
1512 c.Assert(err, gc.IsNil) | |
1513 _, err = getEntity(user.Tag()) | |
1514 c.Assert( | |
1515 err, | |
1516 gc.ErrorMatches, | |
1517 `entity "user-arble" does not support annotations`, | |
1518 ) | |
1519 } | |
1520 | |
1521 func (s *StateSuite) TestLifer(c *gc.C) { | |
1522 getEntity := func(tag string) (state.Tagger, error) { | |
1523 e, err := s.State.Lifer(tag) | |
1524 if err != nil { | |
1525 return nil, err | |
1526 } | |
1527 return e, nil | |
1528 } | |
1529 s.testEntity(c, getEntity) | |
1530 | |
1531 svc, err := s.State.AddService("riak", s.AddTestingCharm(c, "riak")) | |
1532 c.Assert(err, gc.IsNil) | |
1533 service, err := getEntity(svc.Tag()) | |
1534 c.Assert(err, gc.IsNil) | |
1535 c.Assert(service, gc.FitsTypeOf, svc) | |
1536 c.Assert(service.Tag(), gc.Equals, svc.Tag()) | |
1537 | |
1538 // TODO(fwereade): when lp:1199352 (relation lacks Tag) is fixed, check | |
1539 // it works here. | |
1540 | |
1541 cfg, err := s.State.EnvironConfig() | |
1542 c.Assert(err, gc.IsNil) | |
1543 envTag := "environment-" + cfg.Name() | |
1544 _, err = getEntity(envTag) | |
1545 errTemplate := "entity %q does not support lifecycles" | |
1546 c.Assert(err, gc.ErrorMatches, fmt.Sprintf(errTemplate, envTag)) | |
1547 | |
1548 user, err := s.State.AddUser("arble", "pass") | |
1549 c.Assert(err, gc.IsNil) | |
1550 _, err = getEntity(user.Tag()) | |
1551 c.Assert(err, gc.ErrorMatches, fmt.Sprintf(errTemplate, user.Tag())) | |
1552 } | 1478 } |
1553 | 1479 |
1554 func (s *StateSuite) TestParseTag(c *gc.C) { | 1480 func (s *StateSuite) TestParseTag(c *gc.C) { |
1555 bad := []string{ | 1481 bad := []string{ |
1556 "", | 1482 "", |
1557 "machine", | 1483 "machine", |
1558 "-foo", | 1484 "-foo", |
1559 "foo-", | 1485 "foo-", |
1560 "---", | 1486 "---", |
1561 "foo-bar", | 1487 "foo-bar", |
1562 "environment-foo", | 1488 "environment-foo", |
1563 "unit-foo", | 1489 "unit-foo", |
1564 } | 1490 } |
1565 for _, name := range bad { | 1491 for _, name := range bad { |
1566 c.Logf(name) | 1492 c.Logf(name) |
1567 coll, id, err := state.ParseTag(s.State, name) | 1493 coll, id, err := state.ParseTag(s.State, name) |
1568 c.Check(coll, gc.Equals, "") | 1494 c.Check(coll, gc.Equals, "") |
1569 c.Check(id, gc.Equals, "") | 1495 c.Check(id, gc.Equals, "") |
1570 » » c.Assert(err, gc.ErrorMatches, `invalid entity name ".*"`) | 1496 » » c.Assert(err, gc.ErrorMatches, `".*" is not a valid( [a-z]+)? ta
g`) |
1571 } | 1497 } |
1572 | 1498 |
1573 // Parse a machine entity name. | 1499 // Parse a machine entity name. |
1574 m, err := s.State.AddMachine("series", state.JobHostUnits) | 1500 m, err := s.State.AddMachine("series", state.JobHostUnits) |
1575 c.Assert(err, gc.IsNil) | 1501 c.Assert(err, gc.IsNil) |
1576 coll, id, err := state.ParseTag(s.State, m.Tag()) | 1502 coll, id, err := state.ParseTag(s.State, m.Tag()) |
1577 c.Assert(coll, gc.Equals, "machines") | 1503 c.Assert(coll, gc.Equals, "machines") |
1578 c.Assert(id, gc.Equals, m.Id()) | 1504 c.Assert(id, gc.Equals, m.Id()) |
1579 c.Assert(err, gc.IsNil) | 1505 c.Assert(err, gc.IsNil) |
1580 | 1506 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1817 c.Assert(state.ParentId("0"), gc.Equals, "") | 1743 c.Assert(state.ParentId("0"), gc.Equals, "") |
1818 c.Assert(state.ParentId("0/lxc/1"), gc.Equals, "0") | 1744 c.Assert(state.ParentId("0/lxc/1"), gc.Equals, "0") |
1819 c.Assert(state.ParentId("0/lxc/1/kvm/0"), gc.Equals, "0/lxc/1") | 1745 c.Assert(state.ParentId("0/lxc/1/kvm/0"), gc.Equals, "0/lxc/1") |
1820 } | 1746 } |
1821 | 1747 |
1822 func (s *StateSuite) TestContainerTypeFromId(c *gc.C) { | 1748 func (s *StateSuite) TestContainerTypeFromId(c *gc.C) { |
1823 c.Assert(state.ContainerTypeFromId("0"), gc.Equals, instance.ContainerTy
pe("")) | 1749 c.Assert(state.ContainerTypeFromId("0"), gc.Equals, instance.ContainerTy
pe("")) |
1824 c.Assert(state.ContainerTypeFromId("0/lxc/1"), gc.Equals, instance.LXC) | 1750 c.Assert(state.ContainerTypeFromId("0/lxc/1"), gc.Equals, instance.LXC) |
1825 c.Assert(state.ContainerTypeFromId("0/lxc/1/kvm/0"), gc.Equals, instance
.KVM) | 1751 c.Assert(state.ContainerTypeFromId("0/lxc/1/kvm/0"), gc.Equals, instance
.KVM) |
1826 } | 1752 } |
OLD | NEW |