Add Amulet Tests
This change adds amulet tests to the charm and fixes a bug causing the status to never report a unit ready state which was blocking amulet runs. Closes-Bug: 1604172 Change-Id: I345fb1a3c63a17f1b0070426d06c517c908c7d81
This commit is contained in:
parent
068a29eccf
commit
26b4fb2374
|
@ -1,5 +1,4 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
charm-tools>=2.0.0
|
||||
simplejson>=2.2.0
|
||||
# Requirements to build the charm
|
||||
charm-tools
|
||||
simplejson
|
||||
flake8
|
||||
|
|
|
@ -10,5 +10,4 @@ if __name__ == '__main__':
|
|||
# Cloud may have different artifacts (flavors, images etc) since last run
|
||||
# so rerun handlers file to regenerate config.
|
||||
reactive.main()
|
||||
charm = tempest.get_charm()
|
||||
charm.run_test('smoke')
|
||||
tempest.run_test('smoke')
|
||||
|
|
|
@ -15,7 +15,7 @@ import charmhelpers.fetch as fetch
|
|||
|
||||
|
||||
def install():
|
||||
"""Use the singleton from the BarbicanCharm to install the packages on the
|
||||
"""Use the singleton from the TempestCharm to install the packages on the
|
||||
unit
|
||||
"""
|
||||
TempestCharm.singleton.install()
|
||||
|
@ -28,6 +28,14 @@ def render_configs(interfaces_list):
|
|||
if not os.path.isdir(TempestCharm.TEMPEST_LOGDIR):
|
||||
os.makedirs(TempestCharm.TEMPEST_LOGDIR)
|
||||
TempestCharm.singleton.render_with_interfaces(interfaces_list)
|
||||
TempestCharm.singleton.assess_status()
|
||||
|
||||
|
||||
def run_test(tox_target):
|
||||
"""Use the singleton from the TempestCharm to install the packages on the
|
||||
unit
|
||||
"""
|
||||
TempestCharm.singleton.run_test(tox_target)
|
||||
|
||||
|
||||
class TempestAdminAdapter(adapters.OpenStackRelationAdapter):
|
||||
|
@ -247,6 +255,7 @@ class TempestCharm(charm.OpenStackCharm):
|
|||
release = 'liberty'
|
||||
name = 'tempest'
|
||||
|
||||
required_relations = ['identity-admin']
|
||||
"""Directories and files used for running tempest"""
|
||||
TEMPEST_ROOT = '/var/lib/tempest/'
|
||||
TEMPEST_LOGDIR = TEMPEST_ROOT + '/logs'
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../requirements.txt
|
|
@ -1 +0,0 @@
|
|||
../test-requirements.txt
|
|
@ -0,0 +1,23 @@
|
|||
# charm-proof
|
||||
charm-tools>=2.0.0
|
||||
# amulet deployment helpers
|
||||
bzr+lp:charm-helpers#egg=charmhelpers
|
||||
# BEGIN: Amulet OpenStack Charm Helper Requirements
|
||||
# Liberty client lower constraints
|
||||
amulet>=1.14.3,<2.0
|
||||
bundletester>=0.6.1,<1.0
|
||||
aodhclient>=0.1.0
|
||||
python-ceilometerclient>=1.5.0,<2.0
|
||||
python-cinderclient>=1.4.0,<2.0
|
||||
python-glanceclient>=1.1.0,<2.0
|
||||
python-heatclient>=0.8.0,<1.0
|
||||
python-keystoneclient>=1.7.1,<2.0
|
||||
python-neutronclient>=3.1.0,<4.0
|
||||
python-novaclient>=2.30.1,<3.0
|
||||
python-openstackclient>=1.7.0,<2.0
|
||||
python-swiftclient>=2.6.0,<3.0
|
||||
pika>=0.10.0,<1.0
|
||||
distro-info
|
||||
# END: Amulet OpenStack Charm Helper Requirements
|
||||
# NOTE: workaround for 14.04 pip/tox
|
||||
pytz
|
|
@ -0,0 +1,124 @@
|
|||
import subprocess
|
||||
import json
|
||||
import time
|
||||
|
||||
from charmhelpers.contrib.openstack.amulet.deployment import (
|
||||
OpenStackAmuletDeployment
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.amulet.utils import (
|
||||
OpenStackAmuletUtils,
|
||||
DEBUG,
|
||||
)
|
||||
|
||||
# Use DEBUG to turn on debug logging
|
||||
u = OpenStackAmuletUtils(DEBUG)
|
||||
|
||||
|
||||
class TempestBasicDeployment(OpenStackAmuletDeployment):
|
||||
"""Amulet tests on a basic tempest deployment."""
|
||||
|
||||
def __init__(self, series, openstack=None, source=None, stable=False):
|
||||
"""Deploy the entire test environment."""
|
||||
super(TempestBasicDeployment, self).__init__(series, openstack,
|
||||
source, stable)
|
||||
self._add_services()
|
||||
self._add_relations()
|
||||
self._configure_services()
|
||||
self._deploy()
|
||||
|
||||
u.log.info('Waiting on extended status checks...')
|
||||
exclude_services = ['mysql', 'mongodb']
|
||||
self._auto_wait_for_status(exclude_services=exclude_services)
|
||||
|
||||
self._initialize_tests()
|
||||
|
||||
def _add_services(self):
|
||||
"""Add services
|
||||
|
||||
Add the services that we're testing, where tempest is local,
|
||||
and the rest of the service are from lp branches that are
|
||||
compatible with the local charm (e.g. stable or next).
|
||||
"""
|
||||
this_service = {'name': 'tempest'}
|
||||
other_services = [{'name': 'mysql'},
|
||||
{'name': 'rabbitmq-server'},
|
||||
{'name': 'keystone'},
|
||||
{'name': 'openstack-dashboard'},
|
||||
{'name': 'glance'}]
|
||||
super(TempestBasicDeployment, self)._add_services(
|
||||
this_service,
|
||||
other_services,
|
||||
no_origin=['tempest'])
|
||||
|
||||
def _add_relations(self):
|
||||
"""Add all of the relations for the services."""
|
||||
relations = {
|
||||
'keystone:identity-admin': 'tempest:identity-admin',
|
||||
'tempest:dashboard': 'openstack-dashboard:website',
|
||||
'openstack-dashboard:identity-service':
|
||||
'keystone:identity-service',
|
||||
'keystone:shared-db': 'mysql:shared-db',
|
||||
'glance:identity-service': 'keystone:identity-service',
|
||||
'glance:shared-db': 'mysql:shared-db',
|
||||
'glance:amqp': 'rabbitmq-server:amqp'
|
||||
}
|
||||
super(TempestBasicDeployment, self)._add_relations(relations)
|
||||
|
||||
def _configure_services(self):
|
||||
"""Configure all of the services."""
|
||||
keystone_config = {'admin-password': 'openstack',
|
||||
'admin-token': 'ubuntutesting'}
|
||||
configs = {'keystone': keystone_config}
|
||||
super(TempestBasicDeployment, self)._configure_services(configs)
|
||||
|
||||
def _get_token(self):
|
||||
return self.keystone.service_catalog.catalog['token']['id']
|
||||
|
||||
def _initialize_tests(self):
|
||||
"""Perform final initialization before tests get run."""
|
||||
# Access the sentries for inspecting service units
|
||||
self.mysql_sentry = self.d.sentry['mysql'][0]
|
||||
self.keystone_sentry = self.d.sentry['keystone'][0]
|
||||
self.rabbitmq_sentry = self.d.sentry['rabbitmq-server'][0]
|
||||
self.tempest_sentry = self.d.sentry['tempest'][0]
|
||||
self.openstack_dashboard_sentry = \
|
||||
self.d.sentry['openstack-dashboard'][0]
|
||||
u.log.debug('openstack release val: {}'.format(
|
||||
self._get_openstack_release()))
|
||||
u.log.debug('openstack release str: {}'.format(
|
||||
self._get_openstack_release_string()))
|
||||
|
||||
def _run_action(self, unit_id, action, *args):
|
||||
command = ["juju", "action", "do", "--format=json", unit_id, action]
|
||||
command.extend(args)
|
||||
print("Running command: %s\n" % " ".join(command))
|
||||
output = subprocess.check_output(command)
|
||||
output_json = output.decode(encoding="UTF-8")
|
||||
data = json.loads(output_json)
|
||||
action_id = data[u'Action queued with id']
|
||||
return action_id
|
||||
|
||||
def _wait_on_action(self, action_id):
|
||||
command = ["juju", "action", "fetch", "--format=json", action_id]
|
||||
while True:
|
||||
try:
|
||||
output = subprocess.check_output(command)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
output_json = output.decode(encoding="UTF-8")
|
||||
data = json.loads(output_json)
|
||||
if data[u"status"] == "completed":
|
||||
return True
|
||||
elif data[u"status"] == "failed":
|
||||
return False
|
||||
time.sleep(2)
|
||||
|
||||
def test_run_tempest(self):
|
||||
u.log.debug('Running Tempest...')
|
||||
unit = self.tempest_sentry
|
||||
assert u.status_get(unit)[0] == "active"
|
||||
|
||||
action_id = self._run_action(unit.info['unit_name'], "run-tempest")
|
||||
assert self._wait_on_action(action_id), "run-tempest action failed."
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""Amulet tests on a basic tempest deployment on trusty-mitaka."""
|
||||
|
||||
from basic_deployment import TempestBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Tempest is installed through pip so cloud archive is not needed here
|
||||
deployment = TempestBasicDeployment(series='trusty',
|
||||
openstack='cloud:trusty-mitaka',
|
||||
source='cloud:trusty-updates/mitaka')
|
||||
deployment.run_tests()
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""Amulet tests on a basic tempest deployment on xenial-mitaka."""
|
||||
|
||||
from basic_deployment import TempestBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = TempestBasicDeployment(series='xenial')
|
||||
deployment.run_tests()
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Bootstrap the model if necessary.
|
||||
bootstrap: True
|
||||
# Re-use bootstrap node instead of destroying/re-bootstrapping.
|
||||
reset: True
|
||||
# Use tox/requirements to drive the venv instead of bundletester's venv feature.
|
||||
virtualenv: False
|
||||
# Leave makefile empty, otherwise unit/lint tests will rerun ahead of amulet.
|
||||
makefile: []
|
||||
# Do not specify juju PPA sources. Juju is presumed to be pre-installed
|
||||
# and configured in all test runner environments.
|
||||
#sources:
|
||||
# Do not specify or rely on system packages.
|
||||
#packages:
|
||||
# Do not specify python packages here. Use test-requirements.txt
|
||||
# and tox instead. ie. The venv is constructed before bundletester
|
||||
# is invoked.
|
||||
#python-packages:
|
|
@ -1 +0,0 @@
|
|||
Add amulet functional tests.
|
|
@ -1,8 +1,7 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
coverage>=3.6
|
||||
mock>=1.2
|
||||
pep8>=1.7.0
|
||||
# Unit test requirements
|
||||
flake8>=2.2.4,<=2.4.1
|
||||
os-testr>=0.4.1
|
||||
charms.reactive
|
||||
mock>=1.2
|
||||
coverage>=3.6
|
||||
git+https://github.com/openstack/charms.openstack#egg=charms.openstack
|
||||
|
|
Loading…
Reference in New Issue