diff options
author | Wesley Wiedenmeier <wesley.wiedenmeier@gmail.com> | 2016-12-22 17:27:37 -0500 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2016-12-22 17:41:39 -0500 |
commit | f53fc46aa732e3b29991b3e5e39da31a722945ee (patch) | |
tree | a301733aa9991b58b218f61b187240d275e44968 /tests/cloud_tests/testcases | |
parent | b2a9f33616c806ae6e052520a8589113308f567c (diff) | |
download | vyos-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/testcases')
61 files changed, 1529 insertions, 0 deletions
diff --git a/tests/cloud_tests/testcases/__init__.py b/tests/cloud_tests/testcases/__init__.py new file mode 100644 index 00000000..182c090a --- /dev/null +++ b/tests/cloud_tests/testcases/__init__.py @@ -0,0 +1,47 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +import importlib +import inspect +import unittest + +from tests.cloud_tests import config +from tests.cloud_tests.testcases.base import CloudTestCase as base_test + + +def discover_tests(test_name): + """ + discover tests in test file for 'testname' + return_value: list of test classes + """ + testmod_name = 'tests.cloud_tests.testcases.{}'.format( + config.name_sanatize(test_name)) + try: + testmod = importlib.import_module(testmod_name) + except NameError: + raise ValueError('no test verifier found at: {}'.format(testmod_name)) + + return [mod for name, mod in inspect.getmembers(testmod) + if inspect.isclass(mod) and base_test in mod.__bases__ and + getattr(mod, '__test__', True)] + + +def get_suite(test_name, data, conf): + """ + get test suite with all tests for 'testname' + return_value: a test suite + """ + suite = unittest.TestSuite() + for test_class in discover_tests(test_name): + + class tmp(test_class): + + @classmethod + def setUpClass(cls): + cls.data = data + cls.conf = conf + + suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(tmp)) + + return suite + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/base.py b/tests/cloud_tests/testcases/base.py new file mode 100644 index 00000000..5395b9a3 --- /dev/null +++ b/tests/cloud_tests/testcases/base.py @@ -0,0 +1,81 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import util as c_util + +import json +import unittest + + +class CloudTestCase(unittest.TestCase): + """ + base test class for verifiers + """ + data = None + conf = None + _cloud_config = None + + @property + def cloud_config(self): + """ + get the cloud-config used by the test + """ + if not self._cloud_config: + self._cloud_config = c_util.load_yaml(self.conf) + return self._cloud_config + + def get_config_entry(self, name): + """ + get a config entry from cloud-config ensuring that it is present + """ + if name not in self.cloud_config: + raise AssertionError('Key "{}" not in cloud config'.format(name)) + return self.cloud_config[name] + + def get_data_file(self, name): + """ + get data file failing test if it is not present + """ + if name not in self.data: + raise AssertionError('File "{}" missing from collect data' + .format(name)) + return self.data[name] + + def get_instance_id(self): + """ + get recorded instance id + """ + return self.get_data_file('instance-id').strip() + + def get_status_data(self, data, version=None): + """ + parse result.json and status.json like data files + data: data to load + version: cloud-init output version, defaults to 'v1' + return_value: dict of data or None if missing + """ + if not version: + version = 'v1' + data = json.loads(data) + return data.get(version) + + def get_datasource(self): + """ + get datasource name + """ + data = self.get_status_data(self.get_data_file('result.json')) + return data.get('datasource') + + def test_no_stages_errors(self): + """ + ensure that there were no errors in any stage + """ + status = self.get_status_data(self.get_data_file('status.json')) + for stage in ('init', 'init-local', 'modules-config', 'modules-final'): + self.assertIn(stage, status) + self.assertEqual(len(status[stage]['errors']), 0, + 'errors {} were encountered in stage {}' + .format(status[stage]['errors'], stage)) + result = self.get_status_data(self.get_data_file('result.json')) + self.assertEqual(len(result['errors']), 0) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/bugs/__init__.py b/tests/cloud_tests/testcases/bugs/__init__.py new file mode 100644 index 00000000..5251d7c1 --- /dev/null +++ b/tests/cloud_tests/testcases/bugs/__init__.py @@ -0,0 +1,8 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +""" +Test verifiers for cloud-init bugs +See configs/bugs/README.md for more information +""" + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/bugs/lp1511485.py b/tests/cloud_tests/testcases/bugs/lp1511485.py new file mode 100644 index 00000000..ac5ccb42 --- /dev/null +++ b/tests/cloud_tests/testcases/bugs/lp1511485.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestLP1511485(base.CloudTestCase): + """Test LP# 1511485""" + + def test_final_message(self): + """Test final message exists""" + out = self.get_data_file('cloud-init-output.log') + self.assertIn('Final message from cloud-config', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/bugs/lp1628337.py b/tests/cloud_tests/testcases/bugs/lp1628337.py new file mode 100644 index 00000000..af0ffc75 --- /dev/null +++ b/tests/cloud_tests/testcases/bugs/lp1628337.py @@ -0,0 +1,23 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestLP1628337(base.CloudTestCase): + """Test LP# 1511485""" + + def test_fetch_indices(self): + """Verify no apt errors""" + out = self.get_data_file('cloud-init-output.log') + self.assertNotIn('W: Failed to fetch', out) + self.assertNotIn('W: Some index files failed to download. ' + 'They have been ignored, or old ones used instead.', + out) + + def test_ntp(self): + """Verify can find ntp and install it""" + out = self.get_data_file('cloud-init-output.log') + self.assertNotIn('E: Unable to locate package ntp', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/__init__.py b/tests/cloud_tests/testcases/examples/__init__.py new file mode 100644 index 00000000..b3af7f8a --- /dev/null +++ b/tests/cloud_tests/testcases/examples/__init__.py @@ -0,0 +1,8 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +""" +Test verifiers for cloud-init examples +See configs/examples/README.md for more information +""" + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/add_apt_repositories.py b/tests/cloud_tests/testcases/examples/add_apt_repositories.py new file mode 100644 index 00000000..15b8f01c --- /dev/null +++ b/tests/cloud_tests/testcases/examples/add_apt_repositories.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigurePrimary(base.CloudTestCase): + """Example cloud-config test""" + + def test_ubuntu_sources(self): + """Test no default Ubuntu entries exist""" + out = self.get_data_file('ubuntu.sources.list') + self.assertEqual(0, int(out)) + + def test_gatech_sources(self): + """Test GaTech entires exist""" + out = self.get_data_file('gatech.sources.list') + self.assertEqual(20, int(out)) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/alter_completion_message.py b/tests/cloud_tests/testcases/examples/alter_completion_message.py new file mode 100644 index 00000000..b06ad01b --- /dev/null +++ b/tests/cloud_tests/testcases/examples/alter_completion_message.py @@ -0,0 +1,49 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestFinalMessage(base.CloudTestCase): + """ + test cloud init module `cc_final_message` + """ + subs_char = '$' + + def get_final_message_config(self): + """ + get config for final message + """ + self.assertIn('final_message', self.cloud_config) + return self.cloud_config['final_message'] + + def get_final_message(self): + """ + get final message from log + """ + out = self.get_data_file('cloud-init-output.log') + lines = len(self.get_final_message_config().splitlines()) + return '\n'.join(out.splitlines()[-1 * lines:]) + + def test_final_message_string(self): + """ + ensure final handles regular strings + """ + for actual, config in zip( + self.get_final_message().splitlines(), + self.get_final_message_config().splitlines()): + if self.subs_char not in config: + self.assertEqual(actual, config) + + def test_final_message_subs(self): + """ + test variable substitution in final message + """ + # TODO: add verification of other substitutions + patterns = {'$datasource': self.get_datasource()} + for key, expected in patterns.items(): + index = self.get_final_message_config().splitlines().index(key) + actual = self.get_final_message().splitlines()[index] + self.assertEqual(actual, expected) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/configure_instance_trusted_ca_certificates.py b/tests/cloud_tests/testcases/examples/configure_instance_trusted_ca_certificates.py new file mode 100644 index 00000000..8a4a0db0 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/configure_instance_trusted_ca_certificates.py @@ -0,0 +1,27 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestTrustedCA(base.CloudTestCase): + """Example cloud-config test""" + + def test_cert_count_ca(self): + """Test correct count of CAs in .crt""" + out = self.get_data_file('cert_count_ca') + self.assertIn('7 /etc/ssl/certs/ca-certificates.crt', out) + + def test_cert_count_cloudinit(self): + """Test correct count of CAs in .pem""" + out = self.get_data_file('cert_count_cloudinit') + self.assertIn('7 /etc/ssl/certs/cloud-init-ca-certs.pem', out) + + def test_cloudinit_certs(self): + """Test text of cert""" + out = self.get_data_file('cloudinit_certs') + self.assertIn('-----BEGIN CERTIFICATE-----', out) + self.assertIn('YOUR-ORGS-TRUSTED-CA-CERT-HERE', out) + self.assertIn('-----END CERTIFICATE-----', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/configure_instances_ssh_keys.py b/tests/cloud_tests/testcases/examples/configure_instances_ssh_keys.py new file mode 100644 index 00000000..4f651703 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/configure_instances_ssh_keys.py @@ -0,0 +1,31 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSSHKeys(base.CloudTestCase): + """Example cloud-config test""" + + def test_cert_count(self): + """Test cert count""" + out = self.get_data_file('cert_count') + self.assertEqual(20, int(out)) + + def test_dsa_public(self): + """Test DSA key has ending""" + out = self.get_data_file('dsa_public') + self.assertIn('ZN4XnifuO5krqAybngIy66PMEoQ= smoser@localhost', out) + + def test_rsa_public(self): + """Test RSA key has specific ending""" + out = self.get_data_file('rsa_public') + self.assertIn('PemAWthxHO18QJvWPocKJtlsDNi3 smoser@localhost', out) + + def test_auth_keys(self): + """Test authorized keys has specific ending""" + out = self.get_data_file('auth_keys') + self.assertIn('QPOt5Q8zWd9qG7PBl9+eiH5qV7NZ mykey@host', out) + self.assertIn('Hj29SCmXp5Kt5/82cD/VN3NtHw== smoser@brickies', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/including_user_groups.py b/tests/cloud_tests/testcases/examples/including_user_groups.py new file mode 100644 index 00000000..e5732322 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/including_user_groups.py @@ -0,0 +1,43 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestUserGroups(base.CloudTestCase): + """Example cloud-config test""" + + def test_group_ubuntu(self): + """Test ubuntu group exists""" + out = self.get_data_file('group_ubuntu') + self.assertRegex(out, r'ubuntu:x:[0-9]{4}:') + + def test_group_cloud_users(self): + """Test cloud users group exists""" + out = self.get_data_file('group_cloud_users') + self.assertRegex(out, r'cloud-users:x:[0-9]{4}:barfoo') + + def test_user_ubuntu(self): + """Test ubuntu user exists""" + out = self.get_data_file('user_ubuntu') + self.assertRegex( + out, r'ubuntu:x:[0-9]{4}:[0-9]{4}:Ubuntu:/home/ubuntu:/bin/bash') + + def test_user_foobar(self): + """Test foobar user exists""" + out = self.get_data_file('user_foobar') + self.assertRegex( + out, r'foobar:x:[0-9]{4}:[0-9]{4}:Foo B. Bar:/home/foobar:') + + def test_user_barfoo(self): + """Test barfoo user exists""" + out = self.get_data_file('user_barfoo') + self.assertRegex( + out, r'barfoo:x:[0-9]{4}:[0-9]{4}:Bar B. Foo:/home/barfoo:') + + def test_user_cloudy(self): + """Test cloudy user exists""" + out = self.get_data_file('user_cloudy') + self.assertRegex(out, r'cloudy:x:[0-9]{3,4}:') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/install_arbitrary_packages.py b/tests/cloud_tests/testcases/examples/install_arbitrary_packages.py new file mode 100644 index 00000000..660d1aa3 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/install_arbitrary_packages.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestInstall(base.CloudTestCase): + """Example cloud-config test""" + + def test_htop(self): + """Verify htop installed""" + out = self.get_data_file('htop') + self.assertEqual(1, int(out)) + + def test_tree(self): + """Verify tree installed""" + out = self.get_data_file('treeutils') + self.assertEqual(1, int(out)) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/run_apt_upgrade.py b/tests/cloud_tests/testcases/examples/run_apt_upgrade.py new file mode 100644 index 00000000..4c04d315 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/run_apt_upgrade.py @@ -0,0 +1,19 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestUpgrade(base.CloudTestCase): + """Example cloud-config test""" + + def test_upgrade(self): + """Test upgrade exists in apt history""" + out = self.get_data_file('cloud-init.log') + self.assertIn( + '[CLOUDINIT] util.py[DEBUG]: apt-upgrade ' + '[eatmydata apt-get --option=Dpkg::Options::=--force-confold ' + '--option=Dpkg::options::=--force-unsafe-io --assume-yes --quiet ' + 'dist-upgrade] took', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/run_commands.py b/tests/cloud_tests/testcases/examples/run_commands.py new file mode 100644 index 00000000..0be21d0f --- /dev/null +++ b/tests/cloud_tests/testcases/examples/run_commands.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestRunCmd(base.CloudTestCase): + """Example cloud-config test""" + + def test_run_cmd(self): + """Test run command worked""" + out = self.get_data_file('run_cmd') + self.assertIn('cloud-init run cmd test', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/run_commands_first_boot.py b/tests/cloud_tests/testcases/examples/run_commands_first_boot.py new file mode 100644 index 00000000..baa23130 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/run_commands_first_boot.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestBootCmd(base.CloudTestCase): + """Example cloud-config test""" + + def test_bootcmd_host(self): + """Test boot command worked""" + out = self.get_data_file('hosts') + self.assertIn('192.168.1.130 us.archive.ubuntu.com', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/examples/writing_out_arbitrary_files.py b/tests/cloud_tests/testcases/examples/writing_out_arbitrary_files.py new file mode 100644 index 00000000..97dfeec3 --- /dev/null +++ b/tests/cloud_tests/testcases/examples/writing_out_arbitrary_files.py @@ -0,0 +1,30 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestWriteFiles(base.CloudTestCase): + """Example cloud-config test""" + + def test_b64(self): + """Test b64 encoded file reads as ascii""" + out = self.get_data_file('file_b64') + self.assertIn('ASCII text', out) + + def test_binary(self): + """Test binary file reads as executable""" + out = self.get_data_file('file_binary') + self.assertIn('ELF 64-bit LSB executable, x86-64, version 1', out) + + def test_gzip(self): + """Test gzip file shows up as a shell script""" + out = self.get_data_file('file_gzip') + self.assertIn('POSIX shell script, ASCII text executable', out) + + def test_text(self): + """Test text shows up as ASCII text""" + out = self.get_data_file('file_text') + self.assertIn('ASCII text', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/main/__init__.py b/tests/cloud_tests/testcases/main/__init__.py new file mode 100644 index 00000000..5888990d --- /dev/null +++ b/tests/cloud_tests/testcases/main/__init__.py @@ -0,0 +1,8 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +""" +Test verifiers for cloud-init main features +See configs/main/README.md for more information +""" + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/main/command_output_simple.py b/tests/cloud_tests/testcases/main/command_output_simple.py new file mode 100644 index 00000000..c0461a08 --- /dev/null +++ b/tests/cloud_tests/testcases/main/command_output_simple.py @@ -0,0 +1,21 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from tests.cloud_tests.testcases import base + + +class TestCommandOutputSimple(base.CloudTestCase): + """ + test functionality of simple output redirection + """ + + def test_output_file(self): + """ + ensure that the output file is not empty and has all stages + """ + data = self.get_data_file('cloud-init-test-output') + self.assertNotEqual(len(data), 0, "specified log empty") + self.assertEqual(self.get_config_entry('final_message'), + data.splitlines()[-1].strip()) + # TODO: need to test that all stages redirected here + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/__init__.py b/tests/cloud_tests/testcases/modules/__init__.py new file mode 100644 index 00000000..9560fb26 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/__init__.py @@ -0,0 +1,8 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +""" +Test verifiers for cloud-init cc modules +See configs/modules/README.md for more information +""" + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_conf.py b/tests/cloud_tests/testcases/modules/apt_configure_conf.py new file mode 100644 index 00000000..5d96d95c --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_conf.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureConf(base.CloudTestCase): + """Test apt-configure module""" + + def test_apt_conf_assumeyes(self): + """Test config assumes true""" + out = self.get_data_file('94cloud-init-config') + self.assertIn('Assume-Yes "true";', out) + + def test_apt_conf_fixbroken(self): + """Test config fixes broken""" + out = self.get_data_file('94cloud-init-config') + self.assertIn('Fix-Broken "true";', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_disable_suites.py b/tests/cloud_tests/testcases/modules/apt_configure_disable_suites.py new file mode 100644 index 00000000..0e2dfdeb --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_disable_suites.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureDisableSuites(base.CloudTestCase): + """Test apt-configure module""" + + def test_empty_sourcelist(self): + """Test source list is empty""" + out = self.get_data_file('sources.list') + self.assertEqual('', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_primary.py b/tests/cloud_tests/testcases/modules/apt_configure_primary.py new file mode 100644 index 00000000..2918785d --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_primary.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigurePrimary(base.CloudTestCase): + """Test apt-configure module""" + + def test_ubuntu_sources(self): + """Test no default Ubuntu entries exist""" + out = self.get_data_file('ubuntu.sources.list') + self.assertEqual(0, int(out)) + + def test_gatech_sources(self): + """Test GaTech entires exist""" + out = self.get_data_file('gatech.sources.list') + self.assertEqual(20, int(out)) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_proxy.py b/tests/cloud_tests/testcases/modules/apt_configure_proxy.py new file mode 100644 index 00000000..93ae64c6 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_proxy.py @@ -0,0 +1,22 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureProxy(base.CloudTestCase): + """Test apt-configure module""" + + def test_proxy_config(self): + """Test proxy options added to apt config""" + out = self.get_data_file('90cloud-init-aptproxy') + self.assertIn( + 'Acquire::http::Proxy "http://squid.internal:3128";', out) + self.assertIn( + 'Acquire::http::Proxy "http://squid.internal:3128";', out) + self.assertIn( + 'Acquire::ftp::Proxy "ftp://squid.internal:3128";', out) + self.assertIn( + 'Acquire::https::Proxy "https://squid.internal:3128";', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_security.py b/tests/cloud_tests/testcases/modules/apt_configure_security.py new file mode 100644 index 00000000..19c79c64 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_security.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureSecurity(base.CloudTestCase): + """Test apt-configure module""" + + def test_security_mirror(self): + """Test security lines added and uncommented in source.list""" + out = self.get_data_file('sources.list') + self.assertEqual(6, int(out)) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_sources_key.py b/tests/cloud_tests/testcases/modules/apt_configure_sources_key.py new file mode 100644 index 00000000..d2ee2611 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_sources_key.py @@ -0,0 +1,23 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureSourcesKey(base.CloudTestCase): + """Test apt-configure module""" + + def test_apt_key_list(self): + """Test key list updated""" + out = self.get_data_file('apt_key_list') + self.assertIn( + '1FF0 D853 5EF7 E719 E5C8 1B9C 083D 06FB E4D3 04DF', out) + self.assertIn('Launchpad PPA for cloud init development team', out) + + def test_source_list(self): + """Test source.list updated""" + out = self.get_data_file('sources.list') + self.assertIn( + 'http://ppa.launchpad.net/cloud-init-dev/test-archive/ubuntu', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_sources_keyserver.py b/tests/cloud_tests/testcases/modules/apt_configure_sources_keyserver.py new file mode 100644 index 00000000..3931a92c --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_sources_keyserver.py @@ -0,0 +1,23 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureSourcesKeyserver(base.CloudTestCase): + """Test apt-configure module""" + + def test_apt_key_list(self): + """Test specific key added""" + out = self.get_data_file('apt_key_list') + self.assertIn( + '1BC3 0F71 5A3B 8612 47A8 1A5E 55FE 7C8C 0165 013E', out) + self.assertIn('Launchpad PPA for curtin developers', out) + + def test_source_list(self): + """Test source.list updated""" + out = self.get_data_file('sources.list') + self.assertIn( + 'http://ppa.launchpad.net/cloud-init-dev/test-archive/ubuntu', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_sources_list.py b/tests/cloud_tests/testcases/modules/apt_configure_sources_list.py new file mode 100644 index 00000000..a0bb5e6b --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_sources_list.py @@ -0,0 +1,26 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureSourcesList(base.CloudTestCase): + """Test apt-configure module""" + + def test_sources_list(self): + """Test sources.list includes sources""" + out = self.get_data_file('sources.list') + self.assertRegex(out, r'deb http:\/\/archive.ubuntu.com\/ubuntu ' + '[a-z].* main restricted') + self.assertRegex(out, r'deb-src http:\/\/archive.ubuntu.com\/ubuntu ' + '[a-z].* main restricted') + self.assertRegex(out, r'deb http:\/\/archive.ubuntu.com\/ubuntu ' + '[a-z].* universe restricted') + self.assertRegex(out, r'deb-src http:\/\/archive.ubuntu.com\/ubuntu ' + '[a-z].* universe restricted') + self.assertRegex(out, r'deb http:\/\/security.ubuntu.com\/ubuntu ' + '[a-z].*security multiverse') + self.assertRegex(out, r'deb-src http:\/\/security.ubuntu.com\/ubuntu ' + '[a-z].*security multiverse') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_configure_sources_ppa.py b/tests/cloud_tests/testcases/modules/apt_configure_sources_ppa.py new file mode 100644 index 00000000..dcdb3767 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_configure_sources_ppa.py @@ -0,0 +1,23 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptconfigureSourcesPPA(base.CloudTestCase): + """Test apt-configure module""" + + def test_ppa(self): + """test specific ppa added""" + out = self.get_data_file('sources.list') + self.assertIn( + 'http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu', out) + + def test_ppa_key(self): + """test ppa key added""" + out = self.get_data_file('apt-key') + self.assertIn( + '1BC3 0F71 5A3B 8612 47A8 1A5E 55FE 7C8C 0165 013E', out) + self.assertIn('Launchpad PPA for curtin developers', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_pipelining_disable.py b/tests/cloud_tests/testcases/modules/apt_pipelining_disable.py new file mode 100644 index 00000000..446c597d --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_pipelining_disable.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptPipeliningDisable(base.CloudTestCase): + """Test apt-pipelining module""" + + def test_disable_pipelining(self): + """Test pipelining disabled""" + out = self.get_data_file('90cloud-init-pipelining') + self.assertIn('Acquire::http::Pipeline-Depth "0";', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/apt_pipelining_os.py b/tests/cloud_tests/testcases/modules/apt_pipelining_os.py new file mode 100644 index 00000000..ad2a8884 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/apt_pipelining_os.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestAptPipeliningOS(base.CloudTestCase): + """Test apt-pipelining module""" + + def test_os_pipelining(self): + """Test pipelining set to os""" + out = self.get_data_file('90cloud-init-pipelining') + self.assertIn('Acquire::http::Pipeline-Depth "0";', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/bootcmd.py b/tests/cloud_tests/testcases/modules/bootcmd.py new file mode 100644 index 00000000..47a51e0a --- /dev/null +++ b/tests/cloud_tests/testcases/modules/bootcmd.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestBootCmd(base.CloudTestCase): + """Test bootcmd module""" + + def test_bootcmd_host(self): + """Test boot cmd worked""" + out = self.get_data_file('hosts') + self.assertIn('192.168.1.130 us.archive.ubuntu.com', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/byobu.py b/tests/cloud_tests/testcases/modules/byobu.py new file mode 100644 index 00000000..204b37b9 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/byobu.py @@ -0,0 +1,25 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestByobu(base.CloudTestCase): + """Test Byobu module""" + + def test_byobu_installed(self): + """Test byobu installed""" + out = self.get_data_file('byobu_installed') + self.assertIn('/usr/bin/byobu', out) + + def test_byobu_profile_enabled(self): + """Test byobu profile.d file exists""" + out = self.get_data_file('byobu_profile_enabled') + self.assertIn('/etc/profile.d/Z97-byobu.sh', out) + + def test_byobu_launch_exists(self): + """Test byobu-launch exists""" + out = self.get_data_file('byobu_launch_exists') + self.assertIn('/usr/bin/byobu-launch', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ca_certs.py b/tests/cloud_tests/testcases/modules/ca_certs.py new file mode 100644 index 00000000..7448e480 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ca_certs.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestCaCerts(base.CloudTestCase): + """Test ca certs module""" + + def test_cert_count(self): + """Test the count is proper""" + out = self.get_data_file('cert_count') + self.assertEqual(5, int(out)) + + def test_cert_installed(self): + """Test line from our cert exists""" + out = self.get_data_file('cert') + self.assertIn('a36c744454555024e7f82edc420fd2c8', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/debug_disable.py b/tests/cloud_tests/testcases/modules/debug_disable.py new file mode 100644 index 00000000..9899fdfe --- /dev/null +++ b/tests/cloud_tests/testcases/modules/debug_disable.py @@ -0,0 +1,16 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestDebugDisable(base.CloudTestCase): + """Disable debug messages""" + + def test_debug_disable(self): + """Test verbose output missing from logs""" + out = self.get_data_file('cloud-init.log') + self.assertNotIn( + out, r'Skipping module named [a-z].* verbose printing disabled') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/debug_enable.py b/tests/cloud_tests/testcases/modules/debug_enable.py new file mode 100644 index 00000000..21c89524 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/debug_enable.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestDebugEnable(base.CloudTestCase): + """Test debug messages""" + + def test_debug_enable(self): + """Test debug messages in cloud-init log""" + out = self.get_data_file('cloud-init.log') + self.assertIn('[DEBUG]', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/final_message.py b/tests/cloud_tests/testcases/modules/final_message.py new file mode 100644 index 00000000..b06ad01b --- /dev/null +++ b/tests/cloud_tests/testcases/modules/final_message.py @@ -0,0 +1,49 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestFinalMessage(base.CloudTestCase): + """ + test cloud init module `cc_final_message` + """ + subs_char = '$' + + def get_final_message_config(self): + """ + get config for final message + """ + self.assertIn('final_message', self.cloud_config) + return self.cloud_config['final_message'] + + def get_final_message(self): + """ + get final message from log + """ + out = self.get_data_file('cloud-init-output.log') + lines = len(self.get_final_message_config().splitlines()) + return '\n'.join(out.splitlines()[-1 * lines:]) + + def test_final_message_string(self): + """ + ensure final handles regular strings + """ + for actual, config in zip( + self.get_final_message().splitlines(), + self.get_final_message_config().splitlines()): + if self.subs_char not in config: + self.assertEqual(actual, config) + + def test_final_message_subs(self): + """ + test variable substitution in final message + """ + # TODO: add verification of other substitutions + patterns = {'$datasource': self.get_datasource()} + for key, expected in patterns.items(): + index = self.get_final_message_config().splitlines().index(key) + actual = self.get_final_message().splitlines()[index] + self.assertEqual(actual, expected) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/keys_to_console.py b/tests/cloud_tests/testcases/modules/keys_to_console.py new file mode 100644 index 00000000..b36c96cf --- /dev/null +++ b/tests/cloud_tests/testcases/modules/keys_to_console.py @@ -0,0 +1,22 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestKeysToConsole(base.CloudTestCase): + """Test proper keys are included and excluded to console""" + + def test_excluded_keys(self): + """Test excluded keys missing""" + out = self.get_data_file('syslog') + self.assertNotIn('DSA', out) + self.assertNotIn('ECDSA', out) + + def test_expected_keys(self): + """Test expected keys exist""" + out = self.get_data_file('syslog') + self.assertIn('ED25519', out) + self.assertIn('RSA', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/locale.py b/tests/cloud_tests/testcases/modules/locale.py new file mode 100644 index 00000000..bf4e1b07 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/locale.py @@ -0,0 +1,27 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestLocale(base.CloudTestCase): + """Test locale is set properly""" + + def test_locale(self): + """Test locale is set properly""" + out = self.get_data_file('locale_default') + self.assertIn('LANG="en_GB.UTF-8"', out) + + def test_locale_a(self): + """Test locale -a has both options""" + out = self.get_data_file('locale_a') + self.assertIn('en_GB.utf8', out) + self.assertIn('en_US.utf8', out) + + def test_locale_gen(self): + """Test local.gen file has all entries.""" + out = self.get_data_file('locale_gen') + self.assertIn('en_GB.UTF-8', out) + self.assertIn('en_US.UTF-8', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/lxd_bridge.py b/tests/cloud_tests/testcases/modules/lxd_bridge.py new file mode 100644 index 00000000..4087e2f2 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/lxd_bridge.py @@ -0,0 +1,26 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestLxdBridge(base.CloudTestCase): + """Test LXD module""" + + def test_lxd(self): + """Test lxd installed""" + out = self.get_data_file('lxd') + self.assertIn('/usr/bin/lxd', out) + + def test_lxc(self): + """Test lxc installed""" + out = self.get_data_file('lxc') + self.assertIn('/usr/bin/lxc', out) + + def test_bridge(self): + """Test bridge config""" + out = self.get_data_file('lxc-bridge') + self.assertIn('lxdbr0', out) + self.assertIn('10.100.100.1/24', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/lxd_dir.py b/tests/cloud_tests/testcases/modules/lxd_dir.py new file mode 100644 index 00000000..51a9a1f1 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/lxd_dir.py @@ -0,0 +1,20 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestLxdDir(base.CloudTestCase): + """Test LXD module""" + + def test_lxd(self): + """Test lxd installed""" + out = self.get_data_file('lxd') + self.assertIn('/usr/bin/lxd', out) + + def test_lxc(self): + """Test lxc installed""" + out = self.get_data_file('lxc') + self.assertIn('/usr/bin/lxc', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ntp.py b/tests/cloud_tests/testcases/modules/ntp.py new file mode 100644 index 00000000..b1119257 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ntp.py @@ -0,0 +1,28 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestNtp(base.CloudTestCase): + """Test ntp module""" + + def test_ntp_installed(self): + """Test ntp installed""" + out = self.get_data_file('ntp_installed_empty') + self.assertEqual(1, int(out)) + + def test_ntp_dist_entries(self): + """Test dist config file has one entry""" + out = self.get_data_file('ntp_conf_dist_empty') + self.assertEqual(1, int(out)) + + def test_ntp_entires(self): + """Test config entries""" + out = self.get_data_file('ntp_conf_empty') + self.assertIn('pool 0.ubuntu.pool.ntp.org iburst', out) + self.assertIn('pool 1.ubuntu.pool.ntp.org iburst', out) + self.assertIn('pool 2.ubuntu.pool.ntp.org iburst', out) + self.assertIn('pool 3.ubuntu.pool.ntp.org iburst', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ntp_pools.py b/tests/cloud_tests/testcases/modules/ntp_pools.py new file mode 100644 index 00000000..d80cb673 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ntp_pools.py @@ -0,0 +1,28 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestNtpPools(base.CloudTestCase): + """Test ntp module""" + + def test_ntp_installed(self): + """Test ntp installed""" + out = self.get_data_file('ntp_installed_pools') + self.assertEqual(1, int(out)) + + def test_ntp_dist_entries(self): + """Test dist config file has one entry""" + out = self.get_data_file('ntp_conf_dist_pools') + self.assertEqual(1, int(out)) + + def test_ntp_entires(self): + """Test config entries""" + out = self.get_data_file('ntp_conf_pools') + self.assertIn('pool 0.pool.ntp.org iburst', out) + self.assertIn('pool 1.pool.ntp.org iburst', out) + self.assertIn('pool 2.pool.ntp.org iburst', out) + self.assertIn('pool 3.pool.ntp.org iburst', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ntp_servers.py b/tests/cloud_tests/testcases/modules/ntp_servers.py new file mode 100644 index 00000000..4879bb6f --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ntp_servers.py @@ -0,0 +1,25 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestNtpServers(base.CloudTestCase): + """Test ntp module""" + + def test_ntp_installed(self): + """Test ntp installed""" + out = self.get_data_file('ntp_installed_servers') + self.assertEqual(1, int(out)) + + def test_ntp_dist_entries(self): + """Test dist config file has one entry""" + out = self.get_data_file('ntp_conf_dist_servers') + self.assertEqual(1, int(out)) + + def test_ntp_entires(self): + """Test config entries""" + out = self.get_data_file('ntp_conf_servers') + self.assertIn('server pool.ntp.org iburst', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/package_update_upgrade_install.py b/tests/cloud_tests/testcases/modules/package_update_upgrade_install.py new file mode 100644 index 00000000..00353ead --- /dev/null +++ b/tests/cloud_tests/testcases/modules/package_update_upgrade_install.py @@ -0,0 +1,38 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestPackageInstallUpdateUpgrade(base.CloudTestCase): + """Test package install update upgrade module""" + + def test_installed_htop(self): + """Test htop got installed""" + out = self.get_data_file('dpkg_htop') + self.assertEqual(1, int(out)) + + def test_installed_tree(self): + """Test tree got installed""" + out = self.get_data_file('dpkg_tree') + self.assertEqual(1, int(out)) + + def test_apt_history(self): + """Test apt history for update command""" + out = self.get_data_file('apt_history_cmdline') + self.assertIn( + 'Commandline: /usr/bin/apt-get --option=Dpkg::Options' + '::=--force-confold --option=Dpkg::options::=--force-unsafe-io ' + '--assume-yes --quiet install htop tree', out) + + def test_cloud_init_output(self): + """Test cloud-init-output for install & upgrade stuff""" + out = self.get_data_file('cloud-init-output.log') + self.assertIn('Setting up tree (', out) + self.assertIn('Setting up htop (', out) + self.assertIn('Reading package lists...', out) + self.assertIn('Building dependency tree...', out) + self.assertIn('Reading state information...', out) + self.assertIn('Calculating upgrade...', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/runcmd.py b/tests/cloud_tests/testcases/modules/runcmd.py new file mode 100644 index 00000000..780cd186 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/runcmd.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestRunCmd(base.CloudTestCase): + """Test runcmd module""" + + def test_run_cmd(self): + """Test run command worked""" + out = self.get_data_file('run_cmd') + self.assertIn('cloud-init run cmd test', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/salt_minion.py b/tests/cloud_tests/testcases/modules/salt_minion.py new file mode 100644 index 00000000..3ef30f7e --- /dev/null +++ b/tests/cloud_tests/testcases/modules/salt_minion.py @@ -0,0 +1,29 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class Test(base.CloudTestCase): + """Test salt minion module""" + + def test_minon_master(self): + """Test master value in config""" + out = self.get_data_file('minion') + self.assertIn('master: salt.mydomain.com', out) + + def test_minion_pem(self): + """Test private key""" + out = self.get_data_file('minion.pem') + self.assertIn('------BEGIN PRIVATE KEY------', out) + self.assertIn('<key data>', out) + self.assertIn('------END PRIVATE KEY-------', out) + + def test_minion_pub(self): + """Test public key""" + out = self.get_data_file('minion.pub') + self.assertIn('------BEGIN PUBLIC KEY-------', out) + self.assertIn('<key data>', out) + self.assertIn('------END PUBLIC KEY-------', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/seed_random_data.py b/tests/cloud_tests/testcases/modules/seed_random_data.py new file mode 100644 index 00000000..b2121569 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/seed_random_data.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSeedRandom(base.CloudTestCase): + """Test seed random module""" + + def test_random_seed_data(self): + """Test random data passed in exists""" + out = self.get_data_file('seed_data') + self.assertIn('MYUb34023nD:LFDK10913jk;dfnk:Df', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/set_hostname.py b/tests/cloud_tests/testcases/modules/set_hostname.py new file mode 100644 index 00000000..9501b069 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/set_hostname.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestHostname(base.CloudTestCase): + """Test hostname module""" + + def test_hostname(self): + """Test hostname command shows correct output""" + out = self.get_data_file('hostname') + self.assertIn('myhostname', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/set_hostname_fqdn.py b/tests/cloud_tests/testcases/modules/set_hostname_fqdn.py new file mode 100644 index 00000000..d89c299d --- /dev/null +++ b/tests/cloud_tests/testcases/modules/set_hostname_fqdn.py @@ -0,0 +1,26 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestHostnameFqdn(base.CloudTestCase): + """Test Hostname module""" + + def test_hostname(self): + """Test hostname output""" + out = self.get_data_file('hostname') + self.assertIn('myhostname', out) + + def test_hostname_fqdn(self): + """Test hostname fqdn output""" + out = self.get_data_file('fqdn') + self.assertIn('host.myorg.com', out) + + def test_hosts(self): + """Test /etc/hosts file""" + out = self.get_data_file('hosts') + self.assertIn('127.0.1.1 host.myorg.com myhostname', out) + self.assertIn('127.0.0.1 localhost', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/set_password.py b/tests/cloud_tests/testcases/modules/set_password.py new file mode 100644 index 00000000..1411a296 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/set_password.py @@ -0,0 +1,22 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestPassword(base.CloudTestCase): + """Test password module""" + + # TODO add test to make sure password is actually "password" + + def test_shadow(self): + """Test ubuntu user in shadow""" + out = self.get_data_file('shadow') + self.assertIn('ubuntu:', out) + + def test_sshd_config(self): + """Test sshd config allows passwords""" + out = self.get_data_file('sshd_config') + self.assertIn('PasswordAuthentication yes', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/set_password_expire.py b/tests/cloud_tests/testcases/modules/set_password_expire.py new file mode 100644 index 00000000..1ac9c23f --- /dev/null +++ b/tests/cloud_tests/testcases/modules/set_password_expire.py @@ -0,0 +1,23 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestPasswordExpire(base.CloudTestCase): + """Test password module""" + + def test_shadow(self): + """Test user frozen in shadow""" + out = self.get_data_file('shadow') + self.assertIn('harry:!:', out) + self.assertIn('dick:!:', out) + self.assertIn('tom:!:', out) + self.assertIn('harry:!:', out) + + def test_sshd_config(self): + """Test sshd config allows passwords""" + out = self.get_data_file('sshd_config') + self.assertIn('PasswordAuthentication no', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/set_password_list.py b/tests/cloud_tests/testcases/modules/set_password_list.py new file mode 100644 index 00000000..b764362f --- /dev/null +++ b/tests/cloud_tests/testcases/modules/set_password_list.py @@ -0,0 +1,25 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestPasswordList(base.CloudTestCase): + """Test password module""" + + # TODO: Verify dick and harry passwords are random + # TODO: Verify tom's password was changed + + def test_shadow(self): + """Test every tom, dick, and harry user in shadow""" + out = self.get_data_file('shadow') + self.assertIn('tom:', out) + self.assertIn('dick:', out) + self.assertIn('harry:', out) + + def test_sshd_config(self): + """Test sshd config allows passwords""" + out = self.get_data_file('sshd_config') + self.assertIn('PasswordAuthentication yes', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/snappy.py b/tests/cloud_tests/testcases/modules/snappy.py new file mode 100644 index 00000000..3e2f5924 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/snappy.py @@ -0,0 +1,18 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSnappy(base.CloudTestCase): + """Test snappy module""" + + def test_snappy_version(self): + """Test snappy version output""" + out = self.get_data_file('snap_version') + self.assertIn('snap ', out) + self.assertIn('snapd ', out) + self.assertIn('series ', out) + self.assertIn('ubuntu ', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_disable.py b/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_disable.py new file mode 100644 index 00000000..a0f8896b --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_disable.py @@ -0,0 +1,24 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSshKeyFingerprintsDisable(base.CloudTestCase): + """Test ssh key fingerprints module""" + + def test_cloud_init_log(self): + """Verify disabled""" + out = self.get_data_file('cloud-init.log') + self.assertIn('Skipping module named ssh-authkey-fingerprints, ' + 'logging of ssh fingerprints disabled', out) + + def test_syslog(self): + """Verify output of syslog""" + out = self.get_data_file('syslog') + self.assertNotRegexpMatches(out, r'256 SHA256:.*(ECDSA)') + self.assertNotRegexpMatches(out, r'256 SHA256:.*(ED25519)') + self.assertNotRegexpMatches(out, r'1024 SHA256:.*(DSA)') + self.assertNotRegexpMatches(out, r'2048 SHA256:.*(RSA)') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_enable.py b/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_enable.py new file mode 100644 index 00000000..3c44b0cc --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_enable.py @@ -0,0 +1,18 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSshKeyFingerprintsEnable(base.CloudTestCase): + """Test ssh key fingerprints module""" + + def test_syslog(self): + """Verify output of syslog""" + out = self.get_data_file('syslog') + self.assertRegexpMatches(out, r'256 SHA256:.*(ECDSA)') + self.assertRegexpMatches(out, r'256 SHA256:.*(ED25519)') + self.assertNotRegexpMatches(out, r'1024 SHA256:.*(DSA)') + self.assertNotRegexpMatches(out, r'2048 SHA256:.*(RSA)') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ssh_import_id.py b/tests/cloud_tests/testcases/modules/ssh_import_id.py new file mode 100644 index 00000000..214e710d --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ssh_import_id.py @@ -0,0 +1,26 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSshImportId(base.CloudTestCase): + """Test ssh import id module""" + + def test_authorized_keys(self): + """Test that ssh keys were imported""" + out = self.get_data_file('auth_keys_ubuntu') + + # Rather than checking the key fingerprints, you could just check + # the ending comment for where it got imported from in case these + # change in the future :\ + self.assertIn('8sXGTYYw3iQSkOvDUUlIsqdaO+w== powersj@github/' + '18564351 # ssh-import-id gh:powersj', out) + self.assertIn('Hj29SCmXp5Kt5/82cD/VN3NtHw== smoser@brickies-' + 'canonical # ssh-import-id lp:smoser', out) + self.assertIn('7cUDQSXbabilgnzTjHo9mjd/kZ7cLOHP smoser@bart-' + 'canonical # ssh-import-id lp:smoser', out) + self.assertIn('aX0VHGXvHAQlPl4n7+FzAE1UmWFYEGrsSoNvLv3 smose' + 'r@kaypeah # ssh-import-id lp:smoser', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ssh_keys_generate.py b/tests/cloud_tests/testcases/modules/ssh_keys_generate.py new file mode 100644 index 00000000..161ace5f --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ssh_keys_generate.py @@ -0,0 +1,57 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSshKeysGenerate(base.CloudTestCase): + """Test ssh keys module""" + + # TODO: Check cloud-init-output for the correct keys being generated + + def test_ubuntu_authorized_keys(self): + """Test passed in key is not in list for ubuntu""" + out = self.get_data_file('auth_keys_ubuntu') + self.assertEqual('', out) + + def test_dsa_public(self): + """Test dsa public key not generated""" + out = self.get_data_file('dsa_public') + self.assertEqual('', out) + + def test_dsa_private(self): + """Test dsa private key not generated""" + out = self.get_data_file('dsa_private') + self.assertEqual('', out) + + def test_rsa_public(self): + """Test rsa public key not generated""" + out = self.get_data_file('rsa_public') + self.assertEqual('', out) + + def test_rsa_private(self): + """Test rsa public key not generated""" + out = self.get_data_file('rsa_private') + self.assertEqual('', out) + + def test_ecdsa_public(self): + """Test ecdsa public key generated""" + out = self.get_data_file('ecdsa_public') + self.assertIsNotNone(out) + + def test_ecdsa_private(self): + """Test ecdsa public key generated""" + out = self.get_data_file('ecdsa_private') + self.assertIsNotNone(out) + + def test_ed25519_public(self): + """Test ed25519 public key generated""" + out = self.get_data_file('ed25519_public') + self.assertIsNotNone(out) + + def test_ed25519_private(self): + """Test ed25519 public key generated""" + out = self.get_data_file('ed25519_private') + self.assertIsNotNone(out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/ssh_keys_provided.py b/tests/cloud_tests/testcases/modules/ssh_keys_provided.py new file mode 100644 index 00000000..8f18cb94 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/ssh_keys_provided.py @@ -0,0 +1,69 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestSshKeysProvided(base.CloudTestCase): + """Test ssh keys module""" + + def test_ubuntu_authorized_keys(self): + """Test passed in key is not in list for ubuntu""" + out = self.get_data_file('auth_keys_ubuntu') + self.assertEqual('', out) + + def test_root_authorized_keys(self): + """Test passed in key is in authorized list for root""" + out = self.get_data_file('auth_keys_root') + self.assertIn('lzrkPqONphoZx0LDV86w7RUz1ksDzAdcm0tvmNRFMN1a0frDs50' + '6oA3aWK0oDk4Nmvk8sXGTYYw3iQSkOvDUUlIsqdaO+w==', out) + + def test_dsa_public(self): + """Test dsa public key passed in""" + out = self.get_data_file('dsa_public') + self.assertIn('AAAAB3NzaC1kc3MAAACBAPkWy1zbchVIN7qTgM0/yyY8q4RZS8c' + 'NM4ZpeuE5UB/Nnr6OSU/nmbO8LuM', out) + + def test_dsa_private(self): + """Test dsa private key passed in""" + out = self.get_data_file('dsa_private') + self.assertIn('MIIBuwIBAAKBgQD5Fstc23IVSDe6k4DNP8smPKuEWUvHDTOGaXr' + 'hOVAfzZ6+jklP', out) + + def test_rsa_public(self): + """Test rsa public key passed in""" + out = self.get_data_file('rsa_public') + self.assertIn('AAAAB3NzaC1yc2EAAAADAQABAAABAQC0/Ho+o3eJISydO2JvIgT' + 'LnZOtrxPl+fSvJfKDjoOLY0HB2eOjy2s2/2N6d9X9SGZ4', out) + + def test_rsa_private(self): + """Test rsa public key passed in""" + out = self.get_data_file('rsa_private') + self.assertIn('4DOkqNiUGl80Zp1RgZNohHUXlJMtAbrIlAVEk+mTmg7vjfyp2un' + 'RQvLZpMRdywBm', out) + + def test_ecdsa_public(self): + """Test ecdsa public key passed in""" + out = self.get_data_file('ecdsa_public') + self.assertIn('AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAAB' + 'BBFsS5Tvky/IC/dXhE/afxxU', out) + + def test_ecdsa_private(self): + """Test ecdsa public key passed in""" + out = self.get_data_file('ecdsa_private') + self.assertIn('AwEHoUQDQgAEWxLlO+TL8gL91eET9p/HFQbqR1A691AkJgZk3jY' + '5mpZqxgX4vcgb', out) + + def test_ed25519_public(self): + """Test ed25519 public key passed in""" + out = self.get_data_file('ed25519_public') + self.assertIn('AAAAC3NzaC1lZDI1NTE5AAAAINudAZSu4vjZpVWzId5pXmZg1M6' + 'G15dqjQ2XkNVOEnb5', out) + + def test_ed25519_private(self): + """Test ed25519 public key passed in""" + out = self.get_data_file('ed25519_private') + self.assertIn('XAAAAAtzc2gtZWQyNTUxOQAAACDbnQGUruL42aVVsyHeaV5mYNT' + 'OhteXao0Nl5DVThJ2+Q', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/timezone.py b/tests/cloud_tests/testcases/modules/timezone.py new file mode 100644 index 00000000..272c266f --- /dev/null +++ b/tests/cloud_tests/testcases/modules/timezone.py @@ -0,0 +1,15 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestTimezone(base.CloudTestCase): + """Test timezone module""" + + def test_timezone(self): + """Test date prints correct timezone""" + out = self.get_data_file('timezone') + self.assertIn('HST', out) + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/user_groups.py b/tests/cloud_tests/testcases/modules/user_groups.py new file mode 100644 index 00000000..e5732322 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/user_groups.py @@ -0,0 +1,43 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestUserGroups(base.CloudTestCase): + """Example cloud-config test""" + + def test_group_ubuntu(self): + """Test ubuntu group exists""" + out = self.get_data_file('group_ubuntu') + self.assertRegex(out, r'ubuntu:x:[0-9]{4}:') + + def test_group_cloud_users(self): + """Test cloud users group exists""" + out = self.get_data_file('group_cloud_users') + self.assertRegex(out, r'cloud-users:x:[0-9]{4}:barfoo') + + def test_user_ubuntu(self): + """Test ubuntu user exists""" + out = self.get_data_file('user_ubuntu') + self.assertRegex( + out, r'ubuntu:x:[0-9]{4}:[0-9]{4}:Ubuntu:/home/ubuntu:/bin/bash') + + def test_user_foobar(self): + """Test foobar user exists""" + out = self.get_data_file('user_foobar') + self.assertRegex( + out, r'foobar:x:[0-9]{4}:[0-9]{4}:Foo B. Bar:/home/foobar:') + + def test_user_barfoo(self): + """Test barfoo user exists""" + out = self.get_data_file('user_barfoo') + self.assertRegex( + out, r'barfoo:x:[0-9]{4}:[0-9]{4}:Bar B. Foo:/home/barfoo:') + + def test_user_cloudy(self): + """Test cloudy user exists""" + out = self.get_data_file('user_cloudy') + self.assertRegex(out, r'cloudy:x:[0-9]{3,4}:') + +# vi: ts=4 expandtab diff --git a/tests/cloud_tests/testcases/modules/write_files.py b/tests/cloud_tests/testcases/modules/write_files.py new file mode 100644 index 00000000..97dfeec3 --- /dev/null +++ b/tests/cloud_tests/testcases/modules/write_files.py @@ -0,0 +1,30 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +"""cloud-init Integration Test Verify Script""" +from tests.cloud_tests.testcases import base + + +class TestWriteFiles(base.CloudTestCase): + """Example cloud-config test""" + + def test_b64(self): + """Test b64 encoded file reads as ascii""" + out = self.get_data_file('file_b64') + self.assertIn('ASCII text', out) + + def test_binary(self): + """Test binary file reads as executable""" + out = self.get_data_file('file_binary') + self.assertIn('ELF 64-bit LSB executable, x86-64, version 1', out) + + def test_gzip(self): + """Test gzip file shows up as a shell script""" + out = self.get_data_file('file_gzip') + self.assertIn('POSIX shell script, ASCII text executable', out) + + def test_text(self): + """Test text shows up as ASCII text""" + out = self.get_data_file('file_text') + self.assertIn('ASCII text', out) + +# vi: ts=4 expandtab |