diff --git a/Makefile b/Makefile index 54682e9..55a93c8 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,16 @@ #!/usr/bin/make -PYTHON := /usr/bin/env python +PYTHON := /usr/bin/env python3 lint: @tox -e pep8 test: @echo Starting unit tests... - @tox -e py27 + @tox -e py3 functional_test: @echo Starting functional tests... - @tox -e func27 + @tox -e func bin/charm_helpers_sync.py: @mkdir -p bin diff --git a/hooks/certificates-relation-changed b/hooks/certificates-relation-changed new file mode 120000 index 0000000..9416ca6 --- /dev/null +++ b/hooks/certificates-relation-changed @@ -0,0 +1 @@ +hooks.py \ No newline at end of file diff --git a/hooks/certificates-relation-joined b/hooks/certificates-relation-joined new file mode 120000 index 0000000..9416ca6 --- /dev/null +++ b/hooks/certificates-relation-joined @@ -0,0 +1 @@ +hooks.py \ No newline at end of file diff --git a/hooks/hooks.py b/hooks/hooks.py index f0f5637..db36587 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -45,10 +45,16 @@ from charmhelpers.contrib.openstack.utils import ( set_unit_paused, set_unit_upgrading, ) + from charmhelpers.contrib.openstack.templating import OSConfigRenderer from charmhelpers.contrib.charmsupport import nrpe +from charmhelpers.contrib.openstack.cert_utils import ( + get_certificate_request, + process_certificates, +) + CONF_FILE_DIR = '/etc/glance-simplestreams-sync' USR_SHARE_DIR = '/usr/share/glance-simplestreams-sync' @@ -353,6 +359,21 @@ def post_series_upgrade(): hookenv.status_set("active", "") +@hooks.hook('certificates-relation-joined') +def certs_joined(relation_id=None): + hookenv.relation_set( + relation_id=relation_id, + relation_settings=get_certificate_request()) + + +@hooks.hook('certificates-relation-changed') +def certs_changed(relation_id=None, unit=None): + process_certificates('glance-simplestreams-sync', relation_id, unit) + configs = get_configs() + configs.write_all() + identity_service_changed() + + if __name__ == '__main__': try: hooks.execute(sys.argv) diff --git a/metadata.yaml b/metadata.yaml index 82147e3..6090b1a 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -28,3 +28,5 @@ requires: interface: keystone amqp: interface: rabbitmq + certificates: + interface: tls-certificates diff --git a/scripts/glance-simplestreams-sync.py b/scripts/glance-simplestreams-sync.py index 8d2ed81..90ea909 100755 --- a/scripts/glance-simplestreams-sync.py +++ b/scripts/glance-simplestreams-sync.py @@ -392,10 +392,12 @@ class StatusExchange: return False try: - url = "amqp://{}:{}@{}/{}".format(id_conf['rabbit_userid'], - id_conf['rabbit_password'], - host, - id_conf['rabbit_virtual_host']) + # amqp:// implies librabbitmq if available, otherwise pyamqp + # librabbitmq doesn't support SSL + # use pyamqp:// explicitly for SSL + url = "pyamqp://{}:{}@{}/{}".format( + id_conf['rabbit_userid'], id_conf['rabbit_password'], + host, id_conf['rabbit_virtual_host']) ssl = None if 'rabbit_use_ssl' in id_conf: @@ -503,7 +505,9 @@ def main(): "message": "Sync starting."}) do_sync(charm_conf, status_exchange) ts = time.strftime("%x %X") - completed_msg = "Sync completed at {}".format(ts) + # "Unit is ready" is one of approved message prefixes + # Prefix the message with it will help zaza to understand the status. + completed_msg = "Unit is ready. Sync completed at {}".format(ts) status_exchange.send_message({"status": "Done", "message": completed_msg}) status_set('active', completed_msg) diff --git a/test-requirements.txt b/test-requirements.txt index 272ce1d..250122a 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,29 +1,10 @@ -# 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.4.4 +requests>=2.18.4 coverage>=3.6 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 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?) + +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 046be7f..0000000 --- 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 ffd5e5f..0000000 --- a/tests/basic_deployment.py +++ /dev/null @@ -1,263 +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. - -""" -Basic glance-simplestreams-sync functional tests. -""" - -import amulet -import json -import re -import requests -import time - -from charmhelpers.contrib.openstack.amulet.deployment import ( - OpenStackAmuletDeployment -) - -from charmhelpers.contrib.openstack.amulet.utils import ( - OpenStackAmuletUtils, - DEBUG, - # ERROR -) - -# Use DEBUG to turn on debug logging -u = OpenStackAmuletUtils(DEBUG) - - -class GlanceBasicDeployment(OpenStackAmuletDeployment): - """Amulet tests on a basic file-backed glance deployment. Verify - relations, service status, endpoint service catalog, create and - delete new image.""" - - SERVICES = ('apache2', 'haproxy', 'glance-api', 'glance-registry') - - def __init__(self, series=None, openstack=None, source=None, - stable=False): - """Deploy the entire test environment.""" - super(GlanceBasicDeployment, 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...') - - # NOTE(thedac): This charm has a non-standard workload status. - # The default match for ready will fail. Check the other charms - # for standard workload status and check this charm for Sync - # completed. - - # Check for ready - exclude_services = ['glance-simplestreams-sync'] - self._auto_wait_for_status(exclude_services=exclude_services) - - # Check for Sync completed - self._auto_wait_for_status(re.compile('Sync completed.*', - re.IGNORECASE), - include_only=exclude_services) - - self.d.sentry.wait() - self._initialize_tests() - - def _assert_services(self, should_run): - u.get_unit_process_ids( - {self.glance_sentry: self.SERVICES}, - expect_success=should_run) - - def _add_services(self): - """Add services - - Add the services that we're testing, where glance 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': 'glance-simplestreams-sync'} - other_services = [ - self.get_percona_service_entry(), - {'name': 'glance'}, - {'name': 'rabbitmq-server'}, - {'name': 'keystone'}, - ] - super(GlanceBasicDeployment, self)._add_services( - this_service, - other_services, - use_source=['glance-simplestreams-sync'], - ) - - def _add_relations(self): - """Add relations for the services.""" - relations = { - 'glance:identity-service': 'keystone:identity-service', - 'glance:shared-db': 'percona-cluster:shared-db', - 'keystone:shared-db': 'percona-cluster:shared-db', - 'glance:amqp': 'rabbitmq-server:amqp', - 'glance-simplestreams-sync:identity-service': - 'keystone:identity-service', - 'glance-simplestreams-sync:amqp': - 'rabbitmq-server:amqp', - } - - super(GlanceBasicDeployment, self)._add_relations(relations) - - def _configure_services(self): - """Configure all of the services.""" - gss_config = { - # https://bugs.launchpad.net/bugs/1686437 - 'source': 'ppa:simplestreams-dev/trunk', - 'use_swift': 'False', - } - glance_config = {} - keystone_config = { - 'admin-password': 'openstack', - 'admin-token': 'ubuntutesting', - } - pxc_config = { - 'dataset-size': '25%', - 'max-connections': 1000, - 'root-password': 'ChangeMe123', - 'sst-password': 'ChangeMe123', - } - configs = { - 'glance-simplestreams-sync': gss_config, - 'glance': glance_config, - 'keystone': keystone_config, - 'percona-cluster': pxc_config, - } - super(GlanceBasicDeployment, self)._configure_services(configs) - - def _initialize_tests(self): - """Perform final initialization before tests get run.""" - # Access the sentries for inspecting service units - self.gss_sentry = self.d.sentry['glance-simplestreams-sync'][0] - self.pxc_sentry = self.d.sentry['percona-cluster'][0] - self.glance_sentry = self.d.sentry['glance'][0] - self.keystone_sentry = self.d.sentry['keystone'][0] - self.rabbitmq_sentry = self.d.sentry['rabbitmq-server'][0] - u.log.debug('openstack release val: {}'.format( - self._get_openstack_release())) - u.log.debug('openstack release str: {}'.format( - self._get_openstack_release_string())) - - # Authenticate admin with keystone - self.keystone_session, self.keystone = u.get_default_keystone_session( - self.keystone_sentry, - openstack_release=self._get_openstack_release()) - - # Authenticate admin with glance endpoint - self.glance = u.authenticate_glance_admin(self.keystone) - - def test_010_wait_for_image_sync(self): - """Wait for images to be synced. Expect at least one.""" - - max_image_wait = 600 - retry_sleep = 2 - images = [] - - time_start = time.time() - while not images: - images = [image.name for image in self.glance.images.list()] - u.log.debug('Images: {}'.format(images)) - if images: - break - - time_now = time.time() - if time_now - time_start >= max_image_wait: - raise Exception('Images not synced within ' - '{}s'.format(time_now - time_start)) - else: - u.log.debug('Waiting {}s'.format(retry_sleep)) - time.sleep(retry_sleep) - retry_sleep = retry_sleep + 4 if retry_sleep < 30 else 30 - - def test_050_gss_permissions_regression_check_lp1611987(self): - """Assert the intended file permissions on gss config files - https://bugs.launchpad.net/bugs/1611987""" - - perm_check = [ - { - 'file_path': '/etc/glance-simplestreams-sync/identity.yaml', - 'expected_perms': '640', - 'unit_sentry': self.gss_sentry - }, - { - 'file_path': '/etc/glance-simplestreams-sync/mirrors.yaml', - 'expected_perms': '640', - 'unit_sentry': self.gss_sentry - }, - { - 'file_path': '/var/log/glance-simplestreams-sync.log', - 'expected_perms': '640', - 'unit_sentry': self.gss_sentry - }, - ] - - for _check in perm_check: - cmd = 'stat -c %a {}'.format(_check['file_path']) - output, _ = u.run_cmd_unit(_check['unit_sentry'], cmd) - - assert output == _check['expected_perms'], \ - '{} perms not as expected'.format(_check['file_path']) - - u.log.debug('Permissions on {}: {}'.format( - _check['file_path'], output)) - - def test_102_service_catalog(self): - """Verify that the service catalog endpoint data is valid.""" - u.log.debug('Checking keystone service catalog...') - endpoint_check = { - 'adminURL': u.valid_url, - 'id': u.not_null, - 'region': 'RegionOne', - 'publicURL': u.valid_url, - 'internalURL': u.valid_url - } - expected = { - 'product-streams': [endpoint_check], - 'image': [endpoint_check], - 'identity': [endpoint_check] - } - actual = self.keystone.service_catalog.get_endpoints() - - ret = u.validate_svc_catalog_endpoint_data( - expected, - actual, - openstack_release=self._get_openstack_release()) - if ret: - amulet.raise_status(amulet.FAIL, msg=ret) - - def test_110_local_product_stream(self): - """Verify that the local product stream is accessible and has data""" - u.log.debug('Checking local product streams...') - _expected = ['com.ubuntu.cloud:server:14.04:amd64', - 'com.ubuntu.cloud:server:16.04:amd64', - 'com.ubuntu.cloud:server:18.04:amd64'] - _uri = "streams/v1/auto.sync.json" - _key = "url" - if self._get_openstack_release() <= self.xenial_pike: - _key = "publicURL" - - _catalog = self.keystone.service_catalog.get_endpoints() - _ps_interface = _catalog["product-streams"][0][_key] - _url = "{}/{}".format(_ps_interface, _uri) - _client = requests.session() - _json_data = _client.get(_url).text - _product_streams = json.loads(_json_data) - - for image in _expected: - assert image in _product_streams["products"].keys() - u.log.debug("Local product stream successful") diff --git a/tests/basic_deployment_ssl.py b/tests/basic_deployment_ssl.py deleted file mode 100644 index c658c58..0000000 --- a/tests/basic_deployment_ssl.py +++ /dev/null @@ -1,165 +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. - -""" -Basic glance-simplestreams-sync functional tests. -""" - -import base64 -import os -import re -import tempfile - -from charmhelpers.contrib.openstack.amulet.deployment import ( - OpenStackAmuletDeployment -) - -from charmhelpers.contrib.openstack.amulet.utils import ( - OpenStackAmuletUtils, - DEBUG, - # ERROR -) - -import generate_certs - -# Use DEBUG to turn on debug logging -u = OpenStackAmuletUtils(DEBUG) - - -class GlanceBasicDeployment(OpenStackAmuletDeployment): - """Amulet tests on a basic file-backed glance deployment. Verify - relations, service status, endpoint service catalog, create and - delete new image.""" - - SERVICES = ('apache2', 'haproxy', 'glance-api', 'glance-registry') - - def __init__(self, series=None, openstack=None, source=None, - stable=False): - """Deploy the entire test environment.""" - super(GlanceBasicDeployment, 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...') - - # NOTE(thedac): This charm has a non-standard workload status. - # The default match for ready will fail. Check the other charms - # for standard workload status and check this charm for Sync - # completed. - - # Check for ready - exclude_services = ['glance-simplestreams-sync'] - self._auto_wait_for_status(exclude_services=exclude_services) - - # Check for Sync completed; if SSL is okay, this should work - self._auto_wait_for_status(re.compile('Sync completed.*', - re.IGNORECASE), - include_only=exclude_services) - - self.d.sentry.wait() - - def _assert_services(self, should_run): - u.get_unit_process_ids( - {self.glance_sentry: self.SERVICES}, - expect_success=should_run) - - def _add_services(self): - """Add services - - Add the services that we're testing, where glance 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': 'glance-simplestreams-sync'} - other_services = [ - {'name': 'percona-cluster', 'constraints': {'mem': '3072M'}}, - {'name': 'glance'}, - {'name': 'rabbitmq-server'}, - {'name': 'keystone'}, - ] - super(GlanceBasicDeployment, self)._add_services( - this_service, - other_services, - use_source=['glance-simplestreams-sync'], - ) - - def _add_relations(self): - """Add relations for the services.""" - relations = { - 'glance:identity-service': 'keystone:identity-service', - 'glance:shared-db': 'percona-cluster:shared-db', - 'keystone:shared-db': 'percona-cluster:shared-db', - 'glance:amqp': 'rabbitmq-server:amqp', - 'glance-simplestreams-sync:identity-service': - 'keystone:identity-service', - 'glance-simplestreams-sync:amqp': - 'rabbitmq-server:amqp', - } - - super(GlanceBasicDeployment, self)._add_relations(relations) - - def _configure_services(self): - """Configure all of the services.""" - _path = tempfile.gettempdir() - generate_certs.generate_certs(_path) - - _cacert = self.load_base64(_path, 'cacert.pem') - _cert = self.load_base64(_path, 'cert.pem') - _key = self.load_base64(_path, 'cert.key') - - gss_config = { - # https://bugs.launchpad.net/bugs/1686437 - 'source': 'ppa:simplestreams-dev/trunk', - 'use_swift': 'False', - 'ssl_ca': _cacert, - } - glance_config = { - 'ssl_ca': _cacert, - 'ssl_cert': _cert, - 'ssl_key': _key, - } - keystone_config = { - 'admin-password': 'openstack', - 'admin-token': 'ubuntutesting', - 'ssl_ca': _cacert, - 'ssl_cert': _cert, - 'ssl_key': _key, - } - pxc_config = { - 'dataset-size': '25%', - 'max-connections': 1000, - 'root-password': 'ChangeMe123', - 'sst-password': 'ChangeMe123', - } - rabbitmq_server_config = { - 'ssl': 'on', - } - configs = { - 'glance-simplestreams-sync': gss_config, - 'glance': glance_config, - 'keystone': keystone_config, - 'percona-cluster': pxc_config, - 'rabbitmq-server': rabbitmq_server_config, - } - super(GlanceBasicDeployment, self)._configure_services(configs) - - @staticmethod - def load_base64(*path): - with open(os.path.join(*path)) as f: - return base64.b64encode(f.read()) diff --git a/tests/bundles/bionic-queens.yaml b/tests/bundles/bionic-queens.yaml new file mode 100644 index 0000000..5781216 --- /dev/null +++ b/tests/bundles/bionic-queens.yaml @@ -0,0 +1,62 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/bionic-rocky.yaml b/tests/bundles/bionic-rocky.yaml new file mode 100644 index 0000000..046915b --- /dev/null +++ b/tests/bundles/bionic-rocky.yaml @@ -0,0 +1,66 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-rocky + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:bionic-rocky + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/bionic-stein.yaml b/tests/bundles/bionic-stein.yaml new file mode 100644 index 0000000..e844d2a --- /dev/null +++ b/tests/bundles/bionic-stein.yaml @@ -0,0 +1,67 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + series: bionic + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-stein + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:bionic-stein + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/bionic-train.yaml b/tests/bundles/bionic-train.yaml new file mode 100644 index 0000000..048d924 --- /dev/null +++ b/tests/bundles/bionic-train.yaml @@ -0,0 +1,67 @@ +series: bionic + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + series: bionic + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:bionic-train + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:bionic-train + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/disco-stein.yaml b/tests/bundles/disco-stein.yaml new file mode 100644 index 0000000..5a93084 --- /dev/null +++ b/tests/bundles/disco-stein.yaml @@ -0,0 +1,62 @@ +series: disco + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/trusty-mitaka.yaml b/tests/bundles/trusty-mitaka.yaml new file mode 100644 index 0000000..a6e8b58 --- /dev/null +++ b/tests/bundles/trusty-mitaka.yaml @@ -0,0 +1,59 @@ +series: trusty + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + - 'no ssl for this bundle since charm-vault does not support trusty' + +machines: + '0': + constraints: mem=3072M + # series "trusty" not supported by mysql charm + series: xenial + '1': + '2': + '3': + '4': + +relations: + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + # series "trusty" not supported by mysql charm + series: xenial + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + to: + - '1' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:trusty-mitaka + to: + - '2' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:trusty-mitaka + to: + - '3' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '4' diff --git a/tests/bundles/xenial-mitaka.yaml b/tests/bundles/xenial-mitaka.yaml new file mode 100644 index 0000000..8b9dd4d --- /dev/null +++ b/tests/bundles/xenial-mitaka.yaml @@ -0,0 +1,62 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/xenial-ocata.yaml b/tests/bundles/xenial-ocata.yaml new file mode 100644 index 0000000..10df792 --- /dev/null +++ b/tests/bundles/xenial-ocata.yaml @@ -0,0 +1,66 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-ocata + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:xenial-ocata + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/xenial-pike.yaml b/tests/bundles/xenial-pike.yaml new file mode 100644 index 0000000..a753717 --- /dev/null +++ b/tests/bundles/xenial-pike.yaml @@ -0,0 +1,66 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-pike + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:xenial-pike + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/bundles/xenial-queens.yaml b/tests/bundles/xenial-queens.yaml new file mode 100644 index 0000000..bd89458 --- /dev/null +++ b/tests/bundles/xenial-queens.yaml @@ -0,0 +1,66 @@ +series: xenial + +comment: + - 'machines section to decide order of deployment. database sooner = faster' + +machines: + '0': + constraints: mem=3072M + '1': + '2': + '3': + '4': + '5': + +relations: + - ['vault:shared-db', 'mysql:shared-db'] + - ['keystone:shared-db', 'mysql:shared-db'] + - ['glance:shared-db', 'mysql:shared-db'] + - ['glance:amqp', 'rabbitmq-server:amqp'] + - ['glance-simplestreams-sync:amqp', 'rabbitmq-server:amqp'] + - ['keystone:certificates', 'vault:certificates'] + - ['glance:certificates', 'vault:certificates'] + - ['glance-simplestreams-sync:certificates', 'vault:certificates'] + - ['glance:identity-service', 'keystone:identity-service'] + - ['glance-simplestreams-sync:identity-service', 'keystone:identity-service'] + +applications: + mysql: + charm: cs:~openstack-charmers-next/percona-cluster + num_units: 1 + to: + - '0' + rabbitmq-server: + charm: cs:~openstack-charmers-next/rabbitmq-server + num_units: 1 + options: + ssl: 'on' # must be str(in quote), otherwise it's bool + to: + - '1' + vault: + charm: cs:~openstack-charmers-next/vault + num_units: 1 + to: + - '2' + keystone: + charm: cs:~openstack-charmers-next/keystone + num_units: 1 + options: + openstack-origin: cloud:xenial-queens + to: + - '3' + glance: + charm: cs:~openstack-charmers-next/glance + num_units: 1 + options: + openstack-origin: cloud:xenial-queens + to: + - '4' + glance-simplestreams-sync: + charm: ../../glance-simplestreams-sync + num_units: 1 + options: + source: ppa:simplestreams-dev/trunk + use_swift: False + to: + - '5' diff --git a/tests/cert.py b/tests/cert.py deleted file mode 100644 index 3edf689..0000000 --- a/tests/cert.py +++ /dev/null @@ -1,243 +0,0 @@ -# Copyright 2018 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. -"""Module for working with x.509 certificates.""" - -import cryptography -from cryptography.hazmat.primitives.asymmetric import padding, rsa -import cryptography.hazmat.primitives.hashes as hashes -import cryptography.hazmat.primitives.serialization as serialization -import datetime -import ipaddress - - -def generate_cert(common_name, - alternative_names=None, - password=None, - issuer_name=None, - signing_key=None, - signing_key_password=None, - generate_ca=False): - """Generate x.509 certificate. - - Example of how to create a certificate chain:: - - (cakey, cacert) = generate_cert( - 'DivineAuthority', - generate_ca=True) - (crkey, crcert) = generate_cert( - 'test.com', - issuer_name='DivineAuthority', - signing_key=cakey) - - :param common_name: Common Name to use in generated certificate - :type common_name: str - :param alternative_names: List of names to add as SubjectAlternativeName - :type alternative_names: Optional[list(str)] - :param password: Password to protect encrypted private key with - :type password: Optional[str] - :param issuer_name: Issuer name, must match provided_private_key issuer - :type issuer_name: Optional[str] - :param signing_key: PEM encoded PKCS8 formatted private key - :type signing_key: Optional[str] - :param signing_key_password: Password to decrypt private key - :type signing_key_password: Optional[str] - :param generate_ca: Generate a certificate usable as a CA certificate - :type generate_ca: bool - :returns: x.509 certificate - :rtype: cryptography.x509.Certificate - """ - if password is not None: - encryption_algorithm = serialization.BestAvailableEncryption(password) - else: - encryption_algorithm = serialization.NoEncryption() - - if signing_key: - _signing_key = serialization.load_pem_private_key( - signing_key, - password=signing_key_password, - backend=cryptography.hazmat.backends.default_backend(), - ) - - private_key = rsa.generate_private_key( - public_exponent=65537, # per RFC 5280 Appendix C - key_size=2048, - backend=cryptography.hazmat.backends.default_backend() - ) - - public_key = private_key.public_key() - - builder = cryptography.x509.CertificateBuilder() - builder = builder.subject_name(cryptography.x509.Name([ - cryptography.x509.NameAttribute( - cryptography.x509.oid.NameOID.COMMON_NAME, common_name), - ])) - - if issuer_name is None: - issuer_name = common_name - - builder = builder.issuer_name(cryptography.x509.Name([ - cryptography.x509.NameAttribute( - cryptography.x509.oid.NameOID.COMMON_NAME, issuer_name), - ])) - builder = builder.not_valid_before( - datetime.datetime.today() - datetime.timedelta(1, 0, 0), - ) - builder = builder.not_valid_after( - datetime.datetime.today() + datetime.timedelta(1, 0, 0), - ) - builder = builder.serial_number(cryptography.x509.random_serial_number()) - builder = builder.public_key(public_key) - - san_list = [cryptography.x509.DNSName(common_name)] - if alternative_names is not None: - for name in alternative_names: - try: - addr = ipaddress.ip_address(name) - except ValueError: - san_list.append(cryptography.x509.DNSName(name)) - else: - san_list.append(cryptography.x509.IPAddress(addr)) - - builder = builder.add_extension( - cryptography.x509.SubjectAlternativeName( - san_list, - ), - critical=False, - ) - builder = builder.add_extension( - cryptography.x509.BasicConstraints(ca=generate_ca, path_length=None), - critical=True, - ) - - if signing_key: - sign_key = _signing_key - else: - sign_key = private_key - - certificate = builder.sign( - private_key=sign_key, - algorithm=cryptography.hazmat.primitives.hashes.SHA256(), - backend=cryptography.hazmat.backends.default_backend(), - ) - - return ( - private_key.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.PKCS8, - encryption_algorithm=encryption_algorithm), - certificate.public_bytes( - serialization.Encoding.PEM) - ) - - -def sign_csr(csr, ca_private_key, ca_cert=None, issuer_name=None, - ca_private_key_password=None, generate_ca=False): - """Sign CSR with the given key. - - :param csr: Certificate to sign - :type csr: str - :param ca_private_key: Private key to be used to sign csr - :type ca_private_key: str - :param ca_cert: Cert to base some options from - :type ca_cert: str - :param issuer_name: Issuer name, must match provided_private_key issuer - :type issuer_name: Optional[str] - :param ca_private_key_password: Password to decrypt ca_private_key - :type ca_private_key_password: Optional[str] - :param generate_ca: Allow resulting cert to be used as ca - :type generate_ca: bool - :returns: x.509 certificate - :rtype: cryptography.x509.Certificate - """ - backend = cryptography.hazmat.backends.default_backend() - # Create x509 artifacts - root_ca_pkey = serialization.load_pem_private_key( - ca_private_key.encode(), - password=ca_private_key_password, - backend=backend) - - new_csr = cryptography.x509.load_pem_x509_csr( - csr.encode(), - backend) - - if ca_cert: - root_ca_cert = cryptography.x509.load_pem_x509_certificate( - ca_cert.encode(), - backend) - issuer_name = root_ca_cert.subject - else: - issuer_name = issuer_name - # Create builder - builder = cryptography.x509.CertificateBuilder() - builder = builder.serial_number( - cryptography.x509.random_serial_number()) - builder = builder.issuer_name(issuer_name) - builder = builder.not_valid_before( - datetime.datetime.today() - datetime.timedelta(1, 0, 0), - ) - builder = builder.not_valid_after( - datetime.datetime.today() + datetime.timedelta(80, 0, 0), - ) - builder = builder.subject_name(new_csr.subject) - builder = builder.public_key(new_csr.public_key()) - - builder = builder.add_extension( - cryptography.x509.BasicConstraints(ca=generate_ca, path_length=None), - critical=True - ) - - # Sign the csr - signer_ca_cert = builder.sign( - private_key=root_ca_pkey, - algorithm=hashes.SHA256(), - backend=backend) - - return signer_ca_cert.public_bytes(encoding=serialization.Encoding.PEM) - - -def is_keys_valid(public_key_string, private_key_string): - """Test whether these are a valid public/private key pair. - - :param public_key_string: PEM encoded key data. - :type public_key_string: str - :param private_key_string: OpenSSH encoded key data. - :type private_key_string: str - """ - private_key = serialization.load_pem_private_key( - private_key_string.encode(), - password=None, - backend=cryptography.hazmat.backends.default_backend() - ) - public_key = serialization.load_ssh_public_key( - public_key_string.encode(), - backend=cryptography.hazmat.backends.default_backend() - ) - message = b"encrypted data" - ciphertext = public_key.encrypt( - message, - padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA256()), - algorithm=hashes.SHA256(), - label=None)) - - try: - plaintext = private_key.decrypt( - ciphertext, - padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA256()), - algorithm=hashes.SHA256(), - label=None)) - except ValueError: - plaintext = '' - return plaintext == message diff --git a/tests/dev-basic-cosmic-rocky b/tests/dev-basic-cosmic-rocky deleted file mode 100755 index b9910b2..0000000 --- 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 Glance deployment on cosmic-rocky.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='cosmic') - deployment.run_tests() diff --git a/tests/dev-basic-xenial-pike-ssl b/tests/dev-basic-xenial-pike-ssl deleted file mode 100755 index e4410dd..0000000 --- a/tests/dev-basic-xenial-pike-ssl +++ /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 glance deployment on xenial-pike.""" - -from basic_deployment_ssl import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='xenial', - openstack='cloud:xenial-pike', - source='cloud:xenial-updates/pike') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-queens b/tests/gate-basic-bionic-queens deleted file mode 100755 index 41763ea..0000000 --- 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 Glance deployment on bionic-queens.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='bionic') - deployment.run_tests() diff --git a/tests/gate-basic-bionic-rocky b/tests/gate-basic-bionic-rocky deleted file mode 100755 index 6a12155..0000000 --- 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 glance deployment on bionic-rocky.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(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 f364db2..0000000 --- a/tests/gate-basic-bionic-stein +++ /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 glance deployment on bionic-stein.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='bionic', - openstack='cloud:bionic-stein', - source='cloud:bionic-stein') - deployment.run_tests() diff --git a/tests/gate-basic-disco-stein b/tests/gate-basic-disco-stein deleted file mode 100755 index 3a7b6d5..0000000 --- a/tests/gate-basic-disco-stein +++ /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 Glance deployment on disco-stein.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='disco') - deployment.run_tests() diff --git a/tests/gate-basic-trusty-mitaka b/tests/gate-basic-trusty-mitaka deleted file mode 100755 index 6eeaa12..0000000 --- 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 glance deployment on trusty-mitaka.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(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 98b343e..0000000 --- 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 Glance deployment on xenial-mitaka.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='xenial') - deployment.run_tests() diff --git a/tests/gate-basic-xenial-ocata b/tests/gate-basic-xenial-ocata deleted file mode 100755 index ce43ab0..0000000 --- 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 glance deployment on xenial-ocata.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(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 188259e..0000000 --- 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 glance deployment on xenial-pike.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(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 44f06e6..0000000 --- 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 glance deployment on xenial-queens.""" - -from basic_deployment import GlanceBasicDeployment - -if __name__ == '__main__': - deployment = GlanceBasicDeployment(series='xenial', - openstack='cloud:xenial-queens', - source='cloud:xenial-updates/queens') - deployment.run_tests() diff --git a/tests/generate_certs.py b/tests/generate_certs.py deleted file mode 100755 index f8099d3..0000000 --- a/tests/generate_certs.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2018 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 ipaddress -import itertools -import os -import socket -import tempfile - -import six - -import cert as _cert - -ISSUER_NAME = u'OSCI' - -CERT_DIR = tempfile.gettempdir() - - -def determine_CIDR_EXT(): - ip = socket.gethostbyname(socket.getfqdn()) - if ip.startswith('10.5'): - # running in a bastion - return u"10.5.0.0/24" - else: - # running on UOSCI - return u"172.17.107.0/24" - - -def write_cert(path, filename, data, mode=0o600): - """ - Helper function for writing certificate data to disk. - - :param path: Directory file should be put in - :type path: str - :param filename: Name of file - :type filename: str - :param data: Data to write - :type data: any - :param mode: Create mode (permissions) of file - :type mode: Octal(int) - """ - with os.fdopen(os.open(os.path.join(path, filename), - os.O_WRONLY | os.O_CREAT, mode), 'wb') as f: - f.write(data) - - -# We need to restrain the number of SubjectAlternativeNames we attempt to put -# in the certificate. There is a hard limit for what length the sum of all -# extensions in the certificate can have. -# -# - 2^11 ought to be enough for anybody -def generate_certs(cert_dir=CERT_DIR): - alt_names = [] - for addr in itertools.islice( - ipaddress.IPv4Network(determine_CIDR_EXT()), 2**11): - - if six.PY2: - alt_names.append(unicode(addr)) # NOQA -- py3 doesn't have unicode - else: - alt_names.append(str(addr)) - - (cakey, cacert) = _cert.generate_cert(ISSUER_NAME, - generate_ca=True) - (key, cert) = _cert.generate_cert(u'*.serverstack', - alternative_names=alt_names, - issuer_name=ISSUER_NAME, - signing_key=cakey) - - write_cert(cert_dir, 'cacert.pem', cacert) - write_cert(cert_dir, 'ca.key', cakey) - write_cert(cert_dir, 'cert.pem', cert) - write_cert(cert_dir, 'cert.key', key) - - -if __name__ == '__main__': - generate_certs() diff --git a/tests/tests.yaml b/tests/tests.yaml index a03e7ba..6091b0a 100644 --- a/tests/tests.yaml +++ b/tests/tests.yaml @@ -1,18 +1,47 @@ -# 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: glance-simplestreams-sync + +comment: + - 'the glance configure job validates operation of identity-service relation' + +# functest-run-suite ... +# functest-deploy --bundle /path/to/gate/bundle +gate_bundles: + - model_alias_trusty: trusty-mitaka + - xenial-mitaka + - xenial-ocata + - xenial-pike + - xenial-queens + - bionic-queens + - bionic-rocky + - bionic-stein + - disco-stein + +# functest-run-suite --smoke ... +# functest-deploy --bundle /path/to/smoke/bundle +# smoke bundle should (Ubuntu LTS latest)-(OpenStack latest) +smoke_bundles: + - bionic-stein + +# functest-run-suite --dev ... +# functest-deploy --bundle /path/to/dev/bundle +# smoke bundle should be (Ubuntu LTS latest)-(OpenStack development) +dev_bundles: + - bionic-train + +# special target deploy status for above deploy phase +target_deploy_status: + vault: + # vault will be blocked with functest-deploy, this is ok to move on + # functest-configure will fix it with `auto_initialize` in next phase + workload-status: blocked + workload-status-message: Vault needs to be initialized + +# functest-configure +configure: + - zaza.openstack.charm_tests.vault.setup.auto_initialize + # skip vault init for trusty since vault doesn't suport trusty + - model_alias_trusty: [] + +# functest-test +tests: + - zaza.openstack.charm_tests.glance_simplestreams_sync.tests.GlanceSimpleStreamsSyncTest diff --git a/tox.ini b/tox.ini index b6d37fb..4bfc10e 100644 --- a/tox.ini +++ b/tox.ini @@ -13,19 +13,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 {posargs} whitelist_externals = juju -passenv = HOME TERM AMULET_* CS_API_* - -[testenv:py27] -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -# charm is NOT PY27 compatible -commands = /bin/true +passenv = HOME TERM CS_API_* OS_* +deps = -r{toxinidir}/test-requirements.txt [testenv:py35] basepython = python3.5 @@ -42,6 +35,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 @@ -79,61 +77,27 @@ omit = [testenv:venv] basepython = python3 -commands = {posargs} +commands = /bin/true -[testenv:func27-noop] -# DRY RUN - For Debug -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +[testenv:func] +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" -n --no-destroy + functest-run-suite --keep-model -[testenv:func27] -# 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 +[testenv:func-smoke] +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" --no-destroy + functest-run-suite --keep-model --smoke -[testenv:func27-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 +[testenv:func-dev] +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json gate-basic-bionic-stein --no-destroy + functest-run-suite --keep-model --dev -[testenv:func27-dfs] -# Charm Functional Test -# Run all deploy-from-source tests which are +x (may not always pass!) -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt +[testenv:func-target] +basepython = python3 commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dfs-*" --no-destroy - -[testenv:func27-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 -commands = - bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dev-*" --no-destroy - -[testenv:func27-smoke-ssl] -# Charm functional test, minimal, model setup using SSL - no basic_deployment tests as -# Amulet doesn't do SSL, and basic deployment tests the actual functionality. -# This just tests that the SSL verification bits get to the right places. -basepython = python2.7 -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = - bundletester -vl DEBUG -r json -o func-results.json dev-basic-xenial-pike-ssl --no-destroy + functest-run-suite --keep-model --bundle {posargs} [flake8] ignore = E402,E226