Merge lp:~hopem/charms/trusty/keystone/stable-backport-lp1415579 into lp:~openstack-charmers-archive/charms/trusty/keystone/trunk

Proposed by Edward Hope-Morley
Status: Merged
Merged at revision: 117
Proposed branch: lp:~hopem/charms/trusty/keystone/stable-backport-lp1415579
Merge into: lp:~openstack-charmers-archive/charms/trusty/keystone/trunk
Diff against target: 588 lines (+270/-102)
5 files modified
hooks/charmhelpers/contrib/unison/__init__.py (+6/-4)
hooks/charmhelpers/core/sysctl.py (+11/-5)
hooks/keystone_hooks.py (+36/-15)
hooks/keystone_utils.py (+78/-36)
unit_tests/test_keystone_utils.py (+139/-42)
To merge this branch: bzr merge lp:~hopem/charms/trusty/keystone/stable-backport-lp1415579
Reviewer Review Type Date Requested Status
James Page Approve
Review via email: mp+248894@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #1781 keystone for hopem mp248894
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/1781/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #1609 keystone for hopem mp248894
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/1609/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_amulet_test #1801 keystone for hopem mp248894
    AMULET OK: passed

Build: http://10.245.162.77:8080/job/charm_amulet_test/1801/

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'hooks/charmhelpers/contrib/unison/__init__.py'
--- hooks/charmhelpers/contrib/unison/__init__.py 2015-01-26 09:44:47 +0000
+++ hooks/charmhelpers/contrib/unison/__init__.py 2015-02-06 12:31:31 +0000
@@ -73,6 +73,7 @@
73 relation_set,73 relation_set,
74 relation_get,74 relation_get,
75 unit_private_ip,75 unit_private_ip,
76 INFO,
76 ERROR,77 ERROR,
77)78)
7879
@@ -86,7 +87,7 @@
86 user = pwd.getpwnam(user)87 user = pwd.getpwnam(user)
87 return user.pw_dir88 return user.pw_dir
88 except KeyError:89 except KeyError:
89 log('Could not get homedir for user %s: user exists?', ERROR)90 log('Could not get homedir for user %s: user exists?' % (user), ERROR)
90 raise Exception91 raise Exception
9192
9293
@@ -233,14 +234,15 @@
233 rid=r_id, unit=unit)234 rid=r_id, unit=unit)
234235
235 if not authed_hosts:236 if not authed_hosts:
236 log('Peer %s has not authorized *any* hosts yet, skipping.')237 log('Peer %s has not authorized *any* hosts yet, skipping.' %
238 (unit), level=INFO)
237 continue239 continue
238240
239 if unit_private_ip() in authed_hosts.split(':'):241 if unit_private_ip() in authed_hosts.split(':'):
240 hosts.append(private_addr)242 hosts.append(private_addr)
241 else:243 else:
242 log('Peer %s has not authorized *this* host yet, skipping.')244 log('Peer %s has not authorized *this* host yet, skipping.' %
243245 (unit), level=INFO)
244 return hosts246 return hosts
245247
246248
247249
=== modified file 'hooks/charmhelpers/core/sysctl.py'
--- hooks/charmhelpers/core/sysctl.py 2015-01-26 09:44:47 +0000
+++ hooks/charmhelpers/core/sysctl.py 2015-02-06 12:31:31 +0000
@@ -26,25 +26,31 @@
26from charmhelpers.core.hookenv import (26from charmhelpers.core.hookenv import (
27 log,27 log,
28 DEBUG,28 DEBUG,
29 ERROR,
29)30)
3031
3132
32def create(sysctl_dict, sysctl_file):33def create(sysctl_dict, sysctl_file):
33 """Creates a sysctl.conf file from a YAML associative array34 """Creates a sysctl.conf file from a YAML associative array
3435
35 :param sysctl_dict: a dict of sysctl options eg { 'kernel.max_pid': 1337 }36 :param sysctl_dict: a YAML-formatted string of sysctl options eg "{ 'kernel.max_pid': 1337 }"
36 :type sysctl_dict: dict37 :type sysctl_dict: str
37 :param sysctl_file: path to the sysctl file to be saved38 :param sysctl_file: path to the sysctl file to be saved
38 :type sysctl_file: str or unicode39 :type sysctl_file: str or unicode
39 :returns: None40 :returns: None
40 """41 """
41 sysctl_dict = yaml.load(sysctl_dict)42 try:
43 sysctl_dict_parsed = yaml.safe_load(sysctl_dict)
44 except yaml.YAMLError:
45 log("Error parsing YAML sysctl_dict: {}".format(sysctl_dict),
46 level=ERROR)
47 return
4248
43 with open(sysctl_file, "w") as fd:49 with open(sysctl_file, "w") as fd:
44 for key, value in sysctl_dict.items():50 for key, value in sysctl_dict_parsed.items():
45 fd.write("{}={}\n".format(key, value))51 fd.write("{}={}\n".format(key, value))
4652
47 log("Updating sysctl_file: %s values: %s" % (sysctl_file, sysctl_dict),53 log("Updating sysctl_file: %s values: %s" % (sysctl_file, sysctl_dict_parsed),
48 level=DEBUG)54 level=DEBUG)
4955
50 check_call(["sysctl", "-p", sysctl_file])56 check_call(["sysctl", "-p", sysctl_file])
5157
=== modified file 'hooks/keystone_hooks.py'
--- hooks/keystone_hooks.py 2015-01-27 22:21:37 +0000
+++ hooks/keystone_hooks.py 2015-02-06 12:31:31 +0000
@@ -67,6 +67,7 @@
67 is_str_true,67 is_str_true,
68 is_ssl_cert_master,68 is_ssl_cert_master,
69 is_db_ready,69 is_db_ready,
70 clear_ssl_synced_units,
70)71)
7172
72from charmhelpers.contrib.hahelpers.cluster import (73from charmhelpers.contrib.hahelpers.cluster import (
@@ -150,11 +151,8 @@
150 admin_relation_changed(rid)151 admin_relation_changed(rid)
151152
152 # Ensure sync request is sent out (needed for upgrade to ssl from non-ssl)153 # Ensure sync request is sent out (needed for upgrade to ssl from non-ssl)
153 settings = {}154 send_ssl_sync_request()
154 append_ssl_sync_request(settings)155
155 if settings:
156 for rid in relation_ids('cluster'):
157 relation_set(relation_id=rid, relation_settings=settings)
158 for r_id in relation_ids('ha'):156 for r_id in relation_ids('ha'):
159 ha_joined(relation_id=r_id)157 ha_joined(relation_id=r_id)
160158
@@ -283,15 +281,39 @@
283 send_notifications(notifications)281 send_notifications(notifications)
284282
285283
286def append_ssl_sync_request(settings):284def send_ssl_sync_request():
287 """Add request to be synced to relation settings.285 """Set sync request on cluster relation.
288286
289 This will be consumed by cluster-relation-changed ssl master.287 Value set equals number of ssl configs currently enabled so that if they
288 change, we ensure that certs are synced. This setting is consumed by
289 cluster-relation-changed ssl master. We also clear the 'synced' set to
290 guarantee that a sync will occur.
291
292 Note the we do nothing if the setting is already applied.
290 """293 """
291 if (is_str_true(config('use-https')) or294 unit = local_unit().replace('/', '-')
292 is_str_true(config('https-service-endpoints'))):295 count = 0
293 unit = local_unit().replace('/', '-')296 if is_str_true(config('use-https')):
294 settings['ssl-sync-required-%s' % (unit)] = '1'297 count += 1
298
299 if is_str_true(config('https-service-endpoints')):
300 count += 2
301
302 if count:
303 key = 'ssl-sync-required-%s' % (unit)
304 settings = {key: count}
305 prev = 0
306 rid = None
307 for rid in relation_ids('cluster'):
308 for unit in related_units(rid):
309 _prev = relation_get(rid=rid, unit=unit, attribute=key) or 0
310 if _prev and _prev > prev:
311 prev = _prev
312
313 if rid and prev < count:
314 clear_ssl_synced_units()
315 log("Setting %s=%s" % (key, count), level=DEBUG)
316 relation_set(relation_id=rid, relation_settings=settings)
295317
296318
297@hooks.hook('cluster-relation-joined')319@hooks.hook('cluster-relation-joined')
@@ -314,9 +336,8 @@
314 private_addr = get_ipv6_addr(exc_list=[config('vip')])[0]336 private_addr = get_ipv6_addr(exc_list=[config('vip')])[0]
315 settings['private-address'] = private_addr337 settings['private-address'] = private_addr
316338
317 append_ssl_sync_request(settings)
318
319 relation_set(relation_settings=settings)339 relation_set(relation_settings=settings)
340 send_ssl_sync_request()
320341
321342
322def apply_echo_filters(settings, echo_whitelist):343def apply_echo_filters(settings, echo_whitelist):
323344
=== modified file 'hooks/keystone_utils.py'
--- hooks/keystone_utils.py 2015-02-02 13:52:05 +0000
+++ hooks/keystone_utils.py 2015-02-06 12:31:31 +0000
@@ -21,7 +21,6 @@
21 determine_api_port,21 determine_api_port,
22 https,22 https,
23 peer_units,23 peer_units,
24 oldest_peer,
25)24)
2625
27from charmhelpers.contrib.openstack import context, templating26from charmhelpers.contrib.openstack import context, templating
@@ -764,14 +763,27 @@
764def unison_sync(paths_to_sync):763def unison_sync(paths_to_sync):
765 """Do unison sync and retry a few times if it fails since peers may not be764 """Do unison sync and retry a few times if it fails since peers may not be
766 ready for sync.765 ready for sync.
766
767 Returns list of synced units or None if one or more peers was not synced.
767 """768 """
768 log('Synchronizing CA (%s) to all peers.' % (', '.join(paths_to_sync)),769 log('Synchronizing CA (%s) to all peers.' % (', '.join(paths_to_sync)),
769 level=INFO)770 level=INFO)
770 keystone_gid = grp.getgrnam('keystone').gr_gid771 keystone_gid = grp.getgrnam('keystone').gr_gid
772
773 # NOTE(dosaboy): This will sync to all peers who have already provided
774 # their ssh keys. If any existing peers have not provided their keys yet,
775 # they will be silently ignored.
771 unison.sync_to_peers(peer_interface='cluster', paths=paths_to_sync,776 unison.sync_to_peers(peer_interface='cluster', paths=paths_to_sync,
772 user=SSH_USER, verbose=True, gid=keystone_gid,777 user=SSH_USER, verbose=True, gid=keystone_gid,
773 fatal=True)778 fatal=True)
774779
780 synced_units = peer_units()
781 if len(unison.collect_authed_hosts('cluster')) != len(synced_units):
782 log("Not all peer units synced due to missing public keys", level=INFO)
783 return None
784 else:
785 return synced_units
786
775787
776def get_ssl_sync_request_units():788def get_ssl_sync_request_units():
777 """Get list of units that have requested to be synced.789 """Get list of units that have requested to be synced.
@@ -791,14 +803,22 @@
791 return units803 return units
792804
793805
794def is_ssl_cert_master():806def is_ssl_cert_master(votes=None):
795 """Return True if this unit is ssl cert master."""807 """Return True if this unit is ssl cert master."""
796 master = None808 master = None
797 for rid in relation_ids('cluster'):809 for rid in relation_ids('cluster'):
798 master = relation_get(attribute='ssl-cert-master', rid=rid,810 master = relation_get(attribute='ssl-cert-master', rid=rid,
799 unit=local_unit())811 unit=local_unit())
800812
801 return master == local_unit()813 if master == local_unit():
814 votes = votes or get_ssl_cert_master_votes()
815 if not peer_units() or (len(votes) == 1 and master in votes):
816 return True
817
818 log("Did not get consensus from peers on who is ssl-cert-master "
819 "(%s)" % (votes), level=INFO)
820
821 return False
802822
803823
804def is_ssl_enabled():824def is_ssl_enabled():
@@ -812,7 +832,21 @@
812 return True832 return True
813833
814834
815def ensure_ssl_cert_master(use_oldest_peer=False):835def get_ssl_cert_master_votes():
836 """Returns a list of unique votes."""
837 votes = []
838 # Gather election results from peers. These will need to be consistent.
839 for rid in relation_ids('cluster'):
840 for unit in related_units(rid):
841 m = relation_get(rid=rid, unit=unit,
842 attribute='ssl-cert-master')
843 if m is not None:
844 votes.append(m)
845
846 return list(set(votes))
847
848
849def ensure_ssl_cert_master():
816 """Ensure that an ssl cert master has been elected.850 """Ensure that an ssl cert master has been elected.
817851
818 Normally the cluster leader will take control but we allow for this to be852 Normally the cluster leader will take control but we allow for this to be
@@ -822,31 +856,19 @@
822 if not is_ssl_enabled():856 if not is_ssl_enabled():
823 return False857 return False
824858
825 elect = False
826 peers = peer_units()
827 master_override = False859 master_override = False
828 if use_oldest_peer:860 elect = is_elected_leader(CLUSTER_RES)
829 elect = oldest_peer(peers)
830 else:
831 elect = is_elected_leader(CLUSTER_RES)
832861
833 # If no peers we allow this unit to elect itsef as master and do862 # If no peers we allow this unit to elect itsef as master and do
834 # sync immediately.863 # sync immediately.
835 if not peers and not is_ssl_cert_master():864 if not peer_units():
836 elect = True865 elect = True
837 master_override = True866 master_override = True
838867
839 if elect:868 if elect:
840 masters = []869 votes = get_ssl_cert_master_votes()
841 for rid in relation_ids('cluster'):
842 for unit in related_units(rid):
843 m = relation_get(rid=rid, unit=unit,
844 attribute='ssl-cert-master')
845 if m is not None:
846 masters.append(m)
847
848 # We expect all peers to echo this setting870 # We expect all peers to echo this setting
849 if not masters or 'unknown' in masters:871 if not votes or 'unknown' in votes:
850 log("Notifying peers this unit is ssl-cert-master", level=INFO)872 log("Notifying peers this unit is ssl-cert-master", level=INFO)
851 for rid in relation_ids('cluster'):873 for rid in relation_ids('cluster'):
852 settings = {'ssl-cert-master': local_unit()}874 settings = {'ssl-cert-master': local_unit()}
@@ -855,10 +877,11 @@
855 # Return now and wait for cluster-relation-changed (peer_echo) for877 # Return now and wait for cluster-relation-changed (peer_echo) for
856 # sync.878 # sync.
857 return master_override879 return master_override
858 elif len(set(masters)) != 1 and local_unit() not in masters:880 elif not is_ssl_cert_master(votes):
859 log("Did not get consensus from peers on who is ssl-cert-master "881 if not master_override:
860 "(%s) - waiting for current master to release before "882 log("Conscensus not reached - current master will need to "
861 "self-electing" % (masters), level=INFO)883 "release", level=INFO)
884
862 return master_override885 return master_override
863886
864 if not is_ssl_cert_master():887 if not is_ssl_cert_master():
@@ -887,15 +910,18 @@
887 log("Syncing all endpoint certs since https-service-endpoints=True",910 log("Syncing all endpoint certs since https-service-endpoints=True",
888 level=DEBUG)911 level=DEBUG)
889 paths_to_sync.append(SSL_DIR)912 paths_to_sync.append(SSL_DIR)
890 paths_to_sync.append(APACHE_SSL_DIR)
891 paths_to_sync.append(CA_CERT_PATH)913 paths_to_sync.append(CA_CERT_PATH)
892 elif is_str_true(config('use-https')):914
915 if is_str_true(config('use-https')):
893 log("Syncing keystone-endpoint certs since use-https=True",916 log("Syncing keystone-endpoint certs since use-https=True",
894 level=DEBUG)917 level=DEBUG)
895 paths_to_sync.append(SSL_DIR)918 paths_to_sync.append(SSL_DIR)
896 paths_to_sync.append(APACHE_SSL_DIR)919 paths_to_sync.append(APACHE_SSL_DIR)
897 paths_to_sync.append(CA_CERT_PATH)920 paths_to_sync.append(CA_CERT_PATH)
898921
922 # Ensure unique
923 paths_to_sync = list(set(paths_to_sync))
924
899 if not paths_to_sync:925 if not paths_to_sync:
900 log("Nothing to sync - skipping", level=DEBUG)926 log("Nothing to sync - skipping", level=DEBUG)
901 return {}927 return {}
@@ -908,8 +934,7 @@
908 create_peer_service_actions('restart', ['apache2'])934 create_peer_service_actions('restart', ['apache2'])
909 create_peer_actions(['update-ca-certificates'])935 create_peer_actions(['update-ca-certificates'])
910936
911 # Format here needs to match that used when peers request sync937 cluster_rel_settings = {}
912 synced_units = [unit.replace('/', '-') for unit in peer_units()]
913938
914 retries = 3939 retries = 3
915 while True:940 while True:
@@ -918,7 +943,12 @@
918 update_hash_from_path(hash1, path)943 update_hash_from_path(hash1, path)
919944
920 try:945 try:
921 unison_sync(paths_to_sync)946 synced_units = unison_sync(paths_to_sync)
947 if synced_units:
948 # Format here needs to match that used when peers request sync
949 synced_units = [u.replace('/', '-') for u in synced_units]
950 cluster_rel_settings['ssl-synced-units'] = \
951 json.dumps(synced_units)
922 except:952 except:
923 if fatal:953 if fatal:
924 raise954 raise
@@ -947,10 +977,22 @@
947 hash = hash1.hexdigest()977 hash = hash1.hexdigest()
948 log("Sending restart-services-trigger=%s to all peers" % (hash),978 log("Sending restart-services-trigger=%s to all peers" % (hash),
949 level=DEBUG)979 level=DEBUG)
980 cluster_rel_settings['restart-services-trigger'] = hash
950981
951 log("Sync complete", level=DEBUG)982 log("Sync complete", level=DEBUG)
952 return {'restart-services-trigger': hash,983 return cluster_rel_settings
953 'ssl-synced-units': json.dumps(synced_units)}984
985
986def clear_ssl_synced_units():
987 """Clear the 'synced' units record on the cluster relation.
988
989 If new unit sync reauests are set this will ensure that a sync occurs when
990 the sync master receives the requests.
991 """
992 log("Clearing ssl sync units", level=DEBUG)
993 for rid in relation_ids('cluster'):
994 relation_set(relation_id=rid,
995 relation_settings={'ssl-synced-units': None})
954996
955997
956def update_hash_from_path(hash, path, recurse_depth=10):998def update_hash_from_path(hash, path, recurse_depth=10):
@@ -1058,11 +1100,11 @@
1058 '%s' % SSL_DIR])1100 '%s' % SSL_DIR])
1059 subprocess.check_output(['chmod', '-R', 'g+rwx', '%s' % SSL_DIR])1101 subprocess.check_output(['chmod', '-R', 'g+rwx', '%s' % SSL_DIR])
10601102
1061 # Ensure a master has been elected and prefer this unit. Note that we1103 # Ensure a master is elected. This should cover the following cases:
1062 # prefer oldest peer as predicate since this action i normally only1104 # * single unit == 'oldest' unit is elected as master
1063 # performed once at deploy time when the oldest peer should be the1105 # * multi unit + not clustered == 'oldest' unit is elcted as master
1064 # first to be ready.1106 # * multi unit + clustered == cluster leader is elected as master
1065 ensure_ssl_cert_master(use_oldest_peer=True)1107 ensure_ssl_cert_master()
10661108
1067 ssl.CA_SINGLETON.append(ca)1109 ssl.CA_SINGLETON.append(ca)
10681110
10691111
=== modified file 'unit_tests/test_keystone_utils.py'
--- unit_tests/test_keystone_utils.py 2015-02-02 13:52:05 +0000
+++ unit_tests/test_keystone_utils.py 2015-02-06 12:31:31 +0000
@@ -28,6 +28,7 @@
28 'grant_role',28 'grant_role',
29 'configure_installation_source',29 'configure_installation_source',
30 'is_elected_leader',30 'is_elected_leader',
31 'is_ssl_cert_master',
31 'https',32 'https',
32 'peer_store_and_set',33 'peer_store_and_set',
33 'service_stop',34 'service_stop',
@@ -380,45 +381,141 @@
380 self.assertTrue(utils.is_db_ready())381 self.assertTrue(utils.is_db_ready())
381382
382 @patch.object(utils, 'peer_units')383 @patch.object(utils, 'peer_units')
383 @patch.object(utils, 'is_elected_leader')384 @patch.object(utils, 'is_ssl_enabled')
384 @patch.object(utils, 'oldest_peer')385 def test_ensure_ssl_cert_master_no_ssl(self, mock_is_ssl_enabled,
385 @patch.object(utils, 'is_ssl_enabled')386 mock_peer_units):
386 def test_ensure_ssl_cert_master(self, mock_is_str_true, mock_oldest_peer,387 mock_is_ssl_enabled.return_value = False
387 mock_is_elected_leader, mock_peer_units):388 self.assertFalse(utils.ensure_ssl_cert_master())
388 self.relation_ids.return_value = ['cluster:0']389 self.assertFalse(self.relation_set.called)
389 self.local_unit.return_value = 'unit/0'390
390391 @patch.object(utils, 'peer_units')
391 mock_is_str_true.return_value = False392 @patch.object(utils, 'is_ssl_enabled')
392 self.assertFalse(utils.ensure_ssl_cert_master())393 def test_ensure_ssl_cert_master_ssl_no_peers(self, mock_is_ssl_enabled,
393 self.assertFalse(self.relation_set.called)394 mock_peer_units):
394395 def mock_rel_get(unit=None, **kwargs):
395 mock_is_elected_leader.return_value = False396 return None
396 self.assertFalse(utils.ensure_ssl_cert_master())397
397 self.assertFalse(self.relation_set.called)398 self.relation_get.side_effect = mock_rel_get
398399 mock_is_ssl_enabled.return_value = True
399 mock_is_str_true.return_value = True400 self.relation_ids.return_value = ['cluster:0']
400 mock_is_elected_leader.return_value = False401 self.local_unit.return_value = 'unit/0'
401 mock_peer_units.return_value = ['unit/0']402 self.related_units.return_value = []
402 self.assertFalse(utils.ensure_ssl_cert_master())403 mock_peer_units.return_value = []
403 self.assertFalse(self.relation_set.called)404 # This should get ignored since we are overriding
404405 self.is_ssl_cert_master.return_value = False
405 mock_peer_units.return_value = []406 self.is_elected_leader.return_value = False
406 self.assertTrue(utils.ensure_ssl_cert_master())407 self.assertTrue(utils.ensure_ssl_cert_master())
407 settings = {'ssl-cert-master': 'unit/0'}408 settings = {'ssl-cert-master': 'unit/0'}
408 self.relation_set.assert_called_with(relation_id='cluster:0',409 self.relation_set.assert_called_with(relation_id='cluster:0',
409 relation_settings=settings)410 relation_settings=settings)
410 self.relation_set.reset_mock()411
411412 @patch.object(utils, 'peer_units')
412 self.assertTrue(utils.ensure_ssl_cert_master(use_oldest_peer=True))413 @patch.object(utils, 'is_ssl_enabled')
413 settings = {'ssl-cert-master': 'unit/0'}414 def test_ensure_ssl_cert_master_ssl_master_no_peers(self,
414 self.relation_set.assert_called_with(relation_id='cluster:0',415 mock_is_ssl_enabled,
415 relation_settings=settings)416 mock_peer_units):
416 self.relation_set.reset_mock()417 def mock_rel_get(unit=None, **kwargs):
417418 if unit == 'unit/0':
418 mock_peer_units.return_value = ['unit/0']419 return 'unit/0'
419 self.assertFalse(utils.ensure_ssl_cert_master())420
420 self.assertFalse(utils.ensure_ssl_cert_master(use_oldest_peer=True))421 return None
421 settings = {'ssl-cert-master': 'unit/0'}422
422 self.relation_set.assert_called_with(relation_id='cluster:0',423 self.relation_get.side_effect = mock_rel_get
423 relation_settings=settings)424 mock_is_ssl_enabled.return_value = True
424 self.relation_set.reset_mock()425 self.relation_ids.return_value = ['cluster:0']
426 self.local_unit.return_value = 'unit/0'
427 self.related_units.return_value = []
428 mock_peer_units.return_value = []
429 # This should get ignored since we are overriding
430 self.is_ssl_cert_master.return_value = False
431 self.is_elected_leader.return_value = False
432 self.assertTrue(utils.ensure_ssl_cert_master())
433 settings = {'ssl-cert-master': 'unit/0'}
434 self.relation_set.assert_called_with(relation_id='cluster:0',
435 relation_settings=settings)
436
437 @patch.object(utils, 'peer_units')
438 @patch.object(utils, 'is_ssl_enabled')
439 def test_ensure_ssl_cert_master_ssl_not_leader(self, mock_is_ssl_enabled,
440 mock_peer_units):
441 mock_is_ssl_enabled.return_value = True
442 self.relation_ids.return_value = ['cluster:0']
443 self.local_unit.return_value = 'unit/0'
444 mock_peer_units.return_value = ['unit/1']
445 self.is_ssl_cert_master.return_value = False
446 self.is_elected_leader.return_value = False
447 self.assertFalse(utils.ensure_ssl_cert_master())
448 self.assertFalse(self.relation_set.called)
449
450 @patch.object(utils, 'peer_units')
451 @patch.object(utils, 'is_ssl_enabled')
452 def test_ensure_ssl_cert_master_is_leader_new_peer(self,
453 mock_is_ssl_enabled,
454 mock_peer_units):
455 def mock_rel_get(unit=None, **kwargs):
456 if unit == 'unit/0':
457 return 'unit/0'
458
459 return 'unknown'
460
461 self.relation_get.side_effect = mock_rel_get
462 mock_is_ssl_enabled.return_value = True
463 self.relation_ids.return_value = ['cluster:0']
464 self.local_unit.return_value = 'unit/0'
465 mock_peer_units.return_value = ['unit/1']
466 self.related_units.return_value = ['unit/1']
467 self.is_ssl_cert_master.return_value = False
468 self.is_elected_leader.return_value = True
469 self.assertFalse(utils.ensure_ssl_cert_master())
470 settings = {'ssl-cert-master': 'unit/0'}
471 self.relation_set.assert_called_with(relation_id='cluster:0',
472 relation_settings=settings)
473
474 @patch.object(utils, 'peer_units')
475 @patch.object(utils, 'is_ssl_enabled')
476 def test_ensure_ssl_cert_master_is_leader_no_new_peer(self,
477 mock_is_ssl_enabled,
478 mock_peer_units):
479 def mock_rel_get(unit=None, **kwargs):
480 if unit == 'unit/0':
481 return 'unit/0'
482
483 return 'unit/0'
484
485 self.relation_get.side_effect = mock_rel_get
486 mock_is_ssl_enabled.return_value = True
487 self.relation_ids.return_value = ['cluster:0']
488 self.local_unit.return_value = 'unit/0'
489 mock_peer_units.return_value = ['unit/1']
490 self.related_units.return_value = ['unit/1']
491 self.is_ssl_cert_master.return_value = False
492 self.is_elected_leader.return_value = True
493 self.assertFalse(utils.ensure_ssl_cert_master())
494 self.assertFalse(self.relation_set.called)
495
496 @patch.object(utils, 'peer_units')
497 @patch.object(utils, 'is_ssl_enabled')
498 def test_ensure_ssl_cert_master_is_leader_bad_votes(self,
499 mock_is_ssl_enabled,
500 mock_peer_units):
501 counter = {0: 0}
502
503 def mock_rel_get(unit=None, **kwargs):
504 """Returns a mix of votes."""
505 if unit == 'unit/0':
506 return 'unit/0'
507
508 ret = 'unit/%d' % (counter[0])
509 counter[0] += 1
510 return ret
511
512 self.relation_get.side_effect = mock_rel_get
513 mock_is_ssl_enabled.return_value = True
514 self.relation_ids.return_value = ['cluster:0']
515 self.local_unit.return_value = 'unit/0'
516 mock_peer_units.return_value = ['unit/1']
517 self.related_units.return_value = ['unit/1']
518 self.is_ssl_cert_master.return_value = False
519 self.is_elected_leader.return_value = True
520 self.assertFalse(utils.ensure_ssl_cert_master())
521 self.assertFalse(self.relation_set.called)

Subscribers

People subscribed via source and target branches