tests: fix/cleanup functional and unit tests
Remove non-working unit tests (left only the ones that pass - let's make it a baseline and add more afterwards). Fix functional tests (dependency + API urls) Repository tidy up: Remove log files from tox from git repo; Fixup gitreview to point to trove repository; Make gate tests executable. Change-Id: Ide6b833f77f76e43ebbc9fbe435cff0bd4060ef8
This commit is contained in:
parent
eaf141d76c
commit
8d6211a75c
|
@ -1,4 +1,4 @@
|
|||
[gerrit]
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/charm-designate.git
|
||||
project=openstack/charm-trove.git
|
||||
|
|
|
@ -5,21 +5,85 @@ This charm provides the Trove (DBaaS) for an OpenStack Cloud.
|
|||
|
||||
# Usage
|
||||
|
||||
Designate relies on services from the mysql, rabbitmq-server and keystone
|
||||
charms:
|
||||
As described in the installation guide,
|
||||
|
||||
http://docs.openstack.org/developer/trove/dev/manual_install.html
|
||||
|
||||
a running OpenStack environment is required to use Trove, including
|
||||
the following components:
|
||||
|
||||
- Compute (Nova)
|
||||
- Image Service (Glance)
|
||||
- Identity (Keystone)
|
||||
- Neutron or Nova-Network
|
||||
- Cinder, if you want to provision datastores on block-storage volumes
|
||||
- Swift, if you want to do backup/restore and replication
|
||||
- AMQP service (RabbitMQ or QPID)
|
||||
- MySQL (SQLite, PostgreSQL) database for Trove's internal needs
|
||||
- Certain OpenStack services must be accessible from VMs:
|
||||
- Swift
|
||||
|
||||
OpenStack services must be accessible directly from the environment where
|
||||
Trove is deployed:
|
||||
- Nova
|
||||
- Cinder
|
||||
- Swift
|
||||
- Heat
|
||||
|
||||
|
||||
A basic setup with using charms would look like the following:
|
||||
|
||||
juju deploy trove
|
||||
juju deploy mysql
|
||||
juju deploy rabbitmq-server
|
||||
juju deploy keystone
|
||||
juju deploy heat
|
||||
juju deploy cinder
|
||||
juju deploy glance
|
||||
juju deploy nova-compute
|
||||
juju deploy nova-cloud-controller
|
||||
juju deploy neutron
|
||||
juju deploy neutron-openvswitch
|
||||
juju deploy neutron-gateway
|
||||
|
||||
juju add-relation trove mysql
|
||||
juju add-relation trove rabbitmq-server
|
||||
juju add-relation trove keystone
|
||||
|
||||
juju add-relation nova-compute rabbitmq-server
|
||||
juju add-relation nova-compute glance
|
||||
|
||||
juju add-relation cinder keystone
|
||||
juju add-relation cinder mysql
|
||||
juju add-relation cinder rabbitmq-server
|
||||
|
||||
juju add-relation glance keystone
|
||||
juju add-relation glance mysql
|
||||
|
||||
juju add-relation neutron-gateway mysql
|
||||
juju add-relation neutron-gateway rabbitmq-server
|
||||
juju add-relation neutron-gateway:amqp rabbitmq-server:amqp
|
||||
juju add-relation neutron-openvswitch nova-compute
|
||||
juju add-relation neutron-openvswitch neutron-api
|
||||
juju add-relation neutron-openvswitch rabbitmq-server
|
||||
juju add-relation neutron-api mysql
|
||||
juju add-relation neutron-api keystone
|
||||
juju add-relation neutron-api rabbitmq-server
|
||||
|
||||
juju add-relation nova-cloud-controller keystone
|
||||
juju add-relation nova-cloud-controller rabbitmq-server
|
||||
juju add-relation nova-cloud-controller nova-compute
|
||||
juju add-relation nova-cloud-controller mysql
|
||||
juju add-relation nova-cloud-controller glance
|
||||
juju add-relation nova-cloud-controller cinder
|
||||
juju add-relation nova-cloud-controller neutron-api
|
||||
|
||||
This will get the necessary services deployed, however, you will still need
|
||||
to create images, flavors and data stores for your specific needs.
|
||||
|
||||
http://docs.openstack.org/admin-guide/database.html
|
||||
|
||||
# Bugs
|
||||
|
||||
Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-designate/+filebug).
|
||||
Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-trove/+filebug).
|
||||
|
||||
For general questions please refer to the OpenStack [Charm Guide](http://docs.openstack.org/developer/charm-guide/).
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
# needed on the class.
|
||||
from __future__ import absolute_import
|
||||
|
||||
# import subprocess
|
||||
import collections
|
||||
|
||||
import charmhelpers.contrib.openstack.utils as ch_utils
|
||||
# import charmhelpers.core.hookenv as hookenv
|
||||
import charmhelpers.core.unitdata as unitdata
|
||||
# import charmhelpers.fetch
|
||||
|
||||
import charms_openstack.charm
|
||||
import charms_openstack.adapters
|
||||
|
@ -50,6 +48,15 @@ def install():
|
|||
TroveCharm.singleton.install()
|
||||
|
||||
|
||||
def db_sync_done():
|
||||
"""Use the singleton from the TroveCharm to check if db migration has
|
||||
been run
|
||||
|
||||
@returns: str or None. Str if sync has been done otherwise None
|
||||
"""
|
||||
return TroveCharm.singleton.db_sync_done()
|
||||
|
||||
|
||||
def restart_all():
|
||||
"""Use the singleton from the TroveCharm to restart services on the
|
||||
unit
|
||||
|
@ -110,23 +117,15 @@ def configure_ssl(keystone=None):
|
|||
TroveCharm.singleton.configure_ssl(keystone)
|
||||
|
||||
|
||||
def configure_cloud_compute():
|
||||
# TODO
|
||||
pass
|
||||
def update_peers(hacluster):
|
||||
"""Use the singleton from the TroveCharm to update peers with details
|
||||
of this unit.
|
||||
|
||||
@param hacluster: OpenstackHAPeers() interface class
|
||||
@returns: None
|
||||
"""
|
||||
TroveCharm.singleton.update_peers(hacluster)
|
||||
|
||||
def configure_cinder():
|
||||
# TODO
|
||||
pass
|
||||
|
||||
|
||||
def configure_image_service():
|
||||
# TODO
|
||||
pass
|
||||
|
||||
|
||||
###
|
||||
# Implementation of the Trove Charm classes
|
||||
|
||||
class TroveConfigurationAdapter(
|
||||
charms_openstack.adapters.APIConfigurationAdapter):
|
||||
|
@ -150,9 +149,7 @@ class TroveAdapters(charms_openstack.adapters.OpenStackAPIRelationAdapters):
|
|||
|
||||
|
||||
class TroveCharm(charms_openstack.charm.HAOpenStackCharm):
|
||||
service_name = 'trove'
|
||||
|
||||
name = 'trove'
|
||||
service_name = name = 'trove'
|
||||
|
||||
release = 'mitaka'
|
||||
|
||||
|
@ -189,14 +186,14 @@ class TroveCharm(charms_openstack.charm.HAOpenStackCharm):
|
|||
|
||||
ha_resources = ['vips', 'haproxy']
|
||||
|
||||
def __init__(self, release=None, **kwargs):
|
||||
"""
|
||||
Copied out of the github congress example. Checks to make sure a
|
||||
release is give, if not it pull the one out of keystone.
|
||||
"""
|
||||
if release is None:
|
||||
release = ch_utils.os_release('python-keystonemiddleware')
|
||||
super(TroveCharm, self).__init__(release=release, **kwargs)
|
||||
release_pkg = 'trove-common'
|
||||
package_codenames = {
|
||||
'aodh-common': collections.OrderedDict([
|
||||
('2', 'mitaka'),
|
||||
('3', 'newton'),
|
||||
('4', 'ocata'),
|
||||
]),
|
||||
}
|
||||
|
||||
def install(self):
|
||||
"""Customise the installation, configure the source and then call the
|
||||
|
|
|
@ -36,8 +36,7 @@ def setup_amqp_req(amqp):
|
|||
Use the amqp interface to request access to the amqp broker using our
|
||||
local configuration.
|
||||
"""
|
||||
amqp.request_access(username=hookenv.config('rabbit-user'),
|
||||
vhost=hookenv.config('rabbit-vhost'))
|
||||
amqp.request_access(username='trove', vhost='openstack')
|
||||
trove.assess_status()
|
||||
|
||||
|
||||
|
@ -83,6 +82,12 @@ def run_db_migration():
|
|||
trove.assess_status()
|
||||
|
||||
|
||||
@reactive.when('cluster.available')
|
||||
def update_peers(cluster):
|
||||
"""Inform designate peers about this unit"""
|
||||
trove.update_peers(cluster)
|
||||
|
||||
|
||||
@reactive.when('config.changed')
|
||||
def config_changed():
|
||||
trove.assess_status()
|
||||
|
@ -91,28 +96,3 @@ def config_changed():
|
|||
@reactive.when('identity-service.available')
|
||||
def configure_ssl(keystone):
|
||||
trove.configure_ssl(keystone)
|
||||
|
||||
|
||||
# when cloud-compute.available
|
||||
@reactive.when('cloud-compute.available')
|
||||
def configure_cloud_compute():
|
||||
trove.configure_cloud_compute()
|
||||
trove.assess_status()
|
||||
|
||||
|
||||
# when image-service.available
|
||||
@reactive.when('image-service.available')
|
||||
def configure_image_service():
|
||||
trove.configure_image_service()
|
||||
trove.assess_status()
|
||||
|
||||
|
||||
# when cinder-volume-service
|
||||
@reactive.when('cinder-volume-service.available')
|
||||
def configure_cinder():
|
||||
trove.configure_cinder()
|
||||
trove.assess_status()
|
||||
|
||||
# when heat - I need to find out what juju calls this
|
||||
|
||||
# when ceph.available
|
||||
|
|
|
@ -7,7 +7,7 @@ bzr+lp:charm-helpers#egg=charmhelpers
|
|||
amulet>=1.14.3,<2.0
|
||||
bundletester>=0.6.1,<1.0
|
||||
python-keystoneclient>=1.7.1,<2.0
|
||||
python-designateclient>=1.5,<2.0
|
||||
python-troveclient>=1.5,<=2.7.0
|
||||
python-cinderclient>=1.4.0,<2.0
|
||||
python-glanceclient>=1.1.0,<2.0
|
||||
python-heatclient>=0.8.0,<1.0
|
||||
|
|
|
@ -216,7 +216,7 @@ class TroveBasicDeployment(amulet_deployment.OpenStackAmuletDeployment):
|
|||
trove_ip = unit.relation(
|
||||
'identity-service',
|
||||
'keystone:identity-service')['private-address']
|
||||
trove_endpoint = "http://%s:8779" % (trove_ip)
|
||||
trove_endpoint = "http://{}:8779/v1.0/%(tenant_id)s".format(trove_ip)
|
||||
|
||||
expected = {
|
||||
'admin_url': trove_endpoint,
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
pep8 installed: blessings==1.6,charm-tools==2.1.4,Cheetah==2.4.4,colander==1.3.1,configparser==3.5.0,ecdsa==0.13,enum34==1.1.6,flake8==3.0.4,functools32==3.2.3.post2,httplib2==0.9.2,iso8601==0.1.11,jsonschema==2.5.1,jujubundlelib==0.5.2,keyring==9.3.1,launchpadlib==1.10.4,lazr.authentication==0.1.3,lazr.restfulclient==0.13.1,lazr.uri==1.0.3,libcharmstore==0.0.3,Markdown==2.6.7,mccabe==0.5.2,oauth==1.0.1,otherstuf==1.1.0,paramiko==1.17.2,parse==1.6.6,path.py==8.2.1,pathspec==0.5.0,pbr==1.10.0,pkg-resources==0.0.0,pycodestyle==2.0.0,pycrypto==2.6.1,pyflakes==1.2.3,PyYAML==3.12,requests==2.11.1,ruamel.ordereddict==0.4.9,ruamel.yaml==0.12.14,SecretStorage==2.2.1,simplejson==3.8.2,six==1.10.0,stuf==0.9.16,testresources==2.0.1,theblues==0.3.6,translationstring==1.3,typing==3.5.2.2,virtualenv==15.0.3,wadllib==1.3.2,wsgi-intercept==1.4.1,zope.interface==4.3.2
|
||||
pep8 runtests: PYTHONHASHSEED='0'
|
||||
pep8 runtests: commands[0] | flake8 src/reactive src/lib unit_tests
|
||||
py34 create: /home/charm/charms/layers/charm-trove/.tox/py34
|
||||
ERROR: InterpreterNotFound: python3.4
|
||||
py35 installed: Babel==2.3.4,charmhelpers==0.9.1,charms.openstack==0.0.1.dev1,charms.reactive==0.4.4,coverage==4.2,extras==1.0.0,fixtures==3.0.0,flake8==2.4.1,Jinja2==2.8,linecache2==1.0.0,MarkupSafe==0.23,mccabe==0.3.1,mock==2.0.0,netaddr==0.7.18,os-testr==0.8.0,pbr==1.10.0,pep8==1.7.0,pkg-resources==0.0.0,pyaml==16.9.0,pyflakes==0.8.1,python-mimeparse==1.5.5,python-subunit==1.2.0,pytz==2016.7,PyYAML==3.12,six==1.10.0,Tempita==0.5.2,testrepository==0.0.20,testtools==2.2.0,traceback2==1.4.0,unittest2==1.1.0
|
||||
py35 runtests: PYTHONHASHSEED='0'
|
||||
py35 runtests: commands[0] | ostestr
|
||||
running=ONon-zero exit code (2) from test listing.
|
||||
S_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
|
||||
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
|
||||
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
|
||||
${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests --list
|
||||
--- import errors ---
|
||||
Failed to import test module: unit_tests.test_trove_handlers
|
||||
Traceback (most recent call last):
|
||||
File "/home/charm/charms/layers/charm-trove/.tox/py35/lib/python3.5/site-packages/unittest2/loader.py", line 456, in _find_test_path
|
||||
module = self._get_module_from_name(name)
|
||||
File "/home/charm/charms/layers/charm-trove/.tox/py35/lib/python3.5/site-packages/unittest2/loader.py", line 395, in _get_module_from_name
|
||||
__import__(name)
|
||||
File "/home/charm/charms/layers/charm-trove/unit_tests/test_trove_handlers.py", line 8, in <module>
|
||||
import reactive.designate_handlers as handlers
|
||||
ImportError: No module named 'reactive.designate_handlers'
|
||||
|
||||
Failed to import test module: unit_tests.test_trove_utils
|
||||
Traceback (most recent call last):
|
||||
File "/home/charm/charms/layers/charm-trove/.tox/py35/lib/python3.5/site-packages/unittest2/loader.py", line 456, in _find_test_path
|
||||
module = self._get_module_from_name(name)
|
||||
File "/home/charm/charms/layers/charm-trove/.tox/py35/lib/python3.5/site-packages/unittest2/loader.py", line 395, in _get_module_from_name
|
||||
__import__(name)
|
||||
File "/home/charm/charms/layers/charm-trove/unit_tests/test_trove_utils.py", line 4, in <module>
|
||||
import reactive.designate_utils as dutils
|
||||
ImportError: No module named 'reactive.designate_utils'
|
||||
The test run didn't actually run any tests
|
||||
|
||||
Slowest Tests:
|
||||
|
||||
ERROR: InvocationError: '/home/charm/charms/layers/charm-trove/.tox/py35/bin/ostestr'
|
||||
___________________________________ summary ____________________________________
|
||||
pep8: commands succeeded
|
||||
SKIPPED: py34: InterpreterNotFound: python3.4
|
||||
ERROR: py35: commands failed
|
|
@ -15,42 +15,87 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
# import contextlib
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
# import charm.openstack.designate as designate
|
||||
import charm.openstack.trove as trove
|
||||
|
||||
import charms_openstack.test_utils as test_utils
|
||||
|
||||
|
||||
def FakeConfig(init_dict):
|
||||
|
||||
def _config(key=None):
|
||||
return init_dict[key] if key else init_dict
|
||||
|
||||
return _config
|
||||
|
||||
|
||||
class Helper(unittest.TestCase):
|
||||
class Helper(test_utils.PatchHelper):
|
||||
|
||||
def setUp(self):
|
||||
self._patches = {}
|
||||
self._patches_start = {}
|
||||
self.ch_config_patch = mock.patch('charmhelpers.core.hookenv.config')
|
||||
self.ch_config = self.ch_config_patch.start()
|
||||
self.ch_config.side_effect = lambda: {'ssl_param': None}
|
||||
super().setUp()
|
||||
self.patch_release(trove.TroveCharm.release)
|
||||
|
||||
def tearDown(self):
|
||||
for k, v in self._patches.items():
|
||||
v.stop()
|
||||
setattr(self, k, None)
|
||||
self._patches = None
|
||||
self._patches_start = None
|
||||
self.ch_config_patch.stop()
|
||||
|
||||
def patch(self, obj, attr, return_value=None, **kwargs):
|
||||
mocked = mock.patch.object(obj, attr, **kwargs)
|
||||
self._patches[attr] = mocked
|
||||
started = mocked.start()
|
||||
started.return_value = return_value
|
||||
self._
|
||||
class TestOpenStackTrove(Helper):
|
||||
|
||||
def test_install(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'install')
|
||||
trove.install()
|
||||
self.install.assert_called_once_with()
|
||||
|
||||
def test_setup_endpoint(self):
|
||||
self.patch_object(trove.TroveCharm, 'service_name',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch_object(trove.TroveCharm, 'region',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch_object(trove.TroveCharm, 'public_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch_object(trove.TroveCharm, 'internal_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch_object(trove.TroveCharm, 'admin_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.service_name.return_value = 'type1'
|
||||
self.region.return_value = 'region1'
|
||||
self.public_url.return_value = 'public_url'
|
||||
self.internal_url.return_value = 'internal_url'
|
||||
self.admin_url.return_value = 'admin_url'
|
||||
keystone = mock.MagicMock()
|
||||
trove.setup_endpoint(keystone)
|
||||
keystone.register_endpoints.assert_called_once_with(
|
||||
'trove', 'region1', 'public_url/v1.0/%(tenant_id)s',
|
||||
'internal_url/v1.0/%(tenant_id)s',
|
||||
'admin_url/v1.0/%(tenant_id)s')
|
||||
|
||||
def test_render_configs(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'render_with_interfaces')
|
||||
trove.render_configs('interfaces-list')
|
||||
self.render_with_interfaces.assert_called_once_with(
|
||||
'interfaces-list')
|
||||
|
||||
def test_db_sync_done(self):
|
||||
self.patch_object(trove.TroveCharm, 'db_sync_done')
|
||||
trove.db_sync_done()
|
||||
self.db_sync_done.assert_called_once_with()
|
||||
|
||||
def test_db_sync(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'db_sync')
|
||||
trove.db_sync()
|
||||
self.db_sync.assert_called_once_with()
|
||||
|
||||
def test_configure_ha_resources(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'db_sync')
|
||||
trove.db_sync()
|
||||
self.db_sync.assert_called_once_with()
|
||||
|
||||
def test_restart_all(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'restart_all')
|
||||
trove.restart_all()
|
||||
self.restart_all.assert_called_once_with()
|
||||
|
||||
def test_configure_ssl(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'configure_ssl')
|
||||
trove.configure_ssl()
|
||||
self.configure_ssl.assert_called_once_with(None)
|
||||
|
||||
def test_update_peers(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'update_peers')
|
||||
trove.update_peers('cluster')
|
||||
self.update_peers.assert_called_once_with('cluster')
|
||||
|
||||
def test_assess_status(self):
|
||||
self.patch_object(trove.TroveCharm.singleton, 'assess_status')
|
||||
trove.assess_status()
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
|
|
@ -5,7 +5,7 @@ import unittest
|
|||
|
||||
import mock
|
||||
|
||||
import reactive.designate_handlers as handlers
|
||||
import reactive.trove_handlers as handlers
|
||||
|
||||
|
||||
_when_args = {}
|
||||
|
@ -29,7 +29,7 @@ def mock_hook_factory(d):
|
|||
return mock_hook
|
||||
|
||||
|
||||
class TestDesignateHandlers(unittest.TestCase):
|
||||
class TestTroveHandlers(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -86,11 +86,6 @@ class TestDesignateHandlers(unittest.TestCase):
|
|||
# test that the hooks actually registered the relation expressions that
|
||||
# are meaningful for this interface: this is to handle regressions.
|
||||
# The keys are the function names that the hook attaches to.
|
||||
all_interfaces = (
|
||||
'dns-backend.available',
|
||||
'shared-db.available',
|
||||
'identity-service.available',
|
||||
'amqp.available')
|
||||
when_patterns = {
|
||||
'setup_amqp_req': [('amqp.connected', )],
|
||||
'setup_database': [('shared-db.connected', )],
|
||||
|
@ -99,136 +94,70 @@ class TestDesignateHandlers(unittest.TestCase):
|
|||
'update_peers': [('cluster.available', )],
|
||||
'config_changed': [('config.changed', )],
|
||||
'cluster_connected': [('ha.connected', )],
|
||||
'create_servers_and_domains': [
|
||||
all_interfaces,
|
||||
('base-config.rendered', ),
|
||||
('db.synched', ),
|
||||
],
|
||||
'configure_designate_full': [
|
||||
all_interfaces,
|
||||
('db.synched', ),
|
||||
],
|
||||
'run_db_migration': [
|
||||
all_interfaces,
|
||||
('base-config.rendered', ),
|
||||
],
|
||||
'configure_designate_basic': [
|
||||
all_interfaces,
|
||||
],
|
||||
'render_stuff': [('amqp.available',),
|
||||
('identity-service.available',),
|
||||
('shared-db.available',)],
|
||||
'run_db_migration': [('config.complete',)]
|
||||
}
|
||||
when_not_patterns = {
|
||||
'install_packages': [('installed', )],
|
||||
'run_db_migration': [('db.synched', )],
|
||||
'configure_designate_basic': [('base-config.rendered', )],
|
||||
'create_servers_and_domains': [('domains.created', )],
|
||||
'install_packages': [('charm.installed', )],
|
||||
'run_db_migration': [('db.synced',)],
|
||||
}
|
||||
# check the when hooks are attached to the expected functions
|
||||
for t, p in [(_when_args, when_patterns),
|
||||
(_when_not_args, when_not_patterns)]:
|
||||
for f, args in t.items():
|
||||
# check that function is in patterns
|
||||
print(f)
|
||||
print('f: {}'.format(f))
|
||||
self.assertTrue(f in p.keys())
|
||||
# check that the lists are equal
|
||||
l = [a['args'] for a in args]
|
||||
self.assertEqual(l, p[f])
|
||||
|
||||
def test_install_packages(self):
|
||||
self.patch(handlers.designate, 'install')
|
||||
self.patch(handlers.trove, 'install')
|
||||
self.patch(handlers.reactive, 'set_state')
|
||||
handlers.install_packages()
|
||||
self.install.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('installed')
|
||||
self.set_state.assert_called_once_with('charm.installed')
|
||||
|
||||
def test_setup_amqp_req(self):
|
||||
self.patch(handlers.designate, 'assess_status')
|
||||
self.patch(handlers.trove, 'assess_status')
|
||||
amqp = mock.MagicMock()
|
||||
handlers.setup_amqp_req(amqp)
|
||||
amqp.request_access.assert_called_once_with(
|
||||
username='designate', vhost='openstack')
|
||||
username='trove', vhost='openstack')
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_database(self):
|
||||
self.patch(handlers.designate, 'assess_status')
|
||||
self.patch(handlers.trove, 'assess_status')
|
||||
database = mock.MagicMock()
|
||||
self.patch(handlers.hookenv, 'unit_private_ip', 'private_ip')
|
||||
handlers.setup_database(database)
|
||||
calls = [
|
||||
mock.call(
|
||||
'designate',
|
||||
'designate',
|
||||
'trove',
|
||||
'trove',
|
||||
'private_ip',
|
||||
prefix='designate'),
|
||||
mock.call(
|
||||
'dpm',
|
||||
'dpm',
|
||||
'private_ip',
|
||||
prefix='dpm'),
|
||||
prefix='trove'),
|
||||
]
|
||||
database.configure.has_calls(calls)
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_setup_endpoint(self):
|
||||
self.patch(handlers.designate, 'assess_status')
|
||||
self.patch(handlers.designate, 'register_endpoints')
|
||||
self.patch(handlers.trove, 'assess_status')
|
||||
self.patch(handlers.trove, 'setup_endpoint')
|
||||
handlers.setup_endpoint('endpoint_object')
|
||||
self.register_endpoints.assert_called_once_with('endpoint_object')
|
||||
self.setup_endpoint.assert_called_once_with('endpoint_object')
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_configure_designate_basic(self):
|
||||
self.patch(handlers.reactive, 'set_state')
|
||||
self.patch(handlers.designate, 'render_base_config')
|
||||
self.patch(handlers.reactive.RelationBase, 'from_state')
|
||||
handlers.configure_designate_basic('arg1', 'arg2')
|
||||
self.render_base_config.assert_called_once_with(('arg1', 'arg2', ))
|
||||
self.set_state.assert_called_once_with('base-config.rendered')
|
||||
|
||||
def test_run_db_migration(self):
|
||||
self.patch(handlers.reactive, 'set_state')
|
||||
self.patch(handlers.designate, 'db_sync')
|
||||
self.patch(handlers.designate, 'db_sync_done')
|
||||
self.db_sync_done.return_value = False
|
||||
handlers.run_db_migration('arg1', 'arg2')
|
||||
self.db_sync.assert_called_once_with()
|
||||
self.assertFalse(self.set_state.called)
|
||||
self.db_sync.reset_mock()
|
||||
self.db_sync_done.return_value = True
|
||||
handlers.run_db_migration('arg1', 'arg2')
|
||||
self.db_sync.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('db.synched')
|
||||
|
||||
def test_update_peers(self):
|
||||
cluster = mock.MagicMock()
|
||||
self.patch(handlers.designate, 'update_peers')
|
||||
self.patch(handlers.trove, 'update_peers')
|
||||
handlers.update_peers(cluster)
|
||||
self.update_peers.assert_called_once_with(cluster)
|
||||
|
||||
def test_configure_designate_full(self):
|
||||
self.patch(handlers.reactive.RelationBase, 'from_state',
|
||||
return_value=None)
|
||||
self.patch(handlers.designate, 'configure_ssl')
|
||||
self.patch(handlers.designate, 'render_full_config')
|
||||
self.patch(handlers.designate, 'create_initial_servers_and_domains')
|
||||
self.patch(handlers.designate, 'render_sink_configs')
|
||||
self.patch(handlers.designate, 'render_rndc_keys')
|
||||
self.patch(handlers.designate, 'update_pools')
|
||||
handlers.configure_designate_full('arg1', 'arg2')
|
||||
self.configure_ssl.assert_called_once_with()
|
||||
self.render_full_config.assert_called_once_with(('arg1', 'arg2', ))
|
||||
self.create_initial_servers_and_domains.assert_called_once_with()
|
||||
self.render_sink_configs.assert_called_once_with(('arg1', 'arg2', ))
|
||||
self.render_rndc_keys.assert_called_once_with()
|
||||
self.update_pools.assert_called_once_with()
|
||||
|
||||
def test_cluster_connected(self):
|
||||
hacluster = mock.MagicMock()
|
||||
self.patch(handlers.designate, 'configure_ha_resources')
|
||||
self.patch(handlers.designate, 'assess_status')
|
||||
handlers.cluster_connected(hacluster)
|
||||
self.configure_ha_resources.assert_called_once_with(hacluster)
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_config_changed(self):
|
||||
self.patch(handlers.designate, 'assess_status')
|
||||
self.patch(handlers.trove, 'assess_status')
|
||||
handlers.config_changed()
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
import mock
|
||||
import unittest
|
||||
|
||||
import reactive.designate_utils as dutils
|
||||
|
||||
DOMAIN_LIST = b"""
|
||||
b78d458c-2a69-47e7-aa40-a1f9ff8809e3 frodo.com. 1467534540
|
||||
fa5111a7-5659-45c6-a101-525b4259e8f0 bilbo.com. 1467534855
|
||||
"""
|
||||
|
||||
SERVER_LIST = b"""
|
||||
77eee1aa-27fc-49b9-acca-3faf68126530 ns1.www.example.com.
|
||||
"""
|
||||
|
||||
|
||||
class TestTroveUtils(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self._patches = {}
|
||||
self._patches_start = {}
|
||||
|
||||
def tearDown(self):
|
||||
for k, v in self._patches.items():
|
||||
v.stop()
|
||||
setattr(self, k, None)
|
||||
self._patches = None
|
||||
self._patches_start = None
|
||||
|
||||
def patch(self, obj, attr, return_value=None):
|
||||
mocked = mock.patch.object(obj, attr)
|
||||
self._patches[attr] = mocked
|
||||
started = mocked.start()
|
||||
started.return_value = return_value
|
||||
self._patches_start[attr] = started
|
||||
setattr(self, attr, started)
|
||||
|
||||
def test_run_command(self):
|
||||
self.patch(dutils, 'get_environment')
|
||||
self.patch(dutils.subprocess, 'Popen')
|
||||
process_mock = mock.Mock()
|
||||
attrs = {
|
||||
'communicate.return_value': ('ouput', 'error'),
|
||||
'returncode': 0}
|
||||
process_mock.configure_mock(**attrs)
|
||||
self.Popen.return_value = process_mock
|
||||
self.Popen.returncode.return_value = 0
|
||||
dutils.run_command(['ls'])
|
||||
self.Popen.assert_called_once_with(
|
||||
['ls'],
|
||||
env=None,
|
||||
stderr=-1,
|
||||
stdout=-1)
|
||||
|
||||
def test_run_command_fail(self):
|
||||
self.patch(dutils, 'get_environment')
|
||||
self.patch(dutils.subprocess, 'Popen')
|
||||
process_mock = mock.Mock()
|
||||
attrs = {
|
||||
'communicate.return_value': ('ouput', 'error'),
|
||||
'returncode': 1}
|
||||
process_mock.configure_mock(**attrs)
|
||||
self.Popen.return_value = process_mock
|
||||
self.Popen.returncode.return_value = 0
|
||||
with self.assertRaises(RuntimeError):
|
||||
dutils.run_command(['ls'])
|
||||
|
||||
def test_get_environment(self):
|
||||
text_file_data = '\n'.join(["export a=b", "export c=d"])
|
||||
with mock.patch('builtins.open',
|
||||
mock.mock_open(read_data=text_file_data),
|
||||
create=True) as m:
|
||||
m.return_value.__iter__.return_value = text_file_data.splitlines()
|
||||
with open('filename', 'rU'):
|
||||
self.assertEqual(
|
||||
dutils.get_environment({}),
|
||||
{'a': 'b', 'c': 'd'})
|
||||
|
||||
def test_get_server_id(self):
|
||||
self.patch(dutils, 'get_servers')
|
||||
self.get_servers.return_value = {'server1': {'id': 'servid1'}}
|
||||
self.assertEquals(dutils.get_server_id('server1'), 'servid1')
|
||||
self.assertEquals(dutils.get_server_id('server2'), None)
|
||||
|
||||
def test_get_domain_id(self):
|
||||
self.patch(dutils, 'get_domains')
|
||||
self.get_domains.return_value = {'domain1': {'id': 'domainid1'}}
|
||||
self.assertEquals(dutils.get_domain_id('domain1'), 'domainid1')
|
||||
self.assertEquals(dutils.get_domain_id('domain2'), None)
|
||||
|
||||
def test_create_server(self):
|
||||
_server_ids = ['servid1', None]
|
||||
self.patch(dutils, 'get_server_id')
|
||||
self.patch(dutils, 'display')
|
||||
self.get_server_id.side_effect = lambda x: _server_ids.pop()
|
||||
self.patch(dutils, 'run_command')
|
||||
self.run_command.return_value = ('out', 'err')
|
||||
dutils.create_server('server1')
|
||||
cmd = [
|
||||
'designate', 'server-create',
|
||||
'--name', 'server1',
|
||||
'-f', 'value',
|
||||
]
|
||||
self.run_command.assert_called_with(cmd)
|
||||
self.display.assert_called_with('servid1')
|
||||
|
||||
def test_create_domain(self):
|
||||
_domain_ids = ['domainid1', None]
|
||||
self.patch(dutils, 'get_domain_id')
|
||||
self.patch(dutils, 'display')
|
||||
self.get_domain_id.side_effect = lambda x: _domain_ids.pop()
|
||||
self.patch(dutils, 'run_command')
|
||||
self.run_command.return_value = ('out', 'err')
|
||||
dutils.create_domain('dom1', 'email1')
|
||||
cmd = [
|
||||
'designate', 'domain-create',
|
||||
'--name', 'dom1',
|
||||
'--email', 'email1',
|
||||
'-f', 'value',
|
||||
]
|
||||
self.run_command.assert_called_with(cmd)
|
||||
self.display.assert_called_with('domainid1')
|
||||
|
||||
def test_delete_domain(self):
|
||||
self.patch(dutils, 'get_domain_id', return_value='dom1')
|
||||
self.patch(dutils, 'run_command')
|
||||
dutils.delete_domain('dom1')
|
||||
self.run_command.assert_called_with(['domain-delete', 'dom1'])
|
||||
|
||||
def test_get_domains(self):
|
||||
self.patch(dutils, 'run_command')
|
||||
self.run_command.return_value = (DOMAIN_LIST, 'err')
|
||||
expect = {
|
||||
'bilbo.com.':
|
||||
{
|
||||
'id': 'fa5111a7-5659-45c6-a101-525b4259e8f0',
|
||||
'serial': '1467534855'},
|
||||
'frodo.com.':
|
||||
{
|
||||
'id': 'b78d458c-2a69-47e7-aa40-a1f9ff8809e3',
|
||||
'serial': '1467534540'}}
|
||||
self.assertEqual(dutils.get_domains(), expect)
|
||||
self.run_command.assert_called_with(
|
||||
['designate', 'domain-list', '-f', 'value'])
|
||||
|
||||
def test_get_servers(self):
|
||||
self.patch(dutils, 'run_command')
|
||||
self.run_command.return_value = (SERVER_LIST, 'err')
|
||||
expect = {
|
||||
'ns1.www.example.com.': {
|
||||
'id': '77eee1aa-27fc-49b9-acca-3faf68126530'}}
|
||||
self.assertEqual(dutils.get_servers(), expect)
|
||||
self.run_command.assert_called_with(
|
||||
['designate', 'server-list', '-f', 'value'])
|
Loading…
Reference in New Issue