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