Merge lp:~stub/charm-helpers/integration into lp:charm-helpers
- integration
- Merge into devel
Status: | Merged |
---|---|
Merged at revision: | 371 |
Proposed branch: | lp:~stub/charm-helpers/integration |
Merge into: | lp:charm-helpers |
Diff against target: |
423 lines (+120/-37) 11 files modified
charmhelpers/contrib/peerstorage/__init__.py (+2/-0) charmhelpers/contrib/unison/__init__.py (+5/-4) charmhelpers/core/hookenv.py (+18/-4) charmhelpers/core/host.py (+1/-1) charmhelpers/core/services/base.py (+2/-2) charmhelpers/fetch/__init__.py (+1/-1) tests/contrib/peerstorage/test_peerstorage.py (+8/-0) tests/contrib/unison/test_unison.py (+7/-5) tests/core/test_hookenv.py (+51/-5) tests/core/test_services.py (+12/-0) tests/core/test_templating.py (+13/-15) |
To merge this branch: | bzr merge lp:~stub/charm-helpers/integration |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
This is an integration branch containing the last few months worth of outstanding merge proposals. If you review and land this, all my other outstanding ones will automatically get flagged as merged.
Or if you rather, review and land the smaller focused MPs which will leave this one empty.
https:/
https:/
https:/
https:/
https:/
https:/
https:/
Preview Diff
1 | === modified file 'charmhelpers/contrib/peerstorage/__init__.py' | |||
2 | --- charmhelpers/contrib/peerstorage/__init__.py 2015-01-22 06:06:03 +0000 | |||
3 | +++ charmhelpers/contrib/peerstorage/__init__.py 2015-04-29 13:11:45 +0000 | |||
4 | @@ -73,6 +73,8 @@ | |||
5 | 73 | exc_list = exc_list if exc_list else [] | 73 | exc_list = exc_list if exc_list else [] |
6 | 74 | peerdb_settings = peer_retrieve('-', relation_name=relation_name) | 74 | peerdb_settings = peer_retrieve('-', relation_name=relation_name) |
7 | 75 | matched = {} | 75 | matched = {} |
8 | 76 | if peerdb_settings is None: | ||
9 | 77 | return matched | ||
10 | 76 | for k, v in peerdb_settings.items(): | 78 | for k, v in peerdb_settings.items(): |
11 | 77 | full_prefix = prefix + delimiter | 79 | full_prefix = prefix + delimiter |
12 | 78 | if k.startswith(full_prefix): | 80 | if k.startswith(full_prefix): |
13 | 79 | 81 | ||
14 | === modified file 'charmhelpers/contrib/unison/__init__.py' | |||
15 | --- charmhelpers/contrib/unison/__init__.py 2015-01-28 22:09:21 +0000 | |||
16 | +++ charmhelpers/contrib/unison/__init__.py 2015-04-29 13:11:45 +0000 | |||
17 | @@ -63,6 +63,7 @@ | |||
18 | 63 | from charmhelpers.core.host import ( | 63 | from charmhelpers.core.host import ( |
19 | 64 | adduser, | 64 | adduser, |
20 | 65 | add_user_to_group, | 65 | add_user_to_group, |
21 | 66 | pwgen, | ||
22 | 66 | ) | 67 | ) |
23 | 67 | 68 | ||
24 | 68 | from charmhelpers.core.hookenv import ( | 69 | from charmhelpers.core.hookenv import ( |
25 | @@ -140,7 +141,7 @@ | |||
26 | 140 | ssh_dir = os.path.join(home_dir, '.ssh') | 141 | ssh_dir = os.path.join(home_dir, '.ssh') |
27 | 141 | auth_keys = os.path.join(ssh_dir, 'authorized_keys') | 142 | auth_keys = os.path.join(ssh_dir, 'authorized_keys') |
28 | 142 | log('Syncing authorized_keys @ %s.' % auth_keys) | 143 | log('Syncing authorized_keys @ %s.' % auth_keys) |
30 | 143 | with open(auth_keys, 'wb') as out: | 144 | with open(auth_keys, 'w') as out: |
31 | 144 | for k in keys: | 145 | for k in keys: |
32 | 145 | out.write('%s\n' % k) | 146 | out.write('%s\n' % k) |
33 | 146 | 147 | ||
34 | @@ -152,16 +153,16 @@ | |||
35 | 152 | khosts = [] | 153 | khosts = [] |
36 | 153 | for host in hosts: | 154 | for host in hosts: |
37 | 154 | cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host] | 155 | cmd = ['ssh-keyscan', '-H', '-t', 'rsa', host] |
39 | 155 | remote_key = check_output(cmd).strip() | 156 | remote_key = check_output(cmd, universal_newlines=True).strip() |
40 | 156 | khosts.append(remote_key) | 157 | khosts.append(remote_key) |
41 | 157 | log('Syncing known_hosts @ %s.' % known_hosts) | 158 | log('Syncing known_hosts @ %s.' % known_hosts) |
43 | 158 | with open(known_hosts, 'wb') as out: | 159 | with open(known_hosts, 'w') as out: |
44 | 159 | for host in khosts: | 160 | for host in khosts: |
45 | 160 | out.write('%s\n' % host) | 161 | out.write('%s\n' % host) |
46 | 161 | 162 | ||
47 | 162 | 163 | ||
48 | 163 | def ensure_user(user, group=None): | 164 | def ensure_user(user, group=None): |
50 | 164 | adduser(user) | 165 | adduser(user, pwgen()) |
51 | 165 | if group: | 166 | if group: |
52 | 166 | add_user_to_group(user, group) | 167 | add_user_to_group(user, group) |
53 | 167 | 168 | ||
54 | 168 | 169 | ||
55 | === modified file 'charmhelpers/core/hookenv.py' | |||
56 | --- charmhelpers/core/hookenv.py 2015-04-07 16:12:51 +0000 | |||
57 | +++ charmhelpers/core/hookenv.py 2015-04-29 13:11:45 +0000 | |||
58 | @@ -21,6 +21,7 @@ | |||
59 | 21 | # Charm Helpers Developers <juju@lists.ubuntu.com> | 21 | # Charm Helpers Developers <juju@lists.ubuntu.com> |
60 | 22 | 22 | ||
61 | 23 | from __future__ import print_function | 23 | from __future__ import print_function |
62 | 24 | from functools import wraps | ||
63 | 24 | import os | 25 | import os |
64 | 25 | import json | 26 | import json |
65 | 26 | import yaml | 27 | import yaml |
66 | @@ -58,15 +59,17 @@ | |||
67 | 58 | 59 | ||
68 | 59 | will cache the result of unit_get + 'test' for future calls. | 60 | will cache the result of unit_get + 'test' for future calls. |
69 | 60 | """ | 61 | """ |
70 | 62 | @wraps(func) | ||
71 | 61 | def wrapper(*args, **kwargs): | 63 | def wrapper(*args, **kwargs): |
72 | 62 | global cache | 64 | global cache |
73 | 63 | key = str((func, args, kwargs)) | 65 | key = str((func, args, kwargs)) |
74 | 64 | try: | 66 | try: |
75 | 65 | return cache[key] | 67 | return cache[key] |
76 | 66 | except KeyError: | 68 | except KeyError: |
80 | 67 | res = func(*args, **kwargs) | 69 | pass # Drop out of the exception handler scope. |
81 | 68 | cache[key] = res | 70 | res = func(*args, **kwargs) |
82 | 69 | return res | 71 | cache[key] = res |
83 | 72 | return res | ||
84 | 70 | return wrapper | 73 | return wrapper |
85 | 71 | 74 | ||
86 | 72 | 75 | ||
87 | @@ -178,7 +181,7 @@ | |||
88 | 178 | 181 | ||
89 | 179 | def remote_unit(): | 182 | def remote_unit(): |
90 | 180 | """The remote unit for the current relation hook""" | 183 | """The remote unit for the current relation hook""" |
92 | 181 | return os.environ['JUJU_REMOTE_UNIT'] | 184 | return os.environ.get('JUJU_REMOTE_UNIT', None) |
93 | 182 | 185 | ||
94 | 183 | 186 | ||
95 | 184 | def service_name(): | 187 | def service_name(): |
96 | @@ -250,6 +253,12 @@ | |||
97 | 250 | except KeyError: | 253 | except KeyError: |
98 | 251 | return (self._prev_dict or {})[key] | 254 | return (self._prev_dict or {})[key] |
99 | 252 | 255 | ||
100 | 256 | def get(self, key, default=None): | ||
101 | 257 | try: | ||
102 | 258 | return self[key] | ||
103 | 259 | except KeyError: | ||
104 | 260 | return default | ||
105 | 261 | |||
106 | 253 | def keys(self): | 262 | def keys(self): |
107 | 254 | prev_keys = [] | 263 | prev_keys = [] |
108 | 255 | if self._prev_dict is not None: | 264 | if self._prev_dict is not None: |
109 | @@ -509,6 +518,11 @@ | |||
110 | 509 | return None | 518 | return None |
111 | 510 | 519 | ||
112 | 511 | 520 | ||
113 | 521 | def unit_public_ip(): | ||
114 | 522 | """Get this unit's public IP address""" | ||
115 | 523 | return unit_get('public-address') | ||
116 | 524 | |||
117 | 525 | |||
118 | 512 | def unit_private_ip(): | 526 | def unit_private_ip(): |
119 | 513 | """Get this unit's private IP address""" | 527 | """Get this unit's private IP address""" |
120 | 514 | return unit_get('private-address') | 528 | return unit_get('private-address') |
121 | 515 | 529 | ||
122 | === modified file 'charmhelpers/core/host.py' | |||
123 | --- charmhelpers/core/host.py 2015-03-12 10:56:57 +0000 | |||
124 | +++ charmhelpers/core/host.py 2015-04-29 13:11:45 +0000 | |||
125 | @@ -90,7 +90,7 @@ | |||
126 | 90 | ['service', service_name, 'status'], | 90 | ['service', service_name, 'status'], |
127 | 91 | stderr=subprocess.STDOUT).decode('UTF-8') | 91 | stderr=subprocess.STDOUT).decode('UTF-8') |
128 | 92 | except subprocess.CalledProcessError as e: | 92 | except subprocess.CalledProcessError as e: |
130 | 93 | return 'unrecognized service' not in e.output | 93 | return b'unrecognized service' not in e.output |
131 | 94 | else: | 94 | else: |
132 | 95 | return True | 95 | return True |
133 | 96 | 96 | ||
134 | 97 | 97 | ||
135 | === modified file 'charmhelpers/core/services/base.py' | |||
136 | --- charmhelpers/core/services/base.py 2015-01-22 06:06:03 +0000 | |||
137 | +++ charmhelpers/core/services/base.py 2015-04-29 13:11:45 +0000 | |||
138 | @@ -17,7 +17,7 @@ | |||
139 | 17 | import os | 17 | import os |
140 | 18 | import re | 18 | import re |
141 | 19 | import json | 19 | import json |
143 | 20 | from collections import Iterable | 20 | from collections import Iterable, OrderedDict |
144 | 21 | 21 | ||
145 | 22 | from charmhelpers.core import host | 22 | from charmhelpers.core import host |
146 | 23 | from charmhelpers.core import hookenv | 23 | from charmhelpers.core import hookenv |
147 | @@ -119,7 +119,7 @@ | |||
148 | 119 | """ | 119 | """ |
149 | 120 | self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json') | 120 | self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json') |
150 | 121 | self._ready = None | 121 | self._ready = None |
152 | 122 | self.services = {} | 122 | self.services = OrderedDict() |
153 | 123 | for service in services or []: | 123 | for service in services or []: |
154 | 124 | service_name = service['service'] | 124 | service_name = service['service'] |
155 | 125 | self.services[service_name] = service | 125 | self.services[service_name] = service |
156 | 126 | 126 | ||
157 | === modified file 'charmhelpers/fetch/__init__.py' | |||
158 | --- charmhelpers/fetch/__init__.py 2015-01-22 06:11:15 +0000 | |||
159 | +++ charmhelpers/fetch/__init__.py 2015-04-29 13:11:45 +0000 | |||
160 | @@ -158,7 +158,7 @@ | |||
161 | 158 | 158 | ||
162 | 159 | def apt_cache(in_memory=True): | 159 | def apt_cache(in_memory=True): |
163 | 160 | """Build and return an apt cache""" | 160 | """Build and return an apt cache""" |
165 | 161 | import apt_pkg | 161 | from apt import apt_pkg |
166 | 162 | apt_pkg.init() | 162 | apt_pkg.init() |
167 | 163 | if in_memory: | 163 | if in_memory: |
168 | 164 | apt_pkg.config.set("Dir::Cache::pkgcache", "") | 164 | apt_pkg.config.set("Dir::Cache::pkgcache", "") |
169 | 165 | 165 | ||
170 | === modified file 'tests/contrib/peerstorage/test_peerstorage.py' | |||
171 | --- tests/contrib/peerstorage/test_peerstorage.py 2014-08-19 09:38:07 +0000 | |||
172 | +++ tests/contrib/peerstorage/test_peerstorage.py 2015-04-29 13:11:45 +0000 | |||
173 | @@ -146,6 +146,14 @@ | |||
174 | 146 | self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id), settings) | 146 | self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id), settings) |
175 | 147 | 147 | ||
176 | 148 | @patch.object(peerstorage, 'peer_retrieve') | 148 | @patch.object(peerstorage, 'peer_retrieve') |
177 | 149 | def test_peer_retrieve_by_prefix_empty_relation(self, peer_retrieve): | ||
178 | 150 | # If relation-get returns None, peer_retrieve_by_prefix returns | ||
179 | 151 | # an empty dictionary. | ||
180 | 152 | peer_retrieve.return_value = None | ||
181 | 153 | rel_id = 'db:2' | ||
182 | 154 | self.assertEquals(peerstorage.peer_retrieve_by_prefix(rel_id), {}) | ||
183 | 155 | |||
184 | 156 | @patch.object(peerstorage, 'peer_retrieve') | ||
185 | 149 | def test_peer_retrieve_by_prefix_exc_list(self, peer_retrieve): | 157 | def test_peer_retrieve_by_prefix_exc_list(self, peer_retrieve): |
186 | 150 | rel_id = 'db:2' | 158 | rel_id = 'db:2' |
187 | 151 | settings = { | 159 | settings = { |
188 | 152 | 160 | ||
189 | === modified file 'tests/contrib/unison/test_unison.py' | |||
190 | --- tests/contrib/unison/test_unison.py 2015-01-05 10:30:39 +0000 | |||
191 | +++ tests/contrib/unison/test_unison.py 2015-04-29 13:11:45 +0000 | |||
192 | @@ -1,5 +1,5 @@ | |||
193 | 1 | 1 | ||
195 | 2 | from mock import call, patch, MagicMock | 2 | from mock import call, patch, MagicMock, sentinel |
196 | 3 | from testtools import TestCase | 3 | from testtools import TestCase |
197 | 4 | 4 | ||
198 | 5 | from tests.helpers import patch_open, FakeRelation | 5 | from tests.helpers import patch_open, FakeRelation |
199 | @@ -146,7 +146,7 @@ | |||
200 | 146 | ] | 146 | ] |
201 | 147 | with patch_open() as (_open, _file): | 147 | with patch_open() as (_open, _file): |
202 | 148 | unison.write_authorized_keys('foo', keys) | 148 | unison.write_authorized_keys('foo', keys) |
204 | 149 | _open.assert_called_with('/home/foo/.ssh/authorized_keys', 'wb') | 149 | _open.assert_called_with('/home/foo/.ssh/authorized_keys', 'w') |
205 | 150 | for k in keys: | 150 | for k in keys: |
206 | 151 | self.assertIn(call('%s\n' % k), _file.write.call_args_list) | 151 | self.assertIn(call('%s\n' % k), _file.write.call_args_list) |
207 | 152 | 152 | ||
208 | @@ -160,15 +160,17 @@ | |||
209 | 160 | self.check_output.side_effect = keys | 160 | self.check_output.side_effect = keys |
210 | 161 | with patch_open() as (_open, _file): | 161 | with patch_open() as (_open, _file): |
211 | 162 | unison.write_known_hosts('foo', ['10.0.0.1', '10.0.0.2']) | 162 | unison.write_known_hosts('foo', ['10.0.0.1', '10.0.0.2']) |
213 | 163 | _open.assert_called_with('/home/foo/.ssh/known_hosts', 'wb') | 163 | _open.assert_called_with('/home/foo/.ssh/known_hosts', 'w') |
214 | 164 | for k in keys: | 164 | for k in keys: |
215 | 165 | self.assertIn(call('%s\n' % k), _file.write.call_args_list) | 165 | self.assertIn(call('%s\n' % k), _file.write.call_args_list) |
216 | 166 | 166 | ||
217 | 167 | @patch.object(unison, 'pwgen') | ||
218 | 167 | @patch.object(unison, 'add_user_to_group') | 168 | @patch.object(unison, 'add_user_to_group') |
219 | 168 | @patch.object(unison, 'adduser') | 169 | @patch.object(unison, 'adduser') |
221 | 169 | def test_ensure_user(self, adduser, to_group): | 170 | def test_ensure_user(self, adduser, to_group, pwgen): |
222 | 171 | pwgen.return_value = sentinel.password | ||
223 | 170 | unison.ensure_user('foo', group='foobar') | 172 | unison.ensure_user('foo', group='foobar') |
225 | 171 | adduser.assert_called_with('foo') | 173 | adduser.assert_called_with('foo', sentinel.password) |
226 | 172 | to_group.assert_called_with('foo', 'foobar') | 174 | to_group.assert_called_with('foo', 'foobar') |
227 | 173 | 175 | ||
228 | 174 | @patch.object(unison, '_run_as_user') | 176 | @patch.object(unison, '_run_as_user') |
229 | 175 | 177 | ||
230 | === modified file 'tests/core/test_hookenv.py' | |||
231 | --- tests/core/test_hookenv.py 2015-03-12 10:31:22 +0000 | |||
232 | +++ tests/core/test_hookenv.py 2015-04-29 13:11:45 +0000 | |||
233 | @@ -3,8 +3,7 @@ | |||
234 | 3 | from subprocess import CalledProcessError | 3 | from subprocess import CalledProcessError |
235 | 4 | import shutil | 4 | import shutil |
236 | 5 | import tempfile | 5 | import tempfile |
239 | 6 | from mock import patch, call, mock_open | 6 | from mock import call, MagicMock, mock_open, patch, sentinel |
238 | 7 | from mock import MagicMock | ||
240 | 8 | from testtools import TestCase | 7 | from testtools import TestCase |
241 | 9 | import yaml | 8 | import yaml |
242 | 10 | 9 | ||
243 | @@ -128,11 +127,47 @@ | |||
244 | 128 | self.assertEqual(c['foo'], 'bar') | 127 | self.assertEqual(c['foo'], 'bar') |
245 | 129 | self.assertEqual(c['baz'], 'bam') | 128 | self.assertEqual(c['baz'], 'bam') |
246 | 130 | 129 | ||
247 | 130 | def test_get(self): | ||
248 | 131 | c = hookenv.Config(dict(foo='bar')) | ||
249 | 132 | c.save() | ||
250 | 133 | c = hookenv.Config(dict(baz='bam')) | ||
251 | 134 | |||
252 | 135 | self.assertIsNone(c.get('missing')) | ||
253 | 136 | self.assertIs(c.get('missing', sentinel.missing), sentinel.missing) | ||
254 | 137 | self.assertEqual(c.get('foo'), 'bar') | ||
255 | 138 | self.assertEqual(c.get('baz'), 'bam') | ||
256 | 139 | |||
257 | 131 | def test_keys(self): | 140 | def test_keys(self): |
258 | 132 | c = hookenv.Config(dict(foo='bar')) | 141 | c = hookenv.Config(dict(foo='bar')) |
259 | 133 | c["baz"] = "bar" | 142 | c["baz"] = "bar" |
260 | 134 | self.assertEqual(sorted([six.u("foo"), "baz"]), sorted(c.keys())) | 143 | self.assertEqual(sorted([six.u("foo"), "baz"]), sorted(c.keys())) |
261 | 135 | 144 | ||
262 | 145 | def test_in(self): | ||
263 | 146 | # Test behavior of the in operator. | ||
264 | 147 | |||
265 | 148 | # Items that exist in the dict exist. Items that don't don't. | ||
266 | 149 | c = hookenv.Config(dict(foo='one')) | ||
267 | 150 | self.assertTrue('foo' in c) | ||
268 | 151 | self.assertTrue('bar' not in c) | ||
269 | 152 | c.save() | ||
270 | 153 | self.assertTrue('foo' in c) | ||
271 | 154 | self.assertTrue('bar' not in c) | ||
272 | 155 | |||
273 | 156 | # Adding items works as expected. | ||
274 | 157 | c['foo'] = 'two' | ||
275 | 158 | c['bar'] = 'two' | ||
276 | 159 | self.assertTrue('foo' in c) | ||
277 | 160 | self.assertTrue('bar' in c) | ||
278 | 161 | c.save() | ||
279 | 162 | self.assertTrue('foo' in c) | ||
280 | 163 | self.assertTrue('bar' in c) | ||
281 | 164 | |||
282 | 165 | # Removing items works as expected. | ||
283 | 166 | del c['foo'] | ||
284 | 167 | self.assertTrue('foo' not in c) | ||
285 | 168 | c.save() | ||
286 | 169 | self.assertTrue('foo' not in c) | ||
287 | 170 | |||
288 | 136 | 171 | ||
289 | 137 | class SerializableTest(TestCase): | 172 | class SerializableTest(TestCase): |
290 | 138 | def test_serializes_object_to_json(self): | 173 | def test_serializes_object_to_json(self): |
291 | @@ -298,10 +333,16 @@ | |||
292 | 298 | self.assertEqual(hookenv.local_unit(), 'foo') | 333 | self.assertEqual(hookenv.local_unit(), 'foo') |
293 | 299 | 334 | ||
294 | 300 | @patch('charmhelpers.core.hookenv.unit_get') | 335 | @patch('charmhelpers.core.hookenv.unit_get') |
295 | 336 | def test_gets_unit_public_ip(self, _unitget): | ||
296 | 337 | _unitget.return_value = sentinel.public_ip | ||
297 | 338 | self.assertEqual(sentinel.public_ip, hookenv.unit_public_ip()) | ||
298 | 339 | _unitget.assert_called_once_with('public-address') | ||
299 | 340 | |||
300 | 341 | @patch('charmhelpers.core.hookenv.unit_get') | ||
301 | 301 | def test_gets_unit_private_ip(self, _unitget): | 342 | def test_gets_unit_private_ip(self, _unitget): |
305 | 302 | _unitget.return_value = 'foo' | 343 | _unitget.return_value = sentinel.private_ip |
306 | 303 | self.assertEqual("foo", hookenv.unit_private_ip()) | 344 | self.assertEqual(sentinel.private_ip, hookenv.unit_private_ip()) |
307 | 304 | _unitget.assert_called_with('private-address') | 345 | _unitget.assert_called_once_with('private-address') |
308 | 305 | 346 | ||
309 | 306 | @patch('charmhelpers.core.hookenv.os') | 347 | @patch('charmhelpers.core.hookenv.os') |
310 | 307 | def test_checks_that_is_running_in_relation_hook(self, os_): | 348 | def test_checks_that_is_running_in_relation_hook(self, os_): |
311 | @@ -447,6 +488,11 @@ | |||
312 | 447 | 488 | ||
313 | 448 | self.assertEqual(hookenv.remote_unit(), 'foo') | 489 | self.assertEqual(hookenv.remote_unit(), 'foo') |
314 | 449 | 490 | ||
315 | 491 | @patch('charmhelpers.core.hookenv.os') | ||
316 | 492 | def test_no_remote_unit(self, os_): | ||
317 | 493 | os_.environ = {} | ||
318 | 494 | self.assertEqual(hookenv.remote_unit(), None) | ||
319 | 495 | |||
320 | 450 | @patch('charmhelpers.core.hookenv.remote_unit') | 496 | @patch('charmhelpers.core.hookenv.remote_unit') |
321 | 451 | @patch('charmhelpers.core.hookenv.relation_get') | 497 | @patch('charmhelpers.core.hookenv.relation_get') |
322 | 452 | def test_gets_relation_for_unit(self, relation_get, remote_unit): | 498 | def test_gets_relation_for_unit(self, relation_get, remote_unit): |
323 | 453 | 499 | ||
324 | === modified file 'tests/core/test_services.py' | |||
325 | --- tests/core/test_services.py 2015-03-19 15:00:13 +0000 | |||
326 | +++ tests/core/test_services.py 2015-04-29 13:11:45 +0000 | |||
327 | @@ -27,6 +27,18 @@ | |||
328 | 27 | 'qux': 'baz'}, | 27 | 'qux': 'baz'}, |
329 | 28 | }) | 28 | }) |
330 | 29 | 29 | ||
331 | 30 | def test_register_preserves_order(self): | ||
332 | 31 | service_list = [dict(service='a'), dict(service='b')] | ||
333 | 32 | |||
334 | 33 | # Test that the services list order is preserved by checking | ||
335 | 34 | # both forwards and backwards - only one of these will be | ||
336 | 35 | # dictionary order, and if both work we know order is being | ||
337 | 36 | # preserved. | ||
338 | 37 | manager = services.ServiceManager(service_list) | ||
339 | 38 | self.assertEqual(list(manager.services.keys()), ['a', 'b']) | ||
340 | 39 | manager = services.ServiceManager(reversed(service_list)) | ||
341 | 40 | self.assertEqual(list(manager.services.keys()), ['b', 'a']) | ||
342 | 41 | |||
343 | 30 | @mock.patch.object(services.ServiceManager, 'reconfigure_services') | 42 | @mock.patch.object(services.ServiceManager, 'reconfigure_services') |
344 | 31 | @mock.patch.object(services.ServiceManager, 'stop_services') | 43 | @mock.patch.object(services.ServiceManager, 'stop_services') |
345 | 32 | @mock.patch.object(hookenv, 'hook_name') | 44 | @mock.patch.object(hookenv, 'hook_name') |
346 | 33 | 45 | ||
347 | === modified file 'tests/core/test_templating.py' | |||
348 | --- tests/core/test_templating.py 2015-02-03 21:52:36 +0000 | |||
349 | +++ tests/core/test_templating.py 2015-04-29 13:11:45 +0000 | |||
350 | @@ -1,9 +1,9 @@ | |||
351 | 1 | import os | ||
352 | 2 | import pkg_resources | 1 | import pkg_resources |
353 | 3 | import shutil | 2 | import shutil |
354 | 4 | import tempfile | 3 | import tempfile |
355 | 5 | import unittest | 4 | import unittest |
356 | 6 | import jinja2 | 5 | import jinja2 |
357 | 6 | import os.path | ||
358 | 7 | import pwd | 7 | import pwd |
359 | 8 | import grp | 8 | import grp |
360 | 9 | 9 | ||
361 | @@ -17,7 +17,8 @@ | |||
362 | 17 | class TestTemplating(unittest.TestCase): | 17 | class TestTemplating(unittest.TestCase): |
363 | 18 | def setUp(self): | 18 | def setUp(self): |
364 | 19 | self.charm_dir = pkg_resources.resource_filename(__name__, '') | 19 | self.charm_dir = pkg_resources.resource_filename(__name__, '') |
366 | 20 | self._charm_dir_patch = mock.patch.object(templating.hookenv, 'charm_dir') | 20 | self._charm_dir_patch = mock.patch.object(templating.hookenv, |
367 | 21 | 'charm_dir') | ||
368 | 21 | self._charm_dir_mock = self._charm_dir_patch.start() | 22 | self._charm_dir_mock = self._charm_dir_patch.start() |
369 | 22 | self._charm_dir_mock.side_effect = lambda: self.charm_dir | 23 | self._charm_dir_mock.side_effect = lambda: self.charm_dir |
370 | 23 | 24 | ||
371 | @@ -28,9 +29,8 @@ | |||
372 | 28 | @mock.patch.object(templating.host, 'mkdir') | 29 | @mock.patch.object(templating.host, 'mkdir') |
373 | 29 | @mock.patch.object(templating.host, 'log') | 30 | @mock.patch.object(templating.host, 'log') |
374 | 30 | def test_render(self, log, mkdir, fchown): | 31 | def test_render(self, log, mkdir, fchown): |
378 | 31 | _, fn1 = tempfile.mkstemp() | 32 | with tempfile.NamedTemporaryFile() as fn1, \ |
379 | 32 | _, fn2 = tempfile.mkstemp() | 33 | tempfile.NamedTemporaryFile() as fn2: |
377 | 33 | try: | ||
380 | 34 | context = { | 34 | context = { |
381 | 35 | 'nats': { | 35 | 'nats': { |
382 | 36 | 'port': '1234', | 36 | 'port': '1234', |
383 | @@ -41,23 +41,19 @@ | |||
384 | 41 | }, | 41 | }, |
385 | 42 | 'nginx_port': 80, | 42 | 'nginx_port': 80, |
386 | 43 | } | 43 | } |
388 | 44 | templating.render('fake_cc.yml', fn1, | 44 | templating.render('fake_cc.yml', fn1.name, |
389 | 45 | context, templates_dir=TEMPLATES_DIR) | 45 | context, templates_dir=TEMPLATES_DIR) |
391 | 46 | contents = open(fn1).read() | 46 | contents = open(fn1.name).read() |
392 | 47 | self.assertRegexpMatches(contents, 'port: 1234') | 47 | self.assertRegexpMatches(contents, 'port: 1234') |
393 | 48 | self.assertRegexpMatches(contents, 'host: example.com') | 48 | self.assertRegexpMatches(contents, 'host: example.com') |
394 | 49 | self.assertRegexpMatches(contents, 'domain: api.foo.com') | 49 | self.assertRegexpMatches(contents, 'domain: api.foo.com') |
395 | 50 | 50 | ||
397 | 51 | templating.render('test.conf', fn2, context, | 51 | templating.render('test.conf', fn2.name, context, |
398 | 52 | templates_dir=TEMPLATES_DIR) | 52 | templates_dir=TEMPLATES_DIR) |
400 | 53 | contents = open(fn2).read() | 53 | contents = open(fn2.name).read() |
401 | 54 | self.assertRegexpMatches(contents, 'listen 80') | 54 | self.assertRegexpMatches(contents, 'listen 80') |
402 | 55 | self.assertEqual(fchown.call_count, 2) | 55 | self.assertEqual(fchown.call_count, 2) |
403 | 56 | self.assertEqual(mkdir.call_count, 2) | 56 | self.assertEqual(mkdir.call_count, 2) |
404 | 57 | finally: | ||
405 | 58 | for fn in (fn1, fn2): | ||
406 | 59 | if os.path.exists(fn): | ||
407 | 60 | os.remove(fn) | ||
408 | 61 | 57 | ||
409 | 62 | @mock.patch.object(templating.host.os, 'fchown') | 58 | @mock.patch.object(templating.host.os, 'fchown') |
410 | 63 | @mock.patch.object(templating.host, 'log') | 59 | @mock.patch.object(templating.host, 'log') |
411 | @@ -80,8 +76,10 @@ | |||
412 | 80 | @mock.patch.object(templating, 'hookenv') | 76 | @mock.patch.object(templating, 'hookenv') |
413 | 81 | @mock.patch('jinja2.Environment') | 77 | @mock.patch('jinja2.Environment') |
414 | 82 | def test_load_error(self, Env, hookenv): | 78 | def test_load_error(self, Env, hookenv): |
416 | 83 | Env().get_template.side_effect = jinja2.exceptions.TemplateNotFound('fake_cc.yml') | 79 | Env().get_template.side_effect = jinja2.exceptions.TemplateNotFound( |
417 | 80 | 'fake_cc.yml') | ||
418 | 84 | self.assertRaises( | 81 | self.assertRaises( |
419 | 85 | jinja2.exceptions.TemplateNotFound, templating.render, | 82 | jinja2.exceptions.TemplateNotFound, templating.render, |
420 | 86 | 'fake.src', 'fake.tgt', {}, templates_dir='tmpl') | 83 | 'fake.src', 'fake.tgt', {}, templates_dir='tmpl') |
422 | 87 | hookenv.log.assert_called_once_with('Could not load template fake.src from tmpl.', level=hookenv.ERROR) | 84 | hookenv.log.assert_called_once_with( |
423 | 85 | 'Could not load template fake.src from tmpl.', level=hookenv.ERROR) |
Approve