diff options
author | Stuart Mackie <wsmackie@juniper.net> | 2016-10-19 14:29:38 -0700 |
---|---|---|
committer | Stuart Mackie <wsmackie@juniper.net> | 2016-10-19 14:29:38 -0700 |
commit | f02da72993eb8e5a34ed049bad442c6d6db4701a (patch) | |
tree | 5fb6f17e788ce0e32024767c4fa7da1999a8b702 /charms/trusty/cassandra/testing | |
parent | c6fafdeceefaa82f5960acf462d916370e52bc75 (diff) |
Removed cassandra charm. Will fetch in fetch-charms.sh in joid
Change-Id: I668ca30b3b76fc2107045907be5b6010a552e6a9
Signed-off-by: Stuart Mackie <wsmackie@juniper.net>
Diffstat (limited to 'charms/trusty/cassandra/testing')
-rw-r--r-- | charms/trusty/cassandra/testing/__init__.py | 15 | ||||
-rw-r--r-- | charms/trusty/cassandra/testing/amuletfixture.py | 234 | ||||
-rw-r--r-- | charms/trusty/cassandra/testing/mocks.py | 182 |
3 files changed, 0 insertions, 431 deletions
diff --git a/charms/trusty/cassandra/testing/__init__.py b/charms/trusty/cassandra/testing/__init__.py deleted file mode 100644 index b1b7fcd..0000000 --- a/charms/trusty/cassandra/testing/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2015 Canonical Ltd. -# -# This file is part of the Cassandra Charm for Juju. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. diff --git a/charms/trusty/cassandra/testing/amuletfixture.py b/charms/trusty/cassandra/testing/amuletfixture.py deleted file mode 100644 index 988267f..0000000 --- a/charms/trusty/cassandra/testing/amuletfixture.py +++ /dev/null @@ -1,234 +0,0 @@ -# Copyright 2015 Canonical Ltd. -# -# This file is part of the Cassandra Charm for Juju. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from functools import wraps -import json -import os -import shutil -import subprocess -import tempfile -import time - -import amulet -import yaml - - -class AmuletFixture(amulet.Deployment): - def __init__(self, series, verbose=False): - if verbose: - super(AmuletFixture, self).__init__(series=series) - else: - # We use a wrapper around juju-deployer so we can fix how it is - # invoked. In particular, turn off all the noise so we can - # actually read our test output. - juju_deployer = os.path.abspath(os.path.join( - os.path.dirname(__file__), os.pardir, 'lib', - 'juju-deployer-wrapper.py')) - super(AmuletFixture, self).__init__(series=series, - juju_deployer=juju_deployer) - assert self.series == series - - def setUp(self): - self._temp_dirs = [] - - self.reset_environment(force=True) - - # Repackage our charm to a temporary directory, allowing us - # to strip our virtualenv symlinks that would otherwise cause - # juju to abort. We also strip the .bzr directory, working - # around Bug #1394078. - self.repackage_charm() - - # Fix amulet.Deployment so it doesn't depend on environment - # variables or the current working directory, but rather the - # environment we have introspected. - with open(os.path.join(self.charm_dir, 'metadata.yaml'), 'r') as s: - self.charm_name = yaml.safe_load(s)['name'] - self.charm_cache.test_charm = None - self.charm_cache.fetch(self.charm_name, self.charm_dir, - series=self.series) - - # Explicitly reset $JUJU_REPOSITORY to ensure amulet and - # juju-deployer does not mess with the real one, per Bug #1393792 - self.org_repo = os.environ.get('JUJU_REPOSITORY', None) - temp_repo = tempfile.mkdtemp(suffix='.repo') - self._temp_dirs.append(temp_repo) - os.environ['JUJU_REPOSITORY'] = temp_repo - os.makedirs(os.path.join(temp_repo, self.series), mode=0o700) - - def tearDown(self, reset_environment=True): - if reset_environment: - self.reset_environment() - if self.org_repo is None: - del os.environ['JUJU_REPOSITORY'] - else: - os.environ['JUJU_REPOSITORY'] = self.org_repo - - def deploy(self, timeout=None): - '''Deploying or updating the configured system. - - Invokes amulet.Deployer.setup with a nicer name and standard - timeout handling. - ''' - if timeout is None: - timeout = int(os.environ.get('AMULET_TIMEOUT', 900)) - - # juju-deployer is buried under here, and has race conditions. - # Sleep a bit before invoking it, so its cached view of the - # environment matches reality. - time.sleep(15) - - # If setUp fails, tearDown is never called leaving the - # environment setup. This is useful for debugging. - self.setup(timeout=timeout) - self.wait(timeout=timeout) - - def __del__(self): - for temp_dir in self._temp_dirs: - if os.path.exists(temp_dir): - shutil.rmtree(temp_dir, ignore_errors=True) - - def get_status(self): - try: - raw = subprocess.check_output(['juju', 'status', '--format=json'], - universal_newlines=True) - except subprocess.CalledProcessError as x: - print(x.output) - raise - if raw: - return json.loads(raw) - return None - - def wait(self, timeout=None): - '''Wait until the environment has reached a stable state.''' - if timeout is None: - timeout = int(os.environ.get('AMULET_TIMEOUT', 900)) - cmd = ['timeout', str(timeout), 'juju', 'wait', '-q'] - try: - subprocess.check_output(cmd, universal_newlines=True) - except subprocess.CalledProcessError as x: - print(x.output) - raise - - def reset_environment(self, force=False): - if force: - status = self.get_status() - machines = [m for m in status.get('machines', {}).keys() - if m != '0'] - if machines: - subprocess.call(['juju', 'destroy-machine', - '--force'] + machines, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL) - fails = dict() - while True: - status = self.get_status() - service_items = status.get('services', {}).items() - if not service_items: - break - for service_name, service in service_items: - if service.get('life', '') not in ('dying', 'dead'): - subprocess.call(['juju', 'destroy-service', service_name], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - for unit_name, unit in service.get('units', {}).items(): - if unit.get('agent-state', None) == 'error': - if force: - # If any units have failed hooks, unstick them. - # This should no longer happen now we are - # using the 'destroy-machine --force' command - # earlier. - try: - subprocess.check_output( - ['juju', 'resolved', unit_name], - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError: - # A previous 'resolved' call make cause a - # subsequent one to fail if it is still - # being processed. However, we need to keep - # retrying because after a successful - # resolution a subsequent hook may cause an - # error state. - pass - else: - fails[unit_name] = unit - time.sleep(1) - - harvest_machines = [] - for machine, state in status.get('machines', {}).items(): - if machine != "0" and state.get('life') not in ('dying', 'dead'): - harvest_machines.append(machine) - - if harvest_machines: - cmd = ['juju', 'remove-machine', '--force'] + harvest_machines - subprocess.check_output(cmd, stderr=subprocess.STDOUT) - - if fails: - raise Exception("Teardown failed", fails) - - def repackage_charm(self): - """Mirror the charm into a staging area. - - We do this to work around issues with Amulet, juju-deployer - and juju. In particular: - - symlinks in the Python virtual env pointing outside of the - charm directory. - - odd bzr interactions, such as tests being run on the committed - version of the charm, rather than the working tree. - - Returns the test charm directory. - """ - # Find the charm_dir we are testing - src_charm_dir = os.path.dirname(__file__) - while True: - if os.path.exists(os.path.join(src_charm_dir, - 'metadata.yaml')): - break - assert src_charm_dir != os.sep, 'metadata.yaml not found' - src_charm_dir = os.path.abspath(os.path.join(src_charm_dir, - os.pardir)) - - with open(os.path.join(src_charm_dir, 'metadata.yaml'), 'r') as s: - self.charm_name = yaml.safe_load(s)['name'] - - repack_root = tempfile.mkdtemp(suffix='.charm') - self._temp_dirs.append(repack_root) - # juju-deployer now requires the series in the path when - # deploying from an absolute path. - repack_root = os.path.join(repack_root, self.series) - os.makedirs(repack_root, mode=0o700) - - self.charm_dir = os.path.join(repack_root, self.charm_name) - - # Ignore .bzr to work around weird bzr interactions with - # juju-deployer, per Bug #1394078, and ignore .venv - # due to a) it containing symlinks juju will reject and b) to avoid - # infinite recursion. - shutil.copytree(src_charm_dir, self.charm_dir, symlinks=True, - ignore=shutil.ignore_patterns('.venv?', '.bzr')) - - -# Bug #1417097 means we need to monkey patch Amulet for now. -real_juju = amulet.helpers.juju - - -@wraps(real_juju) -def patched_juju(args, env=None): - args = [str(a) for a in args] - return real_juju(args, env) - -amulet.helpers.juju = patched_juju -amulet.deployer.juju = patched_juju diff --git a/charms/trusty/cassandra/testing/mocks.py b/charms/trusty/cassandra/testing/mocks.py deleted file mode 100644 index 7d03f23..0000000 --- a/charms/trusty/cassandra/testing/mocks.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2015 Canonical Ltd. -# -# This file is part of the Cassandra Charm for Juju. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -''' -charm-helpers mocks. -''' -import os.path -import shutil -import tempfile -from unittest.mock import patch - -import yaml - -from charmhelpers import fetch -from charmhelpers.core import hookenv - - -CHARM_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), os.pardir)) - - -def mock_charmhelpers(test_case): - hookenv.cache.clear() # Clear the hookenv memorisation. - - mocks = [] - - # Mock environment - charm_dir = tempfile.TemporaryDirectory() - test_case.addCleanup(charm_dir.cleanup) - mock_env = patch.dict(os.environ, dict(CHARM_DIR=charm_dir.name)) - mock_env.start() - test_case.addCleanup(mock_env.stop) - shutil.copyfile(os.path.join(CHARM_DIR, 'metadata.yaml'), - os.path.join(charm_dir.name, 'metadata.yaml')) - - # Mock config. - # Set items: - # hookenv.config()['foo'] = 'bar' - # Reset 'previous' state: - # hookenv.config().save(); - # hookenv.config().load_previous() - config = hookenv.Config() - tmp = tempfile.NamedTemporaryFile(suffix='.config') - config.CONFIG_FILE_NAME = tmp.name - test_case.addCleanup(tmp.close) - with open(os.path.join(CHARM_DIR, 'config.yaml'), 'rb') as f: - defaults = yaml.safe_load(f)['options'] - for k, v in defaults.items(): - opt_type = v.get('type', 'string') - opt_val = v.get('default', None) - if opt_val is None: - config[k] = None - elif opt_type == 'string': - config[k] = str(opt_val) - elif opt_type == 'int': - config[k] = int(opt_val) - elif opt_type == 'boolean': - config[k] = bool(opt_val) - - def mock_config(scope=None): - if scope is None: - return config - return config.get(scope, None) - mocks.append(patch('charmhelpers.core.hookenv.config', - side_effect=mock_config, autospec=True)) - - # Magic mocks. - methods = [ - 'charmhelpers.core.hookenv.log', - 'charmhelpers.core.hookenv.hook_name', - 'charmhelpers.core.hookenv.related_units', - 'charmhelpers.core.hookenv.relation_get', - 'charmhelpers.core.hookenv.relation_set', - 'charmhelpers.core.hookenv.relation_ids', - 'charmhelpers.core.hookenv.relation_type', - 'charmhelpers.core.hookenv.service_name', - 'charmhelpers.core.hookenv.local_unit', - 'charmhelpers.core.hookenv.unit_private_ip', - 'charmhelpers.core.hookenv.unit_public_ip', - 'charmhelpers.core.host.log', - 'charmhelpers.fetch.filter_installed_packages', - 'os.chown', 'os.fchown', - ] - for m in methods: - mocks.append(patch(m, autospec=True)) - - for mock in mocks: - mock.start() - test_case.addCleanup(mock.stop) - - hookenv.local_unit.return_value = 'service/1' - - def mock_unit_private_ip(): - return '10.20.0.{}'.format(hookenv.local_unit().split('/')[-1]) - hookenv.unit_private_ip.side_effect = mock_unit_private_ip - - def mock_unit_public_ip(): - return '10.30.0.{}'.format(hookenv.local_unit().split('/')[-1]) - hookenv.unit_public_ip.side_effect = mock_unit_public_ip - - def mock_service_name(): - return hookenv.local_unit().split('/')[0] - hookenv.service_name.side_effect = mock_service_name - - hookenv.relation_ids.side_effect = ( - lambda x: ['{}:1'.format(x)] if x else []) - hookenv.related_units.return_value = ('service/2', 'service/3') - - relinfos = dict() - - def mock_relation_set(relation_id=None, relation_settings=None, **kwargs): - if relation_id is None: - relation_id = hookenv.relation_id() - unit = hookenv.local_unit() - relinfo = mock_relation_get(unit=unit, rid=relation_id) - if relation_settings is not None: - relinfo.update(relation_settings) - relinfo.update(kwargs) - return None - hookenv.relation_set.side_effect = mock_relation_set - - def mock_relation_get(attribute=None, unit=None, rid=None): - if rid is None: - rid = hookenv.relation_id() - if unit is None: - unit = hookenv.remove_unit() - service, unit_num = unit.split('/') - unit_num = int(unit_num) - relinfos.setdefault(rid, {}) - relinfos[rid].setdefault( - unit, {'private-address': '10.20.0.{}'.format(unit_num)}) - relinfo = relinfos[rid][unit] - if attribute is None or attribute == '-': - return relinfo - return relinfo.get(attribute) - hookenv.relation_get.side_effect = mock_relation_get - - def mock_chown(target, uid, gid): - assert uid == 0 - assert gid == 0 - assert os.path.exists(target) - os.chown.side_effect = mock_chown - - def mock_fchown(fd, uid, gid): - assert uid == 0 - assert gid == 0 - os.fchown.side_effect = mock_fchown - - fetch.filter_installed_packages.side_effect = lambda pkgs: list(pkgs) - - def mock_relation_for_unit(unit=None, rid=None): - if unit is None: - unit = hookenv.remote_unit() - service, unit_num = unit.split('/') - unit_num = int(unit_num) - return {'private-address': '10.20.0.{}'.format(unit_num)} - hookenv.relation_for_unit.side_effect = mock_relation_for_unit - - def mock_chown(target, uid, gid): - assert uid == 0 - assert gid == 0 - assert os.path.exists(target) - os.chown.side_effect = mock_chown - - def mock_fchown(fd, uid, gid): - assert uid == 0 - assert gid == 0 - os.fchown.side_effect = mock_fchown - - fetch.filter_installed_packages.side_effect = lambda pkgs: list(pkgs) |