LEFT | RIGHT |
1 // launchpad.net/juju/go/state | 1 // launchpad.net/juju/go/state |
2 // | 2 // |
3 // Copyright (c) 2011-2012 Canonical Ltd. | 3 // Copyright (c) 2011-2012 Canonical Ltd. |
4 package state_test | 4 package state_test |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
8 . "launchpad.net/gocheck" | 8 . "launchpad.net/gocheck" |
9 "launchpad.net/gozk/zookeeper" | 9 "launchpad.net/gozk/zookeeper" |
10 "launchpad.net/juju/go/charm" | 10 "launchpad.net/juju/go/charm" |
11 "launchpad.net/juju/go/state" | 11 "launchpad.net/juju/go/state" |
12 » "launchpad.net/juju/go/testutil" | 12 » "launchpad.net/juju/go/testing" |
13 "net/url" | 13 "net/url" |
14 "path/filepath" | 14 "path/filepath" |
15 » "testing" | 15 » "sort" |
| 16 » stdtesting "testing" |
16 ) | 17 ) |
17 | 18 |
18 // TestPackage integrates the tests into gotest. | 19 // TestPackage integrates the tests into gotest. |
19 func TestPackage(t *testing.T) { | 20 func TestPackage(t *stdtesting.T) { |
20 » testutil.ZkTestingT(t, &state.ZkAddr) | 21 » srv := testing.StartZkServer(t) |
| 22 » defer srv.Destroy() |
| 23 » var err error |
| 24 » state.TestingZkAddr, err = srv.Addr() |
| 25 » if err != nil { |
| 26 » » t.Fatalf("could not get zk server address") |
| 27 » } |
| 28 » TestingT(t) |
21 } | 29 } |
22 | 30 |
23 // charmDir returns a directory containing the given test charm. | 31 // charmDir returns a directory containing the given test charm. |
24 func charmDir(name string) string { | 32 func charmDir(name string) string { |
25 return filepath.Join("..", "charm", "testrepo", "series", name) | 33 return filepath.Join("..", "charm", "testrepo", "series", name) |
26 } | 34 } |
27 | 35 |
28 // readCharm returns a test charm by its name. | 36 // readCharm returns a test charm by its name. |
29 func readCharm(c *C, name string) charm.Charm { | 37 func readCharm(c *C, name string) charm.Charm { |
30 ch, err := charm.ReadDir(charmDir(name)) | 38 ch, err := charm.ReadDir(charmDir(name)) |
(...skipping 25 matching lines...) Expand all Loading... |
56 zkAddr string | 64 zkAddr string |
57 zkConn *zookeeper.Conn | 65 zkConn *zookeeper.Conn |
58 st *state.State | 66 st *state.State |
59 } | 67 } |
60 | 68 |
61 var _ = Suite(&StateSuite{}) | 69 var _ = Suite(&StateSuite{}) |
62 | 70 |
63 func (s *StateSuite) SetUpTest(c *C) { | 71 func (s *StateSuite) SetUpTest(c *C) { |
64 var err error | 72 var err error |
65 s.st, err = state.Open(&state.Info{ | 73 s.st, err = state.Open(&state.Info{ |
66 » » Addrs: []string{state.ZkAddr}, | 74 » » Addrs: []string{state.TestingZkAddr}, |
67 }) | 75 }) |
68 c.Assert(err, IsNil) | 76 c.Assert(err, IsNil) |
69 err = s.st.Initialize() | 77 err = s.st.Initialize() |
70 c.Assert(err, IsNil) | 78 c.Assert(err, IsNil) |
71 s.zkConn = state.ZkConn(s.st) | 79 s.zkConn = state.ZkConn(s.st) |
72 } | 80 } |
73 | 81 |
74 func (s *StateSuite) TearDownTest(c *C) { | 82 func (s *StateSuite) TearDownTest(c *C) { |
75 // Delete possible nodes, ignore errors. | 83 // Delete possible nodes, ignore errors. |
76 zkRemoveTree(s.zkConn, "/topology") | 84 zkRemoveTree(s.zkConn, "/topology") |
77 zkRemoveTree(s.zkConn, "/charms") | 85 zkRemoveTree(s.zkConn, "/charms") |
78 zkRemoveTree(s.zkConn, "/services") | 86 zkRemoveTree(s.zkConn, "/services") |
79 zkRemoveTree(s.zkConn, "/machines") | 87 zkRemoveTree(s.zkConn, "/machines") |
80 zkRemoveTree(s.zkConn, "/units") | 88 zkRemoveTree(s.zkConn, "/units") |
81 zkRemoveTree(s.zkConn, "/relations") | 89 zkRemoveTree(s.zkConn, "/relations") |
82 zkRemoveTree(s.zkConn, "/initialized") | 90 zkRemoveTree(s.zkConn, "/initialized") |
83 s.zkConn.Close() | 91 s.zkConn.Close() |
84 } | 92 } |
85 | 93 |
86 func (s StateSuite) TestAddCharm(c *C) { | 94 func (s StateSuite) TestAddCharm(c *C) { |
87 // Check that adding charms works correctly. | 95 // Check that adding charms works correctly. |
88 dummyCharm := readCharm(c, "dummy") | 96 dummyCharm := readCharm(c, "dummy") |
89 curl := localCharmURL(dummyCharm) | 97 curl := localCharmURL(dummyCharm) |
90 bundleURL, err := url.Parse("http://bundle.url") | 98 bundleURL, err := url.Parse("http://bundle.url") |
91 c.Assert(err, IsNil) | 99 c.Assert(err, IsNil) |
92 dummy, err := s.st.AddCharm(dummyCharm, curl, bundleURL) | 100 dummy, err := s.st.AddCharm(dummyCharm, curl, bundleURL) |
93 c.Assert(err, IsNil) | 101 c.Assert(err, IsNil) |
94 c.Assert(dummy.URL().String(), Equals, curl.String()) | 102 c.Assert(dummy.URL().String(), Equals, curl.String()) |
95 » _, _, err = s.zkConn.Children("/charms") | 103 » children, _, err := s.zkConn.Children("/charms") |
96 » c.Assert(err, IsNil) | 104 » c.Assert(err, IsNil) |
| 105 » c.Assert(children, DeepEquals, []string{"local_3a_series_2f_dummy-1"}) |
97 } | 106 } |
98 | 107 |
99 func (s StateSuite) TestCharmAttributes(c *C) { | 108 func (s StateSuite) TestCharmAttributes(c *C) { |
100 // Check that the basic (invariant) fields of the charm | 109 // Check that the basic (invariant) fields of the charm |
101 // are correctly in place. | 110 // are correctly in place. |
102 _, curl := addDummyCharm(c, s.st) | 111 _, curl := addDummyCharm(c, s.st) |
103 | 112 |
104 dummy, err := s.st.Charm(curl) | 113 dummy, err := s.st.Charm(curl) |
105 c.Assert(err, IsNil) | 114 c.Assert(err, IsNil) |
106 c.Assert(dummy.URL().String(), Equals, curl.String()) | 115 c.Assert(dummy.URL().String(), Equals, curl.String()) |
(...skipping 23 matching lines...) Expand all Loading... |
130 | 139 |
131 func (s StateSuite) TestGetNonExistentCharm(c *C) { | 140 func (s StateSuite) TestGetNonExistentCharm(c *C) { |
132 // Check that getting a non-existent charm fails nicely. | 141 // Check that getting a non-existent charm fails nicely. |
133 addDummyCharm(c, s.st) | 142 addDummyCharm(c, s.st) |
134 | 143 |
135 curl := charm.MustParseURL("local:anotherseries/dummy-1") | 144 curl := charm.MustParseURL("local:anotherseries/dummy-1") |
136 _, err := s.st.Charm(curl) | 145 _, err := s.st.Charm(curl) |
137 c.Assert(err, ErrorMatches, `charm not found: "local:anotherseries/dummy
-1"`) | 146 c.Assert(err, ErrorMatches, `charm not found: "local:anotherseries/dummy
-1"`) |
138 } | 147 } |
139 | 148 |
| 149 func (s StateSuite) TestAddMachine(c *C) { |
| 150 machine0, err := s.st.AddMachine() |
| 151 c.Assert(err, IsNil) |
| 152 c.Assert(machine0.Id(), Equals, 0) |
| 153 machine1, err := s.st.AddMachine() |
| 154 c.Assert(err, IsNil) |
| 155 c.Assert(machine1.Id(), Equals, 1) |
| 156 |
| 157 children, _, err := s.zkConn.Children("/machines") |
| 158 c.Assert(err, IsNil) |
| 159 sort.Strings(children) |
| 160 c.Assert(children, DeepEquals, []string{"machine-0000000000", "machine-0
000000001"}) |
| 161 } |
| 162 |
| 163 func (s StateSuite) TestRemoveMachine(c *C) { |
| 164 machine, err := s.st.AddMachine() |
| 165 c.Assert(err, IsNil) |
| 166 _, err = s.st.AddMachine() |
| 167 c.Assert(err, IsNil) |
| 168 err = s.st.RemoveMachine(machine.Id()) |
| 169 c.Assert(err, IsNil) |
| 170 |
| 171 children, _, err := s.zkConn.Children("/machines") |
| 172 c.Assert(err, IsNil) |
| 173 sort.Strings(children) |
| 174 c.Assert(children, DeepEquals, []string{"machine-0000000001"}) |
| 175 |
| 176 // Removing a non-existing machine has to fail. |
| 177 err = s.st.RemoveMachine(machine.Id()) |
| 178 c.Assert(err, ErrorMatches, "can't remove machine 0: machine not found") |
| 179 } |
| 180 |
| 181 func (s StateSuite) TestReadMachine(c *C) { |
| 182 machine, err := s.st.AddMachine() |
| 183 c.Assert(err, IsNil) |
| 184 expectedId := machine.Id() |
| 185 machine, err = s.st.Machine(expectedId) |
| 186 c.Assert(err, IsNil) |
| 187 c.Assert(machine.Id(), Equals, expectedId) |
| 188 } |
| 189 |
| 190 func (s StateSuite) TestReadNonExistentMachine(c *C) { |
| 191 _, err := s.st.Machine(0) |
| 192 c.Assert(err, ErrorMatches, "machine 0 not found") |
| 193 |
| 194 _, err = s.st.AddMachine() |
| 195 c.Assert(err, IsNil) |
| 196 _, err = s.st.Machine(1) |
| 197 c.Assert(err, ErrorMatches, "machine 1 not found") |
| 198 } |
| 199 |
| 200 func (s StateSuite) TestAllMachines(c *C) { |
| 201 machines, err := s.st.AllMachines() |
| 202 c.Assert(err, IsNil) |
| 203 c.Assert(len(machines), Equals, 0) |
| 204 |
| 205 _, err = s.st.AddMachine() |
| 206 c.Assert(err, IsNil) |
| 207 machines, err = s.st.AllMachines() |
| 208 c.Assert(err, IsNil) |
| 209 c.Assert(len(machines), Equals, 1) |
| 210 |
| 211 _, err = s.st.AddMachine() |
| 212 c.Assert(err, IsNil) |
| 213 machines, err = s.st.AllMachines() |
| 214 c.Assert(err, IsNil) |
| 215 c.Assert(len(machines), Equals, 2) |
| 216 } |
| 217 |
140 func (s StateSuite) TestAddService(c *C) { | 218 func (s StateSuite) TestAddService(c *C) { |
141 // Check that adding services works correctly. | |
142 dummy, curl := addDummyCharm(c, s.st) | 219 dummy, curl := addDummyCharm(c, s.st) |
143 wordpress, err := s.st.AddService("wordpress", dummy) | 220 wordpress, err := s.st.AddService("wordpress", dummy) |
144 c.Assert(err, IsNil) | 221 c.Assert(err, IsNil) |
145 c.Assert(wordpress.Name(), Equals, "wordpress") | 222 c.Assert(wordpress.Name(), Equals, "wordpress") |
146 mysql, err := s.st.AddService("mysql", dummy) | 223 mysql, err := s.st.AddService("mysql", dummy) |
147 c.Assert(err, IsNil) | 224 c.Assert(err, IsNil) |
148 c.Assert(mysql.Name(), Equals, "mysql") | 225 c.Assert(mysql.Name(), Equals, "mysql") |
149 | 226 |
150 // Check that retrieving the new created services works correctly. | 227 // Check that retrieving the new created services works correctly. |
151 wordpress, err = s.st.Service("wordpress") | 228 wordpress, err = s.st.Service("wordpress") |
152 c.Assert(err, IsNil) | 229 c.Assert(err, IsNil) |
153 c.Assert(wordpress.Name(), Equals, "wordpress") | 230 c.Assert(wordpress.Name(), Equals, "wordpress") |
154 url, err := wordpress.CharmURL() | 231 url, err := wordpress.CharmURL() |
155 c.Assert(err, IsNil) | 232 c.Assert(err, IsNil) |
156 c.Assert(url.String(), Equals, curl.String()) | 233 c.Assert(url.String(), Equals, curl.String()) |
157 mysql, err = s.st.Service("mysql") | 234 mysql, err = s.st.Service("mysql") |
158 c.Assert(err, IsNil) | 235 c.Assert(err, IsNil) |
159 c.Assert(mysql.Name(), Equals, "mysql") | 236 c.Assert(mysql.Name(), Equals, "mysql") |
160 url, err = mysql.CharmURL() | 237 url, err = mysql.CharmURL() |
161 c.Assert(err, IsNil) | 238 c.Assert(err, IsNil) |
162 c.Assert(url.String(), Equals, curl.String()) | 239 c.Assert(url.String(), Equals, curl.String()) |
163 } | 240 } |
164 | 241 |
165 func (s StateSuite) TestRemoveService(c *C) { | 242 func (s StateSuite) TestRemoveService(c *C) { |
166 dummy, _ := addDummyCharm(c, s.st) | 243 dummy, _ := addDummyCharm(c, s.st) |
167 service, err := s.st.AddService("wordpress", dummy) | 244 service, err := s.st.AddService("wordpress", dummy) |
168 c.Assert(err, IsNil) | 245 c.Assert(err, IsNil) |
169 | 246 |
170 // Check that removing the service works correctly. | |
171 err = s.st.RemoveService(service) | 247 err = s.st.RemoveService(service) |
172 c.Assert(err, IsNil) | 248 c.Assert(err, IsNil) |
173 service, err = s.st.Service("wordpress") | 249 service, err = s.st.Service("wordpress") |
174 c.Assert(err, ErrorMatches, `service with name "wordpress" not found`) | 250 c.Assert(err, ErrorMatches, `service with name "wordpress" not found`) |
175 } | 251 } |
176 | 252 |
177 func (s StateSuite) TestReadNonExistentService(c *C) { | 253 func (s StateSuite) TestReadNonExistentService(c *C) { |
178 _, err := s.st.Service("pressword") | 254 _, err := s.st.Service("pressword") |
179 c.Assert(err, ErrorMatches, `service with name "pressword" not found`) | 255 c.Assert(err, ErrorMatches, `service with name "pressword" not found`) |
180 } | 256 } |
181 | 257 |
182 func (s StateSuite) TestAllServices(c *C) { | 258 func (s StateSuite) TestAllServices(c *C) { |
183 // Check without existing services. | |
184 services, err := s.st.AllServices() | 259 services, err := s.st.AllServices() |
185 c.Assert(err, IsNil) | 260 c.Assert(err, IsNil) |
186 c.Assert(len(services), Equals, 0) | 261 c.Assert(len(services), Equals, 0) |
187 | 262 |
188 // Check that after adding services the result is ok. | 263 // Check that after adding services the result is ok. |
189 dummy, _ := addDummyCharm(c, s.st) | 264 dummy, _ := addDummyCharm(c, s.st) |
190 _, err = s.st.AddService("wordpress", dummy) | 265 _, err = s.st.AddService("wordpress", dummy) |
191 c.Assert(err, IsNil) | 266 c.Assert(err, IsNil) |
192 services, err = s.st.AllServices() | 267 services, err = s.st.AllServices() |
193 c.Assert(err, IsNil) | 268 c.Assert(err, IsNil) |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 err = mysqlUnit.AssignToMachine(mysqlMachine) | 685 err = mysqlUnit.AssignToMachine(mysqlMachine) |
611 c.Assert(err, IsNil) | 686 c.Assert(err, IsNil) |
612 | 687 |
613 wordpressService, err := s.st.AddService("wordpress", dummy) | 688 wordpressService, err := s.st.AddService("wordpress", dummy) |
614 c.Assert(err, IsNil) | 689 c.Assert(err, IsNil) |
615 wordpressUnit, err := wordpressService.AddUnit() | 690 wordpressUnit, err := wordpressService.AddUnit() |
616 c.Assert(err, IsNil) | 691 c.Assert(err, IsNil) |
617 | 692 |
618 _, err = wordpressUnit.AssignToUnusedMachine() | 693 _, err = wordpressUnit.AssignToUnusedMachine() |
619 c.Assert(err, ErrorMatches, "no unused machine found") | 694 c.Assert(err, ErrorMatches, "no unused machine found") |
| 695 } |
| 696 |
| 697 func (s StateSuite) TestGetSetClearUnitUpgrate(c *C) { |
| 698 // Check that setting and clearing an upgrade flag on a unit works. |
| 699 dummy, _ := addDummyCharm(c, s.st) |
| 700 wordpress, err := s.st.AddService("wordpress", dummy) |
| 701 c.Assert(err, IsNil) |
| 702 unit, err := wordpress.AddUnit() |
| 703 c.Assert(err, IsNil) |
| 704 |
| 705 // Defaults to false. |
| 706 upgrade, err := unit.NeedsUpgrade() |
| 707 c.Assert(err, IsNil) |
| 708 c.Assert(upgrade, Equals, false) |
| 709 |
| 710 // Can be set. |
| 711 err = unit.SetNeedsUpgrade() |
| 712 c.Assert(err, IsNil) |
| 713 upgrade, err = unit.NeedsUpgrade() |
| 714 c.Assert(err, IsNil) |
| 715 c.Assert(upgrade, Equals, true) |
| 716 |
| 717 // Can be set multiple times. |
| 718 err = unit.SetNeedsUpgrade() |
| 719 c.Assert(err, IsNil) |
| 720 upgrade, err = unit.NeedsUpgrade() |
| 721 c.Assert(err, IsNil) |
| 722 c.Assert(upgrade, Equals, true) |
| 723 |
| 724 // Can be cleared. |
| 725 err = unit.ClearNeedsUpgrade() |
| 726 c.Assert(err, IsNil) |
| 727 upgrade, err = unit.NeedsUpgrade() |
| 728 c.Assert(err, IsNil) |
| 729 c.Assert(upgrade, Equals, false) |
| 730 |
| 731 // Can be cleared multiple times |
| 732 err = unit.ClearNeedsUpgrade() |
| 733 c.Assert(err, IsNil) |
| 734 upgrade, err = unit.NeedsUpgrade() |
| 735 c.Assert(err, IsNil) |
| 736 c.Assert(upgrade, Equals, false) |
| 737 } |
| 738 |
| 739 func (s StateSuite) TestGetSetClearResolved(c *C) { |
| 740 // Check that setting and clearing the resolved setting on a unit works. |
| 741 dummy, _ := addDummyCharm(c, s.st) |
| 742 wordpress, err := s.st.AddService("wordpress", dummy) |
| 743 c.Assert(err, IsNil) |
| 744 unit, err := wordpress.AddUnit() |
| 745 c.Assert(err, IsNil) |
| 746 |
| 747 setting, err := unit.Resolved() |
| 748 c.Assert(err, IsNil) |
| 749 c.Assert(setting, Equals, state.ResolvedNone) |
| 750 |
| 751 err = unit.SetResolved(state.ResolvedNoHooks) |
| 752 c.Assert(err, IsNil) |
| 753 err = unit.SetResolved(state.ResolvedNoHooks) |
| 754 c.Assert(err, ErrorMatches, `unit "wordpress/0" resolved flag already se
t`) |
| 755 retry, err := unit.Resolved() |
| 756 c.Assert(err, IsNil) |
| 757 c.Assert(retry, Equals, state.ResolvedNoHooks) |
| 758 |
| 759 err = unit.ClearResolved() |
| 760 c.Assert(err, IsNil) |
| 761 setting, err = unit.Resolved() |
| 762 c.Assert(err, IsNil) |
| 763 c.Assert(setting, Equals, state.ResolvedNone) |
| 764 err = unit.ClearResolved() |
| 765 c.Assert(err, IsNil) |
| 766 |
| 767 err = unit.SetResolved(state.ResolvedMode(999)) |
| 768 c.Assert(err, ErrorMatches, `invalid error resolution mode: 999`) |
| 769 } |
| 770 |
| 771 func (s StateSuite) TestGetOpenPorts(c *C) { |
| 772 // Check that changes to the open ports of units work porperly. |
| 773 dummy, _ := addDummyCharm(c, s.st) |
| 774 wordpress, err := s.st.AddService("wordpress", dummy) |
| 775 c.Assert(err, IsNil) |
| 776 unit, err := wordpress.AddUnit() |
| 777 c.Assert(err, IsNil) |
| 778 |
| 779 // Verify no open ports before activity. |
| 780 open, err := unit.OpenPorts() |
| 781 c.Assert(err, IsNil) |
| 782 c.Assert(open, HasLen, 0) |
| 783 |
| 784 // Now open and close port. |
| 785 err = unit.OpenPort("tcp", 80) |
| 786 c.Assert(err, IsNil) |
| 787 open, err = unit.OpenPorts() |
| 788 c.Assert(err, IsNil) |
| 789 c.Assert(open, DeepEquals, []state.Port{ |
| 790 {"tcp", 80}, |
| 791 }) |
| 792 |
| 793 err = unit.OpenPort("udp", 53) |
| 794 c.Assert(err, IsNil) |
| 795 open, err = unit.OpenPorts() |
| 796 c.Assert(err, IsNil) |
| 797 c.Assert(open, DeepEquals, []state.Port{ |
| 798 {"tcp", 80}, |
| 799 {"udp", 53}, |
| 800 }) |
| 801 |
| 802 err = unit.OpenPort("tcp", 53) |
| 803 c.Assert(err, IsNil) |
| 804 open, err = unit.OpenPorts() |
| 805 c.Assert(err, IsNil) |
| 806 c.Assert(open, DeepEquals, []state.Port{ |
| 807 {"tcp", 80}, |
| 808 {"udp", 53}, |
| 809 {"tcp", 53}, |
| 810 }) |
| 811 |
| 812 err = unit.OpenPort("tcp", 443) |
| 813 c.Assert(err, IsNil) |
| 814 open, err = unit.OpenPorts() |
| 815 c.Assert(err, IsNil) |
| 816 c.Assert(open, DeepEquals, []state.Port{ |
| 817 {"tcp", 80}, |
| 818 {"udp", 53}, |
| 819 {"tcp", 53}, |
| 820 {"tcp", 443}, |
| 821 }) |
| 822 |
| 823 err = unit.ClosePort("tcp", 80) |
| 824 c.Assert(err, IsNil) |
| 825 open, err = unit.OpenPorts() |
| 826 c.Assert(err, IsNil) |
| 827 c.Assert(open, DeepEquals, []state.Port{ |
| 828 {"udp", 53}, |
| 829 {"tcp", 53}, |
| 830 {"tcp", 443}, |
| 831 }) |
620 } | 832 } |
621 | 833 |
622 // zkRemoveTree recursively removes a tree. | 834 // zkRemoveTree recursively removes a tree. |
623 func zkRemoveTree(zk *zookeeper.Conn, path string) error { | 835 func zkRemoveTree(zk *zookeeper.Conn, path string) error { |
624 // First recursively delete the children. | 836 // First recursively delete the children. |
625 children, _, err := zk.Children(path) | 837 children, _, err := zk.Children(path) |
626 if err != nil { | 838 if err != nil { |
627 return err | 839 return err |
628 } | 840 } |
629 for _, child := range children { | 841 for _, child := range children { |
630 if err = zkRemoveTree(zk, fmt.Sprintf("%s/%s", path, child)); er
r != nil { | 842 if err = zkRemoveTree(zk, fmt.Sprintf("%s/%s", path, child)); er
r != nil { |
631 return err | 843 return err |
632 } | 844 } |
633 } | 845 } |
634 // Now delete the path itself. | 846 // Now delete the path itself. |
635 return zk.Delete(path, -1) | 847 return zk.Delete(path, -1) |
636 } | 848 } |
LEFT | RIGHT |