def setUp(self): super(TestCloudStackPasswordFetching, self).setUp() self.patches = ExitStack() self.addCleanup(self.patches.close) mod_name = MOD_PATH self.patches.enter_context(mock.patch("{0}.ec2".format(mod_name))) self.patches.enter_context(mock.patch("{0}.uhelp".format(mod_name))) default_gw = "192.201.20.0" get_latest_lease = mock.MagicMock(return_value=None) self.patches.enter_context( mock.patch(mod_name + ".get_latest_lease", get_latest_lease)) get_default_gw = mock.MagicMock(return_value=default_gw) self.patches.enter_context( mock.patch(mod_name + ".get_default_gateway", get_default_gw)) get_networkd_server_address = mock.MagicMock(return_value=None) self.patches.enter_context( mock.patch( mod_name + ".dhcp.networkd_get_option_from_leases", get_networkd_server_address, )) get_data_server = mock.MagicMock(return_value=None) self.patches.enter_context( mock.patch(mod_name + ".get_data_server", get_data_server)) self.tmp = self.tmp_dir()
def test_valid_filesystem_returns_true(self): self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1)) self.check_fs.return_value = ( mock.MagicMock(), "ext4", mock.MagicMock(), ) self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))
def test_handle_no_drivers_does_nothing(self, m_install_drivers): """If no 'drivers' key in the config, nothing should be done.""" myCloud = mock.MagicMock() myLog = mock.MagicMock() drivers.handle("ubuntu_drivers", {"foo": "bzr"}, myCloud, myLog, None) self.assertIn("Skipping module named", myLog.debug.call_args_list[0][0][0]) self.assertEqual(0, m_install_drivers.call_count)
def test_handle_no_drivers_does_nothing( self, m_install_drivers, m_debconf, cfg_accepted, install_gpgpu ): """If no 'drivers' key in the config, nothing should be done.""" myCloud = mock.MagicMock() myLog = mock.MagicMock() drivers.handle("ubuntu_drivers", {"foo": "bzr"}, myCloud, myLog, None) assert "Skipping module named" in myLog.debug.call_args_list[0][0][0] assert 0 == m_install_drivers.call_count
def test_maybe_install_ua_tools_noop_when_ua_tools_present(self, m_which): """Do nothing if ubuntu-advantage-tools already exists.""" m_which.return_value = '/usr/bin/ua' # already installed distro = mock.MagicMock() distro.update_package_sources.side_effect = RuntimeError( 'Some apt error') maybe_install_ua_tools(cloud=FakeCloud(distro)) # No RuntimeError
def test_handler_skips_empty_landscape_cloudconfig(self): """Empty landscape cloud-config section does no work.""" mycloud = get_cloud("ubuntu") mycloud.distro = mock.MagicMock() cfg = {"landscape": {}} cc_landscape.handle("notimportant", cfg, mycloud, LOG, None) self.assertFalse(mycloud.distro.install_packages.called)
def test_readurl_timeout(self, readurl_timeout, request_timeout): url = "http://hostname/path" m_response = mock.MagicMock() class FakeSession(requests.Session): @classmethod def request(cls, **kwargs): expected_kwargs = { "url": url, "allow_redirects": True, "method": "GET", "headers": { "User-Agent": "Cloud-Init/%s" % (version.version_string()) }, "timeout": request_timeout, } if request_timeout is None: expected_kwargs.pop("timeout") assert kwargs == expected_kwargs return m_response with mock.patch( M_PATH + "requests.Session", side_effect=[FakeSession()] ): response = read_file_or_url(url, timeout=readurl_timeout) assert response._response == m_response
def test_install_drivers_handles_old_ubuntu_drivers_gracefully( self, m_which, m_subp, m_tmp): """Older ubuntu-drivers versions should emit message and raise error""" tdir = self.tmp_dir() debconf_file = os.path.join(tdir, "nvidia.template") m_tmp.return_value = tdir myCloud = mock.MagicMock() def fake_subp(cmd): if cmd[0].startswith(tdir): return raise ProcessExecutionError(stderr=OLD_UBUNTU_DRIVERS_ERROR_STDERR, exit_code=2) m_subp.side_effect = fake_subp with self.assertRaises(Exception): drivers.handle("ubuntu_drivers", self.cfg_accepted, myCloud, None, None) self.assertEqual( [mock.call(["ubuntu-drivers-common"])], myCloud.distro.install_packages.call_args_list, ) self.assertEqual( [ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), mock.call(self.install_gpgpu), ], m_subp.call_args_list, ) self.assertIn( "WARNING: the available version of ubuntu-drivers is" " too old to perform requested driver installation", self.logs.getvalue(), )
def test_handle_raises_error_if_no_drivers_found( self, m_which, m_subp, m_tmp, m_debconf, caplog, tmpdir, cfg_accepted, install_gpgpu, ): """If ubuntu-drivers doesn't install any drivers, raise an error.""" tdir = tmpdir debconf_file = os.path.join(tdir, "nvidia.template") m_tmp.return_value = tdir myCloud = mock.MagicMock() m_subp.side_effect = ProcessExecutionError( stdout="No drivers found for installation.\n", exit_code=1 ) with pytest.raises(Exception): drivers.handle("ubuntu_drivers", cfg_accepted, myCloud, None, None) assert [ mock.call(drivers.X_LOADTEMPLATEFILE, debconf_file) ] == m_debconf.DebconfCommunicator().__enter__().command.call_args_list assert [ mock.call(["ubuntu-drivers-common"]) ] == myCloud.distro.install_packages.call_args_list assert [mock.call(install_gpgpu)] == m_subp.call_args_list assert ( "ubuntu-drivers found no drivers for installation" in caplog.text )
def test_happy_path_taken( self, m_which, m_subp, m_tmp, m_debconf, tmpdir, cfg_accepted, install_gpgpu, true_value, ): """Positive path test through handle. Package should be installed.""" new_config: dict = copy.deepcopy(cfg_accepted) new_config["drivers"]["nvidia"]["license-accepted"] = true_value tdir = tmpdir debconf_file = tdir.join("nvidia.template") m_tmp.return_value = tdir myCloud = mock.MagicMock() drivers.handle("ubuntu_drivers", new_config, myCloud, None, None) assert [ mock.call(drivers.X_LOADTEMPLATEFILE, debconf_file) ] == m_debconf.DebconfCommunicator().__enter__().command.call_args_list assert [ mock.call(["ubuntu-drivers-common"]) ] == myCloud.distro.install_packages.call_args_list assert [mock.call(install_gpgpu)] == m_subp.call_args_list
def test_handle_raises_error_if_no_drivers_found(self, m_which, m_subp, m_tmp): """If ubuntu-drivers doesn't install any drivers, raise an error.""" tdir = self.tmp_dir() debconf_file = os.path.join(tdir, "nvidia.template") m_tmp.return_value = tdir myCloud = mock.MagicMock() def fake_subp(cmd): if cmd[0].startswith(tdir): return raise ProcessExecutionError( stdout="No drivers found for installation.\n", exit_code=1) m_subp.side_effect = fake_subp with self.assertRaises(Exception): drivers.handle("ubuntu_drivers", self.cfg_accepted, myCloud, None, None) self.assertEqual( [mock.call(["ubuntu-drivers-common"])], myCloud.distro.install_packages.call_args_list, ) self.assertEqual( [ mock.call(AnyTempScriptAndDebconfFile(tdir, debconf_file)), mock.call(self.install_gpgpu), ], m_subp.call_args_list, ) self.assertIn( "ubuntu-drivers found no drivers for installation", self.logs.getvalue(), )
def test_handler_installs_client_and_creates_config_file(self): """Write landscape client.conf and install landscape-client.""" mycloud = get_cloud('ubuntu') cfg = {'landscape': {'client': {}}} expected = { 'client': { 'log_level': 'info', 'url': 'https://landscape.canonical.com/message-system', 'ping_url': 'http://landscape.canonical.com/ping', 'data_path': '/var/lib/landscape/client' } } mycloud.distro = mock.MagicMock() wrap_and_call( 'cloudinit.config.cc_landscape', { 'LSC_CLIENT_CFG_FILE': { 'new': self.conf }, 'LS_DEFAULT_FILE': { 'new': self.default_file } }, cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None) self.assertEqual([mock.call('landscape-client')], mycloud.distro.install_packages.call_args) self.assertEqual(expected, dict(ConfigObj(self.conf))) self.assertIn('Wrote landscape config file to {0}'.format(self.conf), self.logs.getvalue()) default_content = util.load_file(self.default_file) self.assertEqual('RUN=1\n', default_content)
def test_install_drivers_rejects_invalid_config( self, m_debconf, cfg_accepted, install_gpgpu ): """install_drivers should raise TypeError if not given a config dict""" pkg_install = mock.MagicMock() with pytest.raises(TypeError, match=".*expected dict.*"): drivers.install_drivers("mystring", pkg_install_func=pkg_install) assert 0 == pkg_install.call_count
def test_maybe_install_ua_tools_happy_path(self, m_which): """maybe_install_ua_tools installs ubuntu-advantage-tools.""" m_which.return_value = None distro = mock.MagicMock() # No errors raised maybe_install_ua_tools(cloud=FakeCloud(distro)) distro.update_package_sources.assert_called_once_with() distro.install_packages.assert_called_once_with( ['ubuntu-advantage-tools'])
def test_handle_inert( self, m_which, m_subp, m_debconf, cfg_accepted, install_gpgpu, config ): """Helper to reduce repetition when testing negative cases""" myCloud = mock.MagicMock() drivers.handle("ubuntu_drivers", config, myCloud, None, None) assert 0 == myCloud.distro.install_packages.call_count assert 0 == m_subp.call_count
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, mock.MagicMock(), None) self.assertEqual(1, m_write_file.call_count) args, _ = m_write_file.call_args self.assertEqual(cc_apt_pipelining.DEFAULT_FILE, args[0]) self.assertIn('Pipeline-Depth "0"', args[1])
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, mock.MagicMock(), None) assert 1 == m_write_file.call_count args, _ = m_write_file.call_args assert cc_apt_pipelining.DEFAULT_FILE == args[0] assert 'Pipeline-Depth "0"' in args[1]
def test_puppet_config_installs_puppet_on_true(self, m_subp, _): """Cloud-config with 'puppet' key installs when 'install' is True.""" self.cloud.distro = mock.MagicMock() cfg = {'puppet': {'install': True}} cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None) self.assertEqual([mock.call(('puppet', None))], self.cloud.distro.install_packages.call_args_list)
def test_puppet_config_installs_puppet_version(self, m_subp, _): """Cloud-config 'puppet' configuration can specify a version.""" self.cloud.distro = mock.MagicMock() cfg = {'puppet': {'version': '3.8'}} cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None) self.assertEqual([mock.call(('puppet', '3.8'))], self.cloud.distro.install_packages.call_args_list)
def test_empty_puppet_config_installs_puppet(self, m_subp, m_auto): """Cloud-config empty 'puppet' configuration installs latest puppet.""" self.cloud.distro = mock.MagicMock() cfg = {'puppet': {}} cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None) self.assertEqual([mock.call(('puppet', None))], self.cloud.distro.install_packages.call_args_list)
def test_ntp_install_no_op_with_empty_pkg_list(self, mock_subp): """ntp_install_client runs install_func with empty list""" mock_subp.which.return_value = None # check_exe not found install_func = mock.MagicMock() cc_ntp.install_ntp_client(install_func, packages=[], check_exe='timesyncd') install_func.assert_called_once_with([])
def test_puppet_config_installs_puppet_aio(self, m_subp, m_aio, _): """Cloud-config with 'puppet' key installs when 'install_type' is 'aio'.""" self.cloud.distro = mock.MagicMock() cfg = {'puppet': {'install': True, 'install_type': 'aio'}} cc_puppet.handle('notimportant', cfg, self.cloud, LOG, None) m_aio.assert_called_with(cc_puppet.AIO_INSTALL_URL, None, None, True)
def test_collect_logs_includes_optional_userdata(self, m_getuid): """collect-logs include userdata when --include-userdata is set.""" m_getuid.return_value = 0 log1 = self.tmp_path('cloud-init.log', self.new_root) write_file(log1, 'cloud-init-log') log2 = self.tmp_path('cloud-init-output.log', self.new_root) write_file(log2, 'cloud-init-output-log') userdata = self.tmp_path('user-data.txt', self.new_root) write_file(userdata, 'user-data') ensure_dir(self.run_dir) write_file(self.tmp_path('results.json', self.run_dir), 'results') write_file(self.tmp_path(INSTANCE_JSON_SENSITIVE_FILE, self.run_dir), 'sensitive') output_tarfile = self.tmp_path('logs.tgz') date = datetime.utcnow().date().strftime('%Y-%m-%d') date_logdir = 'cloud-init-logs-{0}'.format(date) version_out = '/usr/bin/cloud-init 18.2fake\n' expected_subp = { ('dpkg-query', '--show', "-f=${Version}\n", 'cloud-init'): '0.7fake', ('cloud-init', '--version'): version_out, ('dmesg',): 'dmesg-out\n', ('journalctl', '--boot=0', '-o', 'short-precise'): 'journal-out\n', ('tar', 'czvf', output_tarfile, date_logdir): '' } def fake_subp(cmd): cmd_tuple = tuple(cmd) if cmd_tuple not in expected_subp: raise AssertionError( 'Unexpected command provided to subp: {0}'.format(cmd)) if cmd == ['tar', 'czvf', output_tarfile, date_logdir]: subp(cmd) # Pass through tar cmd so we can check output return expected_subp[cmd_tuple], '' fake_stderr = mock.MagicMock() wrap_and_call( 'cloudinit.cmd.devel.logs', {'subp': {'side_effect': fake_subp}, 'sys.stderr': {'new': fake_stderr}, 'CLOUDINIT_LOGS': {'new': [log1, log2]}, 'CLOUDINIT_RUN_DIR': {'new': self.run_dir}, 'USER_DATA_FILE': {'new': userdata}}, logs.collect_logs, output_tarfile, include_userdata=True) # unpack the tarfile and check file contents subp(['tar', 'zxvf', output_tarfile, '-C', self.new_root]) out_logdir = self.tmp_path(date_logdir, self.new_root) self.assertEqual( 'user-data', load_file(os.path.join(out_logdir, 'user-data.txt'))) self.assertEqual( 'sensitive', load_file(os.path.join(out_logdir, 'run', 'cloud-init', INSTANCE_JSON_SENSITIVE_FILE))) fake_stderr.write.assert_any_call('Wrote %s\n' % output_tarfile)
def test_ntp_install_not_needed(self, mock_subp): """ntp_install_client doesn't install when check_exe is found.""" client = 'chrony' mock_subp.which.return_value = [client] # check_exe found. install_func = mock.MagicMock() cc_ntp.install_ntp_client(install_func, packages=[client], check_exe=client) install_func.assert_not_called()
def test_ntp_install(self, mock_subp): """ntp_install_client runs install_func when check_exe is absent.""" mock_subp.which.return_value = None # check_exe not found. install_func = mock.MagicMock() cc_ntp.install_ntp_client(install_func, packages=['ntpx'], check_exe='ntpdx') mock_subp.which.assert_called_with('ntpdx') install_func.assert_called_once_with(['ntpx'])
def test_maybe_install_squashfuse_happy_path(self, m_container): """maybe_install_squashfuse logs and raises package install errors.""" m_container.return_value = True distro = mock.MagicMock() # No errors raised maybe_install_squashfuse(cloud=FakeCloud(distro)) self.assertEqual([mock.call()], distro.update_package_sources.call_args_list) self.assertEqual([mock.call(['squashfuse'])], distro.install_packages.call_args_list)
def test_maybe_install_ua_tools_raises_update_errors(self, m_which): """maybe_install_ua_tools logs and raises apt update errors.""" m_which.return_value = None distro = mock.MagicMock() distro.update_package_sources.side_effect = RuntimeError( "Some apt error") with self.assertRaises(RuntimeError) as context_manager: maybe_install_ua_tools(cloud=FakeCloud(distro)) self.assertEqual("Some apt error", str(context_manager.exception)) self.assertIn("Package update failed\nTraceback", self.logs.getvalue())
def test_puppet_config_installs_puppet_version(self, m_subp, _): """Cloud-config 'puppet' configuration can specify a version.""" self.cloud.distro = mock.MagicMock() cfg = {"puppet": {"version": "3.8"}} cc_puppet.handle("notimportant", cfg, self.cloud, LOG, None) self.assertEqual( [mock.call(("puppet", "3.8"))], self.cloud.distro.install_packages.call_args_list, )
def test_maybe_install_squashfuse_raises_update_errors(self, m_container): """maybe_install_squashfuse logs and raises package update errors.""" m_container.return_value = True distro = mock.MagicMock() distro.update_package_sources.side_effect = RuntimeError( 'Some apt error') with self.assertRaises(RuntimeError) as context_manager: maybe_install_squashfuse(cloud=FakeCloud(distro)) self.assertEqual('Some apt error', str(context_manager.exception)) self.assertIn('Package update failed\nTraceback', self.logs.getvalue())
def test_maybe_install_ua_raises_install_errors(self, m_which): """maybe_install_ua_tools logs and raises package install errors.""" m_which.return_value = None distro = mock.MagicMock() distro.update_package_sources.return_value = None distro.install_packages.side_effect = RuntimeError( 'Some install error') with self.assertRaises(RuntimeError) as context_manager: maybe_install_ua_tools(cloud=FakeCloud(distro)) self.assertEqual('Some install error', str(context_manager.exception)) self.assertIn('Failed to install ubuntu-advantage-tools\n', self.logs.getvalue())