summaryrefslogtreecommitdiff
path: root/tests/cloud_tests/testcases
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/testcases
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/testcases')
-rw-r--r--tests/cloud_tests/testcases/__init__.py47
-rw-r--r--tests/cloud_tests/testcases/base.py81
-rw-r--r--tests/cloud_tests/testcases/bugs/__init__.py8
-rw-r--r--tests/cloud_tests/testcases/bugs/lp1511485.py15
-rw-r--r--tests/cloud_tests/testcases/bugs/lp1628337.py23
-rw-r--r--tests/cloud_tests/testcases/examples/__init__.py8
-rw-r--r--tests/cloud_tests/testcases/examples/add_apt_repositories.py20
-rw-r--r--tests/cloud_tests/testcases/examples/alter_completion_message.py49
-rw-r--r--tests/cloud_tests/testcases/examples/configure_instance_trusted_ca_certificates.py27
-rw-r--r--tests/cloud_tests/testcases/examples/configure_instances_ssh_keys.py31
-rw-r--r--tests/cloud_tests/testcases/examples/including_user_groups.py43
-rw-r--r--tests/cloud_tests/testcases/examples/install_arbitrary_packages.py20
-rw-r--r--tests/cloud_tests/testcases/examples/run_apt_upgrade.py19
-rw-r--r--tests/cloud_tests/testcases/examples/run_commands.py15
-rw-r--r--tests/cloud_tests/testcases/examples/run_commands_first_boot.py15
-rw-r--r--tests/cloud_tests/testcases/examples/writing_out_arbitrary_files.py30
-rw-r--r--tests/cloud_tests/testcases/main/__init__.py8
-rw-r--r--tests/cloud_tests/testcases/main/command_output_simple.py21
-rw-r--r--tests/cloud_tests/testcases/modules/__init__.py8
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_conf.py20
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_disable_suites.py15
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_primary.py20
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_proxy.py22
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_security.py15
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_sources_key.py23
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_sources_keyserver.py23
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_sources_list.py26
-rw-r--r--tests/cloud_tests/testcases/modules/apt_configure_sources_ppa.py23
-rw-r--r--tests/cloud_tests/testcases/modules/apt_pipelining_disable.py15
-rw-r--r--tests/cloud_tests/testcases/modules/apt_pipelining_os.py15
-rw-r--r--tests/cloud_tests/testcases/modules/bootcmd.py15
-rw-r--r--tests/cloud_tests/testcases/modules/byobu.py25
-rw-r--r--tests/cloud_tests/testcases/modules/ca_certs.py20
-rw-r--r--tests/cloud_tests/testcases/modules/debug_disable.py16
-rw-r--r--tests/cloud_tests/testcases/modules/debug_enable.py15
-rw-r--r--tests/cloud_tests/testcases/modules/final_message.py49
-rw-r--r--tests/cloud_tests/testcases/modules/keys_to_console.py22
-rw-r--r--tests/cloud_tests/testcases/modules/locale.py27
-rw-r--r--tests/cloud_tests/testcases/modules/lxd_bridge.py26
-rw-r--r--tests/cloud_tests/testcases/modules/lxd_dir.py20
-rw-r--r--tests/cloud_tests/testcases/modules/ntp.py28
-rw-r--r--tests/cloud_tests/testcases/modules/ntp_pools.py28
-rw-r--r--tests/cloud_tests/testcases/modules/ntp_servers.py25
-rw-r--r--tests/cloud_tests/testcases/modules/package_update_upgrade_install.py38
-rw-r--r--tests/cloud_tests/testcases/modules/runcmd.py15
-rw-r--r--tests/cloud_tests/testcases/modules/salt_minion.py29
-rw-r--r--tests/cloud_tests/testcases/modules/seed_random_data.py15
-rw-r--r--tests/cloud_tests/testcases/modules/set_hostname.py15
-rw-r--r--tests/cloud_tests/testcases/modules/set_hostname_fqdn.py26
-rw-r--r--tests/cloud_tests/testcases/modules/set_password.py22
-rw-r--r--tests/cloud_tests/testcases/modules/set_password_expire.py23
-rw-r--r--tests/cloud_tests/testcases/modules/set_password_list.py25
-rw-r--r--tests/cloud_tests/testcases/modules/snappy.py18
-rw-r--r--tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_disable.py24
-rw-r--r--tests/cloud_tests/testcases/modules/ssh_auth_key_fingerprints_enable.py18
-rw-r--r--tests/cloud_tests/testcases/modules/ssh_import_id.py26
-rw-r--r--tests/cloud_tests/testcases/modules/ssh_keys_generate.py57
-rw-r--r--tests/cloud_tests/testcases/modules/ssh_keys_provided.py69
-rw-r--r--tests/cloud_tests/testcases/modules/timezone.py15
-rw-r--r--tests/cloud_tests/testcases/modules/user_groups.py43
-rw-r--r--tests/cloud_tests/testcases/modules/write_files.py30
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