Merge lp:~mbruzek/charms/precise/rabbitmq-server/add-tests into lp:charms/rabbitmq-server
- Precise Pangolin (12.04)
- add-tests
- Merge into trunk
Proposed by
Matt Bruzek
Status: | Merged |
---|---|
Merged at revision: | 74 |
Proposed branch: | lp:~mbruzek/charms/precise/rabbitmq-server/add-tests |
Merge into: | lp:charms/rabbitmq-server |
Diff against target: |
657 lines (+605/-1) 9 files modified
Makefile (+5/-1) tests/00_setup.sh (+16/-0) tests/10_basic_deploy_test.py (+101/-0) tests/20_deploy_relations_test.py (+214/-0) tests/30_configuration_test.py (+142/-0) tests/amqp_tester.py (+65/-0) tests/rabbit-server-cacert.pem (+17/-0) tests/rabbit-server-cert.pem (+18/-0) tests/rabbit-server-privkey.pem (+27/-0) |
To merge this branch: | bzr merge lp:~mbruzek/charms/precise/rabbitmq-server/add-tests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Review Queue (community) | automated testing | Needs Fixing | |
José Antonio Rey (community) | charmers | Approve | |
Ryan Beisner (community) | Approve | ||
Review via email: mp+246025@code.launchpad.net |
Commit message
Description of the change
Adding tests for the rabbitmq-server charm.
To post a comment you must log in.
Revision history for this message
Ryan Beisner (1chb1n) wrote : | # |
- 76. By Matt Bruzek
-
Adding Makefile changes
Revision history for this message
Matt Bruzek (mbruzek) wrote : | # |
Thanks for the review. I added the functional_test target to the Makefile so these tests work on both testing systems. Charmers please review these changes for inclusion to the precise charm.
Revision history for this message
Ryan Beisner (1chb1n) wrote : | # |
Re-confirmed with rev76. Precise charm amulet tests succeed. Clear from the OSCI perspective. Thanks again!
review:
Approve
Revision history for this message
José Antonio Rey (jose) wrote : | # |
Hey Matt!
Thank you for taking the time to write this tests. I have ran them on EC2, and turns out they successfully pass!
I will be pushing these on the next few minutes. Thanks again!
review:
Approve
(charmers)
Revision history for this message
Review Queue (review-queue) wrote : | # |
This items has failed automated testing! Results available here http://
review:
Needs Fixing
(automated testing)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Makefile' | |||
2 | --- Makefile 2014-10-08 15:57:57 +0000 | |||
3 | +++ Makefile 2015-01-12 15:19:55 +0000 | |||
4 | @@ -20,7 +20,11 @@ | |||
5 | 20 | bzr push lp:charms/rabbitmq-server | 20 | bzr push lp:charms/rabbitmq-server |
6 | 21 | bzr push lp:charms/trusty/rabbitmq-server | 21 | bzr push lp:charms/trusty/rabbitmq-server |
7 | 22 | 22 | ||
8 | 23 | functional_test: | ||
9 | 24 | @echo Starting functional tests... | ||
10 | 25 | @juju test -v -p AMULET_HTTP_PROXY --timeout 900 | ||
11 | 26 | |||
12 | 23 | unit_test: | 27 | unit_test: |
14 | 24 | @echo Starting tests... | 28 | @echo Starting unit tests... |
15 | 25 | CHARM_DIR=$(CHARM_DIR) $(TEST_PREFIX) nosetests unit_tests | 29 | CHARM_DIR=$(CHARM_DIR) $(TEST_PREFIX) nosetests unit_tests |
16 | 26 | 30 | ||
17 | 27 | 31 | ||
18 | === added directory 'tests' | |||
19 | === added file 'tests/00_setup.sh' | |||
20 | --- tests/00_setup.sh 1970-01-01 00:00:00 +0000 | |||
21 | +++ tests/00_setup.sh 2015-01-12 15:19:55 +0000 | |||
22 | @@ -0,0 +1,16 @@ | |||
23 | 1 | #!/bin/sh | ||
24 | 2 | |||
25 | 3 | # Install Juju Amulet and any other applications that are needed for the tests. | ||
26 | 4 | |||
27 | 5 | set -x | ||
28 | 6 | |||
29 | 7 | # Check if amulet is installed before adding repository and updating apt-get. | ||
30 | 8 | dpkg -s amulet | ||
31 | 9 | if [ $? -ne 0 ]; then | ||
32 | 10 | sudo add-apt-repository -y ppa:juju/stable | ||
33 | 11 | sudo apt-get update | ||
34 | 12 | sudo apt-get install -y amulet | ||
35 | 13 | fi | ||
36 | 14 | |||
37 | 15 | # Install any additional python packages, or software here. | ||
38 | 16 | sudo apt-get install -y python python-pika python3-requests | ||
39 | 0 | 17 | ||
40 | === added file 'tests/10_basic_deploy_test.py' | |||
41 | --- tests/10_basic_deploy_test.py 1970-01-01 00:00:00 +0000 | |||
42 | +++ tests/10_basic_deploy_test.py 2015-01-12 15:19:55 +0000 | |||
43 | @@ -0,0 +1,101 @@ | |||
44 | 1 | #!/usr/bin/python3 | ||
45 | 2 | |||
46 | 3 | # This Amulet test performs a basic deploy and checks if rabbitmq is running. | ||
47 | 4 | |||
48 | 5 | import amulet | ||
49 | 6 | import os | ||
50 | 7 | import socket | ||
51 | 8 | import ssl | ||
52 | 9 | |||
53 | 10 | # The number of seconds to wait for the environment to setup. | ||
54 | 11 | seconds = 900 | ||
55 | 12 | # Get the directory in this way to load the files from the tests directory. | ||
56 | 13 | path = os.path.abspath(os.path.dirname(__file__)) | ||
57 | 14 | |||
58 | 15 | key_path = os.path.join(path, 'rabbit-server-privkey.pem') | ||
59 | 16 | # Read the private key file. | ||
60 | 17 | with open(key_path) as f: | ||
61 | 18 | privateKey = f.read() | ||
62 | 19 | # Read the certificate file. | ||
63 | 20 | cert_path = os.path.join(path, 'rabbit-server-cert.pem') | ||
64 | 21 | with open(cert_path) as f: | ||
65 | 22 | certificate = f.read() | ||
66 | 23 | |||
67 | 24 | # Create a dictionary for the rabbitmq configuration. | ||
68 | 25 | rabbitmq_configuration = { | ||
69 | 26 | 'ssl_enabled': True, | ||
70 | 27 | 'ssl_key': privateKey, | ||
71 | 28 | 'ssl_cert': certificate, | ||
72 | 29 | 'ssl_port': 5671 | ||
73 | 30 | } | ||
74 | 31 | |||
75 | 32 | d = amulet.Deployment() | ||
76 | 33 | # Add the rabbitmq-server charm to the deployment. | ||
77 | 34 | d.add('rabbitmq-server') | ||
78 | 35 | # Configure options on the rabbitmq-server. | ||
79 | 36 | d.configure('rabbitmq-server', rabbitmq_configuration) | ||
80 | 37 | # Expose the server so we can connect. | ||
81 | 38 | d.expose('rabbitmq-server') | ||
82 | 39 | |||
83 | 40 | try: | ||
84 | 41 | # Execute the deployer with the current mapping. | ||
85 | 42 | d.setup(timeout=seconds) | ||
86 | 43 | except amulet.helpers.TimeoutError: | ||
87 | 44 | message = 'The environment did not setup in %d seconds.' % seconds | ||
88 | 45 | # The SKIP status enables skip or fail the test based on configuration. | ||
89 | 46 | amulet.raise_status(amulet.SKIP, msg=message) | ||
90 | 47 | except: | ||
91 | 48 | raise | ||
92 | 49 | print('The rabbitmq-server has been successfully deployed.') | ||
93 | 50 | |||
94 | 51 | ############################################################################### | ||
95 | 52 | ## Verify that the rabbit service is running on the deployed server. | ||
96 | 53 | ############################################################################### | ||
97 | 54 | rabbitmq_sentry = d.sentry.unit['rabbitmq-server/0'] | ||
98 | 55 | # Get the public address for rabbitmq-server instance. | ||
99 | 56 | server_address = rabbitmq_sentry.info['public-address'] | ||
100 | 57 | # Create the command that checks if the rabbitmq-server service is running. | ||
101 | 58 | command = 'rabbitmqctl status' | ||
102 | 59 | print(command) | ||
103 | 60 | # Execute the command on the deployed service. | ||
104 | 61 | output, code = rabbitmq_sentry.run(command) | ||
105 | 62 | print(output) | ||
106 | 63 | # Check the return code for the success and failure of this test. | ||
107 | 64 | if (code != 0): | ||
108 | 65 | message = 'The ' + command + ' did not return the expected code of 0.' | ||
109 | 66 | amulet.raise_status(amulet.FAIL, msg=message) | ||
110 | 67 | else: | ||
111 | 68 | print('The rabbitmq-server is running on %s' % server_address) | ||
112 | 69 | |||
113 | 70 | ############################################################################### | ||
114 | 71 | ## Test the ssl certificate. | ||
115 | 72 | ############################################################################### | ||
116 | 73 | # Get the port for ssl_port instance. | ||
117 | 74 | server_port = rabbitmq_configuration['ssl_port'] | ||
118 | 75 | |||
119 | 76 | # Get the path to the certificate authority file. | ||
120 | 77 | ca_cert_path = os.path.join(path, 'rabbit-server-cacert.pem') | ||
121 | 78 | |||
122 | 79 | print('Testing ssl connection to rabbitmq-server.') | ||
123 | 80 | try: | ||
124 | 81 | # Create a normal socket. | ||
125 | 82 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
126 | 83 | # Require a certificate from the server, since a self-signed certificate | ||
127 | 84 | # was used, the ca_certs must be the server certificate file itself. | ||
128 | 85 | ssl_sock = ssl.wrap_socket(s, ca_certs=ca_cert_path, | ||
129 | 86 | cert_reqs=ssl.CERT_REQUIRED) | ||
130 | 87 | # Connect to the rabbitmq server using ssl. | ||
131 | 88 | ssl_sock.connect((server_address, server_port)) | ||
132 | 89 | # Get the certificate. | ||
133 | 90 | certificate = ssl_sock.getpeercert() | ||
134 | 91 | # SSL socket connected and got the certificate, this passes the ssl test! | ||
135 | 92 | print('Connected to the rabbitmq-server {0}:{1} using ssl!'.format( | ||
136 | 93 | server_address, server_port)) | ||
137 | 94 | except Exception as e: | ||
138 | 95 | message = 'Failed to create an ssl connection to {0}:{1}\n{2}'.format( | ||
139 | 96 | server_address, server_port, str(e)) | ||
140 | 97 | amulet.raise_status(amulet.FAIL, msg=message) | ||
141 | 98 | finally: | ||
142 | 99 | ssl_sock.close() | ||
143 | 100 | |||
144 | 101 | print('The rabbitmq-server passed the basic deploy test!') | ||
145 | 0 | 102 | ||
146 | === added file 'tests/20_deploy_relations_test.py' | |||
147 | --- tests/20_deploy_relations_test.py 1970-01-01 00:00:00 +0000 | |||
148 | +++ tests/20_deploy_relations_test.py 2015-01-12 15:19:55 +0000 | |||
149 | @@ -0,0 +1,214 @@ | |||
150 | 1 | #!/usr/bin/python3 | ||
151 | 2 | |||
152 | 3 | # This Amulet test deploys rabbitmq-server, and the related charms. | ||
153 | 4 | |||
154 | 5 | import amulet | ||
155 | 6 | import os | ||
156 | 7 | import subprocess | ||
157 | 8 | import time | ||
158 | 9 | |||
159 | 10 | # The number of seconds to wait for the environment to setup. | ||
160 | 11 | seconds = 900 | ||
161 | 12 | # The number of units to scale rabbitmq-server to. | ||
162 | 13 | scale = 2 | ||
163 | 14 | # The port that amqp traffic is sent on. | ||
164 | 15 | amqp_port = '5672' | ||
165 | 16 | # The directory to use as a block devie for the ceph | ||
166 | 17 | devices = '/srv/osd1' | ||
167 | 18 | # The default version of ceph does not support directories as devices. | ||
168 | 19 | havana = 'cloud:precise-updates/havana' | ||
169 | 20 | # Create a dictionary of configuration values for ceph. | ||
170 | 21 | ceph_configuration = { | ||
171 | 22 | 'fsid': 'ecbb8960-0e21-11e2-b495-83a88f44db01', | ||
172 | 23 | 'monitor-secret': 'AQBomftSyK1LORAAhg71ukxBxN9ml90stexqEw==', | ||
173 | 24 | 'osd-devices': devices, | ||
174 | 25 | 'source': havana | ||
175 | 26 | } | ||
176 | 27 | # Create a dictionary of configuration values for cinder. | ||
177 | 28 | cinder_configuration = { | ||
178 | 29 | 'block-device': 'None' | ||
179 | 30 | } | ||
180 | 31 | # Create a dictionary of the rabbit configuration values. | ||
181 | 32 | rabbit_configuration = { | ||
182 | 33 | 'vip': '192.168.77.11', | ||
183 | 34 | 'vip_cidr': 19, | ||
184 | 35 | 'vip_iface': 'eth0', | ||
185 | 36 | 'ha-bindiface': 'eth0', | ||
186 | 37 | 'ha-mcastport': 5406, | ||
187 | 38 | 'rbd-size': '2G', | ||
188 | 39 | 'rbd-name': 'testrabbit1' | ||
189 | 40 | } | ||
190 | 41 | |||
191 | 42 | # The AMQP package is only available for python version 2.x. | ||
192 | 43 | python2 = '/usr/bin/python' | ||
193 | 44 | if not os.path.isfile(python2): | ||
194 | 45 | error_message = 'Error, python version 2 is required for this test.' | ||
195 | 46 | amulet.raise_status(amulet.FAIL, msg=error_message) | ||
196 | 47 | |||
197 | 48 | d = amulet.Deployment() | ||
198 | 49 | # Add rabbitmq-server to the deployment. | ||
199 | 50 | d.add('rabbitmq-server', units=scale) | ||
200 | 51 | # Add the ceph charm to the deployment. | ||
201 | 52 | d.add('ceph') | ||
202 | 53 | # Add cinder to the deployment to test the AMQP relation. | ||
203 | 54 | d.add('cinder') | ||
204 | 55 | # Add hacluster to the deployment to test the ha relation. | ||
205 | 56 | d.add('hacluster') | ||
206 | 57 | # The ceph charm requires configuration to deploy successfully. | ||
207 | 58 | d.configure('ceph', ceph_configuration) | ||
208 | 59 | # Configure the cinder charm. | ||
209 | 60 | d.configure('cinder', cinder_configuration) | ||
210 | 61 | # Configure the rabbit charm. | ||
211 | 62 | d.configure('rabbitmq-server', rabbit_configuration) | ||
212 | 63 | # Add relation from rabbitmq-server to ceph testing the ceph relation. | ||
213 | 64 | d.relate('rabbitmq-server:ceph', 'ceph:client') | ||
214 | 65 | # Add relation from rabbitmq-server to cinder testing the amqp relation. | ||
215 | 66 | d.relate('rabbitmq-server:amqp', 'cinder:amqp') | ||
216 | 67 | # Add relation from rabibtmq-server to hacluster testing the ha relation. | ||
217 | 68 | d.relate('rabbitmq-server:ha', 'hacluster:ha') | ||
218 | 69 | # Expose the rabbitmq-server. | ||
219 | 70 | d.expose('rabbitmq-server') | ||
220 | 71 | |||
221 | 72 | try: | ||
222 | 73 | # Execute the deployer with the current mapping. | ||
223 | 74 | d.setup(timeout=seconds) | ||
224 | 75 | # Wait for the relation to finish the transations. | ||
225 | 76 | d.sentry.wait(seconds) | ||
226 | 77 | except amulet.helpers.TimeoutError: | ||
227 | 78 | message = 'The environment did not setup in %d seconds.' % seconds | ||
228 | 79 | # The SKIP status enables skip or fail the test based on configuration. | ||
229 | 80 | amulet.raise_status(amulet.FAIL, msg=message) | ||
230 | 81 | except: | ||
231 | 82 | raise | ||
232 | 83 | print('The environment successfully deployed.') | ||
233 | 84 | |||
234 | 85 | # Create a counter to make the messages unique. | ||
235 | 86 | counter = 1 | ||
236 | 87 | # Get the directory in this way to load the files from the tests directory. | ||
237 | 88 | path = os.path.abspath(os.path.dirname(__file__)) | ||
238 | 89 | # Create a path to the python test file to call. | ||
239 | 90 | amqp_tester = os.path.join(path, 'amqp_tester.py') | ||
240 | 91 | if not os.path.isfile(amqp_tester): | ||
241 | 92 | error_message = 'Unable to locate python test file %s' % amqp_tester | ||
242 | 93 | amulet.raise_status(amulet.FAIL, msg=error_message) | ||
243 | 94 | |||
244 | 95 | # Verify the ceph unit was created. | ||
245 | 96 | ceph_unit = d.sentry.unit['ceph/0'] | ||
246 | 97 | # Verify the cinder unit was created. | ||
247 | 98 | cinder_unit = d.sentry.unit['cinder/0'] | ||
248 | 99 | rabbit_units = [] | ||
249 | 100 | for n in range(scale): | ||
250 | 101 | # Get each rabbitmq unit that was deployed. | ||
251 | 102 | rabbit_units.append(d.sentry.unit['rabbitmq-server/%d' % n]) | ||
252 | 103 | |||
253 | 104 | # Iterate over every rabbitmq-unit to get the different relations. | ||
254 | 105 | for rabbit_unit in rabbit_units: | ||
255 | 106 | ########################################################################### | ||
256 | 107 | ## Test Relations | ||
257 | 108 | ########################################################################### | ||
258 | 109 | # Verify the ceph relation was created for the rabbit unit. | ||
259 | 110 | rabbit_relation = rabbit_unit.relation('ceph', 'ceph:client') | ||
260 | 111 | print('rabbit relation to ceph:') | ||
261 | 112 | for key, value in rabbit_relation.items(): | ||
262 | 113 | print(key, value) | ||
263 | 114 | # Verify the amqp relation was created for the rabbit unit. | ||
264 | 115 | rabbit_relation = rabbit_unit.relation('amqp', 'cinder:amqp') | ||
265 | 116 | print('rabbit relation to amqp:') | ||
266 | 117 | for key, value in rabbit_relation.items(): | ||
267 | 118 | print(key, value) | ||
268 | 119 | |||
269 | 120 | # The hacluster charm is a subordinate, since the relation-sentry is also | ||
270 | 121 | # a subordinate charm no sentry is created for the hacluster relation. | ||
271 | 122 | |||
272 | 123 | # Verify the rabbit relation was created with the ceph unit. | ||
273 | 124 | ceph_relation = ceph_unit.relation('client', 'rabbitmq-server:ceph') | ||
274 | 125 | print('ceph relation to rabbitmq-server:') | ||
275 | 126 | for key, value in ceph_relation.items(): | ||
276 | 127 | print(key, value) | ||
277 | 128 | # Verify the rabbit relation was created with the cinder unit. | ||
278 | 129 | cinder_relation = cinder_unit.relation('amqp', 'rabbitmq-server:amqp') | ||
279 | 130 | print('cinder relation to rabbitmq-server:') | ||
280 | 131 | for key, value in cinder_relation.items(): | ||
281 | 132 | print(key, value) | ||
282 | 133 | |||
283 | 134 | ########################################################################### | ||
284 | 135 | ## Test AMQP | ||
285 | 136 | ########################################################################### | ||
286 | 137 | |||
287 | 138 | # The AMQP python library is only available for python2 at this time. | ||
288 | 139 | # Call out a command to run the python2 code to test the AMQP protocol. | ||
289 | 140 | |||
290 | 141 | # Get the public address for rabbitmq-server instance. | ||
291 | 142 | server_address = rabbit_unit.info['public-address'] | ||
292 | 143 | # Create a time stamp to help make the AMQP message unique. | ||
293 | 144 | time_stamp = time.strftime('%F %r') | ||
294 | 145 | # Create the message to send on the AMPQ protocol. | ||
295 | 146 | amqp_message = "Message #{0} to send using the AMPQ protocol {1}".format( | ||
296 | 147 | counter, time_stamp) | ||
297 | 148 | # Create the command with arguments that sends the message. | ||
298 | 149 | send_command = [python2, amqp_tester, server_address, amqp_port, | ||
299 | 150 | amqp_message] | ||
300 | 151 | print(send_command) | ||
301 | 152 | # Call the python command to send the AMQP message to the server. | ||
302 | 153 | output = subprocess.check_output(send_command) | ||
303 | 154 | # Create the command with arguments to receive messages. | ||
304 | 155 | receive_command = [python2, amqp_tester, server_address, amqp_port] | ||
305 | 156 | print(receive_command) | ||
306 | 157 | # Call the python command to receive the AMQP message from the same server. | ||
307 | 158 | output = subprocess.check_output(receive_command) | ||
308 | 159 | # The output is a byte string so convert the message to a byte string. | ||
309 | 160 | if output.find(amqp_message.encode()) == -1: | ||
310 | 161 | print('The AMQP test to {0}:{1} failed.'.format(server_address, | ||
311 | 162 | amqp_port)) | ||
312 | 163 | amulet.raise_status(amulet.FAIL, msg=output) | ||
313 | 164 | else: | ||
314 | 165 | print('The AMQP test to {0}:{1} completed successfully.'.format( | ||
315 | 166 | server_address, amqp_port)) | ||
316 | 167 | counter += 1 | ||
317 | 168 | |||
318 | 169 | ########################################################################### | ||
319 | 170 | ## Verify that the rabbitmq cluster status is correct. | ||
320 | 171 | ########################################################################### | ||
321 | 172 | # Create the command that checks if the rabbitmq-server service is running. | ||
322 | 173 | command = 'rabbitmqctl cluster_status' | ||
323 | 174 | print(command) | ||
324 | 175 | # Execute the command on the deployed service. | ||
325 | 176 | output, code = rabbit_unit.run(command) | ||
326 | 177 | print(output) | ||
327 | 178 | # Check the return code for the success and failure of this test. | ||
328 | 179 | if (code != 0): | ||
329 | 180 | message = 'The ' + command + ' did not return the expected code of 0.' | ||
330 | 181 | amulet.raise_status(amulet.FAIL, msg=message) | ||
331 | 182 | else: | ||
332 | 183 | print('The rabbitmq-server cluster status is OK.') | ||
333 | 184 | |||
334 | 185 | ############################################################################### | ||
335 | 186 | ## Test the AMQP messages can be sent from and read from another. | ||
336 | 187 | ############################################################################### | ||
337 | 188 | # Get the public address for rabbitmq-server instance 0. | ||
338 | 189 | send_address = rabbit_units[0].info['public-address'] | ||
339 | 190 | # Create a message to send from instance 0 and read it from instance 1. | ||
340 | 191 | amqp_message = "Message #{0} sent from {1} using the AMQP protocol.".format( | ||
341 | 192 | counter, send_address) | ||
342 | 193 | counter += 1 | ||
343 | 194 | # Create the command that sends the message to instance 0. | ||
344 | 195 | send_command = [python2, amqp_tester, send_address, amqp_port, amqp_message] | ||
345 | 196 | print(send_command) | ||
346 | 197 | output = subprocess.check_output(send_command) | ||
347 | 198 | # Get the public address for rabbitmq-server instance 1. | ||
348 | 199 | receive_address = rabbit_units[1].info['public-address'] | ||
349 | 200 | # Create the command that receives the message from instance 1. | ||
350 | 201 | recieve_command = [python2, amqp_tester, receive_address, amqp_port] | ||
351 | 202 | print(recieve_command) | ||
352 | 203 | output = subprocess.check_output(receive_command) | ||
353 | 204 | # The output is a byte string so convert the message to a byte string. | ||
354 | 205 | if output.find(amqp_message.encode()) == -1: | ||
355 | 206 | print(output) | ||
356 | 207 | message = 'Server {0} did not receive the AMQP message "{1}"'.format( | ||
357 | 208 | receive_address, amqp_message) | ||
358 | 209 | amulet.raise_status(amulet.FAIL, msg=message) | ||
359 | 210 | else: | ||
360 | 211 | print('Server {0} received the AMQP message sent from {1}'.format( | ||
361 | 212 | receive_address, send_address)) | ||
362 | 213 | |||
363 | 214 | print('The rabbitmq-server charm passed this relations test.') | ||
364 | 0 | 215 | ||
365 | === added file 'tests/30_configuration_test.py' | |||
366 | --- tests/30_configuration_test.py 1970-01-01 00:00:00 +0000 | |||
367 | +++ tests/30_configuration_test.py 2015-01-12 15:19:55 +0000 | |||
368 | @@ -0,0 +1,142 @@ | |||
369 | 1 | #!/usr/bin/python3 | ||
370 | 2 | |||
371 | 3 | # This Amulet test exercises the configuration options for rabbitmq-server. | ||
372 | 4 | |||
373 | 5 | import amulet | ||
374 | 6 | import os | ||
375 | 7 | import requests | ||
376 | 8 | import socket | ||
377 | 9 | import ssl | ||
378 | 10 | |||
379 | 11 | # The number of seconds to wait for the environment to setup. | ||
380 | 12 | seconds = 900 | ||
381 | 13 | # Get the directory in this way to load the files from the tests directory. | ||
382 | 14 | path = os.path.abspath(os.path.dirname(__file__)) | ||
383 | 15 | key_path = os.path.join(path, 'rabbit-server-privkey.pem') | ||
384 | 16 | # Read the private key file. | ||
385 | 17 | with open(key_path) as f: | ||
386 | 18 | privateKey = f.read() | ||
387 | 19 | cert_path = os.path.join(path, 'rabbit-server-cert.pem') | ||
388 | 20 | # Read the certificate file. | ||
389 | 21 | with open(cert_path) as f: | ||
390 | 22 | certificate = f.read() | ||
391 | 23 | |||
392 | 24 | # Create a dictionary of all the configuration values. | ||
393 | 25 | rabbit_configuration = { | ||
394 | 26 | 'management_plugin': True, | ||
395 | 27 | 'ssl_enabled': True, | ||
396 | 28 | 'ssl_port': 5999, | ||
397 | 29 | 'ssl_key': privateKey, | ||
398 | 30 | 'ssl_cert': certificate | ||
399 | 31 | } | ||
400 | 32 | |||
401 | 33 | d = amulet.Deployment() | ||
402 | 34 | # Add the rabbitmq-server charm to the deployment. | ||
403 | 35 | d.add('rabbitmq-server') | ||
404 | 36 | # Configure all the options on rabbitmq-server. | ||
405 | 37 | d.configure('rabbitmq-server', rabbit_configuration) | ||
406 | 38 | # Expose the rabbitmq-server. | ||
407 | 39 | d.expose('rabbitmq-server') | ||
408 | 40 | |||
409 | 41 | try: | ||
410 | 42 | # Execute the deployer with the current mapping. | ||
411 | 43 | d.setup(timeout=seconds) | ||
412 | 44 | # Wait for the relation to finish the transations. | ||
413 | 45 | #d.sentry.wait(seconds) | ||
414 | 46 | except amulet.helpers.TimeoutError: | ||
415 | 47 | message = 'The environment did not setup in %d seconds.' % seconds | ||
416 | 48 | # The SKIP status enables skip or fail the test based on configuration. | ||
417 | 49 | amulet.raise_status(amulet.SKIP, msg=message) | ||
418 | 50 | except: | ||
419 | 51 | raise | ||
420 | 52 | |||
421 | 53 | rabbit_unit = d.sentry.unit['rabbitmq-server/0'] | ||
422 | 54 | ############################################################################### | ||
423 | 55 | ## Verify that the rabbit service is running on the deployed server. | ||
424 | 56 | ############################################################################### | ||
425 | 57 | # Create the command that checks if the rabbitmq-server service is running. | ||
426 | 58 | command = 'rabbitmqctl status' | ||
427 | 59 | print(command) | ||
428 | 60 | # Execute the command on the deployed service. | ||
429 | 61 | output, code = rabbit_unit.run(command) | ||
430 | 62 | print(output) | ||
431 | 63 | # Check the return code for the success and failure of this test. | ||
432 | 64 | if (code != 0): | ||
433 | 65 | message = 'The ' + command + ' did not return the expected code of 0.' | ||
434 | 66 | amulet.raise_status(amulet.FAIL, msg=message) | ||
435 | 67 | else: | ||
436 | 68 | print('The rabbitmq-server is running.') | ||
437 | 69 | |||
438 | 70 | ############################################################################### | ||
439 | 71 | ## Verify the configuration values. | ||
440 | 72 | ############################################################################### | ||
441 | 73 | # Get the contents of the private key from the rabbitmq-server | ||
442 | 74 | contents = rabbit_unit.file_contents('/etc/rabbitmq/rabbit-server-privkey.pem') | ||
443 | 75 | # Verify the private key was saved on the rabbitmq server correctly. | ||
444 | 76 | if contents != privateKey: | ||
445 | 77 | message = 'The private keys did not match!' | ||
446 | 78 | amulet.raise_status(amulet.FAIL, msg=message) | ||
447 | 79 | else: | ||
448 | 80 | print('The private keys was configured properly on the rabbitmq server.') | ||
449 | 81 | |||
450 | 82 | # Get the contents of the certificate from the rabbitmq-server. | ||
451 | 83 | contents = rabbit_unit.file_contents('/etc/rabbitmq/rabbit-server-cert.pem') | ||
452 | 84 | # Verify the certificate was saved on the rabbitmq server correctly. | ||
453 | 85 | if contents != certificate: | ||
454 | 86 | message = 'The certificates did not match!' | ||
455 | 87 | amulet.raise_status(amulet.FAIL, msg=message) | ||
456 | 88 | else: | ||
457 | 89 | print('The certificate was configured properly on the rabbitmq server.') | ||
458 | 90 | |||
459 | 91 | # Get the public address for rabbitmq-server instance. | ||
460 | 92 | rabbit_host = rabbit_unit.info['public-address'] | ||
461 | 93 | |||
462 | 94 | ############################################################################### | ||
463 | 95 | ## Verify the management plugin is running and responding on correct port. | ||
464 | 96 | ## According to this: http://www.rabbitmq.com/access-control.html | ||
465 | 97 | ## The guest account can only log in from local host. | ||
466 | 98 | ## Since this test runs on a different system there is no way to test | ||
467 | 99 | ## the management plugin. | ||
468 | 100 | ############################################################################### | ||
469 | 101 | # Create a url for the rabbitmq server's managment plugin (uses 55672). | ||
470 | 102 | #management_url = 'http://{0}:55672'.format(rabbit_host) | ||
471 | 103 | #print(management_url) | ||
472 | 104 | # Get the management url with the authentication for guest. | ||
473 | 105 | #r = requests.get(management_url, auth=('guest', 'guest')) | ||
474 | 106 | # Raise an exception if response is not 200 OK. | ||
475 | 107 | #r.raise_for_status() | ||
476 | 108 | #print(str(r)) | ||
477 | 109 | #print('Successfully authenticated to the management console at %s' % | ||
478 | 110 | # management_url) | ||
479 | 111 | |||
480 | 112 | ############################################################################### | ||
481 | 113 | ## Verify that SSL is set up on the non-default port. | ||
482 | 114 | ############################################################################### | ||
483 | 115 | # Get the port for ssl_port instance. | ||
484 | 116 | ssl_port = rabbit_configuration['ssl_port'] | ||
485 | 117 | |||
486 | 118 | # Get the path to the certificate authority file. | ||
487 | 119 | ca_cert_path = os.path.join(path, 'rabbit-server-cacert.pem') | ||
488 | 120 | |||
489 | 121 | try: | ||
490 | 122 | # Create a normal socket. | ||
491 | 123 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
492 | 124 | # Require a certificate from the server, since a self-signed certificate | ||
493 | 125 | # was used, the ca_certs must be the server certificate file itself. | ||
494 | 126 | ssl_sock = ssl.wrap_socket(s, ca_certs=ca_cert_path, | ||
495 | 127 | cert_reqs=ssl.CERT_REQUIRED) | ||
496 | 128 | # Connect to the rabbitmq server using ssl. | ||
497 | 129 | ssl_sock.connect((rabbit_host, ssl_port)) | ||
498 | 130 | # Get the certificate. | ||
499 | 131 | certificate = ssl_sock.getpeercert() | ||
500 | 132 | # SSL scoket connected and got the certificate, this passes the ssl test! | ||
501 | 133 | print('Connected to the rabbitmq-server {0}:{1} using ssl!'.format( | ||
502 | 134 | rabbit_host, ssl_port)) | ||
503 | 135 | except Exception as e: | ||
504 | 136 | message = 'Failed to create an ssl connection to {0}:{1}\n{2}'.format( | ||
505 | 137 | rabbit_host, ssl_port, str(e)) | ||
506 | 138 | amulet.raise_status(amulet.FAIL, msg=message) | ||
507 | 139 | finally: | ||
508 | 140 | ssl_sock.close() | ||
509 | 141 | |||
510 | 142 | print('The rabbitmq-server passed the configuration tests.') | ||
511 | 0 | 143 | ||
512 | === added file 'tests/amqp_tester.py' | |||
513 | --- tests/amqp_tester.py 1970-01-01 00:00:00 +0000 | |||
514 | +++ tests/amqp_tester.py 2015-01-12 15:19:55 +0000 | |||
515 | @@ -0,0 +1,65 @@ | |||
516 | 1 | #!/usr/bin/python | ||
517 | 2 | |||
518 | 3 | # This class uses Python to make AMQP calls to send and receive messages. | ||
519 | 4 | # To send an AMQP message call this module with a host, port, and message. | ||
520 | 5 | # To receive an AMQP message call this module with a host and port only. | ||
521 | 6 | |||
522 | 7 | import logging | ||
523 | 8 | import pika | ||
524 | 9 | import sys | ||
525 | 10 | |||
526 | 11 | |||
527 | 12 | def send(host, port, message, queue='test'): | ||
528 | 13 | """ Send an AMQP message to a host and port.""" | ||
529 | 14 | connection = None | ||
530 | 15 | try: | ||
531 | 16 | parameters = pika.ConnectionParameters(host, port) | ||
532 | 17 | connection = pika.BlockingConnection(parameters) | ||
533 | 18 | |||
534 | 19 | channel = connection.channel() | ||
535 | 20 | channel.queue_declare(queue) | ||
536 | 21 | channel.basic_publish(exchange='', routing_key=queue, body=message) | ||
537 | 22 | print('Message published to {0}:{1}'.format(host, port)) | ||
538 | 23 | except Exception as e: | ||
539 | 24 | print('Unable to send message to {0}:{1}'.format(host, port)) | ||
540 | 25 | print(e) | ||
541 | 26 | finally: | ||
542 | 27 | if connection: | ||
543 | 28 | connection.close() | ||
544 | 29 | |||
545 | 30 | |||
546 | 31 | def callback(ch, method, properties, body): | ||
547 | 32 | """ Handle the callback when the channel receives a message. """ | ||
548 | 33 | print(body) | ||
549 | 34 | |||
550 | 35 | |||
551 | 36 | def receive(host, port, queue='test'): | ||
552 | 37 | """ Connects to host and port, and consumes AMQP messages. """ | ||
553 | 38 | connection = None | ||
554 | 39 | try: | ||
555 | 40 | parameters = pika.ConnectionParameters(host, port) | ||
556 | 41 | connection = pika.BlockingConnection(parameters) | ||
557 | 42 | channel = connection.channel() | ||
558 | 43 | channel.queue_declare(queue) | ||
559 | 44 | channel.basic_consume(callback, queue, no_ack=True) | ||
560 | 45 | except Exception as e: | ||
561 | 46 | print('Unable to receive message from {0}:{1}'.format(host, port)) | ||
562 | 47 | print(e) | ||
563 | 48 | finally: | ||
564 | 49 | if connection: | ||
565 | 50 | connection.close() | ||
566 | 51 | |||
567 | 52 | # Needed to disable pika complaining about logging levels not set. | ||
568 | 53 | logging.basicConfig(level=logging.ERROR) | ||
569 | 54 | |||
570 | 55 | if len(sys.argv) == 3: | ||
571 | 56 | host = sys.argv[1] | ||
572 | 57 | port = int(sys.argv[2]) | ||
573 | 58 | receive(host, port) | ||
574 | 59 | elif len(sys.argv) > 3: | ||
575 | 60 | host = sys.argv[1] | ||
576 | 61 | port = int(sys.argv[2]) | ||
577 | 62 | message = ' '.join(sys.argv[3:]) | ||
578 | 63 | send(host, port, message) | ||
579 | 64 | else: | ||
580 | 65 | print('Not enough arguments, host and port are required.') | ||
581 | 0 | 66 | ||
582 | === added file 'tests/rabbit-server-cacert.pem' | |||
583 | --- tests/rabbit-server-cacert.pem 1970-01-01 00:00:00 +0000 | |||
584 | +++ tests/rabbit-server-cacert.pem 2015-01-12 15:19:55 +0000 | |||
585 | @@ -0,0 +1,17 @@ | |||
586 | 1 | -----BEGIN CERTIFICATE----- | ||
587 | 2 | MIICxjCCAa6gAwIBAgIJAIOIZyP0JpvLMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV | ||
588 | 3 | BAMTCE15VGVzdENBMB4XDTE0MDIyMzIwMDgxOFoXDTE1MDIyMzIwMDgxOFowEzER | ||
589 | 4 | MA8GA1UEAxMITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB | ||
590 | 5 | AQDceXBJOhn9d68M9UiOViWz00Znds1xk9i+GbZFEsqLPkoReS9g/SeXvR5ZFZlU | ||
591 | 6 | 5gzAcg8z8b+n26wgZLFQJ4wQAIVELIu0S6e4sUPKfKl/fo9NmRVv/sPkfZWUZ5sc | ||
592 | 7 | d9DEk8MiNYjjXT+Ff4TV7DFxdDOJLIDrc09JWzIKrmfOXP5wLFCsIllGbellfNvY | ||
593 | 8 | FxiHHm3Iz5t3t077+uUXeMD5p1Qd2qQdbJ2p8Dwkg2AyTPNG8RA71tEMIT7FX0nB | ||
594 | 9 | sTX5M217ocdEZJI67x+3Z8Ll21m6blcnJI3V3Zk5kvccvYRlDuyGh7tiWcv4YKmv | ||
595 | 10 | xuP64L9174nQ3HXnwipfjBkBAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P | ||
596 | 11 | BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAaQWYVUuPKRtAFd6kyugL/UpVhIa/o | ||
597 | 12 | zfm/2b23UviPA1TIYzzf4m1eDV7kxJynOeP1RRPp166el+sVx7+vqhBsqcm4b5e+ | ||
598 | 13 | epShI3jff0gtODxo5rUVrROS3T6xjHA7AVm60/xmGIIybhDonXzA5YJ8YVBpHUdZ | ||
599 | 14 | Yc2neOwdDT8k/H95cPXBU3pf3vTVpndjN827fBuyO7KwKDAiKHwtwmSedc1uZtLN | ||
600 | 15 | sfwkonXF+gNAHXlk28VeygGQ1jHdloIrNG0zYc4ZX4zqPHd7HDeyYItBBHjrznow | ||
601 | 16 | nf1X6fNjP4YnG5EkUN8hRXf3ct+L8iq8puMNhjb8ssW+bsFRBIufVFaC | ||
602 | 17 | -----END CERTIFICATE----- | ||
603 | 0 | 18 | ||
604 | === added file 'tests/rabbit-server-cert.pem' | |||
605 | --- tests/rabbit-server-cert.pem 1970-01-01 00:00:00 +0000 | |||
606 | +++ tests/rabbit-server-cert.pem 2015-01-12 15:19:55 +0000 | |||
607 | @@ -0,0 +1,18 @@ | |||
608 | 1 | -----BEGIN CERTIFICATE----- | ||
609 | 2 | MIIC5TCCAc2gAwIBAgIBATANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl | ||
610 | 3 | c3RDQTAeFw0xNDAyMjMyMDA5MjFaFw0xNTAyMjMyMDA5MjFaMCgxFTATBgNVBAMM | ||
611 | 4 | DHJlYWxtcy1zbGljZTEPMA0GA1UECgwGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEF | ||
612 | 5 | AAOCAQ8AMIIBCgKCAQEApc6WxtgQZL+PcDHL1S/kLqFyGPaKiJQrOPGYq9djM5pr | ||
613 | 6 | VGPHUZ3F26VWtlBtPB8PgQFT10Sjr+ec7hC9aqT+THyNq2U8qCizGq4l4e44tfEI | ||
614 | 7 | LPuE9IluF/dZuVWFR2nbVYp3FeAjuRQ68AwzpcZOXVup3xsXx7dJrGL4KUx/7NUb | ||
615 | 8 | 5+6TzboM1nXX7o/DYCE5BvXncM7U3cLg16SV58T6Rs+JYATAFdzveN6X88AgvQpB | ||
616 | 9 | rDSD42tSQmQzYu9mO2RwtP48jLvYLHv34dZo2h6G5zNWe/PkUjXxKEGJXHkeXy83 | ||
617 | 10 | vx4UV62Vo8pMLeSSqL4wUV3KMRHJ+MBskP42lmruwQIDAQABoy8wLTAJBgNVHRME | ||
618 | 11 | AjAAMAsGA1UdDwQEAwIFIDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0B | ||
619 | 12 | AQUFAAOCAQEArEFhWRHb1Nn1ACDNXbRueiMSdqwWtiAEU4yAFB+1maKyAG1VAQC2 | ||
620 | 13 | IegIJ7INbzfwDp6CzNpI3CCyelNO2rcBGwOlXre6XA5K7TxKM6WLJDdodPUt30dY | ||
621 | 14 | 3+/DF/XwH5S/C4oGbeRVWxzCBAFbStMlJqpXFIQkAYYCOfvWKoZzSslxGe7Zj+hQ | ||
622 | 15 | NYqJbc8BDe0UTyM8KoL9OWucEbdQMQgn0FxwAPqSLXgDkpSo6XHKL15MUbES1u5/ | ||
623 | 16 | iT9gRJU1eN+bIWfrJA3dqh4JxXntTLDZ28pBdFtOV4WEF2O4fmxGiSktCi34tjK6 | ||
624 | 17 | DsIScb+0mUeKS9b2cyQzLSUCwj8LgJW3rQ== | ||
625 | 18 | -----END CERTIFICATE----- | ||
626 | 0 | 19 | ||
627 | === added file 'tests/rabbit-server-privkey.pem' | |||
628 | --- tests/rabbit-server-privkey.pem 1970-01-01 00:00:00 +0000 | |||
629 | +++ tests/rabbit-server-privkey.pem 2015-01-12 15:19:55 +0000 | |||
630 | @@ -0,0 +1,27 @@ | |||
631 | 1 | -----BEGIN RSA PRIVATE KEY----- | ||
632 | 2 | MIIEpAIBAAKCAQEApc6WxtgQZL+PcDHL1S/kLqFyGPaKiJQrOPGYq9djM5prVGPH | ||
633 | 3 | UZ3F26VWtlBtPB8PgQFT10Sjr+ec7hC9aqT+THyNq2U8qCizGq4l4e44tfEILPuE | ||
634 | 4 | 9IluF/dZuVWFR2nbVYp3FeAjuRQ68AwzpcZOXVup3xsXx7dJrGL4KUx/7NUb5+6T | ||
635 | 5 | zboM1nXX7o/DYCE5BvXncM7U3cLg16SV58T6Rs+JYATAFdzveN6X88AgvQpBrDSD | ||
636 | 6 | 42tSQmQzYu9mO2RwtP48jLvYLHv34dZo2h6G5zNWe/PkUjXxKEGJXHkeXy83vx4U | ||
637 | 7 | V62Vo8pMLeSSqL4wUV3KMRHJ+MBskP42lmruwQIDAQABAoIBAE6jo/ldQrE19acF | ||
638 | 8 | xyIum6/OHJpgXCYY+EMCuyFNf5xa8erNhBxekxfw3CaOELECHk1WPtiLkoL8e/6h | ||
639 | 9 | a+UnqgDG1j5jPpiW7ROLYyY74SPR1MnY5R9CCzhMtX5kZFkRiNiSWpbCfs7qHGX7 | ||
640 | 10 | s4c9fa9jqTbK18V+Ve/v5LlZsha13OQRISQLqZlCM6vKRtHZorQHZVM1KIV4bzdP | ||
641 | 11 | 75/YTrhUA8GKGA+4Le5vZ1PQY8ubTAXPHeeqILvClsmkZ6k0RC/zesB3DUXzMvjA | ||
642 | 12 | ycbarcpZ+muxyp0Icuv9B7pj3iT/dL4udc+BM82Qg3KvLLiteE9aeOPsW3aJxAHa | ||
643 | 13 | YYLLCQECgYEA2EUF4QVgJE1U6RHFsRO6xP1KBJO0mVMMlEpgywPV3oN7D5gOVrCK | ||
644 | 14 | A/iNkyt2ggaX2o2+QHMe+WjINdMLhY6TdhRiYrUQhLteNSrp0w/HDYyY2Cz1IhH3 | ||
645 | 15 | Y/0qHm9rGZhetOWoJ5Ejn/9vnL/ZfsGfSNzwS1VjCUHyXShebS9NHRECgYEAxERZ | ||
646 | 16 | 5HX3zctB2lzzS8KTNAWijUc+hc8c0LV/GcCC8LMsUPNb/V+wQNiSInJa994YI5+9 | ||
647 | 17 | 1BkJkw4Lnexvx8GQPaAkX6DzZsWSmwaNSkLICd75f2ga4dqeohWOAIvS3xb4fanr | ||
648 | 18 | szCLZfd4L8MEb6lVI2wzpM5yADK42y/w03t0drECgYBvDAn3v93c5gRKZIDA6uOE | ||
649 | 19 | 0JXYAcvCypzz67kFpSOEzLg8ipQaOS202kQ/pBqGq0H/y7Y7u6DU6dObp5EL8+iN | ||
650 | 20 | weu+yUABF4BJBo7ne/t2XpIAthzscJM5uT2OQSGaE93VPvL31hOXzP4PW4cfCeZy | ||
651 | 21 | 8FdGJ0Lh9wWuhdLud1I+MQKBgQC7CwzEPmy38mJC8VxoMfnJlSkyDNiX+ybR/HYx | ||
652 | 22 | m5buP0MXrqVXVe8KDZtPOr5ZBI7qvFzTmjzWqYcGrQJmU6DcKhcgD6qHofiyx061 | ||
653 | 23 | m+k6BwatlhAweAHAJFydRqPjOef9Eofu0G+48FvY4LkElVLvHDoncRuR9sTXFtwj | ||
654 | 24 | H7+BMQKBgQDNWXHeXi4bYm17KsBHpK+DMT6O9cF1BqYpgbqLyro554ZjYLYpt0li | ||
655 | 25 | iiekhVM55NpWlbsOfje0lhD8mr0ZYzW+SmWd/XMj03ZF9EeOBHx8SvWemsrz69Es | ||
656 | 26 | wAjiQtQoZlvczaLOHLV89p9EaK3OA1trqjAkqq9GFdLBVmG/zVzSaQ== | ||
657 | 27 | -----END RSA PRIVATE KEY----- |
Thank you for the amulet test coverage work on rmq, much appreciated!
If we can get this added to Makefile, that will make OSCI's engine happy:
test:
@echo Starting amulet tests...
@juju test -v -p AMULET_HTTP_PROXY --timeout 900
I just sent your branch with ^ that mod through to confirm: test.conductor. 00_setup. sh RESULT : ✔ test.conductor. 10_basic_ deploy_ test.py RESULT : ✔ test.conductor. 20_deploy_ relations_ test.py RESULT : ✔ test.conductor. 30_configuratio n_test. py RESULT : ✔
juju-
juju-
juju-
juju-
juju-test INFO : Results: 4 passed, 0 failed, 0 errored
I think most of the openstack charms use the 'test' target name. But actually, you can name the make target anything as OSCI just looks for '@juju test' in a target and runs that target.