diff --git a/pyproject.toml b/pyproject.toml index 0972e89a336..8c7e1e6d3f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,26 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_apt_configure_sources_list_v3", - "tests.unittests.config.test_apt_source_v1", - "tests.unittests.config.test_cc_apt_pipelining", - "tests.unittests.config.test_cc_chef", - "tests.unittests.config.test_cc_final_message", - "tests.unittests.config.test_cc_growpart", - "tests.unittests.config.test_cc_install_hotplug", - "tests.unittests.config.test_cc_keys_to_console", - "tests.unittests.config.test_cc_puppet", - "tests.unittests.config.test_cc_resizefs", - "tests.unittests.config.test_cc_resolv_conf", - "tests.unittests.config.test_cc_rh_subscription", - "tests.unittests.config.test_cc_ubuntu_autoinstall", - "tests.unittests.config.test_cc_update_etc_hosts", - "tests.unittests.config.test_cc_users_groups", - "tests.unittests.config.test_cc_wireguard", - "tests.unittests.config.test_cc_yum_add_repo", - "tests.unittests.config.test_cc_zypper_add_repo", - "tests.unittests.config.test_modules", - "tests.unittests.config.test_schema", "tests.unittests.distros.test_ifconfig", "tests.unittests.distros.test_netbsd", "tests.unittests.distros.test_netconfig", diff --git a/tests/unittests/config/test_apt_configure_sources_list_v3.py b/tests/unittests/config/test_apt_configure_sources_list_v3.py index 30a4d9ac48b..354de9508f9 100644 --- a/tests/unittests/config/test_apt_configure_sources_list_v3.py +++ b/tests/unittests/config/test_apt_configure_sources_list_v3.py @@ -6,6 +6,7 @@ """ import stat +from typing import Any import pytest @@ -238,7 +239,7 @@ def test_apt_v3_empty_cfg_source_list_by_distro( "_should_configure_on_empty_apt", return_value=SubpResult(True, "test"), ) - cc_apt_configure.handle("test", {"apt": {}}, mycloud, None) + cc_apt_configure.handle("test", {"apt": {}}, mycloud, []) sources_file = tmpdir.join(f"/etc/apt/sources.list.d/{distro}.sources") if template_present: @@ -257,13 +258,13 @@ def test_apt_v3_empty_cfg_source_list_by_distro( def test_apt_v3_source_list_ubuntu_snappy(self, mocker): """test_apt_v3_source_list_ubuntu_snappy - without custom sources or params""" - cfg = {"apt": {}} + cfg: dict = {"apt": {}} mycloud = get_cloud() mock_writefile = mocker.patch.object(util, "write_file") mock_issnappy = mocker.patch.object(util, "system_is_snappy") mock_issnappy.return_value = True - cc_apt_configure.handle("test", cfg, mycloud, None) + cc_apt_configure.handle("test", cfg, mycloud, []) mock_writefile.assert_not_called() assert 1 == mock_issnappy.call_count @@ -315,7 +316,7 @@ def test_apt_v3_source_list_psm_deb822_feature_aware( util.write_file(tmpl_file, tmpl_content) mycloud = get_cloud("ubuntu") - cc_apt_configure.handle("test", {"apt": cfg}, mycloud, None) + cc_apt_configure.handle("test", {"apt": cfg}, mycloud, []) sources_file = tmpdir.join(apt_file) assert expected == sources_file.read() @@ -369,7 +370,7 @@ def test_apt_v3_srcl_custom_deb822_feature_aware( cc_apt_configure.features, "APT_DEB822_SOURCE_LIST_FILE", deb822 ) mocker.patch.object(Distro, "get_primary_arch", return_value="amd64") - cc_apt_configure.handle("notimportant", cfg, mycloud, None) + cc_apt_configure.handle("notimportant", cfg, mycloud, []) sources_file = tmpdir.join(apt_file) assert expected == sources_file.read() assert 0o644 == stat.S_IMODE(sources_file.stat().mode) @@ -428,7 +429,7 @@ def test_apt_v3_srcl_deb822_custom_psm_keys( util.write_file(tmpl_file, tmpl_content) # Base config - cfg = { + cfg: dict[str, Any] = { "preserve_sources_list": False, "primary": [{"arches": ["default"], "uri": pm}], } @@ -442,7 +443,7 @@ def test_apt_v3_srcl_deb822_custom_psm_keys( cfg["security"][0]["key"] = smkey mycloud = get_cloud(distro) - cc_apt_configure.handle("test", {"apt": cfg}, mycloud, None) + cc_apt_configure.handle("test", {"apt": cfg}, mycloud, []) apt_file = f"/etc/apt/sources.list.d/{distro}.sources" sources_file = tmpdir.join(apt_file) diff --git a/tests/unittests/config/test_apt_source_v1.py b/tests/unittests/config/test_apt_source_v1.py index c3729dc4fc9..a84717910bb 100644 --- a/tests/unittests/config/test_apt_source_v1.py +++ b/tests/unittests/config/test_apt_source_v1.py @@ -11,6 +11,7 @@ import re from functools import partial from textwrap import dedent +from typing import Any from unittest import mock from unittest.mock import call @@ -844,7 +845,7 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): }, } cfg_3_only = {"apt": {"sources": fullv3}} - cfg_1_and_3 = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3: dict[str, Any] = {"apt_sources": [cfg1, cfg2, cfg3]} cfg_1_and_3.update(cfg_3_only) # collision (equal, so ok to remove) @@ -869,7 +870,9 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): }, } cfg_3_only = {"apt": {"sources": diff}} - cfg_1_and_3_different = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3_different: dict[str, Any] = { + "apt_sources": [cfg1, cfg2, cfg3] + } cfg_1_and_3_different.update(cfg_3_only) # collision (unequal by dict having a different entry) @@ -883,7 +886,9 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): } } cfg_3_only = {"apt": {"sources": missing}} - cfg_1_and_3_missing = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3_missing: dict[str, Any] = { + "apt_sources": [cfg1, cfg2, cfg3] + } cfg_1_and_3_missing.update(cfg_3_only) # collision (unequal by dict missing an entry) with pytest.raises(ValueError): diff --git a/tests/unittests/config/test_cc_apt_pipelining.py b/tests/unittests/config/test_cc_apt_pipelining.py index 6fb2926aa31..ffd9053399e 100644 --- a/tests/unittests/config/test_cc_apt_pipelining.py +++ b/tests/unittests/config/test_cc_apt_pipelining.py @@ -20,14 +20,14 @@ class TestAptPipelining: @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file") def test_not_disabled_by_default(self, m_write_file): """ensure that default behaviour is to not disable pipelining""" - cc_apt_pipelining.handle("foo", {}, None, None) + cc_apt_pipelining.handle("foo", {}, mock.Mock(), []) assert 0 == m_write_file.call_count @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file") def test_false_disables_pipelining(self, m_write_file): """ensure that pipelining can be disabled with correct config""" cc_apt_pipelining.handle( - "foo", {"apt_pipelining": "false"}, None, None + "foo", {"apt_pipelining": "false"}, mock.Mock(), [] ) assert 1 == m_write_file.call_count args, _ = m_write_file.call_args diff --git a/tests/unittests/config/test_cc_chef.py b/tests/unittests/config/test_cc_chef.py index c4e669518b4..8b6eafab32b 100644 --- a/tests/unittests/config/test_cc_chef.py +++ b/tests/unittests/config/test_cc_chef.py @@ -122,7 +122,7 @@ class TestChef: def test_no_config(self): """No chef directories are created on when no chef config provided""" - cfg = {} + cfg: dict = {} cc_chef.handle("chef", cfg, get_cloud(), []) for d in cc_chef.CHEF_DIRS: assert not os.path.isdir(d) @@ -180,11 +180,11 @@ def test_basic_config(self): if k in unrendered_keys: continue assert v in c - for k, v in cc_chef.CHEF_RB_TPL_DEFAULTS.items(): + for k, default_v in cc_chef.CHEF_RB_TPL_DEFAULTS.items(): if k in unrendered_keys: continue # the value from the cfg overrides that in the default - val = cfg["chef"].get(k, v) + val = cfg["chef"].get(k, default_v) if isinstance(val, str): assert val in c c = util.load_text_file(cc_chef.CHEF_FB_PATH) diff --git a/tests/unittests/config/test_cc_final_message.py b/tests/unittests/config/test_cc_final_message.py index e612e3dad52..cd5a67b03b0 100644 --- a/tests/unittests/config/test_cc_final_message.py +++ b/tests/unittests/config/test_cc_final_message.py @@ -35,7 +35,7 @@ def test_boot_finished_written( boot_finished = instance_dir / "boot-finished" m_cloud = get_cloud(paths=paths) - handle(None, {}, m_cloud, []) + handle("", {}, m_cloud, []) # We should not change the status of the instance directory assert instance_dir_exists == instance_dir.exists() @@ -69,7 +69,7 @@ def test_only_warn_when_datasourcenone_is_fallback_in_datasource_list( m_cloud.datasource.dsname = dsname Path(paths.get_ipath_cur()).mkdir() with caplog.at_level(log_level): - handle(None, {}, m_cloud, []) + handle("", {}, m_cloud, []) # We should not change the status of the instance directory if expected_log: diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py index 6f22673945e..e1f15639aed 100644 --- a/tests/unittests/config/test_cc_growpart.py +++ b/tests/unittests/config/test_cc_growpart.py @@ -110,7 +110,7 @@ def test_mode_off(mocker): cc_growpart.handle( name="growpart", cfg=config, - cloud=None, + cloud=mock.Mock(), args=[], ) mock_resizer.assert_not_called() @@ -127,11 +127,11 @@ def freebsd_cloud(mocker): distro = cls("freebsd", {}, None) cloud_obj = cloud.Cloud( - None, - None, + mock.Mock(), + mock.Mock(), {}, distro, - None, + mock.Mock(), ) return cloud_obj @@ -333,7 +333,13 @@ def test_simple_devices(self, mocker): ) resize_calls = [] - class myresizer: + class myresizer(cc_growpart.Resizer): + def __init__(self): + pass + + def available(self, devices: list) -> bool: + return True + def resize(self, diskdev, partnum, partdev, fs): resize_calls.append((diskdev, partnum, partdev, fs)) if partdev == "/dev/YYda2": @@ -518,8 +524,11 @@ def common_mocks(self, mocker): # when needed self.distro = MockDistro() - original_device_part_info = self.distro.device_part_info - self.distro.device_part_info = self._device_part_info_side_effect + mocker.patch.object( + self.distro, + "device_part_info", + side_effect=self._device_part_info_side_effect, + ) mocker.patch("os.stat") mocker.patch("stat.S_ISBLK") mocker.patch("stat.S_ISCHR") @@ -553,7 +562,7 @@ def common_mocks(self, mocker): self.resizer = mock.Mock() self.resizer.resize = mock.Mock(return_value=(1024, 1024)) yield - self.distro.device_part_info = original_device_part_info + # device_part_info is restored automatically by mocker def test_resize_when_encrypted(self, common_mocks, caplog): info = cc_growpart.resize_devices( diff --git a/tests/unittests/config/test_cc_install_hotplug.py b/tests/unittests/config/test_cc_install_hotplug.py index d34d95b0092..fa6fba855ce 100644 --- a/tests/unittests/config/test_cc_install_hotplug.py +++ b/tests/unittests/config/test_cc_install_hotplug.py @@ -1,5 +1,5 @@ # This file is part of cloud-init. See LICENSE file for license information. -from collections import namedtuple +from types import SimpleNamespace from unittest import mock import pytest @@ -22,15 +22,13 @@ def mocks(): m_which = mock.patch("cloudinit.subp.which", return_value=None) m_path_exists = mock.patch("os.path.exists", return_value=False) - yield namedtuple( - "Mocks", "m_update_enabled m_write m_del m_subp m_which m_path_exists" - )( - m_update_enabled.start(), - m_write.start(), - m_del.start(), - m_subp.start(), - m_which.start(), - m_path_exists.start(), + yield SimpleNamespace( + m_update_enabled=m_update_enabled.start(), + m_write=m_write.start(), + m_del=m_del.start(), + m_subp=m_subp.start(), + m_which=m_which.start(), + m_path_exists=m_path_exists.start(), ) m_update_enabled.stop() @@ -59,7 +57,7 @@ def test_rules_installed_when_supported_and_enabled( else: libexecdir = "/usr/lib/cloud-init" with mock.patch("os.path.exists", return_value=libexec_exists): - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) mocks.m_write.assert_called_once_with( filename=HOTPLUG_UDEV_PATH, content=HOTPLUG_UDEV_RULES_TEMPLATE.format( @@ -82,7 +80,7 @@ def test_rules_not_installed_when_unsupported(self, mocks): m_cloud = mock.MagicMock() m_cloud.datasource.get_supported_events.return_value = {} - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_write.call_args_list == [] assert mocks.m_del.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -94,7 +92,7 @@ def test_rules_not_installed_when_disabled(self, mocks): EventScope.NETWORK: {EventType.HOTPLUG} } - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_write.call_args_list == [] assert mocks.m_del.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -105,7 +103,7 @@ def test_rules_uninstalled_when_disabled(self, mocks): m_cloud = mock.MagicMock() m_cloud.datasource.get_supported_events.return_value = {} - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) mocks.m_del.assert_called_with(HOTPLUG_UDEV_PATH) assert mocks.m_subp.call_args_list == [ mock.call( @@ -125,7 +123,7 @@ def test_rules_not_installed_when_no_udevadm(self, mocks): EventScope.NETWORK: {EventType.HOTPLUG} } - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_del.call_args_list == [] assert mocks.m_write.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -142,7 +140,7 @@ def test_rules_installed_on_ec2(self, mocks): ) with mock.patch("os.path.exists", return_value=True): - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) udev_rules = """\ # Installed by cloud-init due to network hotplug userdata diff --git a/tests/unittests/config/test_cc_keys_to_console.py b/tests/unittests/config/test_cc_keys_to_console.py index 28296d09b47..28ce2b2dde6 100644 --- a/tests/unittests/config/test_cc_keys_to_console.py +++ b/tests/unittests/config/test_cc_keys_to_console.py @@ -43,7 +43,7 @@ def test_emit_keys_to_console_config( m_path_exists.return_value = True m_subp.return_value = ("", "") - cc_keys_to_console.handle("name", cfg, mock.Mock(), ()) + cc_keys_to_console.handle("name", cfg, mock.Mock(), []) assert subp_called == (m_subp.call_count == 1) diff --git a/tests/unittests/config/test_cc_puppet.py b/tests/unittests/config/test_cc_puppet.py index 166a7fe0e29..33a96478f10 100644 --- a/tests/unittests/config/test_cc_puppet.py +++ b/tests/unittests/config/test_cc_puppet.py @@ -84,8 +84,8 @@ def test_skips_missing_puppet_key_in_cloudconfig( ): """Cloud-config containing no 'puppet' key is skipped.""" - cfg = {} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cfg: dict = {} + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert "no 'puppet' configuration found" in caplog.text assert 0 == m_man_puppet.call_count @@ -95,7 +95,7 @@ def test_puppet_config_starts_puppet_service(self, m_subp, m_man_puppet): cloud = get_cloud() cfg = {"puppet": {"install": False}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -108,8 +108,8 @@ def test_empty_puppet_config_installs_puppet(self, m_subp, m_man_puppet): """Cloud-config empty 'puppet' configuration installs latest puppet.""" cloud = get_cloud() cloud.distro = mock.MagicMock() - cfg = {"puppet": {}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cfg: dict = {"puppet": {}} + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call(["puppet-agent"]) ] == cloud.distro.install_packages.call_args_list @@ -120,7 +120,7 @@ def test_puppet_config_installs_puppet_on_true(self, m_subp, _): cloud = get_cloud() cloud.distro = mock.MagicMock() cfg = {"puppet": {"install": True}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call(["puppet-agent"]) ] in cloud.distro.install_packages.call_args_list @@ -134,7 +134,7 @@ def test_puppet_config_installs_puppet_aio(self, m_subp, m_aio, _): cloud = get_cloud() cloud.distro = distro cfg = {"puppet": {"install": True, "install_type": "aio"}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, None, True ) @@ -156,7 +156,7 @@ def test_puppet_config_installs_puppet_aio_with_version( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, "6.24.0", None, True ) @@ -178,7 +178,7 @@ def test_puppet_config_installs_puppet_aio_with_collection( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, "puppet6", True ) @@ -200,7 +200,7 @@ def test_puppet_config_installs_puppet_aio_with_custom_url( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, "http://test.url/path/to/script.sh", None, None, True ) @@ -222,7 +222,7 @@ def test_puppet_config_installs_puppet_aio_without_cleanup( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, None, False ) @@ -233,7 +233,7 @@ def test_puppet_config_installs_puppet_version(self, m_subp, _): cloud = get_cloud() cloud.distro = mock.MagicMock() cfg = {"puppet": {"version": "3.8"}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call([["puppet-agent", "3.8"]]) ] == cloud.distro.install_packages.call_args_list @@ -251,7 +251,7 @@ def test_puppet_config_updates_puppet_conf(self, m_subp, m_man_puppet): util.write_file(self.CONF, "[agent]\nserver = origpuppet\nother = 3") cloud = get_cloud() cloud.distro = mock.MagicMock() - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) content = util.load_text_file(self.CONF) expected = "[agent]\nserver = puppetserver.example.org\nother = 3\n\n" assert expected == content @@ -288,7 +288,7 @@ def _fake_get_config_value(puppet_bin, setting): } } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) content = util.load_text_file(self.CSR_ATTRIBUTES_PATH) expected = textwrap.dedent("""\ custom_attributes: @@ -305,7 +305,7 @@ def test_puppet_runs_puppet_if_requested(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cloud = get_cloud() cfg = {"puppet": {"exec": True}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -320,8 +320,8 @@ def test_puppet_runs_puppet_if_requested(self, m_subp, m_man_puppet): def test_puppet_starts_puppetd(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cloud = get_cloud() - cfg = {"puppet": {}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cfg: dict = {"puppet": {}} + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -334,7 +334,7 @@ def test_puppet_skips_puppetd(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cfg = {"puppet": {"start_service": False}} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 0 == m_man_puppet.call_count assert [ mock.call(["systemctl", "start", "puppet-agent"], capture=False) @@ -352,7 +352,7 @@ def test_puppet_runs_puppet_with_args_list_if_requested( "exec_args": ["--onetime", "--detailed-exitcodes"], } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count assert [ mock.call( @@ -373,7 +373,7 @@ def test_puppet_runs_puppet_with_args_string_if_requested( "exec_args": "--onetime --detailed-exitcodes", } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count assert [ mock.call( @@ -384,7 +384,7 @@ def test_puppet_runs_puppet_with_args_string_if_requested( @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", "")) def test_puppet_falls_back_to_older_name(self, m_subp, m_man_puppet): - cfg = {"puppet": {}} + cfg: dict = {"puppet": {}} with mock.patch( "tests.unittests.util.MockDistro.install_packages" ) as install_pkg: @@ -392,7 +392,7 @@ def test_puppet_falls_back_to_older_name(self, m_subp, m_man_puppet): install_pkg.side_effect = (PackageInstallerError, 0) cloud = get_cloud() - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) expected_calls = [ mock.call(cloud, "enable"), mock.call(cloud, "start"), @@ -408,7 +408,7 @@ def test_puppet_with_conf_package_name_fails(self, m_subp, m_man_puppet): # puppet-agent not installed, but puppet is install_pkg.side_effect = (ProcessExecutionError, 0) with pytest.raises(ProcessExecutionError): - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 0 == m_man_puppet.call_count assert [ mock.call(["systemctl", "start", "puppet-agent"], capture=True) @@ -417,7 +417,7 @@ def test_puppet_with_conf_package_name_fails(self, m_subp, m_man_puppet): @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", "")) def test_puppet_with_conf_package_name_success(self, m_subp, m_man_puppet): cfg = {"puppet": {"package_name": "puppet"}} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count diff --git a/tests/unittests/config/test_cc_resizefs.py b/tests/unittests/config/test_cc_resizefs.py index b103f0a7124..8682f7b0ed9 100644 --- a/tests/unittests/config/test_cc_resizefs.py +++ b/tests/unittests/config/test_cc_resizefs.py @@ -81,7 +81,7 @@ def test_can_skip_resize_ext(self): def test_handle_noops_on_disabled(self, caplog): """The handle function logs when the configuration disables resize.""" cfg = {"resize_rootfs": False} - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) assert ( mock.ANY, logging.DEBUG, @@ -96,7 +96,7 @@ def test_handle_warns_on_unknown_mount_info( """handle warns when get_mount_info sees unknown filesystem for /.""" m_get_mount_info.return_value = None cfg = {"resize_rootfs": True} - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) logs = caplog.text assert ( "WARNING: Invalid cloud-config provided:\nresize_rootfs:" @@ -190,7 +190,7 @@ def test_handle_zfs_root( cfg = {"resize_rootfs": True} with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize: - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) ret = dresize.call_args[0] assert (("zpool", "online", "-e", "vmzroot", disk),) == ret @@ -224,7 +224,7 @@ def fake_stat(devpath): with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize: with mock.patch("cloudinit.config.cc_resizefs.os.stat") as m_stat: m_stat.side_effect = fake_stat - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) assert ( ("zpool", "online", "-e", "zroot", "/dev/" + disk), ) == dresize.call_args[0] diff --git a/tests/unittests/config/test_cc_resolv_conf.py b/tests/unittests/config/test_cc_resolv_conf.py index 6bf67dda026..75e887ae05b 100644 --- a/tests/unittests/config/test_cc_resolv_conf.py +++ b/tests/unittests/config/test_cc_resolv_conf.py @@ -32,8 +32,7 @@ class TestResolvConf: cfg = {"manage_resolv_conf": True, "resolv_conf": {}} def call_resolv_conf_handler(self, distro, conf, paths): - ds = None - cc = cloud.Cloud(ds, paths, {}, distro, None) + cc = cloud.Cloud(mock.Mock(), paths, {}, distro, mock.Mock()) cc_resolv_conf.handle("cc_resolv_conf", conf, cc, []) @mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file") @@ -88,10 +87,9 @@ def test_resolv_conf_etc_resolv_conf( def test_resolv_conf_invalid_resolve_conf_fn( self, m_render_to_file, caplog, Distro, tmp_path ): - ds = None dist = Distro("rhel", self.cfg) paths = helpers.Paths({"cloud_dir": str(tmp_path)}) - cc = cloud.Cloud(ds, paths, {}, dist, None) + cc = cloud.Cloud(mock.Mock(), paths, {}, dist, mock.Mock()) cc.distro.resolve_conf_fn = "bla" cc_resolv_conf.handle("rhel", self.cfg, cc, []) diff --git a/tests/unittests/config/test_cc_rh_subscription.py b/tests/unittests/config/test_cc_rh_subscription.py index 18d13dd41c7..af34430ff63 100644 --- a/tests/unittests/config/test_cc_rh_subscription.py +++ b/tests/unittests/config/test_cc_rh_subscription.py @@ -4,6 +4,7 @@ import copy import logging +from typing import cast import pytest @@ -53,7 +54,7 @@ def test_already_registered(self, m_sman_cli, caplog): Emulates a system that is already registered. Ensure it gets a non-ProcessExecution error from is_registered() """ - cc_rh_subscription.handle(NAME, self.CONFIG, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG, mock.Mock(), []) assert m_sman_cli.call_count == 1 assert "System is already registered" in caplog.text @@ -71,7 +72,7 @@ def test_simple_registration( " 12345678-abde-abcde-1234-1234567890abc" ) m_sman_cli.side_effect = [subp.ProcessExecutionError, (reg, "bar")] - cc_rh_subscription.handle(NAME, self.CONFIG, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG, mock.Mock(), []) assert mock.call(["identity"]) in m_sman_cli.call_args_list assert ( mock.call( @@ -106,7 +107,7 @@ def test_update_repos_disable_with_none( enable_repo_key = "enable_repo".replace("_", variable_name_separator) disable_repo_key = "disable_repo".replace("_", variable_name_separator) - cfg["rh_subscription"].update( + cast(dict, cfg["rh_subscription"]).update( {enable_repo_key: ["repo1"], disable_repo_key: None} ) mysm = cc_rh_subscription.SubscriptionManager(cfg) @@ -149,7 +150,7 @@ def test_full_registration(self, m_sman_cli, caplog, mocker): # on the host running the tests mocker.patch("shutil.rmtree") - cc_rh_subscription.handle(NAME, self.CONFIG_FULL, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_FULL, mock.Mock(), []) assert m_sman_cli.call_count == 10 for call in call_lists: assert mock.call(call) in m_sman_cli.call_args_list @@ -225,13 +226,15 @@ def test_no_password(self, m_sman_cli): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_NO_PASSWORD, None, []) + cc_rh_subscription.handle( + NAME, self.CONFIG_NO_PASSWORD, mock.Mock(), [] + ) assert m_sman_cli.call_count == 0 def test_no_org(self, m_sman_cli, caplog): """Attempt to register without the org key/value.""" m_sman_cli.side_effect = [subp.ProcessExecutionError] - cc_rh_subscription.handle(NAME, self.CONFIG_NO_KEY, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_NO_KEY, mock.Mock(), []) m_sman_cli.assert_called_with(["identity"]) assert m_sman_cli.call_count == 1 self.assert_logged_warnings( @@ -272,7 +275,7 @@ def test_service_level_without_auto( subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, auto_attach_cfg, None, []) + cc_rh_subscription.handle(NAME, auto_attach_cfg, mock.Mock(), []) assert m_sman_cli.call_count == 1 self.assert_logged_warnings( warnings, @@ -287,7 +290,7 @@ def test_pool_not_a_list(self, m_sman_cli, caplog): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_BADPOOL, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_BADPOOL, mock.Mock(), []) assert m_sman_cli.call_count == 2 self.assert_logged_warnings( ( @@ -305,7 +308,7 @@ def test_repo_not_a_list(self, m_sman_cli, caplog): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_BADREPO, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_BADREPO, mock.Mock(), []) assert m_sman_cli.call_count == 2 self.assert_logged_warnings( ( @@ -329,7 +332,7 @@ def test_bad_release_version(self, m_delete_pm_cache, m_sman_cli, caplog): subp.ProcessExecutionError, ] cc_rh_subscription.handle( - NAME, self.CONFIG_BAD_RELEASE_VERSION, None, [] + NAME, self.CONFIG_BAD_RELEASE_VERSION, mock.Mock(), [] ) assert m_sman_cli.call_count == 3 assert m_delete_pm_cache.call_count == 0 @@ -362,7 +365,7 @@ def test_pm_cache_deletion_after_setting_release_version( (self.REG, "bar"), ("Release set to: 1.2Server", ""), ] - cc_rh_subscription.handle(NAME, good_release_ver_cfg, None, []) + cc_rh_subscription.handle(NAME, good_release_ver_cfg, mock.Mock(), []) # assert "rh_subscription plugin completed successfully" in caplog.text assert m_sman_cli.call_count == 3 assert m_rmtree.call_args_list == [mock.call("/var/cache/dnf")] @@ -479,8 +482,8 @@ def test_deprecated_values(self): correct python object fields """ - cfg_with_new_keys = {"rh_subscription": {}} - cfg_with_deprecated_keys = {"rh_subscription": {}} + cfg_with_new_keys: dict = {"rh_subscription": {}} + cfg_with_deprecated_keys: dict = {"rh_subscription": {}} deprecation_pairs = [ ("activation-key", "activation_key"), diff --git a/tests/unittests/config/test_cc_ubuntu_autoinstall.py b/tests/unittests/config/test_cc_ubuntu_autoinstall.py index 56534b67db9..87209cc0c19 100644 --- a/tests/unittests/config/test_cc_ubuntu_autoinstall.py +++ b/tests/unittests/config/test_cc_ubuntu_autoinstall.py @@ -96,7 +96,7 @@ def test_handle_autoinstall_cfg( ): subp.return_value = snap_list, "" cloud = get_cloud(distro="ubuntu", paths=Paths({"cloud_dir": tmpdir})) - cc_ubuntu_autoinstall.handle("name", cfg, cloud, None) + cc_ubuntu_autoinstall.handle("name", cfg, cloud, []) assert subp_calls == subp.call_args_list for log in logs: assert log in caplog.text diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py index 26e8b6f210d..fbc0d8c15b1 100644 --- a/tests/unittests/config/test_cc_users_groups.py +++ b/tests/unittests/config/test_cc_users_groups.py @@ -28,7 +28,7 @@ class TestHandleUsersGroups: def test_handle_no_cfg_creates_no_users_or_groups(self, m_user, m_group): """Test handle with no config will not create users or groups.""" - cfg = {} # merged cloud-config + cfg: dict = {} # merged cloud-config # System config defines a default user for the distro. sys_cfg = { "default_user": { @@ -38,9 +38,9 @@ def test_handle_no_cfg_creates_no_users_or_groups(self, m_user, m_group): "shell": "/bin/bash", } } - metadata = {} + metadata: dict = {} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_user.assert_not_called() m_group.assert_not_called() @@ -56,9 +56,9 @@ def test_handle_users_in_cfg_calls_create_users(self, m_user, m_group): "shell": "/bin/bash", } } - metadata = {} + metadata: dict = {} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -96,7 +96,7 @@ def test_handle_users_in_cfg_calls_create_users_on_bsd( "homedir": "/home/freebsd", } } - metadata = {} + metadata: dict = {} # patch ifconfig -a with mock.patch( "cloudinit.distros.networking.subp.subp", return_value=("", None) @@ -104,7 +104,7 @@ def test_handle_users_in_cfg_calls_create_users_on_bsd( cloud = get_cloud( distro="freebsd", sys_cfg=sys_cfg, metadata=metadata ) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_fbsd_user.call_args_list, [ @@ -138,7 +138,7 @@ def test_users_with_ssh_redirect_user_passes_keys(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -177,7 +177,7 @@ def test_users_with_ssh_redirect_user_default_str(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -214,7 +214,7 @@ def test_users_without_home_cannot_import_ssh_keys(self, m_user, m_group): match=r"Not creating user me2. Key\(s\) ssh_import_id cannot be" " provided with no_create_home", ): - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_group.assert_not_called() def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group): @@ -241,7 +241,7 @@ def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group): match="Not creating user me2. Invalid value of ssh_redirect_user:" " snowflake. Expected values: true, default or false.", ): - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_group.assert_not_called() def test_users_with_ssh_redirect_user_default_false(self, m_user, m_group): @@ -258,7 +258,7 @@ def test_users_with_ssh_redirect_user_default_false(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -281,10 +281,10 @@ def test_users_ssh_redirect_user_and_no_default( "users": ["default", {"name": "me2", "ssh_redirect_user": True}] } # System config defines *no* default user for the distro. - sys_cfg = {} - metadata = {} # no public-keys defined + sys_cfg: dict = {} + metadata: dict = {} # no public-keys defined cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_user.assert_called_once_with("me2", default=False) m_group.assert_not_called() assert [ diff --git a/tests/unittests/config/test_cc_wireguard.py b/tests/unittests/config/test_cc_wireguard.py index b87851aaa7e..1ed35151307 100644 --- a/tests/unittests/config/test_cc_wireguard.py +++ b/tests/unittests/config/test_cc_wireguard.py @@ -4,7 +4,7 @@ import pytest -from cloudinit import subp, util +from cloudinit import cloud, subp, util from cloudinit.config import cc_wireguard from cloudinit.config.schema import ( SchemaValidationError, @@ -19,7 +19,7 @@ MIN_KERNEL_VERSION = (5, 6) -class FakeCloud: +class FakeCloud(cloud.Cloud): def __init__(self, distro): self.distro = distro @@ -39,7 +39,7 @@ def test_readiness_probe_schema_non_string_values(self): def test_suppl_schema_error_on_missing_keys(self): """ValueError raised reporting any missing required keys""" - cfg = {} + cfg: dict = {} match = ( f"Invalid wireguard interface configuration:{NL}" "Missing required wg:interfaces keys: config_path, content, name" @@ -207,8 +207,8 @@ def test_handle_no_config( self, m_maybe_install_wireguard_packages, caplog ): """When no wireguard configuration is provided, nothing happens.""" - cfg = {} - cc_wireguard.handle("wg", cfg=cfg, cloud=None, args=None) + cfg: dict = {} + cc_wireguard.handle("wg", cfg=cfg, cloud=mock.Mock(), args=[]) assert ( mock.ANY, logging.DEBUG, diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py index 5d4206310b4..7f8b52dc3c7 100644 --- a/tests/unittests/config/test_cc_yum_add_repo.py +++ b/tests/unittests/config/test_cc_yum_add_repo.py @@ -3,6 +3,7 @@ import configparser import logging import re +from unittest import mock import pytest @@ -36,7 +37,7 @@ def test_bad_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) with pytest.raises(IOError): util.load_text_file("/etc/yum.repos.d/epel_testing.repo") @@ -53,7 +54,7 @@ def test_metalink_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -87,7 +88,7 @@ def test_mirrorlist_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -121,7 +122,7 @@ def test_write_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -159,7 +160,7 @@ def test_write_config_array(self): } } } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file( "/etc/yum.repos.d/puppetlabs-products.repo" ) diff --git a/tests/unittests/config/test_cc_zypper_add_repo.py b/tests/unittests/config/test_cc_zypper_add_repo.py index b30c382a904..2698d148e8f 100644 --- a/tests/unittests/config/test_cc_zypper_add_repo.py +++ b/tests/unittests/config/test_cc_zypper_add_repo.py @@ -4,6 +4,7 @@ import glob import logging import os +from unittest import mock import pytest @@ -13,7 +14,6 @@ LOG = logging.getLogger(__name__) - ZYPP_CONF = "etc/zypp/zypp.conf" @@ -154,7 +154,7 @@ def test_handler_full_setup(self, tmp_path): root_d = str(tmp_path) os.makedirs("%s/etc/zypp/repos.d" % root_d) helpers.populate_dir(root_d, {ZYPP_CONF: "# Zypp config\n"}) - cc_zypper_add_repo.handle("zypper_add_repo", cfg, None, []) + cc_zypper_add_repo.handle("zypper_add_repo", cfg, mock.Mock(), []) cfg_out = os.path.join(root_d, ZYPP_CONF) contents = util.load_text_file(cfg_out) expected = [ diff --git a/tests/unittests/config/test_modules.py b/tests/unittests/config/test_modules.py index e4ccd9c69e6..00aa23461f3 100644 --- a/tests/unittests/config/test_modules.py +++ b/tests/unittests/config/test_modules.py @@ -5,7 +5,7 @@ import inspect import logging from pathlib import Path -from typing import List +from typing import List, cast from unittest import mock import pytest @@ -69,14 +69,17 @@ def test__is_inapplicable( self, activate_by_schema_keys, cfg, active, frequency ): module = mock.Mock() - module.meta = MetaSchema( - name="module_name", - id="cc_module_name", - title="title", - description="description", - distros=[ALL_DISTROS], - examples=["example_0", "example_1"], - frequency=frequency, + module.meta = cast( + MetaSchema, + { + "name": "module_name", + "id": "cc_module_name", + "title": "title", + "description": "description", + "distros": [ALL_DISTROS], + "examples": ["example_0", "example_1"], + "frequency": frequency, + }, ) if activate_by_schema_keys is not None: module.meta["activate_by_schema_keys"] = activate_by_schema_keys @@ -93,7 +96,7 @@ def test__is_inapplicable_examples(self, mod_name, module, example): module_details = ModuleDetails( module=module, name=mod_name, - frequency=["always"], + frequency="always", run_args=[], ) assert True is _is_active(module_details, util.load_yaml(example)) @@ -109,14 +112,17 @@ def test_run_section(self, frequency, active, caplog, mocker): mods._cached_cfg = {} raw_name = "my_module" module = mock.Mock() - module.meta = MetaSchema( - name=raw_name, - id=f"cc_{raw_name}", - title="title", - description="description", - distros=[ALL_DISTROS], - examples=["example_0", "example_1"], - frequency=frequency, + module.meta = cast( + MetaSchema, + { + "name": raw_name, + "id": f"cc_{raw_name}", + "title": "title", + "description": "description", + "distros": [ALL_DISTROS], + "examples": ["example_0", "example_1"], + "frequency": frequency, + }, ) module_details = ModuleDetails( module=module, @@ -160,7 +166,7 @@ def test_run_section_examples( module_details = ModuleDetails( module=module, name=mod_name, - frequency=["always"], + frequency="always", run_args=[], ) mocker.patch.object( @@ -192,10 +198,11 @@ def handle(name, cfg, cloud, log, args): module_details = ModuleDetails( module=module, name="mod_name", - frequency=["always"], + frequency="always", run_args=[], ) - m_cc = mods.init.cloudify.return_value + m_cc = mock.MagicMock() + cast(mock.MagicMock, mods.init.cloudify).return_value = m_cc m_cc.run.return_value = (1, "doesnotmatter") mods._run_modules([module_details]) @@ -211,7 +218,7 @@ def handle(name, cfg, cloud, log, args): "args": [], "log": mock.ANY, }, - freq=["always"], + freq="always", ) ] == m_cc.run.call_args_list diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py index a91234b0748..738598d5a5e 100644 --- a/tests/unittests/config/test_schema.py +++ b/tests/unittests/config/test_schema.py @@ -13,7 +13,7 @@ from pathlib import Path from textwrap import dedent from types import ModuleType -from typing import List +from typing import List, cast import pytest import yaml @@ -1049,10 +1049,16 @@ def test_annotated_cloudconfig_file_no_schema_errors(self): """With no schema_errors, print the original content.""" content = b"ntp:\n pools: [ntp1.pools.com]\n" _, schemamarks = load_with_marks(content) - assert content == annotated_cloudconfig_file( - content, - schemamarks=schemamarks, - schema_errors=[], + assert ( + content + == cast( + str, + annotated_cloudconfig_file( + content.decode(), + schemamarks=schemamarks, + schema_errors=[], + ), + ).encode() ) def test_annotated_cloudconfig_file_schema_annotates_and_adds_footer(self):