Merge lp:~niedbalski/charms/trusty/rabbitmq-server/fix-1442443 into lp:charms/trusty/rabbitmq-server

Proposed by Jorge Niedbalski
Status: Superseded
Proposed branch: lp:~niedbalski/charms/trusty/rabbitmq-server/fix-1442443
Merge into: lp:charms/trusty/rabbitmq-server
Diff against target: 746 lines (+373/-168)
11 files modified
config.yaml (+7/-1)
hooks/rabbit_utils.py (+37/-39)
hooks/rabbitmq_context.py (+125/-0)
hooks/rabbitmq_server_relations.py (+7/-113)
hooks/ssl_utils.py (+55/-0)
templates/rabbitmq.config (+25/-11)
tests/00_setup.sh (+3/-0)
tests/50_test_cluster_partition.py (+31/-0)
unit_tests/test_rabbit_utils.py (+1/-1)
unit_tests/test_rabbitmq_context.py (+79/-0)
unit_tests/test_rabbitmq_server_relations.py (+3/-3)
To merge this branch: bzr merge lp:~niedbalski/charms/trusty/rabbitmq-server/fix-1442443
Reviewer Review Type Date Requested Status
Billy Olsen Needs Fixing
OpenStack Charmers Pending
Review via email: mp+255770@code.launchpad.net

This proposal has been superseded by a proposal from 2015-04-10.

Description of the change

- Added the cluster_partition_handling option fixes LP: #1442443
- Refactored the ssl handling code.
- Added a generic config loader

To post a comment you must log in.
Revision history for this message
Billy Olsen (billy-olsen) wrote :

Jorge,

I think some of the refactor in here is a definite improvement and makes things cleaner, thanks! I've got a few inline comments included, but the biggest thing is that the rabbitmq-server charm now has a /next and /trunk branch to match the rest of the flow of the openstack charms (since this has recently come under ownership of the ~openstack-charmers team). Can you retarget for /next?

Also, I think the README file should be updated with some discussions regarding high availability.

I'll run through some tests on this but wanted to drop some feedback now.

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

charm_lint_check #3202 rabbitmq-server for niedbalski mp255770
    LINT OK: passed

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

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

charm_unit_test #2990 rabbitmq-server for niedbalski mp255770
    UNIT OK: passed

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

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

charm_amulet_test #3019 rabbitmq-server for niedbalski mp255770
    AMULET FAIL: amulet-test failed

AMULET Results (max last 2 lines):
make: *** [functional_test] Error 1
ERROR:root:Make target returned non-zero.

Full amulet test output: http://paste.ubuntu.com/10789138/
Build: http://10.245.162.77:8080/job/charm_amulet_test/3019/

89. By Liam Young

[gnuoy,trivial] Pre-release charmhelper sync

90. By James Page

[wolsen,r=james-page] Fixup SSL tests to not fail when certs expire!

91. By Jorge Niedbalski

Rebase commit

92. By Jorge Niedbalski

Rebase

93. By Jorge Niedbalski

addressing @dosaboy comments

94. By Jorge Niedbalski

addressing @dosaboy comments

95. By Jorge Niedbalski

addressing @dosaboy comments

96. By Jorge Niedbalski

addressing comments

97. By Jorge Niedbalski

Addressed @beisner comments

98. By Jorge Niedbalski

Addressed @beisner comments

Unmerged revisions

98. By Jorge Niedbalski

Addressed @beisner comments

97. By Jorge Niedbalski

Addressed @beisner comments

96. By Jorge Niedbalski

addressing comments

95. By Jorge Niedbalski

addressing @dosaboy comments

94. By Jorge Niedbalski

addressing @dosaboy comments

93. By Jorge Niedbalski

addressing @dosaboy comments

92. By Jorge Niedbalski

Rebase

91. By Jorge Niedbalski

