Merge lp:~yolanda.robla/charms/precise/keystone/unit_testing into lp:~openstack-charmers/charms/precise/keystone/icehouse

Proposed by Yolanda Robla
Status: Merged
Merged at revision: 79
Proposed branch: lp:~yolanda.robla/charms/precise/keystone/unit_testing
Merge into: lp:~openstack-charmers/charms/precise/keystone/icehouse
Diff against target: 653 lines (+579/-5)
3 files modified
unit_tests/test_keystone_contexts.py (+70/-0)
unit_tests/test_keystone_hooks.py (+251/-5)
unit_tests/test_keystone_utils.py (+258/-0)
To merge this branch: bzr merge lp:~yolanda.robla/charms/precise/keystone/unit_testing
Reviewer Review Type Date Requested Status
James Page Needs Fixing
Review via email: mp+214009@code.launchpad.net

Description of the change

Added unit testing

To post a comment you must log in.
Revision history for this message
James Page (james-page) wrote :
Download full text (6.9 KiB)

You need to mock out get_local_endpoint:

======================================================================
ERROR: test_add_service_to_keystone_clustered_https_none_values (unit_tests.test_keystone_utils.TestKeystoneUtils)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/mock.py", line 1210, in patched
    return func(*args, **keywargs)
  File "/home/jamespage/src/charms/icehouse/keystone/unit_tests/test_keystone_utils.py", line 158, in test_add_service_to_keystone_clustered_https_none_values
    utils.add_service_to_keystone(relation_id=relation_id, remote_unit=remote_unit)
  File "hooks/keystone_utils.py", line 608, in add_service_to_keystone
    manager = manager.KeystoneManager(endpoint=get_local_endpoint(),
  File "hooks/keystone_utils.py", line 272, in get_local_endpoint
    determine_api_port(api_port('keystone-admin'))
  File "hooks/charmhelpers/contrib/hahelpers/cluster.py", line 122, in determine_api_port
    if len(peer_units()) > 0 or is_clustered():
  File "hooks/charmhelpers/contrib/hahelpers/cluster.py", line 59, in peer_units
    for r_id in (relation_ids('cluster') or []):
  File "hooks/charmhelpers/core/hookenv.py", line 44, in wrapper
    res = func(*args, **kwargs)
  File "hooks/charmhelpers/core/hookenv.py", line 213, in relation_ids
    return json.loads(subprocess.check_output(relid_cmd_line)) or []
  File "/usr/lib/python2.7/subprocess.py", line 566, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

======================================================================
ERROR: test_add_service_to_keystone_no_clustered_no_https_complete_values (unit_tests.test_keystone_utils.TestKeystoneUtils)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/mock.py", line 1210, in patched
    return func(*args, **keywargs)
  File "/home/jamespage/src/charms/icehouse/keystone/unit_tests/test_keystone_utils.py", line 196, in test_add_service_to_keystone_no_clustered_no_https_complete_values
    utils.add_service_to_keystone(relation_id=relation_id, remote_unit=remote_unit)
  File "hooks/keystone_utils.py", line 608, in add_service_to_keystone
    manager = manager.KeystoneManager(endpoint=get_local_endpoint(),
  File "hooks/keystone_utils.py", line 272, in get_local_endpoint
    determine_api_port(api_port('keystone-admin'))
  File "hooks/charmhelpers/contrib/hahelpers/cluster.py", line 122, in determine_api_port
    if len(peer_units()) > 0 or is_clustered():
  File "hooks/charmhelpers/contrib/hahelpers/cluster.py", line 59, in peer_units
    for r_id in (relation_ids('cluster') or []):
  File "hooks/charmhelpers/core/hookenv.py", line 44, in wrapper
    res = func(*args, **kwargs)
  File "hooks/charmhelpers/core/hookenv.py", line 213, in relation_ids
    return json.loads(subprocess.check_ou...

Read more...

review: Needs Fixing
79. By Yolanda Robla

mocking extra calls

80. By Yolanda Robla

mocking keystone manager

81. By Yolanda Robla

fixing tests for latest changes

Revision history for this message
James Page (james-page) wrote :

Looking better; one further comment - Mocks don't have an "assert_called()" method; this works because its a mock but actually fails to check anything - use :

   self.assertTrue(self.<function>.called).

I see a few instances of this throughout the tests.

review: Needs Fixing
82. By Yolanda Robla

changing assert_called

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'unit_tests/test_keystone_contexts.py'
2--- unit_tests/test_keystone_contexts.py 1970-01-01 00:00:00 +0000
3+++ unit_tests/test_keystone_contexts.py 2014-04-04 12:26:02 +0000
4@@ -0,0 +1,70 @@
5+import keystone_context as context
6+from mock import patch
7+
8+with patch('charmhelpers.core.hookenv.config') as config:
9+ config.return_value = 'keystone'
10+ import keystone_utils as utils
11+
12+from test_utils import (
13+ CharmTestCase
14+)
15+
16+TO_PATCH = [
17+ 'determine_apache_port',
18+ 'determine_api_port',
19+]
20+
21+
22+class TestKeystoneContexts(CharmTestCase):
23+
24+ def setUp(self):
25+ super(TestKeystoneContexts, self).setUp(context, TO_PATCH)
26+
27+ @patch('charmhelpers.contrib.openstack.context.is_clustered')
28+ @patch('charmhelpers.contrib.openstack.context.determine_apache_port')
29+ @patch('charmhelpers.contrib.openstack.context.determine_api_port')
30+ @patch('charmhelpers.contrib.openstack.context.unit_get')
31+ @patch('charmhelpers.contrib.openstack.context.https')
32+ def test_apache_ssl_context_service_enabled(self, mock_https,
33+ mock_unit_get,
34+ mock_determine_api_port,
35+ mock_determine_apache_port,
36+ mock_is_clustered):
37+ mock_https.return_value = True
38+ mock_unit_get.return_value = '1.2.3.4'
39+ mock_determine_api_port.return_value = '12'
40+ mock_determine_apache_port.return_value = '34'
41+ mock_is_clustered.return_value = False
42+
43+ ctxt = context.ApacheSSLContext()
44+ with patch.object(ctxt, 'enable_modules') as mock_enable_modules:
45+ with patch.object(ctxt, 'configure_cert') as mock_configure_cert:
46+ self.assertEquals(ctxt(), {'endpoints': [(34, 12)],
47+ 'private_address': '1.2.3.4',
48+ 'namespace': 'keystone'})
49+ self.assertTrue(mock_https.called)
50+ mock_unit_get.assert_called_with('private-address')
51+
52+ @patch('charmhelpers.contrib.openstack.context.relation_ids')
53+ @patch('charmhelpers.contrib.openstack.context.unit_get')
54+ @patch('charmhelpers.contrib.openstack.context.related_units')
55+ @patch('charmhelpers.contrib.openstack.context.relation_get')
56+ @patch('charmhelpers.contrib.openstack.context.log')
57+ @patch('__builtin__.open')
58+ def test_haproxy_context_service_enabled(self, mock_open, mock_log, mock_relation_get, mock_related_units,
59+ mock_unit_get, mock_relation_ids):
60+ mock_relation_ids.return_value = ['identity-service:0',]
61+ mock_unit_get.return_value = '1.2.3.4'
62+ mock_relation_get.return_value = '10.0.0.0'
63+ mock_related_units.return_value = ['unit/0',]
64+ self.determine_apache_port.return_value = '34'
65+
66+ ctxt = context.HAProxyContext()
67+
68+ self.assertEquals(ctxt(), {'listen_ports': {'admin_port': 'keystone', 'public_port': 'keystone'},
69+ 'service_ports': {'admin-port': ['keystone', '34'],
70+ 'public-port': ['keystone', '34']},
71+ 'units': {'keystone': '1.2.3.4', 'unit-0':'10.0.0.0'}})
72+ mock_unit_get.assert_called_with('private-address')
73+ mock_relation_get.assert_called_with('private-address', rid='identity-service:0', unit='unit/0')
74+ mock_open.assert_called_with('/etc/default/haproxy', 'w')
75
76=== modified file 'unit_tests/test_keystone_hooks.py'
77--- unit_tests/test_keystone_hooks.py 2014-03-31 08:35:19 +0000
78+++ unit_tests/test_keystone_hooks.py 2014-04-04 12:26:02 +0000
79@@ -15,6 +15,7 @@
80 utils.restart_map = MagicMock()
81
82 import keystone_hooks as hooks
83+from charmhelpers.contrib import unison
84
85 utils.register_configs = _reg
86 utils.restart_map = _map
87@@ -25,10 +26,14 @@
88 'config',
89 'is_relation_made',
90 'log',
91+ 'filter_installed_packages',
92 'relation_ids',
93+ 'relation_list',
94 'relation_set',
95 'relation_get',
96+ 'related_units',
97 'unit_get',
98+ 'peer_echo',
99 # charmhelpers.core.host
100 'apt_install',
101 'apt_update',
102@@ -41,11 +46,20 @@
103 'restart_map',
104 'register_configs',
105 'do_openstack_upgrade',
106+ 'openstack_upgrade_available',
107+ 'save_script_rc',
108 'migrate_database',
109+ 'ensure_initial_admin',
110+ 'add_service_to_keystone',
111+ 'synchronize_ca',
112+ 'get_hacluster_config',
113+ 'is_leader',
114 # other
115 'check_call',
116 'execd_preinstall',
117- 'mkdir'
118+ 'mkdir',
119+ 'os',
120+ 'time',
121 ]
122
123
124@@ -54,7 +68,18 @@
125 def setUp(self):
126 super(KeystoneRelationTests, self).setUp(hooks, TO_PATCH)
127 self.config.side_effect = self.test_config.get
128+ self.ssh_user = 'juju_keystone'
129
130+ def test_install_hook(self):
131+ repo = 'cloud:precise-grizzly'
132+ self.test_config.set('openstack-origin', repo)
133+ hooks.install()
134+ self.configure_installation_source.assert_called_with(repo)
135+ self.assertTrue(self.apt_update.called)
136+ self.apt_install.assert_called_with(['haproxy', 'unison', 'python-keystoneclient',
137+ 'uuid', 'python-mysqldb', 'openssl', 'apache2',
138+ 'pwgen', 'keystone', 'python-psycopg2'], fatal=True)
139+ self.assertTrue(self.execd_preinstall.called)
140
141 def test_db_joined(self):
142 self.unit_get.return_value = 'keystone.foohost.com'
143@@ -76,18 +101,20 @@
144
145 with self.assertRaises(Exception) as context:
146 hooks.db_joined()
147- self.assertEqual(context.exception.message,
148+ self.assertEqual(
149+ context.exception.message,
150 'Attempting to associate a mysql database when there '
151- 'is already associated a postgresql one')
152+ 'is already associated a postgresql one')
153
154 def test_postgresql_joined_with_db(self):
155 self.is_relation_made.return_value = True
156
157 with self.assertRaises(Exception) as context:
158 hooks.pgsql_db_joined()
159- self.assertEqual(context.exception.message,
160+ self.assertEqual(
161+ context.exception.message,
162 'Attempting to associate a postgresql database when there '
163- 'is already associated a mysql one')
164+ 'is already associated a mysql one')
165
166 @patch.object(hooks, 'CONFIGS')
167 def test_db_changed_missing_relation_data(self, configs):
168@@ -118,3 +145,222 @@
169 configs.complete_contexts.return_value = ['pgsql-db']
170 configs.write = MagicMock()
171 hooks.pgsql_db_changed()
172+
173+ @patch.object(hooks, 'CONFIGS')
174+ @patch.object(hooks, 'identity_changed')
175+ def test_db_changed(self, identity_changed, configs):
176+ self.relation_ids.return_value = ['identity-service:0']
177+ self.related_units.return_value = ['unit/0']
178+
179+ self._shared_db_test(configs)
180+ self.assertEquals([call('/etc/keystone/keystone.conf')],
181+ configs.write.call_args_list)
182+ self.migrate_database.assert_called_with()
183+ self.assertTrue(self.ensure_initial_admin.called)
184+ identity_changed.assert_called_with(relation_id='identity-service:0', remote_unit='unit/0')
185+
186+ @patch.object(hooks, 'CONFIGS')
187+ @patch.object(hooks, 'identity_changed')
188+ def test_postgresql_db_changed(self, identity_changed, configs):
189+ self.relation_ids.return_value = ['identity-service:0']
190+ self.related_units.return_value = ['unit/0']
191+
192+ self._postgresql_db_test(configs)
193+ self.assertEquals([call('/etc/keystone/keystone.conf')],
194+ configs.write.call_args_list)
195+ self.migrate_database.assert_called_with()
196+ self.assertTrue(self.ensure_initial_admin.called)
197+ identity_changed.assert_called_with(relation_id='identity-service:0', remote_unit='unit/0')
198+
199+ @patch.object(unison, 'ensure_user')
200+ @patch.object(unison, 'get_homedir')
201+ @patch.object(hooks, 'CONFIGS')
202+ @patch.object(hooks, 'identity_changed')
203+ @patch.object(hooks, 'configure_https')
204+ def test_config_changed_no_openstack_upgrade_leader(self, configure_https, identity_changed, configs, get_homedir, ensure_user):
205+ self.openstack_upgrade_available.return_value = False
206+ self.eligible_leader.return_value = True
207+ self.relation_ids.return_value = ['identity-service:0']
208+ self.relation_list.return_value = ['unit/0']
209+
210+ hooks.config_changed()
211+ ensure_user.assert_called_with(user=self.ssh_user, group='keystone')
212+ get_homedir.assert_called_with(self.ssh_user)
213+
214+ self.save_script_rc.assert_called_with()
215+ configure_https.assert_called_with()
216+ self.assertTrue(configs.write_all.called)
217+
218+ self.migrate_database.assert_called_with()
219+ self.assertTrue(self.ensure_initial_admin.called)
220+ self.log.assert_called_with('Firing identity_changed hook for all related services.')
221+ identity_changed.assert_called_with(relation_id='identity-service:0', remote_unit='unit/0')
222+
223+ @patch.object(unison, 'ensure_user')
224+ @patch.object(unison, 'get_homedir')
225+ @patch.object(hooks, 'CONFIGS')
226+ @patch.object(hooks, 'identity_changed')
227+ @patch.object(hooks, 'configure_https')
228+ def test_config_changed_no_openstack_upgrade_not_leader(self, configure_https, identity_changed, configs, get_homedir, ensure_user):
229+ self.openstack_upgrade_available.return_value = False
230+ self.eligible_leader.return_value = False
231+
232+ hooks.config_changed()
233+ ensure_user.assert_called_with(user=self.ssh_user, group='keystone')
234+ get_homedir.assert_called_with(self.ssh_user)
235+
236+ self.save_script_rc.assert_called_with()
237+ configure_https.assert_called_with()
238+ self.assertTrue(configs.write_all.called)
239+
240+ self.assertFalse(self.migrate_database.called)
241+ self.assertFalse(self.ensure_initial_admin.called)
242+ self.assertFalse(identity_changed.called)
243+
244+ @patch.object(unison, 'ensure_user')
245+ @patch.object(unison, 'get_homedir')
246+ @patch.object(hooks, 'CONFIGS')
247+ @patch.object(hooks, 'identity_changed')
248+ @patch.object(hooks, 'configure_https')
249+ def test_config_changed_with_openstack_upgrade(self, configure_https, identity_changed, configs, get_homedir, ensure_user):
250+ self.openstack_upgrade_available.return_value = True
251+ self.eligible_leader.return_value = True
252+ self.relation_ids.return_value = ['identity-service:0']
253+ self.relation_list.return_value = ['unit/0']
254+
255+ hooks.config_changed()
256+ ensure_user.assert_called_with(user=self.ssh_user, group='keystone')
257+ get_homedir.assert_called_with(self.ssh_user)
258+
259+ self.assertTrue(self.do_openstack_upgrade.called)
260+
261+ self.save_script_rc.assert_called_with()
262+ configure_https.assert_called_with()
263+ self.assertTrue(configs.write_all.called)
264+
265+ self.migrate_database.assert_called_with()
266+ self.assertTrue(self.ensure_initial_admin.called)
267+ self.log.assert_called_with('Firing identity_changed hook for all related services.')
268+ identity_changed.assert_called_with(relation_id='identity-service:0', remote_unit='unit/0')
269+
270+ def test_identity_changed_leader(self):
271+ self.eligible_leader.return_value = True
272+ hooks.identity_changed(relation_id='identity-service:0', remote_unit='unit/0')
273+ self.add_service_to_keystone.assert_called_with('identity-service:0', 'unit/0')
274+ self.assertTrue(self.synchronize_ca.called)
275+
276+ def test_identity_changed_no_leader(self):
277+ self.eligible_leader.return_value = False
278+ hooks.identity_changed(relation_id='identity-service:0', remote_unit='unit/0')
279+ self.assertFalse(self.add_service_to_keystone.called)
280+ self.log.assert_called_with('Deferring identity_changed() to service leader.')
281+
282+ @patch.object(unison, 'ssh_authorized_peers')
283+ def test_cluster_joined(self, ssh_authorized_peers):
284+ hooks.cluster_joined()
285+ ssh_authorized_peers.assert_called_with(user=self.ssh_user, group='juju_keystone',
286+ peer_interface='cluster', ensure_local_user=True)
287+
288+ @patch.object(unison, 'ssh_authorized_peers')
289+ @patch.object(hooks, 'CONFIGS')
290+ def test_cluster_changed(self, configs, ssh_authorized_peers):
291+ hooks.cluster_changed()
292+ self.peer_echo.assert_called_with(includes=['_passwd'])
293+ ssh_authorized_peers.assert_called_with(user=self.ssh_user, group='keystone',
294+ peer_interface='cluster', ensure_local_user=True)
295+ self.assertTrue(self.synchronize_ca.called)
296+ self.assertTrue(configs.write_all.called)
297+
298+ def test_ha_joined(self):
299+ self.get_hacluster_config.return_value = {
300+ 'ha-bindiface': 'em0',
301+ 'ha-mcastport': '8080',
302+ 'vip': '10.10.10.10',
303+ 'vip_iface': 'em1',
304+ 'vip_cidr': '24'
305+ }
306+ hooks.ha_joined()
307+ self.assertTrue(self.get_hacluster_config.called)
308+ args = {
309+ 'corosync_bindiface': 'em0',
310+ 'corosync_mcastport': '8080',
311+ 'init_services': {'res_ks_haproxy': 'haproxy'},
312+ 'resources': {'res_ks_vip': 'ocf:heartbeat:IPaddr2',
313+ 'res_ks_haproxy': 'lsb:haproxy'},
314+ 'resource_params': {
315+ 'res_ks_vip': 'params ip="10.10.10.10"'
316+ ' cidr_netmask="24" nic="em1"',
317+ 'res_ks_haproxy': 'op monitor interval="5s"'},
318+ 'clones': {'cl_ks_haproxy': 'res_ks_haproxy'}
319+ }
320+ self.relation_set.assert_called_with(**args)
321+
322+ @patch.object(hooks, 'CONFIGS')
323+ def test_ha_relation_changed_not_clustered_not_leader(self, configs):
324+ self.relation_get.return_value = False
325+ self.is_leader.return_value = False
326+
327+ hooks.ha_changed()
328+ self.assertTrue(configs.write_all.called)
329+
330+ @patch.object(hooks, 'CONFIGS')
331+ def test_ha_relation_changed_clustered_leader(self, configs):
332+ self.relation_get.return_value = True
333+ self.is_leader.return_value = True
334+ self.relation_ids.return_value = ['identity-service:0']
335+ self.test_config.set('vip', '10.10.10.10')
336+
337+ hooks.ha_changed()
338+ self.assertTrue(configs.write_all.called)
339+ self.log.assert_called_with('Cluster configured, notifying other services and updating '
340+ 'keystone endpoint configuration')
341+ self.relation_set.assert_called_with(relation_id='identity-service:0',
342+ auth_host='10.10.10.10',
343+ service_host='10.10.10.10')
344+
345+ @patch.object(hooks, 'CONFIGS')
346+ def test_configure_https_enable(self, configs):
347+ configs.complete_contexts = MagicMock()
348+ configs.complete_contexts.return_value = ['https']
349+ configs.write = MagicMock()
350+
351+ hooks.configure_https()
352+ self.assertTrue(configs.write_all.called)
353+ cmd = ['a2ensite', 'openstack_https_frontend']
354+ self.check_call.assert_called_with(cmd)
355+
356+ @patch.object(hooks, 'CONFIGS')
357+ def test_configure_https_disable(self, configs):
358+ configs.complete_contexts = MagicMock()
359+ configs.complete_contexts.return_value = ['']
360+ configs.write = MagicMock()
361+
362+ hooks.configure_https()
363+ self.assertTrue(configs.write_all.called)
364+ cmd = ['a2dissite', 'openstack_https_frontend']
365+ self.check_call.assert_called_with(cmd)
366+
367+ @patch.object(unison, 'ssh_authorized_peers')
368+ def test_upgrade_charm_leader(self, ssh_authorized_peers):
369+ self.eligible_leader.return_value = True
370+ self.filter_installed_packages.return_value = []
371+ hooks.upgrade_charm()
372+ self.assertTrue(self.apt_install.called)
373+ ssh_authorized_peers.assert_called_with(user=self.ssh_user, group='keystone',
374+ peer_interface='cluster', ensure_local_user=True)
375+ self.assertTrue(self.synchronize_ca.called)
376+ self.log.assert_called_with('Cluster leader - ensuring endpoint configuration'
377+ ' is up to date')
378+ self.assertTrue(self.ensure_initial_admin.called)
379+
380+ @patch.object(unison, 'ssh_authorized_peers')
381+ def test_upgrade_charm_not_leader(self, ssh_authorized_peers):
382+ self.eligible_leader.return_value = False
383+ self.filter_installed_packages.return_value = []
384+ hooks.upgrade_charm()
385+ self.assertTrue(self.apt_install.called)
386+ ssh_authorized_peers.assert_called_with(user=self.ssh_user, group='keystone',
387+ peer_interface='cluster', ensure_local_user=True)
388+ self.assertTrue(self.synchronize_ca.called)
389+ self.assertFalse(self.log.called)
390+ self.assertFalse(self.ensure_initial_admin.called)
391
392=== added file 'unit_tests/test_keystone_utils.py'
393--- unit_tests/test_keystone_utils.py 1970-01-01 00:00:00 +0000
394+++ unit_tests/test_keystone_utils.py 2014-04-04 12:26:02 +0000
395@@ -0,0 +1,258 @@
396+from mock import patch, call, MagicMock
397+from test_utils import CharmTestCase
398+from copy import deepcopy
399+
400+from collections import OrderedDict
401+import os
402+import manager
403+
404+os.environ['JUJU_UNIT_NAME'] = 'keystone'
405+with patch('charmhelpers.core.hookenv.config') as config:
406+ import keystone_utils as utils
407+
408+import keystone_context
409+import keystone_hooks as hooks
410+from charmhelpers.contrib.openstack import context
411+
412+TO_PATCH = [
413+ 'api_port',
414+ 'config',
415+ 'create_user',
416+ 'os_release',
417+ 'log',
418+ 'get_ca',
419+ 'create_role',
420+ 'create_service_entry',
421+ 'create_endpoint_template',
422+ 'get_admin_token',
423+ 'get_local_endpoint',
424+ 'get_requested_roles',
425+ 'get_service_password',
426+ 'get_os_codename_install_source',
427+ 'grant_role',
428+ 'configure_installation_source',
429+ 'eligible_leader',
430+ 'https',
431+ 'is_clustered',
432+ 'service_stop',
433+ 'service_start',
434+ 'relation_get',
435+ 'relation_set',
436+ 'https',
437+ 'unit_private_ip',
438+ # generic
439+ 'apt_update',
440+ 'apt_upgrade',
441+ 'apt_install',
442+ 'subprocess',
443+ 'time',
444+ 'pwgen',
445+]
446+
447+class TestKeystoneUtils(CharmTestCase):
448+
449+ def setUp(self):
450+ super(TestKeystoneUtils, self).setUp(utils, TO_PATCH)
451+ self.config.side_effect = self.test_config.get
452+
453+ self.ctxt = MagicMock()
454+ self.rsc_map = {
455+ '/etc/keystone/keystone.conf': {
456+ 'services': ['keystone'],
457+ 'contexts': [self.ctxt],
458+ },
459+ '/etc/apache2/sites-available/openstack_https_frontend': {
460+ 'services': ['apache2'],
461+ 'contexts': [self.ctxt],
462+ },
463+ '/etc/apache2/sites-available/openstack_https_frontend.conf': {
464+ 'services': ['apache2'],
465+ 'contexts': [self.ctxt],
466+ }
467+ }
468+
469+ @patch('charmhelpers.contrib.openstack.templating.OSConfigRenderer')
470+ @patch('os.path.exists')
471+ @patch.object(utils, 'resource_map')
472+ def test_register_configs_apache(self, resource_map, exists, renderer):
473+ exists.return_value = False
474+ self.os_release.return_value = 'havana'
475+ fake_renderer = MagicMock()
476+ fake_renderer.register = MagicMock()
477+ renderer.return_value = fake_renderer
478+
479+ resource_map.return_value = self.rsc_map
480+ utils.register_configs()
481+ renderer.assert_called_with(
482+ openstack_release='havana', templates_dir='templates/')
483+
484+ ex_reg = [
485+ call('/etc/keystone/keystone.conf', [self.ctxt]),
486+ call('/etc/apache2/sites-available/openstack_https_frontend', [self.ctxt]),
487+ call('/etc/apache2/sites-available/openstack_https_frontend.conf', [self.ctxt]),
488+ ]
489+ self.assertEquals(fake_renderer.register.call_args_list, ex_reg)
490+
491+ def test_determine_ports(self):
492+ self.test_config.set('admin-port','80')
493+ self.test_config.set('service-port','81')
494+ result = utils.determine_ports()
495+ self.assertEquals(result, ['80', '81'])
496+
497+ def test_determine_packages(self):
498+ result = utils.determine_packages()
499+ ex = utils.BASE_PACKAGES + ['keystone', 'haproxy', 'apache2']
500+ self.assertEquals(set(ex), set(result))
501+
502+ @patch.object(hooks, 'CONFIGS')
503+ @patch.object(utils, 'determine_packages')
504+ @patch.object(utils, 'migrate_database')
505+ def test_openstack_upgrade_leader(self, migrate_database, determine_packages, configs):
506+ self.test_config.set('openstack-origin', 'precise')
507+ determine_packages.return_value = []
508+ self.eligible_leader.return_value = True
509+
510+ utils.do_openstack_upgrade(configs)
511+
512+ self.get_os_codename_install_source.assert_called_with('precise')
513+ self.configure_installation_source.assert_called_with('precise')
514+ self.assertTrue(self.apt_update.called)
515+
516+ dpkg_opts = [
517+ '--option', 'Dpkg::Options::=--force-confnew',
518+ '--option', 'Dpkg::Options::=--force-confdef',
519+ ]
520+ self.apt_upgrade.assert_called_with(options=dpkg_opts, fatal=True, dist=True)
521+ self.apt_install.assert_called_with(packages=[], options=dpkg_opts, fatal=True)
522+
523+ self.assertTrue(configs.set_release.called)
524+ self.assertTrue(configs.write_all.called)
525+ self.assertTrue(migrate_database.called)
526+
527+ def test_migrate_database(self):
528+ utils.migrate_database()
529+
530+ self.service_stop.assert_called_with('keystone')
531+ cmd = ['sudo', '-u', 'keystone', 'keystone-manage', 'db_sync']
532+ self.subprocess.check_output.assert_called_with(cmd)
533+ self.service_start.assert_called_wkth('keystone')
534+
535+ @patch.object(utils, 'b64encode')
536+ def test_add_service_to_keystone_clustered_https_none_values(self, b64encode):
537+ relation_id = 'identity-service:0'
538+ remote_unit = 'unit/0'
539+ self.is_clustered.return_value = True
540+ self.https.return_value = True
541+ self.test_config.set('https-service-endpoints', 'True')
542+ self.test_config.set('vip', '10.10.10.10')
543+ self.test_config.set('admin-port', 80)
544+ self.test_config.set('service-port', 81)
545+ b64encode.return_value = 'certificate'
546+ self.get_requested_roles.return_value = ['role1',]
547+
548+ self.relation_get.return_value = {'service': 'keystone',
549+ 'region': 'RegionOne',
550+ 'public_url': 'None',
551+ 'admin_url': '10.0.0.2',
552+ 'internal_url': '192.168.1.2'}
553+
554+ utils.add_service_to_keystone(relation_id=relation_id, remote_unit=remote_unit)
555+ self.assertTrue(self.is_clustered.called)
556+ self.assertTrue(self.https.called)
557+ self.assertTrue(self.create_role.called)
558+
559+ relation_data = {'auth_host': '10.10.10.10',
560+ 'service_host': '10.10.10.10',
561+ 'auth_protocol': 'https',
562+ 'service_protocol': 'https',
563+ 'auth_port': 80,
564+ 'service_port': 81,
565+ 'https_keystone': 'True',
566+ 'ca_cert': 'certificate'}
567+ self.relation_set.assert_called_with(relation_id=relation_id, **relation_data)
568+
569+ @patch.object(utils, 'ensure_valid_service')
570+ @patch.object(utils, 'add_endpoint')
571+ @patch.object(manager, 'KeystoneManager')
572+ def test_add_service_to_keystone_no_clustered_no_https_complete_values(self, KeystoneManager, add_endpoint, ensure_valid_service):
573+ relation_id = 'identity-service:0'
574+ remote_unit = 'unit/0'
575+ self.get_admin_token.return_value = 'token'
576+ self.get_service_password.return_value = 'password'
577+ self.test_config.set('service-tenant', 'tenant')
578+ self.test_config.set('admin-role', 'admin')
579+ self.get_requested_roles.return_value = ['role1',]
580+ self.unit_private_ip.return_value = '10.0.0.3'
581+ self.test_config.set('admin-port', 80)
582+ self.test_config.set('service-port', 81)
583+ self.is_clustered.return_value = False
584+ self.https.return_value = False
585+ self.test_config.set('https-service-endpoints', 'False')
586+ self.get_local_endpoint.return_value = 'http://localhost:80/v2.0/'
587+
588+ mock_keystone = MagicMock()
589+ mock_keystone.resolve_tenant_id.return_value = 'tenant_id'
590+ KeystoneManager.return_value = mock_keystone
591+
592+ self.relation_get.return_value = {'service': 'keystone',
593+ 'region': 'RegionOne',
594+ 'public_url': '10.0.0.1',
595+ 'admin_url': '10.0.0.2',
596+ 'internal_url': '192.168.1.2'}
597+
598+ utils.add_service_to_keystone(relation_id=relation_id, remote_unit=remote_unit)
599+ ensure_valid_service.assert_called_with('keystone')
600+ add_endpoint.assert_called_with(region='RegionOne', service='keystone',
601+ publicurl='10.0.0.1', adminurl='10.0.0.2',
602+ internalurl='192.168.1.2')
603+ self.assertTrue(self.get_admin_token.called)
604+ self.get_service_password.assert_called_with('keystone')
605+ self.create_user.assert_called_with('keystone', 'password', 'tenant')
606+ self.grant_role.assert_called_with('keystone', 'admin', 'tenant')
607+ self.create_role.assert_called_with('role1', 'keystone', 'tenant')
608+
609+ self.assertTrue(self.is_clustered.called)
610+ relation_data = {'admin_token': 'token', 'service_port':81,
611+ 'auth_port':80, 'service_username':'keystone',
612+ 'service_password': 'password', 'service_tenant': 'tenant',
613+ 'https_keystone': 'False', 'ssl_cert': '', 'ssl_key': '',
614+ 'ca_cert': '', 'auth_host':'10.0.0.3', 'service_host': '10.0.0.3',
615+ 'auth_protocol': 'http', 'service_protocol': 'http',
616+ 'service_tenant_id': 'tenant_id'}
617+ self.relation_set.assert_called_with(relation_id=relation_id, **relation_data)
618+
619+ @patch.object(utils, 'ensure_valid_service')
620+ @patch.object(utils, 'add_endpoint')
621+ @patch.object(manager, 'KeystoneManager')
622+ def test_add_service_to_keystone_nosubset(self, KeystoneManager, add_endpoint, ensure_valid_service):
623+ relation_id = 'identity-service:0'
624+ remote_unit = 'unit/0'
625+
626+ self.relation_get.return_value = {'ec2_service': 'nova',
627+ 'ec2_region': 'RegionOne',
628+ 'ec2_public_url': '10.0.0.1',
629+ 'ec2_admin_url': '10.0.0.2',
630+ 'ec2_internal_url': '192.168.1.2'}
631+ self.get_local_endpoint.return_value = 'http://localhost:80/v2.0/'
632+ KeystoneManager.resolve_tenant_id.return_value = 'tenant_id'
633+
634+ utils.add_service_to_keystone(relation_id=relation_id, remote_unit=remote_unit)
635+ ensure_valid_service.assert_called_with('nova')
636+ add_endpoint.assert_called_with(region='RegionOne', service='nova',
637+ publicurl='10.0.0.1', adminurl='10.0.0.2',
638+ internalurl='192.168.1.2')
639+
640+ def test_ensure_valid_service_incorrect(self):
641+ utils.ensure_valid_service('fakeservice')
642+ self.log.assert_called_with("Invalid service requested: 'fakeservice'")
643+ self.relation_set.assert_called_with(admin_token=-1)
644+
645+ def test_add_endpoint(self):
646+ publicurl = '10.0.0.1'
647+ adminurl = '10.0.0.2'
648+ internalurl = '10.0.0.3'
649+ utils.add_endpoint('RegionOne', 'nova', publicurl, adminurl, internalurl)
650+ self.create_service_entry.assert_called_with('nova', 'compute', 'Nova Compute Service')
651+ self.create_endpoint_template.asssert_called_with(region='RegionOne', service='nova',
652+ publicurl=publicurl, adminurl=adminurl,
653+ internalurl=internalurl)

Subscribers

People subscribed via source and target branches