summaryrefslogtreecommitdiff
path: root/tests/cloud_tests/setup_image.py
diff options
context:
space:
mode:
authorWesley Wiedenmeier <wesley.wiedenmeier@gmail.com>2016-12-22 17:27:37 -0500
committerScott Moser <smoser@brickies.net>2016-12-22 17:41:39 -0500
commitf53fc46aa732e3b29991b3e5e39da31a722945ee (patch)
treea301733aa9991b58b218f61b187240d275e44968 /tests/cloud_tests/setup_image.py
parentb2a9f33616c806ae6e052520a8589113308f567c (diff)
downloadvyos-cloud-init-f53fc46aa732e3b29991b3e5e39da31a722945ee.tar.gz
vyos-cloud-init-f53fc46aa732e3b29991b3e5e39da31a722945ee.zip
integration test: initial commit of integration test framework
The adds in end-to-end testing of cloud-init. The framework utilizes LXD and cloud images as a backend to test user-data passed in. Arbitrary data is then captured from predefined commands specified by the user. After collection, data verification is completed by running a series of Python unit tests against the collected data. Currently only the Ubuntu Trusty, Xenial, Yakkety, and Zesty releases are supported. Test cases for 50% of the modules is complete and available. Additionally a Read the Docs file was created to guide test writing and execution.
Diffstat (limited to 'tests/cloud_tests/setup_image.py')
-rw-r--r--tests/cloud_tests/setup_image.py195
1 files changed, 195 insertions, 0 deletions
diff --git a/tests/cloud_tests/setup_image.py b/tests/cloud_tests/setup_image.py
new file mode 100644
index 00000000..5d6c6387
--- /dev/null
+++ b/tests/cloud_tests/setup_image.py
@@ -0,0 +1,195 @@
+# This file is part of cloud-init. See LICENSE file for license information.
+
+from tests.cloud_tests import LOG
+from tests.cloud_tests import stage, util
+
+from functools import partial
+import os
+
+
+def install_deb(args, image):
+ """
+ install deb into image
+ args: cmdline arguments, must contain --deb
+ image: cloud_tests.images instance to operate on
+ return_value: None, may raise errors
+ """
+ # ensure system is compatible with package format
+ os_family = util.get_os_family(image.properties['os'])
+ if os_family != 'debian':
+ raise NotImplementedError('install deb: {} not supported on os '
+ 'family: {}'.format(args.deb, os_family))
+
+ # install deb
+ LOG.debug('installing deb: %s into target', args.deb)
+ remote_path = os.path.join('/tmp', os.path.basename(args.deb))
+ image.push_file(args.deb, remote_path)
+ (out, err, exit) = image.execute(['dpkg', '-i', remote_path])
+ if exit != 0:
+ raise OSError('failed install deb: {}\n\tstdout: {}\n\tstderr: {}'
+ .format(args.deb, out, err))
+
+ # check installed deb version matches package
+ fmt = ['-W', "--showformat='${Version}'"]
+ (out, err, exit) = image.execute(['dpkg-deb'] + fmt + [remote_path])
+ expected_version = out.strip()
+ (out, err, exit) = image.execute(['dpkg-query'] + fmt + ['cloud-init'])
+ found_version = out.strip()
+ if expected_version != found_version:
+ raise OSError('install deb version "{}" does not match expected "{}"'
+ .format(found_version, expected_version))
+
+ LOG.debug('successfully installed: %s, version: %s', args.deb,
+ found_version)
+
+
+def install_rpm(args, image):
+ """
+ install rpm into image
+ args: cmdline arguments, must contain --rpm
+ image: cloud_tests.images instance to operate on
+ return_value: None, may raise errors
+ """
+ # ensure system is compatible with package format
+ os_family = util.get_os_family(image.properties['os'])
+ if os_family not in ['redhat', 'sles']:
+ raise NotImplementedError('install rpm: {} not supported on os '
+ 'family: {}'.format(args.rpm, os_family))
+
+ # install rpm
+ LOG.debug('installing rpm: %s into target', args.rpm)
+ remote_path = os.path.join('/tmp', os.path.basename(args.rpm))
+ image.push_file(args.rpm, remote_path)
+ (out, err, exit) = image.execute(['rpm', '-U', remote_path])
+ if exit != 0:
+ raise OSError('failed to install rpm: {}\n\tstdout: {}\n\tstderr: {}'
+ .format(args.rpm, out, err))
+
+ fmt = ['--queryformat', '"%{VERSION}"']
+ (out, err, exit) = image.execute(['rpm', '-q'] + fmt + [remote_path])
+ expected_version = out.strip()
+ (out, err, exit) = image.execute(['rpm', '-q'] + fmt + ['cloud-init'])
+ found_version = out.strip()
+ if expected_version != found_version:
+ raise OSError('install rpm version "{}" does not match expected "{}"'
+ .format(found_version, expected_version))
+
+ LOG.debug('successfully installed: %s, version %s', args.rpm,
+ found_version)
+
+
+def upgrade(args, image):
+ """
+ run the system's upgrade command
+ args: cmdline arguments
+ image: cloud_tests.images instance to operate on
+ return_value: None, may raise errors
+ """
+ # determine appropriate upgrade command for os_family
+ # TODO: maybe use cloudinit.distros for this?
+ os_family = util.get_os_family(image.properties['os'])
+ if os_family == 'debian':
+ cmd = 'apt-get update && apt-get upgrade --yes'
+ elif os_family == 'redhat':
+ cmd = 'yum upgrade --assumeyes'
+ else:
+ raise NotImplementedError('upgrade command not configured for distro '
+ 'from family: {}'.format(os_family))
+
+ # upgrade system
+ LOG.debug('upgrading system')
+ (out, err, exit) = image.execute(['/bin/sh', '-c', cmd])
+ if exit != 0:
+ raise OSError('failed to upgrade system\n\tstdout: {}\n\tstderr:{}'
+ .format(out, err))
+
+
+def run_script(args, image):
+ """
+ run a script in the target image
+ args: cmdline arguments, must contain --script
+ image: cloud_tests.images instance to operate on
+ return_value: None, may raise errors
+ """
+ # TODO: get exit status back from script and add error handling here
+ LOG.debug('running setup image script in target image')
+ image.run_script(args.script)
+
+
+def enable_ppa(args, image):
+ """
+ enable a ppa in the target image
+ args: cmdline arguments, must contain --ppa
+ image: cloud_tests.image instance to operate on
+ return_value: None, may raise errors
+ """
+ # ppa only supported on ubuntu (maybe debian?)
+ if image.properties['os'] != 'ubuntu':
+ raise NotImplementedError('enabling a ppa is only available on ubuntu')
+
+ # add ppa with add-apt-repository and update
+ ppa = 'ppa:{}'.format(args.ppa)
+ LOG.debug('enabling %s', ppa)
+ cmd = 'add-apt-repository --yes {} && apt-get update'.format(ppa)
+ (out, err, exit) = image.execute(['/bin/sh', '-c', cmd])
+ if exit != 0:
+ raise OSError('enable ppa for {} failed\n\tstdout: {}\n\tstderr: {}'
+ .format(ppa, out, err))
+
+
+def enable_repo(args, image):
+ """
+ enable a repository in the target image
+ args: cmdline arguments, must contain --repo
+ image: cloud_tests.image instance to operate on
+ return_value: None, may raise errors
+ """
+ # find enable repo command for the distro
+ os_family = util.get_os_family(image.properties['os'])
+ if os_family == 'debian':
+ cmd = ('echo "{}" >> "/etc/apt/sources.list" '.format(args.repo) +
+ '&& apt-get update')
+ elif os_family == 'centos':
+ cmd = 'yum-config-manager --add-repo="{}"'.format(args.repo)
+ else:
+ raise NotImplementedError('enable repo command not configured for '
+ 'distro from family: {}'.format(os_family))
+
+ LOG.debug('enabling repo: "%s"', args.repo)
+ (out, err, exit) = image.execute(['/bin/sh', '-c', cmd])
+ if exit != 0:
+ raise OSError('enable repo {} failed\n\tstdout: {}\n\tstderr: {}'
+ .format(args.repo, out, err))
+
+
+def setup_image(args, image):
+ """
+ set up image as specified in args
+ args: cmdline arguments
+ image: cloud_tests.image instance to operate on
+ return_value: tuple of results and fail count
+ """
+ # mapping of setup cmdline arg name to setup function
+ # represented as a tuple rather than a dict or odict as lookup by name not
+ # needed, and order is important as --script and --upgrade go at the end
+ handlers = (
+ # arg handler description
+ ('deb', install_deb, 'setup func for --deb, install deb'),
+ ('rpm', install_rpm, 'setup func for --rpm, install rpm'),
+ ('repo', enable_repo, 'setup func for --repo, enable repo'),
+ ('ppa', enable_ppa, 'setup func for --ppa, enable ppa'),
+ ('script', run_script, 'setup func for --script, run script'),
+ ('upgrade', upgrade, 'setup func for --upgrade, upgrade pkgs'),
+ )
+
+ # determine which setup functions needed
+ calls = [partial(stage.run_single, desc, partial(func, args, image))
+ for name, func, desc in handlers if getattr(args, name, None)]
+
+ image_name = 'image: distro={}, release={}'.format(
+ image.properties['os'], image.properties['release'])
+ LOG.info('setting up %s', image_name)
+ return stage.run_stage('set up for {}'.format(image_name), calls,
+ continue_after_error=False)
+
+# vi: ts=4 expandtab