Rebase commit

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'config.yaml'
2--- config.yaml 2015-03-03 06:05:14 +0000
3+++ config.yaml 2015-04-10 02:40:31 +0000
4@@ -8,7 +8,7 @@
5 type: string
6 default: "off"
7 description: |
8- Enable SSL connections on rabbitmq, valid values are 'off', 'on', 'only'. If ssl_key,
9+ Enable SSL connections on rabbitmq, valid values are 'off', 'on', 'only'. If ssl_key,
10 ssl_cert, ssl_ca are provided then then those values will be used. Otherwise
11 the service will act as its own certificate authority and pass its ca cert to clients.
12 For HA or clustered rabbits ssl key/cert must be provided.
13@@ -92,6 +92,12 @@
14 description: |
15 When set to true the 'ha-mode: all' policy is applied to all the exchages
16 that match the expression '^(?!amq\.).*'
17+ cluster-partition-handling:
18+ type: string
19+ default: ignore
20+ description: |
21+ How to respond to cluster partitions.
22+ See http://www.rabbitmq.com/partitions.html for further details.
23 rbd-size:
24 type: string
25 default: 5G
26
27=== modified file 'hooks/rabbit_utils.py'
28--- hooks/rabbit_utils.py 2015-03-24 20:17:01 +0000
29+++ hooks/rabbit_utils.py 2015-04-10 02:40:31 +0000
30@@ -1,6 +1,4 @@
31 import os
32-import pwd
33-import grp
34 import re
35 import socket
36 import sys
37@@ -8,6 +6,13 @@
38 import glob
39 import tempfile
40
41+from rabbitmq_context import (
42+ RabbitMQSSLContext,
43+ RabbitMQClusterContext
44+)
45+
46+from charmhelpers.core.templating import render
47+
48 from charmhelpers.contrib.openstack.utils import (
49 get_hostname,
50 )
51@@ -30,8 +35,6 @@
52 cmp_pkgrevno
53 )
54
55-from charmhelpers.core.templating import render
56-
57 from charmhelpers.contrib.peerstorage import (
58 peer_store,
59 peer_retrieve
60@@ -57,7 +60,10 @@
61 # the charm doesn't concern itself with template specifics etc.
62 CONFIG_FILES = OrderedDict([
63 (RABBITMQ_CONF, {
64- 'hook_contexts': None,
65+ 'hook_contexts': [
66+ RabbitMQSSLContext(),
67+ RabbitMQClusterContext(),
68+ ],
69 'services': ['rabbitmq-server']
70 }),
71 (ENV_CONF, {
72@@ -71,6 +77,32 @@
73 ])
74
75
76+class ConfigRenderer():
77+
78+ def __init__(self, config):
79+ self.config_data = {}
80+
81+ for config_path, data in config.items():
82+ if 'hook_contexts' in data and data['hook_contexts']:
83+ ctxt = {}
84+ for svc_context in data['hook_contexts']:
85+ ctxt.update(svc_context())
86+ self.config_data[config_path] = ctxt
87+
88+ def write(self, config_path):
89+ data = self.config_data.get(config_path, None)
90+ if data:
91+ log("writing config file: %s , data: %s" % (config_path,
92+ str(data)), level='DEBUG')
93+
94+ render(os.path.basename(config_path), config_path,
95+ data, perms=0o644)
96+
97+ def write_all(self):
98+ for service in self.config_data.keys():
99+ self.write(service)
100+
101+
102 class RabbitmqError(Exception):
103 pass
104
105@@ -390,40 +422,6 @@
106 def disable_plugin(plugin):
107 _manage_plugin(plugin, 'disable')
108
109-ssl_key_file = "/etc/rabbitmq/rabbit-server-privkey.pem"
110-ssl_cert_file = "/etc/rabbitmq/rabbit-server-cert.pem"
111-ssl_ca_file = "/etc/rabbitmq/rabbit-server-ca.pem"
112-
113-
114-def enable_ssl(ssl_key, ssl_cert, ssl_port,
115- ssl_ca=None, ssl_only=False, ssl_client=None):
116- uid = pwd.getpwnam("root").pw_uid
117- gid = grp.getgrnam("rabbitmq").gr_gid
118-
119- for contents, path in (
120- (ssl_key, ssl_key_file),
121- (ssl_cert, ssl_cert_file),
122- (ssl_ca, ssl_ca_file)):
123- if not contents:
124- continue
125- with open(path, 'w') as fh:
126- fh.write(contents)
127- os.chmod(path, 0o640)
128- os.chown(path, uid, gid)
129-
130- data = {
131- "ssl_port": ssl_port,
132- "ssl_cert_file": ssl_cert_file,
133- "ssl_key_file": ssl_key_file,
134- "ssl_client": ssl_client,
135- "ssl_ca_file": "",
136- "ssl_only": ssl_only}
137-
138- if ssl_ca:
139- data["ssl_ca_file"] = ssl_ca_file
140-
141- render(os.path.basename(RABBITMQ_CONF), RABBITMQ_CONF, data, perms=0o644)
142-
143
144 def execute(cmd, die=False, echo=False):
145 """ Executes a command
146
147=== added file 'hooks/rabbitmq_context.py'
148--- hooks/rabbitmq_context.py 1970-01-01 00:00:00 +0000
149+++ hooks/rabbitmq_context.py 2015-04-10 02:40:31 +0000
150@@ -0,0 +1,125 @@
151+from charmhelpers.contrib.ssl.service import ServiceCA
152+
153+from charmhelpers.core.hookenv import (
154+ open_port,
155+ close_port,
156+ config,
157+ log,
158+ ERROR,
159+)
160+
161+import sys
162+import pwd
163+import grp
164+import os
165+import base64
166+
167+import ssl_utils
168+
169+ssl_key_file = "/etc/rabbitmq/rabbit-server-privkey.pem"
170+ssl_cert_file = "/etc/rabbitmq/rabbit-server-cert.pem"
171+ssl_ca_file = "/etc/rabbitmq/rabbit-server-ca.pem"
172+
173+
174+def convert_from_base64(v):
175+ # Rabbit originally supported pem encoded key/cert in config, play
176+ # nice on upgrades as we now expect base64 encoded key/cert/ca.
177+ if not v:
178+ return v
179+ if v.startswith('-----BEGIN'):
180+ return v
181+ try:
182+ return base64.b64decode(v)
183+ except TypeError:
184+ return v
185+
186+
187+class RabbitMQSSLContext(object):
188+
189+ def enable_ssl(self, ssl_key, ssl_cert, ssl_port,
190+ ssl_ca=None, ssl_only=False, ssl_client=None):
191+
192+ uid = pwd.getpwnam("root").pw_uid
193+ gid = grp.getgrnam("rabbitmq").gr_gid
194+
195+ for contents, path in (
196+ (ssl_key, ssl_key_file),
197+ (ssl_cert, ssl_cert_file),
198+ (ssl_ca, ssl_ca_file)):
199+
200+ if not contents:
201+ continue
202+
203+ with open(path, 'w') as fh:
204+ fh.write(contents)
205+
206+ os.chmod(path, 0o640)
207+ os.chown(path, uid, gid)
208+
209+ data = {
210+ "ssl_port": ssl_port,
211+ "ssl_cert_file": ssl_cert_file,
212+ "ssl_key_file": ssl_key_file,
213+ "ssl_client": ssl_client,
214+ "ssl_ca_file": "",
215+ "ssl_only": ssl_only
216+ }
217+
218+ if ssl_ca:
219+ data["ssl_ca_file"] = ssl_ca_file
220+
221+ return data
222+
223+ def __call__(self):
224+ """
225+ The legacy config support adds some additional complications.
226+
227+ ssl_enabled = True, ssl = off -> ssl enabled
228+ ssl_enabled = False, ssl = on -> ssl enabled
229+ """
230+ ssl_mode, external_ca = ssl_utils.get_ssl_mode()
231+
232+ ctxt = {
233+ 'ssl_mode': ssl_mode,
234+ }
235+
236+ if ssl_mode == 'off':
237+ close_port(config('ssl_port'))
238+ ssl_utils.reconfigure_client_ssl()
239+ return ctxt
240+
241+ ssl_key = convert_from_base64(config('ssl_key'))
242+ ssl_cert = convert_from_base64(config('ssl_cert'))
243+ ssl_ca = convert_from_base64(config('ssl_ca'))
244+ ssl_port = config('ssl_port')
245+
246+ # If external managed certs then we need all the fields.
247+ if (
248+ ssl_mode in ('on', 'only') and
249+ any((ssl_key, ssl_cert)) and
250+ not all((ssl_key, ssl_cert))
251+ ):
252+ log('If ssl_key or ssl_cert are specified both are required.',
253+ level=ERROR)
254+ sys.exit(1)
255+
256+ if not external_ca:
257+ ssl_cert, ssl_key, ssl_ca = ServiceCA.get_service_cert()
258+
259+ ctxt.update(self.enable_ssl(
260+ ssl_key, ssl_cert, ssl_port, ssl_ca,
261+ ssl_only=(ssl_mode == "only"), ssl_client=False
262+ ))
263+
264+ ssl_utils.reconfigure_client_ssl(True)
265+ open_port(ssl_port)
266+
267+ return ctxt
268+
269+
270+class RabbitMQClusterContext(object):
271+
272+ def __call__(self):
273+ return {
274+ 'cluster_partition_handling': config('cluster-partition-handling'),
275+ }
276
277=== modified file 'hooks/rabbitmq_server_relations.py'
278--- hooks/rabbitmq_server_relations.py 2015-03-06 06:39:19 +0000
279+++ hooks/rabbitmq_server_relations.py 2015-04-10 02:40:31 +0000
280@@ -1,5 +1,5 @@
281 #!/usr/bin/python
282-import base64
283+
284 import os
285 import shutil
286 import sys
287@@ -8,6 +8,8 @@
288 import socket
289
290 import rabbit_utils as rabbit
291+import ssl_utils
292+
293 from lib.utils import (
294 chown, chmod,
295 is_newer,
296@@ -46,7 +48,6 @@
297 related_units,
298 service_name,
299 local_unit,
300- relations_of_type,
301 config,
302 unit_get,
303 is_relation_made,
304@@ -61,7 +62,6 @@
305 service_restart,
306 )
307 from charmhelpers.contrib.charmsupport import nrpe
308-from charmhelpers.contrib.ssl.service import ServiceCA
309
310 from charmhelpers.contrib.peerstorage import (
311 peer_echo,
312@@ -176,7 +176,7 @@
313 get_address_in_network(config('access-network'),
314 unit_get('private-address'))
315
316- configure_client_ssl(relation_settings)
317+ ssl_utils.configure_client_ssl(relation_settings)
318
319 if is_clustered():
320 relation_settings['clustered'] = 'true'
321@@ -302,19 +302,6 @@
322 service_restart('rabbitmq-server')
323
324
325-@hooks.hook('cluster-relation-departed')
326-def cluster_departed():
327- if is_relation_made('ha') and \
328- config('ha-vip-only') is False:
329- log('hacluster relation is present, skipping native '
330- 'rabbitmq cluster config.')
331- return
332- if not is_newer():
333- log('cluster_joined: Relation lesser.')
334- return
335- rabbit.break_cluster()
336-
337-
338 @hooks.hook('ha-relation-joined')
339 def ha_joined():
340 corosync_bindiface = config('ha-bindiface')
341@@ -526,103 +513,10 @@
342 MAN_PLUGIN = 'rabbitmq_management'
343
344
345-def configure_client_ssl(relation_data):
346- """Configure client with ssl
347- """
348- ssl_mode, external_ca = _get_ssl_mode()
349- if ssl_mode == 'off':
350- return
351- relation_data['ssl_port'] = config('ssl_port')
352- if external_ca:
353- if config('ssl_ca'):
354- relation_data['ssl_ca'] = base64.b64encode(
355- config('ssl_ca'))
356- return
357- ca = ServiceCA.get_ca()
358- relation_data['ssl_ca'] = base64.b64encode(ca.get_ca_bundle())
359-
360-
361-def _get_ssl_mode():
362- ssl_mode = config('ssl')
363- external_ca = False
364- # Legacy config boolean option
365- ssl_on = config('ssl_enabled')
366- if ssl_mode == 'off' and ssl_on is False:
367- ssl_mode = 'off'
368- elif ssl_mode == 'off' and ssl_on:
369- ssl_mode = 'on'
370- ssl_key = config('ssl_key')
371- ssl_cert = config('ssl_cert')
372- if all((ssl_key, ssl_cert)):
373- external_ca = True
374- return ssl_mode, external_ca
375-
376-
377-def _convert_from_base64(v):
378- # Rabbit originally supported pem encoded key/cert in config, play
379- # nice on upgrades as we now expect base64 encoded key/cert/ca.
380- if not v:
381- return v
382- if v.startswith('-----BEGIN'):
383- return v
384- try:
385- return base64.b64decode(v)
386- except TypeError:
387- return v
388-
389-
390-def reconfigure_client_ssl(ssl_enabled=False):
391- ssl_config_keys = set(('ssl_key', 'ssl_cert', 'ssl_ca'))
392- for rid in relation_ids('amqp'):
393- rdata = relation_get(rid=rid, unit=os.environ['JUJU_UNIT_NAME'])
394- if not ssl_enabled and ssl_config_keys.intersection(rdata):
395- # No clean way to remove entirely, but blank them.
396- relation_set(relation_id=rid, ssl_key='', ssl_cert='', ssl_ca='')
397- elif ssl_enabled and not ssl_config_keys.intersection(rdata):
398- configure_client_ssl(rdata)
399- relation_set(relation_id=rid, **rdata)
400-
401-
402-def configure_rabbit_ssl():
403- """
404- The legacy config support adds some additional complications.
405-
406- ssl_enabled = True, ssl = off -> ssl enabled
407- ssl_enabled = False, ssl = on -> ssl enabled
408- """
409- ssl_mode, external_ca = _get_ssl_mode()
410-
411- if ssl_mode == 'off':
412- if os.path.exists(rabbit.RABBITMQ_CONF):
413- os.remove(rabbit.RABBITMQ_CONF)
414- close_port(config('ssl_port'))
415- reconfigure_client_ssl()
416- return
417- ssl_key = _convert_from_base64(config('ssl_key'))
418- ssl_cert = _convert_from_base64(config('ssl_cert'))
419- ssl_ca = _convert_from_base64(config('ssl_ca'))
420- ssl_port = config('ssl_port')
421-
422- # If external managed certs then we need all the fields.
423- if (ssl_mode in ('on', 'only') and any((ssl_key, ssl_cert)) and
424- not all((ssl_key, ssl_cert))):
425- log('If ssl_key or ssl_cert are specified both are required.',
426- level=ERROR)
427- sys.exit(1)
428-
429- if not external_ca:
430- ssl_cert, ssl_key, ssl_ca = ServiceCA.get_service_cert()
431-
432- rabbit.enable_ssl(
433- ssl_key, ssl_cert, ssl_port, ssl_ca,
434- ssl_only=(ssl_mode == "only"), ssl_client=False)
435- reconfigure_client_ssl(True)
436- open_port(ssl_port)
437-
438-
439 @hooks.hook('config-changed')
440 @restart_on_change(rabbit.restart_map())
441 def config_changed():
442+
443 if config('prefer-ipv6'):
444 rabbit.assert_charm_supports_ipv6()
445
446@@ -652,9 +546,9 @@
447 rabbit.disable_plugin(MAN_PLUGIN)
448 close_port(55672)
449
450- configure_rabbit_ssl()
451-
452 rabbit.set_all_mirroring_queues(config('mirroring-queues'))
453+ rabbit.ConfigRenderer(
454+ rabbit.CONFIG_FILES).write_all()
455
456 if is_relation_made("ha"):
457 ha_is_active_active = config("ha-vip-only")
458
459=== added file 'hooks/ssl_utils.py'
460--- hooks/ssl_utils.py 1970-01-01 00:00:00 +0000
461+++ hooks/ssl_utils.py 2015-04-10 02:40:31 +0000
462@@ -0,0 +1,55 @@
463+from charmhelpers.contrib.ssl.service import ServiceCA
464+
465+from charmhelpers.core.hookenv import (
466+ config,
467+ relation_ids,
468+ relation_set,
469+ relation_get,
470+)
471+
472+import base64
473+import os
474+
475+
476+def get_ssl_mode():
477+ ssl_mode = config('ssl')
478+ external_ca = False
479+ # Legacy config boolean option
480+ ssl_on = config('ssl_enabled')
481+ if ssl_mode == 'off' and ssl_on is False:
482+ ssl_mode = 'off'
483+ elif ssl_mode == 'off' and ssl_on:
484+ ssl_mode = 'on'
485+ ssl_key = config('ssl_key')
486+ ssl_cert = config('ssl_cert')
487+ if all((ssl_key, ssl_cert)):
488+ external_ca = True
489+ return ssl_mode, external_ca
490+
491+
492+def configure_client_ssl(relation_data):
493+ """Configure client with ssl
494+ """
495+ ssl_mode, external_ca = get_ssl_mode()
496+ if ssl_mode == 'off':
497+ return
498+ relation_data['ssl_port'] = config('ssl_port')
499+ if external_ca:
500+ if config('ssl_ca'):
501+ relation_data['ssl_ca'] = base64.b64encode(
502+ config('ssl_ca'))
503+ return
504+ ca = ServiceCA.get_ca()
505+ relation_data['ssl_ca'] = base64.b64encode(ca.get_ca_bundle())
506+
507+
508+def reconfigure_client_ssl(ssl_enabled=False):
509+ ssl_config_keys = set(('ssl_key', 'ssl_cert', 'ssl_ca'))
510+ for rid in relation_ids('amqp'):
511+ rdata = relation_get(rid=rid, unit=os.environ['JUJU_UNIT_NAME'])
512+ if not ssl_enabled and ssl_config_keys.intersection(rdata):
513+ # No clean way to remove entirely, but blank them.
514+ relation_set(relation_id=rid, ssl_key='', ssl_cert='', ssl_ca='')
515+ elif ssl_enabled and not ssl_config_keys.intersection(rdata):
516+ configure_client_ssl(rdata)
517+ relation_set(relation_id=rid, **rdata)
518
519=== modified file 'templates/rabbitmq.config'
520--- templates/rabbitmq.config 2014-05-23 08:13:05 +0000
521+++ templates/rabbitmq.config 2015-04-10 02:40:31 +0000
522@@ -1,21 +1,35 @@
523 [
524- {rabbit, [
525-{% if ssl_only %}
526+ {rabbit, [
527+{% if ssl_only %}
528 {tcp_listeners, []},
529 {% else %}
530 {tcp_listeners, [5672]},
531 {% endif %}
532- {ssl_listeners, [{{ ssl_port }}]},
533+{% if ssl_port %}
534+ {ssl_listeners, [{{ ssl_port }}]},
535+{% endif %}
536+{% if ssl_mode == "on" %}
537 {ssl_options, [
538 {verify, verify_peer},
539-{% if ssl_client %}
540- {fail_if_no_peer_cert, true},
541+{% if ssl_client %}
542+ {fail_if_no_peer_cert, true},
543 {% else %}
544 {fail_if_no_peer_cert, false},
545-{% endif %}{% if ssl_ca_file %}
546- {cacertfile, "{{ ssl_ca_file }}"}, {% endif %}
547- {certfile, "{{ ssl_cert_file }}"},
548- {keyfile, "{{ ssl_key_file }}"}
549- ]}
550+{% endif %}
551+ {% if ssl_ca_file %}
552+ {cacertfile, "{{ ssl_ca_file }}"},
553+ {% endif %}
554+ {% if ssl_cert_file %}
555+ {certfile, "{{ ssl_cert_file }}"},
556+ {% endif %}
557+ {% if ssl_key_file %}
558+ {keyfile, "{{ ssl_key_file }}"}
559+ {% endif %}
560+ ]},
561+{% endif %}
562+
563+ {% if cluster_partition_handling %}
564+ {cluster_partition_handling, {{ cluster_partition_handling }}}
565+ {% endif %}
566 ]}
567-].
568\ No newline at end of file
569+].
570
571=== modified file 'tests/00_setup.sh'
572--- tests/00_setup.sh 2015-03-12 16:42:09 +0000
573+++ tests/00_setup.sh 2015-04-10 02:40:31 +0000
574@@ -15,4 +15,7 @@
575 # Install any additional python packages, or software here.
576 sudo apt-get install -y python python-pika python3-requests python3-setuptools
577
578+# Set http proxy if amulet is using one.
579+[[ -n "$AMULET_HTTP_PROXY" ]] && export http_proxy="$AMULET_HTTP_PROXY" && https_proxy="$AMULET_HTTP_PROXY"
580+
581 sudo easy_install3 python3-pika
582
583=== added file 'tests/50_test_cluster_partition.py'
584--- tests/50_test_cluster_partition.py 1970-01-01 00:00:00 +0000
585+++ tests/50_test_cluster_partition.py 2015-04-10 02:40:31 +0000
586@@ -0,0 +1,31 @@
587+#!/usr/bin/python
588+#
589+# This Amulet test deploys rabbitmq-server
590+#
591+# Note: We use python2, because pika doesn't support python3
592+import amulet
593+
594+# The number of seconds to wait for the environment to setup.
595+seconds = 1200
596+d = amulet.Deployment(series="trusty")
597+
598+d.add('rabbitmq-server', units=1)
599+# Create a configuration.
600+configuration = {'cluster-partition-handling': "autoheal"}
601+d.configure('rabbitmq-server', configuration)
602+
603+d.expose('rabbitmq-server')
604+try:
605+ d.setup(timeout=seconds)
606+ d.sentry.wait(seconds)
607+except amulet.helpers.TimeoutError:
608+ message = 'The environment did not setup in %d seconds.' % seconds
609+ amulet.raise_status(amulet.SKIP, msg=message)
610+except:
611+ raise
612+
613+rabbit_unit = d.sentry.unit['rabbitmq-server/0']
614+output, code = rabbit_unit.run("grep autoheal /etc/rabbitmq/rabbitmq.conf")
615+
616+if code != 0 or output == "":
617+ amulet.raise_status(amulet.FAIL, msg=message)
618
619=== modified file 'unit_tests/test_rabbit_utils.py'
620--- unit_tests/test_rabbit_utils.py 2014-10-08 15:57:57 +0000
621+++ unit_tests/test_rabbit_utils.py 2015-04-10 02:40:31 +0000
622@@ -4,8 +4,8 @@
623 import tempfile
624 import sys
625
626+import rabbit_utils
627 sys.modules['MySQLdb'] = mock.Mock()
628-import rabbit_utils
629
630
631 class UtilsTests(unittest.TestCase):
632
633=== added file 'unit_tests/test_rabbitmq_context.py'
634--- unit_tests/test_rabbitmq_context.py 1970-01-01 00:00:00 +0000
635+++ unit_tests/test_rabbitmq_context.py 2015-04-10 02:40:31 +0000
636@@ -0,0 +1,79 @@
637+import rabbitmq_context
638+
639+import mock
640+import unittest
641+
642+
643+class TestRabbitMQSSLContext(unittest.TestCase):
644+
645+ @mock.patch("rabbitmq_context.config")
646+ @mock.patch("rabbitmq_context.close_port")
647+ @mock.patch("rabbitmq_context.ssl_utils.reconfigure_client_ssl")
648+ @mock.patch("rabbitmq_context.ssl_utils.get_ssl_mode")
649+ def test_context_ssl_off(self, get_ssl_mode, reconfig_ssl, close_port,
650+ config):
651+ get_ssl_mode.return_value = ("off", "off")
652+ self.assertEqual(rabbitmq_context.RabbitMQSSLContext().__call__(), {
653+ "ssl_mode": "off"
654+ })
655+
656+ close_port.assert_called_once()
657+ reconfig_ssl.assert_called_once()
658+
659+ @mock.patch("rabbitmq_context.open_port")
660+ @mock.patch("rabbitmq_context.os.chmod")
661+ @mock.patch("rabbitmq_context.os.chown")
662+ @mock.patch("rabbitmq_context.pwd.getpwnam")
663+ @mock.patch("rabbitmq_context.grp.getgrnam")
664+ @mock.patch("rabbitmq_context.config")
665+ @mock.patch("rabbitmq_context.close_port")
666+ @mock.patch("rabbitmq_context.ssl_utils.reconfigure_client_ssl")
667+ @mock.patch("rabbitmq_context.ssl_utils.get_ssl_mode")
668+ def test_context_ssl_on(self, get_ssl_mode, reconfig_ssl, close_port,
669+ config, gr, pw, chown, chmod, open_port):
670+
671+ get_ssl_mode.return_value = ("on", "on")
672+
673+ def config_get(n):
674+ return None
675+
676+ config.side_effect = config_get
677+
678+ def pw(name):
679+ class Uid(object):
680+ pw_uid = 1
681+ gr_gid = 100
682+ return Uid()
683+
684+ pw.side_effect = pw
685+ gr.side_effect = pw
686+
687+ m = mock.mock_open()
688+ with mock.patch('rabbitmq_context.open', m, create=True):
689+ self.assertEqual(
690+ rabbitmq_context.RabbitMQSSLContext().__call__(), {
691+ "ssl_port": None,
692+ "ssl_cert_file": "/etc/rabbitmq/rabbit-server-cert.pem",
693+ "ssl_key_file": '/etc/rabbitmq/rabbit-server-privkey.pem',
694+ "ssl_client": False,
695+ "ssl_ca_file": "",
696+ "ssl_only": False,
697+ "ssl_mode": "on",
698+ })
699+
700+ reconfig_ssl.assert_called_once()
701+ open_port.assert_called_once()
702+
703+
704+class TestRabbitMQClusterContext(unittest.TestCase):
705+
706+ @mock.patch("rabbitmq_context.config")
707+ def test_context_ssl_off(self, config):
708+ config.return_value = "ignore"
709+
710+ self.assertEqual(
711+ rabbitmq_context.RabbitMQClusterContext().__call__(), {
712+ 'cluster_partition_handling': "ignore"
713+ })
714+
715+ config.assert_called_once_with("cluster-partition-handling")
716
717=== modified file 'unit_tests/test_rabbitmq_server_relations.py'
718--- unit_tests/test_rabbitmq_server_relations.py 2015-01-23 08:23:05 +0000
719+++ unit_tests/test_rabbitmq_server_relations.py 2015-04-10 02:40:31 +0000
720@@ -2,7 +2,7 @@
721 from testtools import TestCase
722 from mock import patch, MagicMock
723
724-os.environ['JUJU_UNIT_NAME'] = 'UNIT_TEST/0'
725+os.environ['JUJU_UNIT_NAME'] = 'UNIT_TEST/0' # noqa - needed for import
726 import rabbitmq_server_relations
727
728
729@@ -37,7 +37,7 @@
730 @patch('rabbitmq_server_relations.relation_set')
731 @patch('apt_pkg.Cache')
732 @patch('rabbitmq_server_relations.is_clustered')
733- @patch('rabbitmq_server_relations.configure_client_ssl')
734+ @patch('rabbitmq_server_relations.ssl_utils.configure_client_ssl')
735 @patch('rabbitmq_server_relations.unit_get')
736 @patch('rabbitmq_server_relations.relation_get')
737 @patch('rabbitmq_server_relations.is_elected_leader')
738@@ -87,7 +87,7 @@
739 @patch('rabbitmq_server_relations.relation_set')
740 @patch('apt_pkg.Cache')
741 @patch('rabbitmq_server_relations.is_clustered')
742- @patch('rabbitmq_server_relations.configure_client_ssl')
743+ @patch('rabbitmq_server_relations.ssl_utils.configure_client_ssl')
744 @patch('rabbitmq_server_relations.unit_get')
745 @patch('rabbitmq_server_relations.relation_get')
746 @patch('rabbitmq_server_relations.is_elected_leader')

Subscribers

People subscribed via source and target branches