diff options
author | zdc <zdc@users.noreply.github.com> | 2020-12-25 18:57:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-25 18:57:19 +0200 |
commit | 27c317f83d8e393254b6766b34fdf8d29148ea8f (patch) | |
tree | ea824de28fa639ba6ba8b212efaf53b5df2e90d9 /tests/integration_tests/instances.py | |
parent | 66dc53b1b3f8786f3bbb25e914c1dc8161af0494 (diff) | |
parent | c6bcb8df28daa234686a563549681082eb3283a1 (diff) | |
download | vyos-cloud-init-27c317f83d8e393254b6766b34fdf8d29148ea8f.tar.gz vyos-cloud-init-27c317f83d8e393254b6766b34fdf8d29148ea8f.zip |
Merge pull request #28 from zdc/T2117-equuleus-20.4
T2117: Cloud-init updated to 20.4
Diffstat (limited to 'tests/integration_tests/instances.py')
-rw-r--r-- | tests/integration_tests/instances.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/tests/integration_tests/instances.py b/tests/integration_tests/instances.py new file mode 100644 index 00000000..9b13288c --- /dev/null +++ b/tests/integration_tests/instances.py @@ -0,0 +1,154 @@ +# This file is part of cloud-init. See LICENSE file for license information. +import logging +import os +import uuid +from tempfile import NamedTemporaryFile + +from pycloudlib.instance import BaseInstance +from pycloudlib.result import Result + +from tests.integration_tests import integration_settings + +try: + from typing import TYPE_CHECKING + if TYPE_CHECKING: + from tests.integration_tests.clouds import IntegrationCloud +except ImportError: + pass + + +log = logging.getLogger('integration_testing') + + +def _get_tmp_path(): + tmp_filename = str(uuid.uuid4()) + return '/var/tmp/{}.tmp'.format(tmp_filename) + + +class IntegrationInstance: + use_sudo = True + + def __init__(self, cloud: 'IntegrationCloud', instance: BaseInstance, + settings=integration_settings): + self.cloud = cloud + self.instance = instance + self.settings = settings + + def destroy(self): + self.instance.delete() + + def execute(self, command, *, use_sudo=None) -> Result: + if self.instance.username == 'root' and use_sudo is False: + raise Exception('Root user cannot run unprivileged') + if use_sudo is None: + use_sudo = self.use_sudo + return self.instance.execute(command, use_sudo=use_sudo) + + def pull_file(self, remote_path, local_path): + # First copy to a temporary directory because of permissions issues + tmp_path = _get_tmp_path() + self.instance.execute('cp {} {}'.format(remote_path, tmp_path)) + self.instance.pull_file(tmp_path, local_path) + + def push_file(self, local_path, remote_path): + # First push to a temporary directory because of permissions issues + tmp_path = _get_tmp_path() + self.instance.push_file(local_path, tmp_path) + self.execute('mv {} {}'.format(tmp_path, remote_path)) + + def read_from_file(self, remote_path) -> str: + result = self.execute('cat {}'.format(remote_path)) + if result.failed: + # TODO: Raise here whatever pycloudlib raises when it has + # a consistent error response + raise IOError( + 'Failed reading remote file via cat: {}\n' + 'Return code: {}\n' + 'Stderr: {}\n' + 'Stdout: {}'.format( + remote_path, result.return_code, + result.stderr, result.stdout) + ) + return result.stdout + + def write_to_file(self, remote_path, contents: str): + # Writes file locally and then pushes it rather + # than writing the file directly on the instance + with NamedTemporaryFile('w', delete=False) as tmp_file: + tmp_file.write(contents) + + try: + self.push_file(tmp_file.name, remote_path) + finally: + os.unlink(tmp_file.name) + + def snapshot(self): + return self.cloud.snapshot(self.instance) + + def _install_new_cloud_init(self, remote_script): + self.execute(remote_script) + version = self.execute('cloud-init -v').split()[-1] + log.info('Installed cloud-init version: %s', version) + self.instance.clean() + image_id = self.snapshot() + log.info('Created new image: %s', image_id) + self.cloud.image_id = image_id + + def install_proposed_image(self): + log.info('Installing proposed image') + remote_script = ( + '{sudo} echo deb "http://archive.ubuntu.com/ubuntu ' + '$(lsb_release -sc)-proposed main" | ' + '{sudo} tee /etc/apt/sources.list.d/proposed.list\n' + '{sudo} apt-get update -q\n' + '{sudo} apt-get install -qy cloud-init' + ).format(sudo='sudo' if self.use_sudo else '') + self._install_new_cloud_init(remote_script) + + def install_ppa(self, repo): + log.info('Installing PPA') + remote_script = ( + '{sudo} add-apt-repository {repo} -y && ' + '{sudo} apt-get update -q && ' + '{sudo} apt-get install -qy cloud-init' + ).format(sudo='sudo' if self.use_sudo else '', repo=repo) + self._install_new_cloud_init(remote_script) + + def install_deb(self): + log.info('Installing deb package') + deb_path = integration_settings.CLOUD_INIT_SOURCE + deb_name = os.path.basename(deb_path) + remote_path = '/var/tmp/{}'.format(deb_name) + self.push_file( + local_path=integration_settings.CLOUD_INIT_SOURCE, + remote_path=remote_path) + remote_script = '{sudo} dpkg -i {path}'.format( + sudo='sudo' if self.use_sudo else '', path=remote_path) + self._install_new_cloud_init(remote_script) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if not self.settings.KEEP_INSTANCE: + self.destroy() + + +class IntegrationEc2Instance(IntegrationInstance): + pass + + +class IntegrationGceInstance(IntegrationInstance): + pass + + +class IntegrationAzureInstance(IntegrationInstance): + pass + + +class IntegrationOciInstance(IntegrationInstance): + pass + + +class IntegrationLxdInstance(IntegrationInstance): + use_sudo = False |