Merge lp:~gz/juju-ci-tools/substrate_maas_refac into lp:juju-ci-tools

Proposed by Martin Packman
Status: Merged
Merged at revision: 1475
Proposed branch: lp:~gz/juju-ci-tools/substrate_maas_refac
Merge into: lp:juju-ci-tools
Diff against target: 200 lines (+47/-43)
2 files modified
substrate.py (+14/-11)
tests/test_substrate.py (+33/-32)
To merge this branch: bzr merge lp:~gz/juju-ci-tools/substrate_maas_refac
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+297783@code.launchpad.net

Description of the change

Changes to maas substrate implementation

As part of adding a bunch more maas substrate commands, I ended up changing some details of how the existing code worked that meant updating the existing tests. This branch is just the existing code with those changes to separate out the new additions from the implementation changes.

Note that login/logout still dump the maas output straight to stdout (and our ci logs), but other commands now consume the output given by maas and parse it as json. Commands that want to output something for the ci logs should include logging of those maas return values.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank you.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'substrate.py'
2--- substrate.py 2016-05-31 23:12:41 +0000
3+++ substrate.py 2016-06-17 15:01:00 +0000
4@@ -414,33 +414,36 @@
5 self.url = urlparse.urljoin(url, self._API_PATH)
6 self.oauth = oauth
7
8+ def _maas(self, *args):
9+ """Call maas api with given arguments and parse json result."""
10+ output = subprocess.check_output(('maas',) + args)
11+ return json.loads(output)
12+
13 def login(self):
14 """Login with the maas cli."""
15- subprocess.check_call(
16- ['maas', 'login', self.profile, self.url, self.oauth])
17+ subprocess.check_call([
18+ 'maas', 'login', self.profile, self.url, self.oauth])
19
20 def logout(self):
21 """Logout with the maas cli."""
22- subprocess.check_call(
23- ['maas', 'logout', self.profile])
24+ subprocess.check_call(['maas', 'logout', self.profile])
25
26 def _machine_release_args(self, machine_id):
27- return ['maas', self.profile, 'machine', 'release', machine_id]
28+ return (self.profile, 'machine', 'release', machine_id)
29
30 def terminate_instances(self, instance_ids):
31 """Terminate the specified instances."""
32 for instance in instance_ids:
33 maas_system_id = instance.split('/')[5]
34 log.info('Deleting %s.' % instance)
35- subprocess.check_call(self._machine_release_args(maas_system_id))
36+ self._maas(*self._machine_release_args(maas_system_id))
37
38 def _list_allocated_args(self):
39- return ['maas', self.profile, 'machines', 'list-allocated']
40+ return (self.profile, 'machines', 'list-allocated')
41
42 def get_allocated_nodes(self):
43 """Return a dict of allocated nodes with the hostname as keys."""
44- data = subprocess.check_output(self._list_allocated_args())
45- nodes = json.loads(data)
46+ nodes = self._maas(*self._list_allocated_args())
47 allocated = {node['hostname']: node for node in nodes}
48 return allocated
49
50@@ -462,10 +465,10 @@
51 _API_PATH = 'api/1.0/'
52
53 def _list_allocated_args(self):
54- return ['maas', self.profile, 'nodes', 'list-allocated']
55+ return (self.profile, 'nodes', 'list-allocated')
56
57 def _machine_release_args(self, machine_id):
58- return ['maas', self.profile, 'node', 'release', machine_id]
59+ return (self.profile, 'node', 'release', machine_id)
60
61
62 @contextmanager
63
64=== modified file 'tests/test_substrate.py'
65--- tests/test_substrate.py 2016-05-31 23:12:41 +0000
66+++ tests/test_substrate.py 2016-06-17 15:01:00 +0000
67@@ -171,18 +171,17 @@
68
69 def test_terminate_maas(self):
70 env = get_maas_env()
71- with patch('subprocess.check_call') as cc_mock:
72- terminate_instances(env, ['/A/B/C/D/node-3d/'])
73- expected = (
74- ['maas', 'login', 'mas', 'http://10.0.10.10/MAAS/api/2.0/',
75- 'a:password:string'],
76- )
77- self.assertEqual(expected, cc_mock.call_args_list[0][0])
78- expected = (['maas', 'mas', 'machine', 'release', 'node-3d'],)
79- self.assertEqual(expected, cc_mock.call_args_list[1][0])
80- expected = (['maas', 'logout', 'mas'],)
81- self.assertEqual(expected, cc_mock.call_args_list[2][0])
82- self.assertEqual(3, len(cc_mock.call_args_list))
83+ with patch('subprocess.check_call', autospec=True) as cc_mock:
84+ with patch('subprocess.check_output', autospec=True,
85+ return_value='{}') as co_mock:
86+ terminate_instances(env, ['/A/B/C/D/node-3d/'])
87+ self.assertEquals(cc_mock.call_args_list, [
88+ call(['maas', 'login', 'mas', 'http://10.0.10.10/MAAS/api/2.0/',
89+ 'a:password:string']),
90+ call(['maas', 'logout', 'mas']),
91+ ])
92+ co_mock.assert_called_once_with(
93+ ('maas', 'mas', 'machine', 'release', 'node-3d'))
94 self.assertEqual(
95 self.log_stream.getvalue(),
96 'INFO Deleting /A/B/C/D/node-3d/.\n')
97@@ -763,17 +762,18 @@
98 account.logout()
99 cc_mock.assert_called_once_with(['maas', 'logout', 'mas'])
100
101- @patch('subprocess.check_call', autospec=True)
102- def test_terminate_instances(self, cc_mock):
103+ def test_terminate_instances(self):
104 config = get_maas_env().config
105 account = MAASAccount(
106 config['name'], config['maas-server'], config['maas-oauth'])
107 instance_ids = ['/A/B/C/D/node-1d/', '/A/B/C/D/node-2d/']
108- account.terminate_instances(instance_ids)
109- cc_mock.assert_any_call(
110- ['maas', 'mas', 'machine', 'release', 'node-1d'])
111- cc_mock.assert_called_with(
112- ['maas', 'mas', 'machine', 'release', 'node-2d'])
113+ with patch('subprocess.check_output', autospec=True,
114+ return_value='{}') as co_mock:
115+ account.terminate_instances(instance_ids)
116+ co_mock.assert_any_call(
117+ ('maas', 'mas', 'machine', 'release', 'node-1d'))
118+ co_mock.assert_called_with(
119+ ('maas', 'mas', 'machine', 'release', 'node-2d'))
120
121 def test_get_allocated_nodes(self):
122 config = get_maas_env().config
123@@ -785,7 +785,7 @@
124 return_value=allocated_nodes_string) as co_mock:
125 allocated = account.get_allocated_nodes()
126 co_mock.assert_called_once_with(
127- ['maas', 'mas', 'machines', 'list-allocated'])
128+ ('maas', 'mas', 'machines', 'list-allocated'))
129 self.assertEqual(node, allocated['maas-node-1.maas'])
130
131 def test_get_allocated_ips(self):
132@@ -798,7 +798,7 @@
133 return_value=allocated_nodes_string) as co_mock:
134 ips = account.get_allocated_ips()
135 co_mock.assert_called_once_with(
136- ['maas', 'mas', 'machines', 'list-allocated'])
137+ ('maas', 'mas', 'machines', 'list-allocated'))
138 self.assertEqual('10.0.30.165', ips['maas-node-1.maas'])
139
140 def test_get_allocated_ips_empty(self):
141@@ -812,7 +812,7 @@
142 return_value=allocated_nodes_string) as co_mock:
143 ips = account.get_allocated_ips()
144 co_mock.assert_called_once_with(
145- ['maas', 'mas', 'machines', 'list-allocated'])
146+ ('maas', 'mas', 'machines', 'list-allocated'))
147 self.assertEqual({}, ips)
148
149
150@@ -836,17 +836,18 @@
151 account.logout()
152 cc_mock.assert_called_once_with(['maas', 'logout', 'mas'])
153
154- @patch('subprocess.check_call', autospec=True)
155- def test_terminate_instances(self, cc_mock):
156+ def test_terminate_instances(self):
157 config = get_maas_env().config
158 account = MAAS1Account(
159 config['name'], config['maas-server'], config['maas-oauth'])
160 instance_ids = ['/A/B/C/D/node-1d/', '/A/B/C/D/node-2d/']
161- account.terminate_instances(instance_ids)
162- cc_mock.assert_any_call(
163- ['maas', 'mas', 'node', 'release', 'node-1d'])
164- cc_mock.assert_called_with(
165- ['maas', 'mas', 'node', 'release', 'node-2d'])
166+ with patch('subprocess.check_output', autospec=True,
167+ return_value='{}') as co_mock:
168+ account.terminate_instances(instance_ids)
169+ co_mock.assert_any_call(
170+ ('maas', 'mas', 'node', 'release', 'node-1d'))
171+ co_mock.assert_called_with(
172+ ('maas', 'mas', 'node', 'release', 'node-2d'))
173
174 def test_get_allocated_nodes(self):
175 config = get_maas_env().config
176@@ -858,7 +859,7 @@
177 return_value=allocated_nodes_string) as co_mock:
178 allocated = account.get_allocated_nodes()
179 co_mock.assert_called_once_with(
180- ['maas', 'mas', 'nodes', 'list-allocated'])
181+ ('maas', 'mas', 'nodes', 'list-allocated'))
182 self.assertEqual(node, allocated['maas-node-1.maas'])
183
184 def test_get_allocated_ips(self):
185@@ -871,7 +872,7 @@
186 return_value=allocated_nodes_string) as co_mock:
187 ips = account.get_allocated_ips()
188 co_mock.assert_called_once_with(
189- ['maas', 'mas', 'nodes', 'list-allocated'])
190+ ('maas', 'mas', 'nodes', 'list-allocated'))
191 self.assertEqual('10.0.30.165', ips['maas-node-1.maas'])
192
193 def test_get_allocated_ips_empty(self):
194@@ -885,7 +886,7 @@
195 return_value=allocated_nodes_string) as co_mock:
196 ips = account.get_allocated_ips()
197 co_mock.assert_called_once_with(
198- ['maas', 'mas', 'nodes', 'list-allocated'])
199+ ('maas', 'mas', 'nodes', 'list-allocated'))
200 self.assertEqual({}, ips)
201
202

Subscribers

People subscribed via source and target branches