diff options
Diffstat (limited to 'tests/unittests')
71 files changed, 880 insertions, 242 deletions
diff --git a/tests/unittests/__init__.py b/tests/unittests/__init__.py index 1b34b5af..d89ed443 100644 --- a/tests/unittests/__init__.py +++ b/tests/unittests/__init__.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + try: # For test cases, avoid the following UserWarning to stderr: # You don't have the C version of NameMapper installed ... diff --git a/tests/unittests/helpers.py b/tests/unittests/helpers.py index a2355a79..cf3b46d2 100644 --- a/tests/unittests/helpers.py +++ b/tests/unittests/helpers.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from __future__ import print_function import functools @@ -300,6 +302,39 @@ def dir2dict(startdir, prefix=None): return flist +def wrap_and_call(prefix, mocks, func, *args, **kwargs): + """ + call func(args, **kwargs) with mocks applied, then unapplies mocks + nicer to read than repeating dectorators on each function + + prefix: prefix for mock names (e.g. 'cloudinit.stages.util') or None + mocks: dictionary of names (under 'prefix') to mock and either + a return value or a dictionary to pass to the mock.patch call + func: function to call with mocks applied + *args,**kwargs: arguments for 'func' + + return_value: return from 'func' + """ + delim = '.' + if prefix is None: + prefix = '' + prefix = prefix.rstrip(delim) + unwraps = [] + for fname, kw in mocks.items(): + if prefix: + fname = delim.join((prefix, fname)) + if not isinstance(kw, dict): + kw = {'return_value': kw} + p = mock.patch(fname, **kw) + p.start() + unwraps.append(p) + try: + return func(*args, **kwargs) + finally: + for p in unwraps: + p.stop() + + try: skipIf = unittest.skipIf except AttributeError: @@ -313,3 +348,5 @@ except AttributeError: print(reason, file=sys.stderr) return wrapper return decorator + +# vi: ts=4 expandtab diff --git a/tests/unittests/test__init__.py b/tests/unittests/test__init__.py index 0154784a..7b6f8c4e 100644 --- a/tests/unittests/test__init__.py +++ b/tests/unittests/test__init__.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os import shutil import tempfile diff --git a/tests/unittests/test_atomic_helper.py b/tests/unittests/test_atomic_helper.py index feb81551..e170c7c3 100644 --- a/tests/unittests/test_atomic_helper.py +++ b/tests/unittests/test_atomic_helper.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import json import os import stat @@ -52,3 +54,5 @@ class TestAtomicHelper(helpers.TempDirTestCase): def check_perms(self, path, perms): file_stat = os.stat(path) self.assertEqual(perms, stat.S_IMODE(file_stat.st_mode)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_builtin_handlers.py b/tests/unittests/test_builtin_handlers.py index dea908d7..dd9d0357 100644 --- a/tests/unittests/test_builtin_handlers.py +++ b/tests/unittests/test_builtin_handlers.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """Tests of the built-in user data handlers.""" import os @@ -71,3 +73,5 @@ class TestBuiltins(test_helpers.FilesystemMockingTestCase): mockobj.assert_called_once_with( ['initctl', 'reload-configuration'], capture=False) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py index 5fa252f7..06f366b2 100644 --- a/tests/unittests/test_cli.py +++ b/tests/unittests/test_cli.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import six from . import helpers as test_helpers @@ -32,3 +34,6 @@ class TestCLI(test_helpers.FilesystemMockingTestCase): self.assertIn('cloud-init: error: too few arguments', self.stderr.getvalue()) self.assertEqual(2, exit_code) + + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_cs_util.py b/tests/unittests/test_cs_util.py index 56c9ce9e..b8f5031c 100644 --- a/tests/unittests/test_cs_util.py +++ b/tests/unittests/test_cs_util.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from __future__ import print_function from . import helpers as test_helpers @@ -61,3 +63,5 @@ class CepkoResultTests(test_helpers.TestCase): self.assertEqual('much server', result[0]) self.assertTrue('very performance' in result) self.assertEqual(2, len(result)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_data.py b/tests/unittests/test_data.py index 55d9b93f..4092d9ca 100644 --- a/tests/unittests/test_data.py +++ b/tests/unittests/test_data.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """Tests for handling of userdata within cloud init.""" import gzip @@ -559,3 +561,56 @@ class TestConvertString(helpers.TestCase): text = "hi mom" msg = ud.convert_string(text) self.assertEqual(text, msg.get_payload(decode=False)) + + +class TestFetchBaseConfig(helpers.TestCase): + + def test_only_builtin_gets_builtin2(self): + ret = helpers.wrap_and_call( + 'cloudinit.stages.util', + {'read_conf_with_confd': None, + 'read_conf_from_cmdline': None}, + stages.fetch_base_config) + self.assertEqual(util.get_builtin_cfg(), ret) + + def test_conf_d_overrides_defaults(self): + builtin = util.get_builtin_cfg() + test_key = sorted(builtin)[0] + test_value = 'test' + ret = helpers.wrap_and_call( + 'cloudinit.stages.util', + {'read_conf_with_confd': {'return_value': {test_key: test_value}}, + 'read_conf_from_cmdline': None}, + stages.fetch_base_config) + self.assertEqual(ret.get(test_key), test_value) + builtin[test_key] = test_value + self.assertEqual(ret, builtin) + + def test_cmdline_overrides_defaults(self): + builtin = util.get_builtin_cfg() + test_key = sorted(builtin)[0] + test_value = 'test' + cmdline = {test_key: test_value} + ret = helpers.wrap_and_call( + 'cloudinit.stages.util', + {'read_conf_from_cmdline': {'return_value': cmdline}, + 'read_conf_with_confd': None}, + stages.fetch_base_config) + self.assertEqual(ret.get(test_key), test_value) + builtin[test_key] = test_value + self.assertEqual(ret, builtin) + + def test_cmdline_overrides_conf_d_and_defaults(self): + builtin = {'key1': 'value0', 'key3': 'other2'} + conf_d = {'key1': 'value1', 'key2': 'other1'} + cmdline = {'key3': 'other3', 'key2': 'other2'} + ret = helpers.wrap_and_call( + 'cloudinit.stages.util', + {'read_conf_with_confd': {'return_value': conf_d}, + 'get_builtin_cfg': {'return_value': builtin}, + 'read_conf_from_cmdline': {'return_value': cmdline}}, + stages.fetch_base_config) + self.assertEqual(ret, {'key1': 'value1', 'key2': 'other2', + 'key3': 'other3'}) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_aliyun.py b/tests/unittests/test_datasource/test_aliyun.py index 6f1de072..c16d1a6e 100644 --- a/tests/unittests/test_datasource/test_aliyun.py +++ b/tests/unittests/test_datasource/test_aliyun.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import functools import httpretty import os @@ -146,3 +148,5 @@ class TestAliYunDatasource(test_helpers.HttprettyTestCase): 'ssh-key-1']}} self.assertEqual(ay.parse_public_keys(public_keys), public_keys['key-pair-0']['openssh-key']) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_altcloud.py b/tests/unittests/test_datasource/test_altcloud.py index 12966563..b0ad86ab 100644 --- a/tests/unittests/test_datasource/test_altcloud.py +++ b/tests/unittests/test_datasource/test_altcloud.py @@ -1,22 +1,11 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2009-2010 Canonical Ltd. -# Copyright (C) 2012 Hewlett-Packard Development Company, L.P. -# Copyright (C) 2012 Yahoo! Inc. -# -# Author: Joe VLcek <JVLcek@RedHat.com> +# Copyright (C) 2009-2010 Canonical Ltd. +# Copyright (C) 2012 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2012 Yahoo! Inc. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Author: Joe VLcek <JVLcek@RedHat.com> # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. + ''' This test file exercises the code in sources DataSourceAltCloud.py ''' @@ -448,5 +437,4 @@ def force_arch(arch=None): elif arch is None: setattr(os, 'uname', OS_UNAME_ORIG) - # vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py index 07127008..8d22bb59 100644 --- a/tests/unittests/test_datasource/test_azure.py +++ b/tests/unittests/test_datasource/test_azure.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import helpers from cloudinit.util import b64e, decode_binary, load_file from cloudinit.sources import DataSourceAzure @@ -93,7 +95,7 @@ class TestAzureDataSource(TestCase): for module, name, new in patches: self.patches.enter_context(mock.patch.object(module, name, new)) - def _get_ds(self, data): + def _get_ds(self, data, agent_command=None): def dsdevs(): return data.get('dsdevs', []) @@ -137,6 +139,8 @@ class TestAzureDataSource(TestCase): dsrc = mod.DataSourceAzureNet( data.get('sys_cfg', {}), distro=None, paths=self.paths) + if agent_command is not None: + dsrc.ds_cfg['agent_command'] = agent_command return dsrc @@ -299,7 +303,7 @@ class TestAzureDataSource(TestCase): data = {'ovfcontent': construct_valid_ovf_env(data=odata, pubkeys=pubkeys)} - dsrc = self._get_ds(data) + dsrc = self._get_ds(data, agent_command=['not', '__builtin__']) ret = dsrc.get_data() self.assertTrue(ret) for mypk in mypklist: @@ -314,7 +318,7 @@ class TestAzureDataSource(TestCase): data = {'ovfcontent': construct_valid_ovf_env(data=odata, pubkeys=pubkeys)} - dsrc = self._get_ds(data) + dsrc = self._get_ds(data, agent_command=['not', '__builtin__']) ret = dsrc.get_data() self.assertTrue(ret) @@ -330,7 +334,7 @@ class TestAzureDataSource(TestCase): data = {'ovfcontent': construct_valid_ovf_env(data=odata, pubkeys=pubkeys)} - dsrc = self._get_ds(data) + dsrc = self._get_ds(data, agent_command=['not', '__builtin__']) ret = dsrc.get_data() self.assertTrue(ret) @@ -487,12 +491,15 @@ class TestAzureBounce(TestCase): def tearDown(self): self.patches.close() - def _get_ds(self, ovfcontent=None): + def _get_ds(self, ovfcontent=None, agent_command=None): if ovfcontent is not None: populate_dir(os.path.join(self.paths.seed_dir, "azure"), {'ovf-env.xml': ovfcontent}) - return DataSourceAzure.DataSourceAzureNet( + dsrc = DataSourceAzure.DataSourceAzureNet( {}, distro=None, paths=self.paths) + if agent_command is not None: + dsrc.ds_cfg['agent_command'] = agent_command + return dsrc def get_ovf_env_with_dscfg(self, hostname, cfg): odata = { @@ -537,14 +544,17 @@ class TestAzureBounce(TestCase): host_name = 'unchanged-host-name' self.get_hostname.return_value = host_name cfg = {'hostname_bounce': {'policy': 'force'}} - self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg)).get_data() + self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg), + agent_command=['not', '__builtin__']).get_data() self.assertEqual(1, perform_hostname_bounce.call_count) def test_different_hostnames_sets_hostname(self): expected_hostname = 'azure-expected-host-name' self.get_hostname.return_value = 'default-host-name' self._get_ds( - self.get_ovf_env_with_dscfg(expected_hostname, {})).get_data() + self.get_ovf_env_with_dscfg(expected_hostname, {}), + agent_command=['not', '__builtin__'], + ).get_data() self.assertEqual(expected_hostname, self.set_hostname.call_args_list[0][0][0]) @@ -554,14 +564,18 @@ class TestAzureBounce(TestCase): expected_hostname = 'azure-expected-host-name' self.get_hostname.return_value = 'default-host-name' self._get_ds( - self.get_ovf_env_with_dscfg(expected_hostname, {})).get_data() + self.get_ovf_env_with_dscfg(expected_hostname, {}), + agent_command=['not', '__builtin__'], + ).get_data() self.assertEqual(1, perform_hostname_bounce.call_count) def test_different_hostnames_sets_hostname_back(self): initial_host_name = 'default-host-name' self.get_hostname.return_value = initial_host_name self._get_ds( - self.get_ovf_env_with_dscfg('some-host-name', {})).get_data() + self.get_ovf_env_with_dscfg('some-host-name', {}), + agent_command=['not', '__builtin__'], + ).get_data() self.assertEqual(initial_host_name, self.set_hostname.call_args_list[-1][0][0]) @@ -572,7 +586,9 @@ class TestAzureBounce(TestCase): initial_host_name = 'default-host-name' self.get_hostname.return_value = initial_host_name self._get_ds( - self.get_ovf_env_with_dscfg('some-host-name', {})).get_data() + self.get_ovf_env_with_dscfg('some-host-name', {}), + agent_command=['not', '__builtin__'], + ).get_data() self.assertEqual(initial_host_name, self.set_hostname.call_args_list[-1][0][0]) @@ -583,7 +599,7 @@ class TestAzureBounce(TestCase): self.get_hostname.return_value = old_hostname cfg = {'hostname_bounce': {'interface': interface, 'policy': 'force'}} data = self.get_ovf_env_with_dscfg(hostname, cfg) - self._get_ds(data).get_data() + self._get_ds(data, agent_command=['not', '__builtin__']).get_data() self.assertEqual(1, self.subp.call_count) bounce_env = self.subp.call_args[1]['env'] self.assertEqual(interface, bounce_env['interface']) @@ -595,7 +611,7 @@ class TestAzureBounce(TestCase): DataSourceAzure.BUILTIN_DS_CONFIG['hostname_bounce']['command'] = cmd cfg = {'hostname_bounce': {'policy': 'force'}} data = self.get_ovf_env_with_dscfg('some-hostname', cfg) - self._get_ds(data).get_data() + self._get_ds(data, agent_command=['not', '__builtin__']).get_data() self.assertEqual(1, self.subp.call_count) bounce_args = self.subp.call_args[1]['args'] self.assertEqual(cmd, bounce_args) @@ -630,3 +646,5 @@ class TestReadAzureOvf(TestCase): (_md, _ud, cfg) = DataSourceAzure.read_azure_ovf(content) for mypk in mypklist: self.assertIn(mypk, cfg['_pubkeys']) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_azure_helper.py b/tests/unittests/test_datasource/test_azure_helper.py index 64523e16..aafdebd7 100644 --- a/tests/unittests/test_datasource/test_azure_helper.py +++ b/tests/unittests/test_datasource/test_azure_helper.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os from cloudinit.sources.helpers import azure as azure_helper @@ -419,3 +421,5 @@ class TestGetMetadataFromFabric(TestCase): self.assertRaises(SentinelException, azure_helper.get_metadata_from_fabric) self.assertEqual(1, shim.return_value.clean_up.call_count) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_cloudsigma.py b/tests/unittests/test_datasource/test_cloudsigma.py index 2a42ce0c..5997102c 100644 --- a/tests/unittests/test_datasource/test_cloudsigma.py +++ b/tests/unittests/test_datasource/test_cloudsigma.py @@ -1,8 +1,9 @@ -# coding: utf-8 +# This file is part of cloud-init. See LICENSE file for license information. import copy from cloudinit.cs_utils import Cepko +from cloudinit import sources from cloudinit.sources import DataSourceCloudSigma from .. import helpers as test_helpers @@ -49,7 +50,8 @@ class DataSourceCloudSigmaTest(test_helpers.TestCase): self.assertEqual("test_server", self.datasource.get_hostname()) self.datasource.metadata['name'] = '' self.assertEqual("65b2fb23", self.datasource.get_hostname()) - self.datasource.metadata['name'] = u'тест' + utf8_hostname = b'\xd1\x82\xd0\xb5\xd1\x81\xd1\x82'.decode('utf-8') + self.datasource.metadata['name'] = utf8_hostname self.assertEqual("65b2fb23", self.datasource.get_hostname()) def test_get_public_ssh_keys(self): @@ -97,3 +99,19 @@ class DataSourceCloudSigmaTest(test_helpers.TestCase): self.datasource.get_data() self.assertIsNone(self.datasource.vendordata_raw) + + +class DsLoads(test_helpers.TestCase): + def test_get_datasource_list_returns_in_local(self): + deps = (sources.DEP_FILESYSTEM,) + ds_list = DataSourceCloudSigma.get_datasource_list(deps) + self.assertEqual(ds_list, + [DataSourceCloudSigma.DataSourceCloudSigma]) + + def test_list_sources_finds_ds(self): + found = sources.list_sources( + ['CloudSigma'], (sources.DEP_FILESYSTEM,), ['cloudinit.sources']) + self.assertEqual([DataSourceCloudSigma.DataSourceCloudSigma], + found) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_cloudstack.py b/tests/unittests/test_datasource/test_cloudstack.py index b1aab17b..e93d28de 100644 --- a/tests/unittests/test_datasource/test_cloudstack.py +++ b/tests/unittests/test_datasource/test_cloudstack.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import helpers from cloudinit.sources.DataSourceCloudStack import DataSourceCloudStack @@ -76,3 +78,5 @@ class TestCloudStackPasswordFetching(TestCase): def test_password_not_saved_if_bad_request(self): self._check_password_not_saved_for('bad_request') + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_common.py b/tests/unittests/test_datasource/test_common.py new file mode 100644 index 00000000..c08717f3 --- /dev/null +++ b/tests/unittests/test_datasource/test_common.py @@ -0,0 +1,75 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import settings +from cloudinit import sources +from cloudinit import type_utils +from cloudinit.sources import ( + DataSourceAliYun as AliYun, + DataSourceAltCloud as AltCloud, + DataSourceAzure as Azure, + DataSourceBigstep as Bigstep, + DataSourceCloudSigma as CloudSigma, + DataSourceCloudStack as CloudStack, + DataSourceConfigDrive as ConfigDrive, + DataSourceDigitalOcean as DigitalOcean, + DataSourceEc2 as Ec2, + DataSourceGCE as GCE, + DataSourceMAAS as MAAS, + DataSourceNoCloud as NoCloud, + DataSourceOpenNebula as OpenNebula, + DataSourceOpenStack as OpenStack, + DataSourceOVF as OVF, + DataSourceSmartOS as SmartOS, +) +from cloudinit.sources import DataSourceNone as DSNone + +from .. import helpers as test_helpers + +DEFAULT_LOCAL = [ + CloudSigma.DataSourceCloudSigma, + ConfigDrive.DataSourceConfigDrive, + DigitalOcean.DataSourceDigitalOcean, + NoCloud.DataSourceNoCloud, + OpenNebula.DataSourceOpenNebula, + OVF.DataSourceOVF, + SmartOS.DataSourceSmartOS, +] + +DEFAULT_NETWORK = [ + AltCloud.DataSourceAltCloud, + Azure.DataSourceAzureNet, + Bigstep.DataSourceBigstep, + CloudStack.DataSourceCloudStack, + DSNone.DataSourceNone, + Ec2.DataSourceEc2, + GCE.DataSourceGCE, + MAAS.DataSourceMAAS, + NoCloud.DataSourceNoCloudNet, + OpenStack.DataSourceOpenStack, + OVF.DataSourceOVFNet, +] + + +class ExpectedDataSources(test_helpers.TestCase): + builtin_list = settings.CFG_BUILTIN['datasource_list'] + deps_local = [sources.DEP_FILESYSTEM] + deps_network = [sources.DEP_FILESYSTEM, sources.DEP_NETWORK] + pkg_list = [type_utils.obj_name(sources)] + + def test_expected_default_local_sources_found(self): + found = sources.list_sources( + self.builtin_list, self.deps_local, self.pkg_list) + self.assertEqual(set(DEFAULT_LOCAL), set(found)) + + def test_expected_default_network_sources_found(self): + found = sources.list_sources( + self.builtin_list, self.deps_network, self.pkg_list) + self.assertEqual(set(DEFAULT_NETWORK), set(found)) + + def test_expected_nondefault_network_sources_found(self): + found = sources.list_sources( + ['AliYun'], self.deps_network, self.pkg_list) + self.assertEqual(set([AliYun.DataSourceAliYun]), set(found)) + + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_configdrive.py b/tests/unittests/test_datasource/test_configdrive.py index 6e00abf4..55153357 100644 --- a/tests/unittests/test_datasource/test_configdrive.py +++ b/tests/unittests/test_datasource/test_configdrive.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from copy import copy, deepcopy import json import os diff --git a/tests/unittests/test_datasource/test_digitalocean.py b/tests/unittests/test_datasource/test_digitalocean.py index 7bde0820..9be6bc19 100644 --- a/tests/unittests/test_datasource/test_digitalocean.py +++ b/tests/unittests/test_datasource/test_digitalocean.py @@ -1,19 +1,8 @@ +# Copyright (C) 2014 Neal Shrader # -# Copyright (C) 2014 Neal Shrader +# Author: Neal Shrader <neal@digitalocean.com> # -# Author: Neal Shrader <neal@digitalocean.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. import json @@ -330,3 +319,5 @@ class TestNetworkConvert(TestCase): self.assertEqual( sorted(['45.55.249.133', '10.17.0.5']), sorted([i['address'] for i in eth0['subnets']])) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py index 6e62a4d2..4f667678 100644 --- a/tests/unittests/test_datasource/test_gce.py +++ b/tests/unittests/test_datasource/test_gce.py @@ -1,19 +1,8 @@ +# Copyright (C) 2014 Vaidas Jablonskis # -# Copyright (C) 2014 Vaidas Jablonskis +# Author: Vaidas Jablonskis <jablonskis@gmail.com> # -# Author: Vaidas Jablonskis <jablonskis@gmail.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. import re @@ -164,3 +153,5 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): _set_mock_metadata() self.ds.get_data() self.assertEqual('bar', self.ds.availability_zone) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_maas.py b/tests/unittests/test_datasource/test_maas.py index 0126c883..693882d2 100644 --- a/tests/unittests/test_datasource/test_maas.py +++ b/tests/unittests/test_datasource/test_maas.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from copy import copy import os import shutil diff --git a/tests/unittests/test_datasource/test_nocloud.py b/tests/unittests/test_datasource/test_nocloud.py index f6a46ce9..ff294395 100644 --- a/tests/unittests/test_datasource/test_nocloud.py +++ b/tests/unittests/test_datasource/test_nocloud.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import helpers from cloudinit.sources import DataSourceNoCloud from cloudinit import util diff --git a/tests/unittests/test_datasource/test_opennebula.py b/tests/unittests/test_datasource/test_opennebula.py index ce5b5550..a266e952 100644 --- a/tests/unittests/test_datasource/test_opennebula.py +++ b/tests/unittests/test_datasource/test_opennebula.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import helpers from cloudinit.sources import DataSourceOpenNebula as ds from cloudinit import util diff --git a/tests/unittests/test_datasource/test_openstack.py b/tests/unittests/test_datasource/test_openstack.py index 125c6d6e..e5b6fcc6 100644 --- a/tests/unittests/test_datasource/test_openstack.py +++ b/tests/unittests/test_datasource/test_openstack.py @@ -1,20 +1,8 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2014 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> +# Copyright (C) 2014 Yahoo! Inc. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Author: Joshua Harlow <harlowja@yahoo-inc.com> # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. import copy import json @@ -344,3 +332,5 @@ class TestVendorDataLoading(test_helpers.TestCase): def test_vd_load_dict_ci_list(self): data = {'foo': 'bar', 'cloud-init': ['VD_1', 'VD_2']} self.assertEqual(self.cvj(data), data['cloud-init']) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_ovf.py b/tests/unittests/test_datasource/test_ovf.py index 5f8e7e44..3e09510c 100644 --- a/tests/unittests/test_datasource/test_ovf.py +++ b/tests/unittests/test_datasource/test_ovf.py @@ -1,20 +1,8 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2016 Canonical Ltd. -# -# Author: Scott Moser <scott.moser@canonical.com> +# Copyright (C) 2016 Canonical Ltd. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Author: Scott Moser <scott.moser@canonical.com> # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. import base64 @@ -81,3 +69,5 @@ class TestReadOvfEnv(test_helpers.TestCase): self.assertEqual({"instance-id": "inst-001"}, md) self.assertEqual({'password': "passw0rd"}, cfg) self.assertEqual(None, ud) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_datasource/test_smartos.py b/tests/unittests/test_datasource/test_smartos.py index 0532f986..e3c99bbb 100644 --- a/tests/unittests/test_datasource/test_smartos.py +++ b/tests/unittests/test_datasource/test_smartos.py @@ -1,26 +1,15 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2013 Canonical Ltd. -# -# Author: Ben Howard <ben.howard@canonical.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# Copyright (C) 2013 Canonical Ltd. # +# Author: Ben Howard <ben.howard@canonical.com> # -# This is a testcase for the SmartOS datasource. It replicates a serial -# console and acts like the SmartOS console does in order to validate -# return responses. -# +# This file is part of cloud-init. See LICENSE file for license information. + +'''This is a testcase for the SmartOS datasource. + +It replicates a serial console and acts like the SmartOS console does in +order to validate return responses. + +''' from __future__ import print_function @@ -881,3 +870,5 @@ class TestNetworkConversion(TestCase): 'type': 'static'}]}]} found = convert_net(SDC_NICS_SINGLE_GATEWAY) self.assertEqual(expected, found) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_create_users.py b/tests/unittests/test_distros/test_create_users.py new file mode 100644 index 00000000..9ded4f6c --- /dev/null +++ b/tests/unittests/test_distros/test_create_users.py @@ -0,0 +1,151 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +from cloudinit import distros +from ..helpers import (TestCase, mock) + + +class MyBaseDistro(distros.Distro): + # MyBaseDistro is here to test base Distro class implementations + + def __init__(self, name="basedistro", cfg={}, paths={}): + super(MyBaseDistro, self).__init__(name, cfg, paths) + + def install_packages(self, pkglist): + raise NotImplementedError() + + def _write_network(self, settings): + raise NotImplementedError() + + def package_command(self, cmd, args=None, pkgs=None): + raise NotImplementedError() + + def update_package_sources(self): + raise NotImplementedError() + + def apply_locale(self, locale, out_fn=None): + raise NotImplementedError() + + def set_timezone(self, tz): + raise NotImplementedError() + + def _read_hostname(self, filename, default=None): + raise NotImplementedError() + + def _write_hostname(self, hostname, filename): + raise NotImplementedError() + + def _read_system_hostname(self): + raise NotImplementedError() + + +class TestCreateUser(TestCase): + def setUp(self): + super(TestCase, self).setUp() + self.dist = MyBaseDistro() + + def _useradd2call(self, args): + # return a mock call for the useradd command in args + # with expected 'logstring'. + args = ['useradd'] + args + logcmd = [a for a in args] + for i in range(len(args)): + if args[i] in ('--password',): + logcmd[i + 1] = 'REDACTED' + return mock.call(args, logstring=logcmd) + + @mock.patch("cloudinit.distros.util.subp") + def test_basic(self, m_subp): + user = 'foouser' + self.dist.create_user(user) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '-m']), + mock.call(['passwd', '-l', user])]) + + @mock.patch("cloudinit.distros.util.subp") + def test_no_home(self, m_subp): + user = 'foouser' + self.dist.create_user(user, no_create_home=True) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '-M']), + mock.call(['passwd', '-l', user])]) + + @mock.patch("cloudinit.distros.util.subp") + def test_system_user(self, m_subp): + # system user should have no home and get --system + user = 'foouser' + self.dist.create_user(user, system=True) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '--system', '-M']), + mock.call(['passwd', '-l', user])]) + + @mock.patch("cloudinit.distros.util.subp") + def test_explicit_no_home_false(self, m_subp): + user = 'foouser' + self.dist.create_user(user, no_create_home=False) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '-m']), + mock.call(['passwd', '-l', user])]) + + @mock.patch("cloudinit.distros.util.subp") + def test_unlocked(self, m_subp): + user = 'foouser' + self.dist.create_user(user, lock_passwd=False) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '-m'])]) + + @mock.patch("cloudinit.distros.util.subp") + def test_set_password(self, m_subp): + user = 'foouser' + password = 'passfoo' + self.dist.create_user(user, passwd=password) + self.assertEqual( + m_subp.call_args_list, + [self._useradd2call([user, '--password', password, '-m']), + mock.call(['passwd', '-l', user])]) + + @mock.patch("cloudinit.distros.util.is_group") + @mock.patch("cloudinit.distros.util.subp") + def test_group_added(self, m_subp, m_is_group): + m_is_group.return_value = False + user = 'foouser' + self.dist.create_user(user, groups=['group1']) + expected = [ + mock.call(['groupadd', 'group1']), + self._useradd2call([user, '--groups', 'group1', '-m']), + mock.call(['passwd', '-l', user])] + self.assertEqual(m_subp.call_args_list, expected) + + @mock.patch("cloudinit.distros.util.is_group") + @mock.patch("cloudinit.distros.util.subp") + def test_only_new_group_added(self, m_subp, m_is_group): + ex_groups = ['existing_group'] + groups = ['group1', ex_groups[0]] + m_is_group.side_effect = lambda m: m in ex_groups + user = 'foouser' + self.dist.create_user(user, groups=groups) + expected = [ + mock.call(['groupadd', 'group1']), + self._useradd2call([user, '--groups', ','.join(groups), '-m']), + mock.call(['passwd', '-l', user])] + self.assertEqual(m_subp.call_args_list, expected) + + @mock.patch("cloudinit.distros.util.is_group") + @mock.patch("cloudinit.distros.util.subp") + def test_create_groups_with_whitespace_string(self, m_subp, m_is_group): + # groups supported as a comma delimeted string even with white space + m_is_group.return_value = False + user = 'foouser' + self.dist.create_user(user, groups='group1, group2') + expected = [ + mock.call(['groupadd', 'group1']), + mock.call(['groupadd', 'group2']), + self._useradd2call([user, '--groups', 'group1,group2', '-m']), + mock.call(['passwd', '-l', user])] + self.assertEqual(m_subp.call_args_list, expected) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_generic.py b/tests/unittests/test_distros/test_generic.py index 24ad115f..c9be277e 100644 --- a/tests/unittests/test_distros/test_generic.py +++ b/tests/unittests/test_distros/test_generic.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import distros from cloudinit import util diff --git a/tests/unittests/test_distros/test_hostname.py b/tests/unittests/test_distros/test_hostname.py index 5f28a868..f6d4dbe5 100644 --- a/tests/unittests/test_distros/test_hostname.py +++ b/tests/unittests/test_distros/test_hostname.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import unittest from cloudinit.distros.parsers import hostname @@ -36,3 +38,5 @@ class TestHostnameHelper(unittest.TestCase): bbbbd ''' self.assertEqual(str(hn).strip(), expected_out.strip()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_hosts.py b/tests/unittests/test_distros/test_hosts.py index ab867c6f..8aaa6e48 100644 --- a/tests/unittests/test_distros/test_hosts.py +++ b/tests/unittests/test_distros/test_hosts.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import unittest from cloudinit.distros.parsers import hosts @@ -39,3 +41,5 @@ class TestHostsHelper(unittest.TestCase): eh.del_entries('127.0.0.0') self.assertEqual(eh.get_entry('127.0.0.0'), []) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_netconfig.py b/tests/unittests/test_distros/test_netconfig.py index 36eae2dc..bde3bb50 100644 --- a/tests/unittests/test_distros/test_netconfig.py +++ b/tests/unittests/test_distros/test_netconfig.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os from six import StringIO @@ -379,3 +381,5 @@ ifconfig_vtnet0="DHCP" ''' self.assertCfgEquals(expected_buf, str(write_buf)) self.assertEqual(write_buf.mode, 0o644) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_resolv.py b/tests/unittests/test_distros/test_resolv.py index 9402b5ea..6b535a95 100644 --- a/tests/unittests/test_distros/test_resolv.py +++ b/tests/unittests/test_distros/test_resolv.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.distros.parsers import resolv_conf from cloudinit.distros import rhel_util @@ -65,3 +67,5 @@ class TestResolvHelper(TestCase): self.assertEqual(len(rp.search_domains), 6) self.assertRaises(ValueError, rp.add_search_domain, 'bbb5.y.com') self.assertEqual(len(rp.search_domains), 6) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_sysconfig.py b/tests/unittests/test_distros/test_sysconfig.py index 8cb55522..235ecebb 100644 --- a/tests/unittests/test_distros/test_sysconfig.py +++ b/tests/unittests/test_distros/test_sysconfig.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import re from cloudinit.distros.parsers.sys_conf import SysConf @@ -80,3 +82,5 @@ USEMD5=no''' contents = str(conf) self.assertIn("Z=d", contents) self.assertIn("BLAH=b", contents) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_distros/test_user_data_normalize.py b/tests/unittests/test_distros/test_user_data_normalize.py index 33bf922d..88746e0a 100755 --- a/tests/unittests/test_distros/test_user_data_normalize.py +++ b/tests/unittests/test_distros/test_user_data_normalize.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import distros from cloudinit.distros import ug_util from cloudinit import helpers @@ -361,3 +363,5 @@ class TestUGNormalize(TestCase): mock_subp.assert_any_call(groupcmd) mock_subp.assert_any_call(addcmd, logstring=addcmd) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_ec2_util.py b/tests/unittests/test_ec2_util.py index d6cf17fa..4a33d747 100644 --- a/tests/unittests/test_ec2_util.py +++ b/tests/unittests/test_ec2_util.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from . import helpers from cloudinit import ec2_utils as eu @@ -137,3 +139,5 @@ class TestEc2Util(helpers.HttprettyTestCase): self.assertEqual(2, len(bdm)) self.assertEqual(bdm['ami'], 'sdb') self.assertEqual(bdm['ephemeral0'], 'sdc') + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_filters/test_launch_index.py b/tests/unittests/test_filters/test_launch_index.py index 395713e6..13137f6d 100644 --- a/tests/unittests/test_filters/test_launch_index.py +++ b/tests/unittests/test_filters/test_launch_index.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import copy from .. import helpers @@ -130,3 +132,5 @@ class TestLaunchFilter(helpers.ResourceUsingTestCase): '1': 2, } self.assertCounts(message, expected_counts) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_apt_conf_v1.py b/tests/unittests/test_handler/test_handler_apt_conf_v1.py index 64acc3e0..554277ff 100644 --- a/tests/unittests/test_handler/test_handler_apt_conf_v1.py +++ b/tests/unittests/test_handler/test_handler_apt_conf_v1.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_apt_configure from cloudinit import util diff --git a/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v1.py b/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v1.py index f4411869..f53ddbb2 100644 --- a/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v1.py +++ b/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v1.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """ test_handler_apt_configure_sources_list Test templating of sources list """ diff --git a/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v3.py b/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v3.py index e53b0450..24e45233 100644 --- a/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v3.py +++ b/tests/unittests/test_handler/test_handler_apt_configure_sources_list_v3.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """ test_apt_custom_sources_list Test templating of custom sources list """ diff --git a/tests/unittests/test_handler/test_handler_apt_source_v1.py b/tests/unittests/test_handler/test_handler_apt_source_v1.py index ddff4341..12502d05 100644 --- a/tests/unittests/test_handler/test_handler_apt_source_v1.py +++ b/tests/unittests/test_handler/test_handler_apt_source_v1.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """ test_handler_apt_source_v1 Testing various config variations of the apt_source config This calls all things with v1 format to stress the conversion code on top of diff --git a/tests/unittests/test_handler/test_handler_apt_source_v3.py b/tests/unittests/test_handler/test_handler_apt_source_v3.py index b92a50d7..292d3f59 100644 --- a/tests/unittests/test_handler/test_handler_apt_source_v3.py +++ b/tests/unittests/test_handler/test_handler_apt_source_v3.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """test_handler_apt_source_v3 Testing various config variations of the apt_source custom config This tries to call all in the new v3 format and cares about new features diff --git a/tests/unittests/test_handler/test_handler_ca_certs.py b/tests/unittests/test_handler/test_handler_ca_certs.py index 5e771731..7cee2c3f 100644 --- a/tests/unittests/test_handler/test_handler_ca_certs.py +++ b/tests/unittests/test_handler/test_handler_ca_certs.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import cloud from cloudinit.config import cc_ca_certs from cloudinit import helpers @@ -269,3 +271,5 @@ class TestRemoveDefaultCaCerts(TestCase): mock_subp.assert_called_once_with( ('debconf-set-selections', '-'), "ca-certificates ca-certificates/trust_new_crts select no") + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_chef.py b/tests/unittests/test_handler/test_handler_chef.py index 7a1bc317..6a152ea2 100644 --- a/tests/unittests/test_handler/test_handler_chef.py +++ b/tests/unittests/test_handler/test_handler_chef.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import json import logging import os @@ -190,3 +192,5 @@ class TestChef(t_help.FilesystemMockingTestCase): self.assertIn(v_path, content) util.load_file(v_path) self.assertEqual(expected_cert, util.load_file(v_path)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_debug.py b/tests/unittests/test_handler/test_handler_debug.py index 80708d7b..929f786e 100644 --- a/tests/unittests/test_handler/test_handler_debug.py +++ b/tests/unittests/test_handler/test_handler_debug.py @@ -1,18 +1,6 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2014 Yahoo! Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Copyright (C) 2014 Yahoo! Inc. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. from cloudinit.config import cc_debug @@ -79,3 +67,5 @@ class TestDebug(t_help.FilesystemMockingTestCase): cc_debug.handle('cc_debug', cfg, cc, LOG, []) self.assertRaises(IOError, util.load_file, '/var/log/cloud-init-debug.log') + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_disk_setup.py b/tests/unittests/test_handler/test_handler_disk_setup.py index ddef8d48..227f0497 100644 --- a/tests/unittests/test_handler/test_handler_disk_setup.py +++ b/tests/unittests/test_handler/test_handler_disk_setup.py @@ -1,3 +1,7 @@ +# This file is part of cloud-init. See LICENSE file for license information. + +import random + from cloudinit.config import cc_disk_setup from ..helpers import ExitStack, mock, TestCase @@ -28,3 +32,75 @@ class TestIsDiskUsed(TestCase): self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1)) self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock()) self.assertFalse(cc_disk_setup.is_disk_used(mock.MagicMock())) + + +class TestGetMbrHddSize(TestCase): + + def setUp(self): + super(TestGetMbrHddSize, self).setUp() + self.patches = ExitStack() + self.subp = self.patches.enter_context( + mock.patch.object(cc_disk_setup.util, 'subp')) + + def tearDown(self): + super(TestGetMbrHddSize, self).tearDown() + self.patches.close() + + def _configure_subp_mock(self, hdd_size_in_bytes, sector_size_in_bytes): + def _subp(cmd, *args, **kwargs): + self.assertEqual(3, len(cmd)) + if '--getsize64' in cmd: + return hdd_size_in_bytes, None + elif '--getss' in cmd: + return sector_size_in_bytes, None + raise Exception('Unexpected blockdev command called') + + self.subp.side_effect = _subp + + def _test_for_sector_size(self, sector_size): + size_in_bytes = random.randint(10000, 10000000) * 512 + size_in_sectors = size_in_bytes / sector_size + self._configure_subp_mock(size_in_bytes, sector_size) + self.assertEqual(size_in_sectors, + cc_disk_setup.get_mbr_hdd_size('/dev/sda1')) + + def test_size_for_512_byte_sectors(self): + self._test_for_sector_size(512) + + def test_size_for_1024_byte_sectors(self): + self._test_for_sector_size(1024) + + def test_size_for_2048_byte_sectors(self): + self._test_for_sector_size(2048) + + def test_size_for_4096_byte_sectors(self): + self._test_for_sector_size(4096) + + +class TestGetPartitionMbrLayout(TestCase): + + def test_single_partition_using_boolean(self): + self.assertEqual('0,', + cc_disk_setup.get_partition_mbr_layout(1000, True)) + + def test_single_partition_using_list(self): + disk_size = random.randint(1000000, 1000000000000) + self.assertEqual( + ',,83', + cc_disk_setup.get_partition_mbr_layout(disk_size, [100])) + + def test_half_and_half(self): + disk_size = random.randint(1000000, 1000000000000) + expected_partition_size = int(float(disk_size) / 2) + self.assertEqual( + ',{0},83\n,,83'.format(expected_partition_size), + cc_disk_setup.get_partition_mbr_layout(disk_size, [50, 50])) + + def test_thirds_with_different_partition_type(self): + disk_size = random.randint(1000000, 1000000000000) + expected_partition_size = int(float(disk_size) * 0.33) + self.assertEqual( + ',{0},83\n,,82'.format(expected_partition_size), + cc_disk_setup.get_partition_mbr_layout(disk_size, [33, [66, 82]])) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_growpart.py b/tests/unittests/test_handler/test_handler_growpart.py index e28067de..c5fc8c9b 100644 --- a/tests/unittests/test_handler/test_handler_growpart.py +++ b/tests/unittests/test_handler/test_handler_growpart.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import cloud from cloudinit.config import cc_growpart from cloudinit import util diff --git a/tests/unittests/test_handler/test_handler_locale.py b/tests/unittests/test_handler/test_handler_locale.py index c91908f4..e9a810c5 100644 --- a/tests/unittests/test_handler/test_handler_locale.py +++ b/tests/unittests/test_handler/test_handler_locale.py @@ -1,20 +1,8 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. # -# Author: Juerg Haefliger <juerg.haefliger@hp.com> +# Author: Juerg Haefliger <juerg.haefliger@hp.com> # -# Based on test_handler_set_hostname.py -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. from cloudinit.config import cc_locale @@ -65,3 +53,5 @@ class TestLocale(t_help.FilesystemMockingTestCase): contents = util.load_file('/etc/sysconfig/language', decode=False) n_cfg = ConfigObj(BytesIO(contents)) self.assertEqual({'RC_LANG': cfg['locale']}, dict(n_cfg)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py index 14366a10..351226bf 100644 --- a/tests/unittests/test_handler/test_handler_lxd.py +++ b/tests/unittests/test_handler/test_handler_lxd.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_lxd from cloudinit.sources import DataSourceNoCloud from cloudinit import (distros, helpers, cloud) @@ -183,3 +185,5 @@ class TestLxd(t_help.TestCase): self.assertEqual( cc_lxd.bridge_to_cmd(data), (None, None)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_mcollective.py b/tests/unittests/test_handler/test_handler_mcollective.py index c3a5a634..2a9f3823 100644 --- a/tests/unittests/test_handler/test_handler_mcollective.py +++ b/tests/unittests/test_handler/test_handler_mcollective.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import (cloud, distros, helpers, util) from cloudinit.config import cc_mcollective from cloudinit.sources import DataSourceNoCloud @@ -148,3 +150,5 @@ class TestHandler(t_help.TestCase): self.assertTrue(mock_util.subp.called) self.assertEqual(mock_util.subp.call_args_list[0][0][0], ['service', 'mcollective', 'restart']) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_mounts.py b/tests/unittests/test_handler/test_handler_mounts.py index 355674b2..650ca0ec 100644 --- a/tests/unittests/test_handler/test_handler_mounts.py +++ b/tests/unittests/test_handler/test_handler_mounts.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os.path import shutil import tempfile @@ -131,3 +133,5 @@ class TestSanitizeDevname(test_helpers.FilesystemMockingTestCase): self.assertIsNone( cc_mounts.sanitize_devname( 'ephemeral0.1', lambda x: disk_path, mock.Mock())) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_ntp.py b/tests/unittests/test_handler/test_handler_ntp.py index 1c7bb06a..ec600077 100644 --- a/tests/unittests/test_handler/test_handler_ntp.py +++ b/tests/unittests/test_handler/test_handler_ntp.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_ntp from cloudinit.sources import DataSourceNone from cloudinit import templater @@ -272,3 +274,5 @@ class TestNtp(FilesystemMockingTestCase): cc_ntp.handle('cc_ntp', {}, cc, LOG, []) self.assertFalse(cc.distro.install_packages.called) self.assertFalse(mock_util.subp.called) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_power_state.py b/tests/unittests/test_handler/test_handler_power_state.py index feff319d..3fd0069d 100644 --- a/tests/unittests/test_handler/test_handler_power_state.py +++ b/tests/unittests/test_handler/test_handler_power_state.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import sys from cloudinit.config import cc_power_state_change as psc @@ -125,3 +127,5 @@ def check_lps_ret(psc_return, mode=None): if len(errs): lines = ["Errors in result: %s" % str(psc_return)] + errs raise Exception('\n'.join(lines)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_rsyslog.py b/tests/unittests/test_handler/test_handler_rsyslog.py index 38636063..cca06678 100644 --- a/tests/unittests/test_handler/test_handler_rsyslog.py +++ b/tests/unittests/test_handler/test_handler_rsyslog.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os import shutil import tempfile @@ -172,3 +174,5 @@ class TestRemotesToSyslog(t_help.TestCase): lines = r.splitlines() self.assertEqual(1, len(lines)) self.assertTrue(myline in r.splitlines()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_seed_random.py b/tests/unittests/test_handler/test_handler_seed_random.py index a0390da9..e5e607fb 100644 --- a/tests/unittests/test_handler/test_handler_seed_random.py +++ b/tests/unittests/test_handler/test_handler_seed_random.py @@ -1,20 +1,12 @@ +# This file is part of cloud-init. See LICENSE file for license information. + # Copyright (C) 2013 Hewlett-Packard Development Company, L.P. # # Author: Juerg Haefliger <juerg.haefliger@hp.com> # # Based on test_handler_set_hostname.py # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. from cloudinit.config import cc_seed_random @@ -225,3 +217,5 @@ def apply_patches(patches): setattr(ref, name, replace) ret.append((ref, name, orig)) return ret + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_set_hostname.py b/tests/unittests/test_handler/test_handler_set_hostname.py index 7effa124..4b18de75 100644 --- a/tests/unittests/test_handler/test_handler_set_hostname.py +++ b/tests/unittests/test_handler/test_handler_set_hostname.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_set_hostname from cloudinit import cloud @@ -70,3 +72,5 @@ class TestHostname(t_help.FilesystemMockingTestCase): cc_set_hostname.handle('cc_set_hostname', cfg, cc, LOG, []) contents = util.load_file("/etc/HOSTNAME") self.assertEqual('blah', contents.strip()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_snappy.py b/tests/unittests/test_handler/test_handler_snappy.py index e320dd82..edb73d6d 100644 --- a/tests/unittests/test_handler/test_handler_snappy.py +++ b/tests/unittests/test_handler/test_handler_snappy.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config.cc_snappy import ( makeop, get_package_ops, render_snap_op) from cloudinit.config.cc_snap_config import ( @@ -595,3 +597,5 @@ def apply_patches(patches): setattr(ref, name, replace) ret.append((ref, name, orig)) return ret + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_spacewalk.py b/tests/unittests/test_handler/test_handler_spacewalk.py index 44f95e4c..28b5892a 100644 --- a/tests/unittests/test_handler/test_handler_spacewalk.py +++ b/tests/unittests/test_handler/test_handler_spacewalk.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_spacewalk from cloudinit import util @@ -40,3 +42,5 @@ class TestSpacewalk(helpers.TestCase): '--profilename', 'test', '--sslCACert', cc_spacewalk.def_ca_cert_path, ], capture=False) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_timezone.py b/tests/unittests/test_handler/test_handler_timezone.py index b7e6b03d..c30fbdfe 100644 --- a/tests/unittests/test_handler/test_handler_timezone.py +++ b/tests/unittests/test_handler/test_handler_timezone.py @@ -1,20 +1,8 @@ -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. +# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. # -# Author: Juerg Haefliger <juerg.haefliger@hp.com> +# Author: Juerg Haefliger <juerg.haefliger@hp.com> # -# Based on test_handler_set_hostname.py -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. from cloudinit.config import cc_timezone @@ -74,3 +62,5 @@ class TestTimezone(t_help.FilesystemMockingTestCase): contents = util.load_file('/etc/localtime') self.assertEqual(dummy_contents, contents.strip()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_handler/test_handler_write_files.py b/tests/unittests/test_handler/test_handler_write_files.py index 466e45f8..fb252d1d 100644 --- a/tests/unittests/test_handler/test_handler_write_files.py +++ b/tests/unittests/test_handler/test_handler_write_files.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config.cc_write_files import write_files from cloudinit import log as logging from cloudinit import util diff --git a/tests/unittests/test_handler/test_handler_yum_add_repo.py b/tests/unittests/test_handler/test_handler_yum_add_repo.py index 28b060f8..3feba86c 100644 --- a/tests/unittests/test_handler/test_handler_yum_add_repo.py +++ b/tests/unittests/test_handler/test_handler_yum_add_repo.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.config import cc_yum_add_repo from cloudinit import util @@ -66,3 +68,5 @@ class TestConfig(helpers.FilesystemMockingTestCase): } } self.assertEqual(expected, dict(contents)) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_helpers.py b/tests/unittests/test_helpers.py index 943a5723..955f8dfa 100644 --- a/tests/unittests/test_helpers.py +++ b/tests/unittests/test_helpers.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + """Tests of the built-in user data handlers.""" import os @@ -31,3 +33,5 @@ class TestPaths(test_helpers.ResourceUsingTestCase): mypaths = self.getCloudPaths(myds) self.assertEqual(None, mypaths.get_ipath()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_merging.py b/tests/unittests/test_merging.py index a33ec184..0658b6b4 100644 --- a/tests/unittests/test_merging.py +++ b/tests/unittests/test_merging.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from . import helpers from cloudinit.handlers import cloud_config @@ -255,3 +257,5 @@ class TestSimpleRun(helpers.ResourceUsingTestCase): c = _old_mergedict(a, b) d = util.mergemanydict([a, b]) self.assertEqual(c, d) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index 78c080ca..1090282a 100644..100755 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import net from cloudinit.net import cmdline from cloudinit.net import eni @@ -8,6 +10,8 @@ from cloudinit import util from .helpers import dir2dict from .helpers import mock +from .helpers import populate_dir +from .helpers import TempDirTestCase from .helpers import TestCase import base64 @@ -54,22 +58,9 @@ DHCP_EXPECTED_1 = { } DHCP6_CONTENT_1 = """ -DEVICE=eno1 -HOSTNAME= -DNSDOMAIN= -reason='PREINIT' -interface='eno1' -DEVICE=eno1 +DEVICE6=eno1 HOSTNAME= DNSDOMAIN= -reason='FAIL' -interface='eno1' -DEVICE=eno1 -HOSTNAME= -DNSDOMAIN= -reason='PREINIT6' -interface='eno1' -DEVICE=eno1 IPV6PROTO=dhcp6 IPV6ADDR=2001:67c:1562:8010:0:1:: IPV6NETMASK=64 @@ -77,11 +68,6 @@ IPV6DNS0=2001:67c:1562:8010::2:1 IPV6DOMAINSEARCH= HOSTNAME= DNSDOMAIN= -reason='BOUND6' -interface='eno1' -new_ip6_address='2001:67c:1562:8010:0:1::' -new_ip6_prefixlen='64' -new_dhcp6_name_servers='2001:67c:1562:8010::2:1' """ DHCP6_EXPECTED_1 = { @@ -461,7 +447,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true } -def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info, +def _setup_test(tmp_dir, mock_get_devicelist, mock_read_sys_net, mock_sys_dev_path): mock_get_devicelist.return_value = ['eth1000'] dev_characteristics = { @@ -474,10 +460,12 @@ def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info, } } - def netdev_info(name, field): - return dev_characteristics[name][field] + def fake_read(devname, path, translate=None, + on_enoent=None, on_keyerror=None, + on_einval=None): + return dev_characteristics[devname][path] - mock_sys_netdev_info.side_effect = netdev_info + mock_read_sys_net.side_effect = fake_read def sys_dev_path(devname, path=""): return tmp_dir + devname + "/" + path @@ -493,15 +481,15 @@ def _setup_test(tmp_dir, mock_get_devicelist, mock_sys_netdev_info, class TestSysConfigRendering(TestCase): @mock.patch("cloudinit.net.sys_dev_path") - @mock.patch("cloudinit.net.sys_netdev_info") + @mock.patch("cloudinit.net.read_sys_net") @mock.patch("cloudinit.net.get_devicelist") def test_default_generation(self, mock_get_devicelist, - mock_sys_netdev_info, + mock_read_sys_net, mock_sys_dev_path): tmp_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, tmp_dir) _setup_test(tmp_dir, mock_get_devicelist, - mock_sys_netdev_info, mock_sys_dev_path) + mock_read_sys_net, mock_sys_dev_path) network_cfg = net.generate_fallback_config() ns = network_state.parse_net_config_data(network_cfg, @@ -550,15 +538,15 @@ USERCTL=no class TestEniNetRendering(TestCase): @mock.patch("cloudinit.net.sys_dev_path") - @mock.patch("cloudinit.net.sys_netdev_info") + @mock.patch("cloudinit.net.read_sys_net") @mock.patch("cloudinit.net.get_devicelist") def test_default_generation(self, mock_get_devicelist, - mock_sys_netdev_info, + mock_read_sys_net, mock_sys_dev_path): tmp_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, tmp_dir) _setup_test(tmp_dir, mock_get_devicelist, - mock_sys_netdev_info, mock_sys_dev_path) + mock_read_sys_net, mock_sys_dev_path) network_cfg = net.generate_fallback_config() ns = network_state.parse_net_config_data(network_cfg, @@ -677,6 +665,66 @@ class TestCmdlineConfigParsing(TestCase): self.assertEqual(found, self.simple_cfg) +class TestCmdlineReadKernelConfig(TempDirTestCase): + macs = { + 'eth0': '14:02:ec:42:48:00', + 'eno1': '14:02:ec:42:48:01', + } + + def test_ip_cmdline_read_kernel_cmdline_ip(self): + content = {'net-eth0.conf': DHCP_CONTENT_1} + populate_dir(self.tmp, content) + files = [os.path.join(self.tmp, k) for k in content.keys()] + found = cmdline.read_kernel_cmdline_config( + files=files, cmdline='foo ip=dhcp', mac_addrs=self.macs) + exp1 = copy.deepcopy(DHCP_EXPECTED_1) + exp1['mac_address'] = self.macs['eth0'] + self.assertEqual(found['version'], 1) + self.assertEqual(found['config'], [exp1]) + + def test_ip_cmdline_read_kernel_cmdline_ip6(self): + content = {'net6-eno1.conf': DHCP6_CONTENT_1} + populate_dir(self.tmp, content) + files = [os.path.join(self.tmp, k) for k in content.keys()] + found = cmdline.read_kernel_cmdline_config( + files=files, cmdline='foo ip6=dhcp root=/dev/sda', + mac_addrs=self.macs) + self.assertEqual( + found, + {'version': 1, 'config': [ + {'type': 'physical', 'name': 'eno1', + 'mac_address': self.macs['eno1'], + 'subnets': [ + {'dns_nameservers': ['2001:67c:1562:8010::2:1'], + 'control': 'manual', 'type': 'dhcp6', 'netmask': '64'}]}]}) + + def test_ip_cmdline_read_kernel_cmdline_none(self): + # if there is no ip= or ip6= on cmdline, return value should be None + content = {'net6-eno1.conf': DHCP6_CONTENT_1} + populate_dir(self.tmp, content) + files = [os.path.join(self.tmp, k) for k in content.keys()] + found = cmdline.read_kernel_cmdline_config( + files=files, cmdline='foo root=/dev/sda', mac_addrs=self.macs) + self.assertEqual(found, None) + + def test_ip_cmdline_both_ip_ip6(self): + content = {'net-eth0.conf': DHCP_CONTENT_1, + 'net6-eth0.conf': DHCP6_CONTENT_1.replace('eno1', 'eth0')} + populate_dir(self.tmp, content) + files = [os.path.join(self.tmp, k) for k in sorted(content.keys())] + found = cmdline.read_kernel_cmdline_config( + files=files, cmdline='foo ip=dhcp ip6=dhcp', mac_addrs=self.macs) + + eth0 = copy.deepcopy(DHCP_EXPECTED_1) + eth0['mac_address'] = self.macs['eth0'] + eth0['subnets'].append( + {'control': 'manual', 'type': 'dhcp6', + 'netmask': '64', 'dns_nameservers': ['2001:67c:1562:8010::2:1']}) + expected = [eth0] + self.assertEqual(found['version'], 1) + self.assertEqual(found['config'], expected) + + class TestEniRoundTrip(TestCase): def setUp(self): super(TestCase, self).setUp() @@ -723,6 +771,52 @@ class TestEniRoundTrip(TestCase): entry['expected_eni'].splitlines(), files['/etc/network/interfaces'].splitlines()) + def test_routes_rendered(self): + # as reported in bug 1649652 + conf = [ + {'name': 'eth0', 'type': 'physical', + 'subnets': [{ + 'address': '172.23.31.42/26', + 'dns_nameservers': [], 'gateway': '172.23.31.2', + 'type': 'static'}]}, + {'type': 'route', 'id': 4, + 'metric': 0, 'destination': '10.0.0.0/12', + 'gateway': '172.23.31.1'}, + {'type': 'route', 'id': 5, + 'metric': 0, 'destination': '192.168.2.0/16', + 'gateway': '172.23.31.1'}, + {'type': 'route', 'id': 6, + 'metric': 1, 'destination': '10.0.200.0/16', + 'gateway': '172.23.31.1'}, + ] + + files = self._render_and_read( + network_config={'config': conf, 'version': 1}) + expected = [ + 'auto lo', + 'iface lo inet loopback', + 'auto eth0', + 'iface eth0 inet static', + ' address 172.23.31.42/26', + ' gateway 172.23.31.2', + ('post-up route add -net 10.0.0.0 netmask 255.240.0.0 gw ' + '172.23.31.1 metric 0 || true'), + ('pre-down route del -net 10.0.0.0 netmask 255.240.0.0 gw ' + '172.23.31.1 metric 0 || true'), + ('post-up route add -net 192.168.2.0 netmask 255.255.0.0 gw ' + '172.23.31.1 metric 0 || true'), + ('pre-down route del -net 192.168.2.0 netmask 255.255.0.0 gw ' + '172.23.31.1 metric 0 || true'), + ('post-up route add -net 10.0.200.0 netmask 255.255.0.0 gw ' + '172.23.31.1 metric 1 || true'), + ('pre-down route del -net 10.0.200.0 netmask 255.255.0.0 gw ' + '172.23.31.1 metric 1 || true'), + ] + found = files['/etc/network/interfaces'].splitlines() + + self.assertEqual( + expected, [line for line in found if line]) + def _gzip_data(data): with io.BytesIO() as iobuf: @@ -730,3 +824,5 @@ def _gzip_data(data): gzfp.write(data) gzfp.close() return iobuf.getvalue() + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_pathprefix2dict.py b/tests/unittests/test_pathprefix2dict.py index 38fd75b6..a4ae284f 100644 --- a/tests/unittests/test_pathprefix2dict.py +++ b/tests/unittests/test_pathprefix2dict.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit import util from .helpers import TestCase, populate_dir diff --git a/tests/unittests/test_registry.py b/tests/unittests/test_registry.py index bcf01475..acf0bf4f 100644 --- a/tests/unittests/test_registry.py +++ b/tests/unittests/test_registry.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from cloudinit.registry import DictRegistry from .helpers import (mock, TestCase) @@ -26,3 +28,5 @@ class TestDictRegistry(TestCase): registry.register_item(item_key, mock.Mock()) self.assertRaises(ValueError, registry.register_item, item_key, mock.Mock()) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_reporting.py b/tests/unittests/test_reporting.py index 20ca23df..f3b8f992 100644 --- a/tests/unittests/test_reporting.py +++ b/tests/unittests/test_reporting.py @@ -1,7 +1,6 @@ # Copyright 2015 Canonical Ltd. -# This file is part of cloud-init. See LICENCE file for license information. # -# vi: ts=4 expandtab +# This file is part of cloud-init. See LICENSE file for license information. from cloudinit import reporting from cloudinit.reporting import events @@ -369,3 +368,5 @@ class TestReportingEventStack(TestCase): class TestStatusAccess(TestCase): def test_invalid_status_access_raises_value_error(self): self.assertRaises(AttributeError, getattr, events.status, "BOGUS") + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_rh_subscription.py b/tests/unittests/test_rh_subscription.py index 891dbe77..ca14cd46 100644 --- a/tests/unittests/test_rh_subscription.py +++ b/tests/unittests/test_rh_subscription.py @@ -1,14 +1,6 @@ -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. + +"""Tests for registering RHEL subscription via rh_subscription.""" import logging @@ -83,8 +75,8 @@ class GoodTests(TestCase): ''' call_lists = [] call_lists.append(['attach', '--pool=pool1', '--pool=pool3']) - call_lists.append(['repos', '--enable=repo2', '--enable=repo3', - '--disable=repo5']) + call_lists.append(['repos', '--disable=repo5', '--enable=repo2', + '--enable=repo3']) call_lists.append(['attach', '--auto', '--servicelevel=self-support']) self.SM.log_success = mock.MagicMock() reg = "The system has been registered with ID:" \ @@ -224,3 +216,5 @@ class TestBadInput(TestCase): self.SM._sub_man_cli.assert_called_with(['identity']) self.assertEqual(self.SM.log_warn.call_count, 4) self.assertEqual(self.SM._sub_man_cli.call_count, 1) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_runs/test_merge_run.py b/tests/unittests/test_runs/test_merge_run.py index ce43798e..65895273 100644 --- a/tests/unittests/test_runs/test_merge_run.py +++ b/tests/unittests/test_runs/test_merge_run.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os import shutil import tempfile @@ -52,3 +54,5 @@ class TestMergeRun(helpers.FilesystemMockingTestCase): self.assertIn('write-files', which_ran) contents = util.load_file('/etc/blah.ini') self.assertEqual(contents, 'blah') + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_runs/test_simple_run.py b/tests/unittests/test_runs/test_simple_run.py index 07e7b1a8..31324204 100644 --- a/tests/unittests/test_runs/test_simple_run.py +++ b/tests/unittests/test_runs/test_simple_run.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + import os import shutil import tempfile @@ -79,3 +81,5 @@ class TestSimpleRun(helpers.FilesystemMockingTestCase): self.assertIn('write-files', which_ran) contents = util.load_file('/etc/blah.ini') self.assertEqual(contents, 'blah') + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_sshutil.py b/tests/unittests/test_sshutil.py index 9aeb1cde..55971b5e 100644 --- a/tests/unittests/test_sshutil.py +++ b/tests/unittests/test_sshutil.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from mock import patch from . import helpers as test_helpers diff --git a/tests/unittests/test_templating.py b/tests/unittests/test_templating.py index 94b6e061..4e627826 100644 --- a/tests/unittests/test_templating.py +++ b/tests/unittests/test_templating.py @@ -1,20 +1,8 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2014 Yahoo! Inc. -# -# Author: Joshua Harlow <harlowja@yahoo-inc.com> +# Copyright (C) 2014 Yahoo! Inc. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Author: Joshua Harlow <harlowja@yahoo-inc.com> # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. from __future__ import print_function @@ -117,3 +105,5 @@ $a,$b''' {'mirror': mirror, 'codename': codename}) self.assertEqual(ex_data, out_data) + +# vi: ts=4 expandtab diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index f6a8ab75..ab74311e 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -1,3 +1,5 @@ +# This file is part of cloud-init. See LICENSE file for license information. + from __future__ import print_function import logging @@ -611,4 +613,73 @@ class TestEncode(helpers.TestCase): text = util.decode_binary(blob) self.assertEqual(text, blob) + +class TestProcessExecutionError(helpers.TestCase): + + template = ('{description}\n' + 'Command: {cmd}\n' + 'Exit code: {exit_code}\n' + 'Reason: {reason}\n' + 'Stdout: {stdout}\n' + 'Stderr: {stderr}') + empty_attr = '-' + empty_description = 'Unexpected error while running command.' + + def test_pexec_error_indent_text(self): + error = util.ProcessExecutionError() + msg = 'abc\ndef' + formatted = 'abc\n{0}def'.format(' ' * 4) + self.assertEqual(error._indent_text(msg, indent_level=4), formatted) + self.assertEqual(error._indent_text(msg.encode(), indent_level=4), + formatted.encode()) + self.assertIsInstance( + error._indent_text(msg.encode()), type(msg.encode())) + + def test_pexec_error_type(self): + self.assertIsInstance(util.ProcessExecutionError(), IOError) + + def test_pexec_error_empty_msgs(self): + error = util.ProcessExecutionError() + self.assertTrue(all(attr == self.empty_attr for attr in + (error.stderr, error.stdout, error.reason))) + self.assertEqual(error.description, self.empty_description) + self.assertEqual(str(error), self.template.format( + description=self.empty_description, exit_code=self.empty_attr, + reason=self.empty_attr, stdout=self.empty_attr, + stderr=self.empty_attr, cmd=self.empty_attr)) + + def test_pexec_error_single_line_msgs(self): + stdout_msg = 'out out' + stderr_msg = 'error error' + cmd = 'test command' + exit_code = 3 + error = util.ProcessExecutionError( + stdout=stdout_msg, stderr=stderr_msg, exit_code=3, cmd=cmd) + self.assertEqual(str(error), self.template.format( + description=self.empty_description, stdout=stdout_msg, + stderr=stderr_msg, exit_code=str(exit_code), + reason=self.empty_attr, cmd=cmd)) + + def test_pexec_error_multi_line_msgs(self): + # make sure bytes is converted handled properly when formatting + stdout_msg = 'multi\nline\noutput message'.encode() + stderr_msg = 'multi\nline\nerror message\n\n\n' + error = util.ProcessExecutionError( + stdout=stdout_msg, stderr=stderr_msg) + self.assertEqual( + str(error), + '\n'.join(( + '{description}', + 'Command: {empty_attr}', + 'Exit code: {empty_attr}', + 'Reason: {empty_attr}', + 'Stdout: multi', + ' line', + ' output message', + 'Stderr: multi', + ' line', + ' error message', + )).format(description=self.empty_description, + empty_attr=self.empty_attr)) + # vi: ts=4 expandtab diff --git a/tests/unittests/test_vmware_config_file.py b/tests/unittests/test_vmware_config_file.py index d5c7367b..18475f10 100644 --- a/tests/unittests/test_vmware_config_file.py +++ b/tests/unittests/test_vmware_config_file.py @@ -1,21 +1,9 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2015 Canonical Ltd. -# Copyright (C) 2016 VMware INC. -# -# Author: Sankar Tanguturi <stanguturi@vmware.com> +# Copyright (C) 2015 Canonical Ltd. +# Copyright (C) 2016 VMware INC. # -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, as -# published by the Free Software Foundation. +# Author: Sankar Tanguturi <stanguturi@vmware.com> # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# This file is part of cloud-init. See LICENSE file for license information. import logging import sys @@ -101,3 +89,5 @@ class TestVmwareConfigFile(unittest.TestCase): self.assertEqual('NIC1', nics[0].name, "nic0") self.assertEqual('00:50:56:a6:8c:08', nics[0].mac, "mac0") self.assertEqual(BootProtoEnum.DHCP, nics[0].bootProto, "bootproto0") + +# vi: ts=4 expandtab |