diff --git a/requirements.txt b/requirements.txt index b8fec1e2..343beed1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,12 @@ -# 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. +# This file is managed centrally by release-tools and should not be modified +# within individual charm repos. See the 'global' dir contents for available +# choices of *requirements.txt files for OpenStack Charms: +# https://github.com/openstack-charmers/release-tools +# +# TODO: Distill the func test requirements from the lint/unit test +# requirements. They are intertwined. Also, Zaza itself should specify +# all of its own requirements and if it doesn't, fix it there. +# pbr>=1.8.0,<1.9.0 simplejson>=2.2.0 netifaces>=0.10.4 diff --git a/test-requirements.txt b/test-requirements.txt index 42e49f90..7d9c2587 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,29 +1,18 @@ -# 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. +# This file is managed centrally by release-tools and should not be modified +# within individual charm repos. See the 'global' dir contents for available +# choices of *requirements.txt files for OpenStack Charms: +# https://github.com/openstack-charmers/release-tools +# +# TODO: Distill the func test requirements from the lint/unit test +# requirements. They are intertwined. Also, Zaza itself should specify +# all of its own requirements and if it doesn't, fix it there. +# charm-tools>=2.4.4 -coverage>=3.6 +requests>=2.18.4 mock>=1.2 flake8>=2.2.4,<=2.4.1 stestr>=2.2.0 -requests>=2.18.4 -# BEGIN: Amulet OpenStack Charm Helper Requirements -# Liberty client lower constraints -amulet>=1.14.3,<2.0;python_version=='2.7' -bundletester>=0.6.1,<1.0;python_version=='2.7' -python-ceilometerclient>=1.5.0 -python-cinderclient>=1.4.0,<5.0 # Train cinderclient removes v1.client -python-glanceclient>=1.1.0 -python-heatclient>=0.8.0 -python-keystoneclient>=1.7.1 -python-neutronclient>=3.1.0 -python-novaclient>=2.30.1 -python-openstackclient>=1.7.0 -python-swiftclient>=2.6.0 -pika>=0.10.0,<1.0 -distro-info -git+https://github.com/juju/charm-helpers.git#egg=charmhelpers -# END: Amulet OpenStack Charm Helper Requirements -# NOTE: workaround for 14.04 pip/tox -pytz -pyudev # for ceph-* charm unit tests (not mocked?) +coverage>=4.5.2 +pyudev # for ceph-* charm unit tests (need to fix the ceph-* charm unit tests/mocking) +git+https://github.com/openstack-charmers/zaza.git#egg=zaza;python_version>='3.0' +git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 046be7fb..00000000 --- a/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Overview - -This directory provides Amulet tests to verify basic deployment functionality -from the perspective of this charm, its requirements and its features, as -exercised in a subset of the full OpenStack deployment test bundle topology. - -For full details on functional testing of OpenStack charms please refer to -the [functional testing](http://docs.openstack.org/developer/charm-guide/testing.html#functional-testing) -section of the OpenStack Charm Guide. diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py deleted file mode 100644 index b94c5052..00000000 --- a/tests/basic_deployment.py +++ /dev/null @@ -1,428 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import amulet -import requests -import urllib2 -import time - -from charmhelpers.contrib.openstack.amulet.deployment import ( - OpenStackAmuletDeployment -) - -from charmhelpers.contrib.openstack.amulet.utils import ( - OpenStackAmuletUtils, - DEBUG, - # ERROR -) - -from charmhelpers.core.decorators import ( - retry_on_exception, -) - -# Use DEBUG to turn on debug logging -u = OpenStackAmuletUtils(DEBUG) - - -class OpenstackDashboardBasicDeployment(OpenStackAmuletDeployment): - """Amulet tests on a basic openstack-dashboard deployment.""" - - def __init__(self, series, openstack=None, source=None, - stable=False): - """Deploy the entire test environment.""" - super(OpenstackDashboardBasicDeployment, 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 = [] - - # Wait for deployment ready msgs, except exclusions - self._auto_wait_for_status(exclude_services=exclude_services) - - self.d.sentry.wait() - self._initialize_tests() - - def _add_services(self): - """Add the services that we're testing, where openstack-dashboard 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': 'openstack-dashboard', - 'constraints': {'mem': '3072M'}} - other_services = [ - {'name': 'keystone'}, - self.get_percona_service_entry(), - ] - super(OpenstackDashboardBasicDeployment, self)._add_services( - this_service, - other_services) - - def _add_relations(self): - """Add all of the relations for the services.""" - relations = { - 'openstack-dashboard:identity-service': - 'keystone:identity-service', - 'openstack-dashboard:shared-db': 'percona-cluster:shared-db', - 'keystone:shared-db': 'percona-cluster:shared-db', - } - super(OpenstackDashboardBasicDeployment, self)._add_relations( - relations) - - def _configure_services(self): - """Configure all of the services.""" - horizon_config = { - 'debug': 'yes', - 'haproxy-server-timeout': 90000, - 'haproxy-client-timeout': 90000, - 'haproxy-queue-timeout': 9000, - 'haproxy-connect-timeout': 9000, - } - keystone_config = { - 'admin-password': 'openstack', - 'admin-token': 'ubuntutesting', - } - pxc_config = { - 'root-password': 'ChangeMe123', - 'sst-password': 'ChangeMe123', - 'tuning-level': 'unsafe', - } - configs = { - 'openstack-dashboard': horizon_config, - 'percona-cluster': pxc_config, - 'keystone': keystone_config, - } - super(OpenstackDashboardBasicDeployment, self)._configure_services( - configs) - - def _initialize_tests(self): - """Perform final initialization before tests get run.""" - # Access the sentries for inspecting service units - self.keystone_sentry = self.d.sentry['keystone'][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())) - - # NOTE(beisner): Switch to helper once the rabbitmq test refactor lands. - def crude_py_parse(self, file_contents, expected): - for line in file_contents.split('\n'): - if '=' in line: - args = line.split('=') - if len(args) <= 1: - continue - key = args[0].strip() - value = args[1].strip() - if key in expected.keys(): - if expected[key] != value: - msg = "Mismatch %s != %s" % (expected[key], value) - amulet.raise_status(amulet.FAIL, msg=msg) - - def test_050_local_settings_permissions_regression_check_lp1755027(self): - """Assert the intended file permissions on openstack-dashboard's - configuration file. Regression coverage for - https://bugs.launchpad.net/bugs/1755027.""" - - file_path = '/etc/openstack-dashboard/local_settings.py' - expected_perms = '640' - unit_sentry = self.openstack_dashboard_sentry - - # NOTE(beisner): This could be a new test helper, but it needs - # to be a clean backport to stable with high prio, so maybe later. - u.log.debug('Checking {} permissions...'.format(file_path)) - cmd = 'stat -c %a {}'.format(file_path) - output, _ = u.run_cmd_unit(unit_sentry, cmd) - assert output == expected_perms, \ - '{} perms not as expected'.format(file_path) - - def test_100_services(self): - """Verify the expected services are running on the corresponding - service units.""" - services = { - self.keystone_sentry: ['keystone'], - self.openstack_dashboard_sentry: ['apache2'] - } - if self._get_openstack_release() >= self.trusty_liberty: - services[self.keystone_sentry] = ['apache2'] - - ret = u.validate_services_by_name(services) - if ret: - amulet.raise_status(amulet.FAIL, msg=ret) - - def test_200_openstack_dashboard_identity_service_relation(self): - """Verify the openstack-dashboard to keystone identity-service - relation data.""" - u.log.debug('Checking dashboard:keystone id relation data...') - unit = self.openstack_dashboard_sentry - relation = ['identity-service', 'keystone:identity-service'] - expected = { - 'private-address': u.valid_ip, - 'requested_roles': 'Member', - } - - ret = u.validate_relation_data(unit, relation, expected) - if ret: - message = u.relation_error('openstack-dashboard identity-service', - ret) - amulet.raise_status(amulet.FAIL, msg=message) - - def test_202_keystone_identity_service_relation(self): - """Verify the keystone to openstack-dashboard identity-service - relation data.""" - u.log.debug('Checking keystone:dashboard id relation data...') - unit = self.keystone_sentry - relation = ['identity-service', 'openstack-dashboard:identity-service'] - expected = { - 'auth_host': u.valid_ip, - 'auth_port': '35357', - 'auth_protocol': 'http', - 'private-address': u.valid_ip, - 'region': 'RegionOne', - 'service_host': u.valid_ip, - 'service_port': '5000', - 'service_protocol': 'http', - } - - ret = u.validate_relation_data(unit, relation, expected) - if ret: - message = u.relation_error('keystone identity-service', ret) - amulet.raise_status(amulet.FAIL, msg=message) - - def test_302_router_settings(self): - if self._get_openstack_release() > self.trusty_icehouse: - u.log.debug('Checking dashboard router settings...') - unit = self.openstack_dashboard_sentry - conf = ('/usr/share/openstack-dashboard/openstack_dashboard/' - 'enabled/_40_router.py') - file_contents = unit.file_contents(conf) - expected = { - 'DISABLED': "True", - } - self.crude_py_parse(file_contents, expected) - - def test_400_connection(self): - u.log.debug('Checking dashboard http response...') - unit = self.openstack_dashboard_sentry - dashboard_relation = unit.relation('identity-service', - 'keystone:identity-service') - dashboard_ip = dashboard_relation['private-address'] - - # NOTE(fnordahl) there is a eluding issue that currently makes the - # first request to the OpenStack Dashboard error out - # with 500 Internal Server Error in CI. Temporarilly - # add retry logic to unwedge the gate. This issue - # should be revisited and root caused properly when time - # allows. - @retry_on_exception(3, base_delay=30) - def do_request(): - response = urllib2.urlopen('http://%s/horizon' % (dashboard_ip)) - return response.read() - html = do_request() - if 'OpenStack Dashboard' not in html: - msg = "Dashboard frontpage check failed" - amulet.raise_status(amulet.FAIL, msg=msg) - - class FailedAuth(Exception): - pass - - def test_401_authenticate(self): - """Validate that authentication succeeds when client logs in through - the OpenStack Dashboard""" - - u.log.debug('Checking authentication through dashboard...') - unit = self.openstack_dashboard_sentry - dashboard_relation = unit.relation('identity-service', - 'keystone:identity-service') - dashboard_ip = dashboard_relation['private-address'] - url = 'http://{}/horizon/auth/login/'.format(dashboard_ip) - - api_version = None - if self._get_openstack_release() < self.xenial_queens: - api_version = 2 - - region = u.get_keystone_endpoint( - self.keystone_sentry.info['public-address'], api_version) - - if self._get_openstack_release() == self.trusty_icehouse: - # icehouse horizon does not operate properly without the compute - # service present in the keystone catalog. However, checking for - # presence of the following text is sufficient to determine whether - # authentication succeeded or not - expect = 'ServiceCatalogException at /admin/' - elif self._get_openstack_release() >= self.bionic_stein: - expect = "Sign Out" - # update the in dashboard seems to require region to be default in - # this test configuration - region = 'default' - else: - expect = 'Projects - OpenStack Dashboard' - - # NOTE(thedac) Similar to the connection test above we get occasional - # intermittent authentication fails. Wrap in a retry loop. - @retry_on_exception(3, base_delay=30) - def _do_auth_check(expect): - # start session, get csrftoken - client = requests.session() - client.get(url) - - if 'csrftoken' in client.cookies: - csrftoken = client.cookies['csrftoken'] - else: - raise Exception("Missing csrftoken") - - # build and send post request - auth = { - 'domain': 'admin_domain', - 'username': 'admin', - 'password': 'openstack', - 'csrfmiddlewaretoken': csrftoken, - 'next': '/horizon/', - 'region': region, - } - - # In the minimal test deployment /horizon/project/ is unauthorized, - # this does not occur in a full deployment and is probably due to - # services/information missing that horizon wants to display data - # for. - # Redirect to /horizon/identity/ instead. - if self._get_openstack_release() >= self.xenial_queens: - auth['next'] = '/horizon/identity/' - - if self._get_openstack_release() >= self.bionic_stein: - auth['region'] = 'default' - - if api_version == 2: - del auth['domain'] - - u.log.debug('POST data: "{}"'.format(auth)) - response = client.post(url, data=auth, headers={'Referer': url}) - - if expect not in response.text: - msg = 'FAILURE code={} text="{}"'.format(response, - response.text) - # NOTE(thedac) amulet.raise_status exits on exception. - # Raise a custom exception. - raise self.FailedAuth(msg) - - try: - _do_auth_check(expect) - except self.FailedAuth as e: - amulet.raise_status(amulet.FAIL, e.message) - - u.log.debug('OK') - - def test_404_connection(self): - """Verify the apache status module gets disabled when - hardening apache.""" - - u.log.debug('Checking apache mod_status gets disabled.') - unit = self.openstack_dashboard_sentry - dashboard_relation = unit.relation('identity-service', - 'keystone:identity-service') - dashboard_ip = dashboard_relation['private-address'] - - u.log.debug('Enabling hardening for apache...') - self.d.configure('openstack-dashboard', {'harden': 'apache'}) - time.sleep(5) # wait for hook to run - self.d.sentry.wait() # wait for hook to finish - - try: - urllib2.urlopen('http://%s/server-status' % (dashboard_ip)) - except urllib2.HTTPError as e: - if e.code == 404: - return - msg = "Apache mod_status check failed." - amulet.raise_status(amulet.FAIL, msg=msg) - - def test_501_security_checklist_action(self): - """Verify expected result on a default install""" - u.log.debug("Testing security-checklist") - sentry_unit = self.openstack_dashboard_sentry - - action_id = u.run_action(sentry_unit, "security-checklist") - u.wait_on_action(action_id) - data = amulet.actions.get_action_output(action_id, full_output=True) - assert data.get(u"status") == "failed", \ - "Security check is expected to not pass by default" - - def test_900_restart_on_config_change(self): - """Verify that the specified services are restarted when the - config is changed.""" - - sentry = self.openstack_dashboard_sentry - juju_service = 'openstack-dashboard' - - # Expected default and alternate values - set_default = {'use-syslog': 'False'} - set_alternate = {'use-syslog': 'True'} - - # Services which are expected to restart upon config change, - # and corresponding config files affected by the change - services = {'apache2': '/etc/openstack-dashboard/local_settings.py', - 'memcached': '/etc/openstack-dashboard/local_settings.py'} - - # Make config change, check for service restarts - u.log.debug('Making config change on {}...'.format(juju_service)) - mtime = u.get_sentry_time(sentry) - self.d.configure(juju_service, set_alternate) - - sleep_time = 30 - for s, conf_file in services.items(): - u.log.debug("Checking that service restarted: {}".format(s)) - if not u.validate_service_config_changed(sentry, mtime, s, - conf_file, - retry_count=6, - retry_sleep_time=20, - sleep_time=sleep_time): - - self.d.configure(juju_service, set_default) - msg = "service {} didn't restart after config change".format(s) - amulet.raise_status(amulet.FAIL, msg=msg) - sleep_time = 0 - - self.d.configure(juju_service, set_default) - - def test_910_pause_and_resume(self): - """The services can be paused and resumed. """ - u.log.debug('Checking pause and resume actions...') - unit = self.d.sentry['openstack-dashboard'][0] - unit_name = unit.info['unit_name'] - - u.log.debug('Checking for active status on {}'.format(unit_name)) - assert u.status_get(unit)[0] == "active" - - u.log.debug('Running pause action on {}'.format(unit_name)) - action_id = u.run_action(unit, "pause") - u.log.debug('Waiting on action {}'.format(action_id)) - assert u.wait_on_action(action_id), "Pause action failed." - u.log.debug('Checking for maintenance status on {}'.format(unit_name)) - assert u.status_get(unit)[0] == "maintenance" - - u.log.debug('Running resume action on {}'.format(unit_name)) - action_id = u.run_action(unit, "resume") - u.log.debug('Waiting on action {}'.format(action_id)) - assert u.wait_on_action(action_id), "Resume action failed." - u.log.debug('Checking for active status on {}'.format(unit_name)) - assert u.status_get(unit)[0] == "active" - u.log.debug('OK') diff --git a/tests/bundles/bionic-queens.yaml b/tests/bundles/bionic-queens.yaml new file mode 100644 index 00000000..6562b3a8 --- /dev/null +++ b/tests/bundles/bionic-queens.yaml @@ -0,0 +1,35 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + to: + - '2' diff --git a/tests/bundles/bionic-rocky.yaml b/tests/bundles/bionic-rocky.yaml new file mode 100644 index 00000000..a999da62 --- /dev/null +++ b/tests/bundles/bionic-rocky.yaml @@ -0,0 +1,39 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-rocky + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:bionic-rocky + to: + - '2' diff --git a/tests/bundles/bionic-stein.yaml b/tests/bundles/bionic-stein.yaml new file mode 100644 index 00000000..fae4f492 --- /dev/null +++ b/tests/bundles/bionic-stein.yaml @@ -0,0 +1,39 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-stein + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:bionic-stein + to: + - '2' diff --git a/tests/bundles/bionic-train.yaml b/tests/bundles/bionic-train.yaml new file mode 100644 index 00000000..e5d79703 --- /dev/null +++ b/tests/bundles/bionic-train.yaml @@ -0,0 +1,39 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-train + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:bionic-train + to: + - '2' diff --git a/tests/bundles/disco-stein.yaml b/tests/bundles/disco-stein.yaml new file mode 100644 index 00000000..9bdbe369 --- /dev/null +++ b/tests/bundles/disco-stein.yaml @@ -0,0 +1,36 @@ +series: disco + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + to: + - '2' diff --git a/tests/bundles/trusty-mitaka.yaml b/tests/bundles/trusty-mitaka.yaml new file mode 100644 index 00000000..846a5259 --- /dev/null +++ b/tests/bundles/trusty-mitaka.yaml @@ -0,0 +1,39 @@ +series: trusty + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:trusty/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:trusty-mitaka + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:trusty-mitaka + to: + - '2' diff --git a/tests/bundles/xenial-mitaka.yaml b/tests/bundles/xenial-mitaka.yaml new file mode 100644 index 00000000..76337a4f --- /dev/null +++ b/tests/bundles/xenial-mitaka.yaml @@ -0,0 +1,35 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + to: + - '2' diff --git a/tests/bundles/xenial-ocata.yaml b/tests/bundles/xenial-ocata.yaml new file mode 100644 index 00000000..12cee9fe --- /dev/null +++ b/tests/bundles/xenial-ocata.yaml @@ -0,0 +1,39 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-ocata + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:xenial-ocata + to: + - '2' diff --git a/tests/bundles/xenial-pike.yaml b/tests/bundles/xenial-pike.yaml new file mode 100644 index 00000000..457016ee --- /dev/null +++ b/tests/bundles/xenial-pike.yaml @@ -0,0 +1,39 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-pike + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:xenial-pike + to: + - '2' diff --git a/tests/bundles/xenial-queens.yaml b/tests/bundles/xenial-queens.yaml new file mode 100644 index 00000000..943f8cc6 --- /dev/null +++ b/tests/bundles/xenial-queens.yaml @@ -0,0 +1,39 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'virt-type=kvm is workaround while awaiting new release of python-libjuju' + +machines: + '0': + constraints: virt-type=kvm mem=3072M + '1': + constraints: virt-type=kvm + '2': + constraints: virt-type=kvm mem=3072M + +relations: + - ["keystone:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:shared-db", "mysql:shared-db"] + - ["openstack-dashboard:identity-service", "keystone:identity-service"] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-queens + to: + - '1' + openstack-dashboard: + charm: ../../../openstack-dashboard + num_units: 1 + options: + openstack-origin: cloud:xenial-queens + to: + - '2' diff --git a/tests/dev-basic-cosmic-rocky b/tests/dev-basic-cosmic-rocky deleted file mode 100755 index 4335c1e9..00000000 --- a/tests/dev-basic-cosmic-rocky +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on cosmic-rocky.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='cosmic') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-queens b/tests/gate-basic-bionic-queens deleted file mode 100755 index dcfb611e..00000000 --- a/tests/gate-basic-bionic-queens +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on bionic-queens.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='bionic') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-rocky b/tests/gate-basic-bionic-rocky deleted file mode 100755 index 6f367e88..00000000 --- a/tests/gate-basic-bionic-rocky +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on bionic-rocky.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='bionic', - openstack='cloud:bionic-rocky', - source='cloud:bionic-updates/rocky') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-stein b/tests/gate-basic-bionic-stein deleted file mode 100755 index 2397e960..00000000 --- a/tests/gate-basic-bionic-stein +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on bionic-stein.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment( - series='bionic', - openstack='cloud:bionic-stein', - source='cloud:bionic-updates/stein') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-train b/tests/gate-basic-bionic-train deleted file mode 100755 index 44a4b289..00000000 --- a/tests/gate-basic-bionic-train +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2019 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on bionic-train.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment( - series='bionic', - openstack='cloud:bionic-train', - source='cloud:bionic-updates/train') - deployment.run_tests() diff --git a/tests/gate-basic-trusty-mitaka b/tests/gate-basic-trusty-mitaka deleted file mode 100755 index 9f8f03eb..00000000 --- a/tests/gate-basic-trusty-mitaka +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on trusty-mitaka.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='trusty', - openstack='cloud:trusty-mitaka', - source='cloud:trusty-updates/mitaka') - deployment.run_tests() diff --git a/tests/gate-basic-xenial-mitaka b/tests/gate-basic-xenial-mitaka deleted file mode 100755 index 4a04eafc..00000000 --- a/tests/gate-basic-xenial-mitaka +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on xenial-mitaka.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='xenial') - deployment.run_tests() diff --git a/tests/gate-basic-xenial-ocata b/tests/gate-basic-xenial-ocata deleted file mode 100755 index f5463d22..00000000 --- a/tests/gate-basic-xenial-ocata +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on xenial-ocata.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='xenial', - openstack='cloud:xenial-ocata', - source='cloud:xenial-updates/ocata') - deployment.run_tests() diff --git a/tests/gate-basic-xenial-pike b/tests/gate-basic-xenial-pike deleted file mode 100755 index a7bbbc21..00000000 --- a/tests/gate-basic-xenial-pike +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on xenial-pike.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='xenial', - openstack='cloud:xenial-pike', - source='cloud:xenial-updates/pike') - deployment.run_tests() diff --git a/tests/gate-basic-xenial-queens b/tests/gate-basic-xenial-queens deleted file mode 100755 index 4ba7c006..00000000 --- a/tests/gate-basic-xenial-queens +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2016 Canonical Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Amulet tests on a basic openstack-dashboard deployment on xenial-queens.""" - -from basic_deployment import OpenstackDashboardBasicDeployment - -if __name__ == '__main__': - deployment = OpenstackDashboardBasicDeployment(series='xenial', - openstack='cloud:xenial-queens', - source='cloud:xenial-updates/queens') - deployment.run_tests() diff --git a/tests/tests.yaml b/tests/tests.yaml index a03e7bad..81f36e5b 100644 --- a/tests/tests.yaml +++ b/tests/tests.yaml @@ -1,18 +1,23 @@ -# Bootstrap the model if necessary. -bootstrap: True -# Re-use bootstrap node. -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: -reset_timeout: 600 +charm_name: openstack-dashboard + +comment: + - '' + +smoke_bundles: + - bionic-stein +gate_bundles: + - trusty-mitaka + - xenial-mitaka + - xenial-ocata + - xenial-pike + - xenial-queens + - bionic-queens + - bionic-rocky + - bionic-stein + - bionic-train + - disco-stein +dev_bundles: + - disco-train + +tests: + - zaza.openstack.charm_tests.openstack_dashboard.tests.OpenStackDashboardTests diff --git a/tox.ini b/tox.ini index b6254346..20dbbfc5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,12 @@ -# Classic charm (with amulet): ./tox.ini +# Classic charm (with zaza): ./tox.ini # This file is managed centrally by release-tools and should not be modified # within individual charm repos. See the 'global' dir contents for available # choices of tox.ini for OpenStack Charms: # https://github.com/openstack-charmers/release-tools +# +# TODO: Distill the func test requirements from the lint/unit test +# requirements. They are intertwined. Also, Zaza itself should specify +# all of its own requirements and if it doesn't, fix it there. [tox] envlist = pep8,py3 skipsdist = True @@ -15,17 +19,12 @@ skip_missing_interpreters = False setenv = VIRTUAL_ENV={envdir} PYTHONHASHSEED=0 CHARM_DIR={envdir} - AMULET_SETUP_TIMEOUT=5400 install_command = pip install {opts} {packages} commands = stestr run --slowest {posargs} whitelist_externals = juju -passenv = HOME TERM AMULET_* CS_* OS_* TEST_* - -[testenv:py3] -basepython = python3 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +passenv = HOME TERM CS_* OS_* TEST_* +deps = -r{toxinidir}/test-requirements.txt [testenv:py35] basepython = python3.5 @@ -42,6 +41,11 @@ basepython = python3.7 deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt +[testenv:py3] +basepython = python3 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + [testenv:pep8] basepython = python3 deps = -r{toxinidir}/requirements.txt @@ -82,39 +86,29 @@ basepython = python3 commands = {posargs} [testenv:func-noop] -# DRY RUN - For Debug -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" -n --no-destroy + functest-run-suite --help [testenv:func] -# Charm Functional Test -# Run all gate tests which are +x (expected to always pass) -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" --no-destroy + functest-run-suite --keep-model [testenv:func-smoke] -# Charm Functional Test -# Run a specific test as an Amulet smoke test (expected to always pass) -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json gate-basic-bionic-train --no-destroy + functest-run-suite --keep-model --smoke [testenv:func-dev] -# Charm Functional Test -# Run all development test targets which are +x (may not always pass!) -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dev-*" --no-destroy + functest-run-suite --keep-model --dev + +[testenv:func-target] +basepython = python3 +commands = + functest-run-suite --keep-model --bundle {posargs} [flake8] ignore = E402,E226