Migrate from Amulet to Zaza

This patch migrate tests from Amulet to Zaza, and Python3 only.

SSL is enabled for all bundles with charm-vault, except trusty, which is
not supported by vault.

func-test-pr: https://github.com/openstack-charmers/zaza-openstack-tests/pull/55

Partial-Bug: 1828424

Change-Id: I4dacf33d3ab4dedbbe62a36b1b2ce5606e51d234
Signed-off-by: Joe Guo <guoqiao@gmail.com>
This commit is contained in:
Joe Guo 2019-09-06 14:51:26 +12:00
parent 77fab98142
commit 660ce5b021
35 changed files with 751 additions and 1140 deletions

View File

@ -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

View File

@ -0,0 +1 @@
hooks.py

View File

@ -0,0 +1 @@
hooks.py

View File

@ -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)

View File

@ -28,3 +28,5 @@ requires:
interface: keystone
amqp:
interface: rabbitmq
certificates:
interface: tls-certificates

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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")

View File

@ -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())

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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

76
tox.ini
View File

@ -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