def test_wrong_b64_content(self): tmp = self._get_tempfile() code = textwrap.dedent(""" write_files: - content: l encoding: b64 path: {} """.format(tmp)) with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfigplugins.' 'write_files') as snatcher: self.plugin.process_non_multipart(code) self.assertTrue( snatcher.output[0].startswith("Fail to decode base64 content."))
def test__http_request(self, mock_urllib_request): mock_urllib_request.Request.return_value = mock.sentinel.request with testutils.LogSnatcher('cloudbaseinit.metadata.services.' 'cloudstack') as snatcher: self._service._http_request(mock.sentinel.url) expected_logging = [ 'Getting metadata from: %s' % mock.sentinel.url, ] mock_urllib_request.Request.assert_called_once_with(mock.sentinel.url) mock_urllib_request.urlopen.assert_called_once_with( mock.sentinel.request) mock_urlopen = mock_urllib_request.urlopen.return_value mock_urlopen.read.assert_called_once_with() self.assertEqual(expected_logging, snatcher.output)
def test_set_metadata_password_already_set(self): mock_service = mock.MagicMock() mock_service.is_password_set = True with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'setuserpassword') as snatcher: response = self._setpassword_plugin._set_metadata_password( mock.sentinel.fake_password, mock_service) self.assertTrue(response) expected_logging = [ 'User\'s password already set in the ' 'instance metadata and it cannot be ' 'updated in the instance metadata' ] self.assertEqual(expected_logging, snatcher.output)
def _test_execute(self, mock_post_create_user, mock_create_user, mock_get_password, mock_get_os_utils, user_exists=True, group_adding_works=True): shared_data = {} mock_osutils = mock.MagicMock() mock_service = mock.MagicMock() mock_get_password.return_value = 'password' mock_get_os_utils.return_value = mock_osutils mock_osutils.user_exists.return_value = user_exists if not group_adding_works: mock_osutils.add_user_to_local_group.side_effect = Exception with testutils.LogSnatcher("cloudbaseinit.plugins.common." "createuser") as snatcher: response = self._create_user.execute(mock_service, shared_data) mock_get_os_utils.assert_called_once_with() mock_get_password.assert_called_once_with(mock_osutils) mock_osutils.user_exists.assert_called_once_with(CONF.username) if user_exists: mock_osutils.set_user_password.assert_called_once_with( CONF.username, 'password') expected_logging = [ "Setting password for existing user \"%s\"" % CONF.username ] else: mock_create_user.assert_called_once_with(CONF.username, 'password', mock_osutils) expected_logging = [ "Creating user \"%s\" and setting password" % CONF.username ] mock_post_create_user.assert_called_once_with(CONF.username, 'password', mock_osutils) self.assertEqual(expected_logging, snatcher.output[:1]) if not group_adding_works: failed = snatcher.output[1].startswith( "Cannot add user to group \"Admins\"") self.assertTrue(failed) mock_osutils.add_user_to_local_group.assert_called_once_with( CONF.username, CONF.groups[0]) self.assertEqual((base.PLUGIN_EXECUTION_DONE, False), response)
def _test_configure_host(self, mock_get_metadata_service, mock_get_os_utils, mock_load_plugins, mock_get_version, mock_check_latest_version, mock_handle_plugins_stage, expected_logging, version, name, instance_id, reboot=True): mock_get_version.return_value = version fake_service = mock.MagicMock() fake_plugin = mock.MagicMock() mock_load_plugins.return_value = [fake_plugin] mock_get_os_utils.return_value = self.osutils mock_get_metadata_service.return_value = fake_service fake_service.get_name.return_value = name fake_service.get_instance_id.return_value = instance_id mock_handle_plugins_stage.side_effect = [False, False, True] stages = [ base.PLUGIN_STAGE_PRE_NETWORKING, base.PLUGIN_STAGE_PRE_METADATA_DISCOVERY, base.PLUGIN_STAGE_MAIN ] stage_calls_list = [[self.osutils, None, None, stage] for stage in stages] stage_calls_list[2][1] = fake_service stage_calls_list[2][2] = instance_id stage_calls = [mock.call(*args) for args in stage_calls_list] with testutils.LogSnatcher('cloudbaseinit.init') as snatcher: self._init.configure_host() self.assertEqual(expected_logging, snatcher.output) mock_check_latest_version.assert_called_once_with() if CONF.reset_service_password: self.osutils.reset_service_password.assert_called_once_with() self.osutils.wait_for_boot_completion.assert_called_once_with() mock_get_metadata_service.assert_called_once_with() fake_service.get_name.assert_called_once_with() fake_service.get_instance_id.assert_called_once_with() fake_service.cleanup.assert_called_once_with() mock_handle_plugins_stage.assert_has_calls(stage_calls) if reboot: self.osutils.reboot.assert_called_once_with() else: self.assertFalse(self.osutils.reboot.called)
def test_execute_hostname_to_be_truncated(self): new_hostname = 'x' * (hostname.NETBIOS_HOST_NAME_MAX_LEN + 1) expected_new_hostname = new_hostname[:-1] with testutils.LogSnatcher('cloudbaseinit.utils.' 'hostname') as snatcher: self._test_set_hostname( new_hostname=new_hostname, expected_new_hostname=expected_new_hostname) expected = [ 'Truncating host name for Netbios compatibility. ' 'Old name: {0}, new name: {1}'.format(new_hostname, expected_new_hostname), 'Setting hostname: xxxxxxxxxxxxxxx' ] self.assertEqual(expected, snatcher.output)
def test_processing_plugin_failed(self, mock_write_files): mock_write_files.side_effect = ValueError code = textwrap.dedent(""" write_files: - content: NDI= path: random_cloudbaseinit_test """) with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfig') as snatcher: self.plugin.process_non_multipart(code) self.assertTrue(snatcher.output[0].startswith( "Processing plugin write_files failed")) self.assertTrue(snatcher.output[0].endswith("ValueError")) self.assertFalse(os.path.exists('random_cloudbaseinit_test'))
def setUp(self): self.mock_wmi = mock.MagicMock() self._moves_mock = mock.MagicMock() patcher = mock.patch.dict( "sys.modules", { "wmi": self.mock_wmi, "six.moves": self._moves_mock } ) patcher.start() self.addCleanup(patcher.stop) self._winreg_mock = self._moves_mock.winreg self._azureguestagent = importlib.import_module(MODPATH) self._azureagentplugin = self._azureguestagent.AzureGuestAgentPlugin() self.snatcher = testutils.LogSnatcher(MODPATH)
def test_missing_required_keys(self): code = textwrap.dedent(""" write_files: - c0ntent: NDI= """) expected_return = [ "Missing required keys from file " "information {'c0ntent': 'NDI='}" ] with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfigplugins.' 'write_files') as snatcher: self.plugin.process_non_multipart(code) self.assertEqual(expected_return, snatcher.output)
def test_exec_plugin_exception_occurs(self): fake_name = 'fake name' mock_plugin = mock.MagicMock() mock_plugin.get_name.return_value = fake_name mock_plugin.execute.side_effect = Exception expected_logging = [ "Executing plugin 'fake name'", "plugin 'fake name' failed with error ''" ] with testutils.LogSnatcher('cloudbaseinit.init') as snatcher: self._init._exec_plugin(osutils=self.osutils, service='fake service', plugin=mock_plugin, instance_id='fake id', shared_data='shared data') self.assertEqual(expected_logging, snatcher.output[:2])
def test_process_permissions(self): for permissions in (0o644, '0644', '0o644', 420, 420.1): self.assertEqual(420, write_files._convert_permissions(permissions)) with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfigplugins.' 'write_files') as snatcher: response = write_files._convert_permissions(mock.sentinel.invalid) expected_logging = [ 'Fail to process permissions %s, assuming 420' % mock.sentinel.invalid ] self.assertEqual(expected_logging, snatcher.output) self.assertEqual(write_files.DEFAULT_PERMISSIONS, response)
def _test_execute(self, mock_get_os_utils, mock_set_metadata_password, mock_set_password, is_password_set, can_post_password, can_update_password=False): mock_service = mock.MagicMock() mock_osutils = mock.MagicMock() fake_shared_data = mock.MagicMock() fake_shared_data.get.return_value = 'fake username' mock_service.is_password_set = is_password_set mock_service.can_post_password = can_post_password mock_service.can_update_password = can_update_password mock_get_os_utils.return_value = mock_osutils mock_osutils.user_exists.return_value = True mock_set_password.return_value = 'fake password' with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'setuserpassword') as snatcher: response = self._setpassword_plugin.execute( mock_service, fake_shared_data) mock_get_os_utils.assert_called_once_with() fake_shared_data.get.assert_called_with(constants.SHARED_DATA_USERNAME, CONF.username) mock_osutils.user_exists.assert_called_once_with('fake username') mock_set_password.assert_called_once_with(mock_service, mock_osutils, 'fake username', fake_shared_data) expected_logging = [ "Password succesfully updated for user fake username", ] if can_post_password: mock_set_metadata_password.assert_called_once_with( 'fake password', mock_service) else: expected_logging.append("Cannot set the password in the metadata " "as it is not supported by this service") self.assertFalse(mock_set_metadata_password.called) if can_update_password: self.assertEqual((2, False), response) else: self.assertEqual((1, False), response) self.assertEqual(expected_logging, snatcher.output)
def _test_set_password(self, mock_get_password, mock_change_logon_behaviour, password, can_update_password, is_password_changed, max_password_length=20, injected=False): expected_password = password expected_logging = [] user = '******' mock_get_password.return_value = (password, injected) mock_service = mock.MagicMock() mock_osutils = mock.MagicMock() if not password: expected_password = "******" * CONF.user_password_length mock_osutils.generate_random_password.return_value = expected_password mock_service.can_update_password = can_update_password mock_service.is_password_changed.return_value = is_password_changed with testutils.ConfPatcher('user_password_length', max_password_length): with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'setuserpassword') as snatcher: response = self._setpassword_plugin._set_password( mock_service, mock_osutils, user, mock.sentinel.shared_data) if can_update_password and not is_password_changed: expected_logging.append('Updating password is not required.') expected_password = None if not password: expected_logging.append('Generating a random user password') if not can_update_password or is_password_changed: mock_get_password.assert_called_once_with( mock_service, mock.sentinel.shared_data) self.assertEqual(expected_password, response) self.assertEqual(expected_logging, snatcher.output) if password and can_update_password and is_password_changed: mock_change_logon_behaviour.assert_called_once_with( user, password_injected=injected)
def test__bind_dhcp_client_socket(self, mock_time_sleep): mock_socket = mock.Mock() exc = socket.error() exc.errno = 48 mock_socket.bind = mock.Mock(side_effect=exc) with testutils.LogSnatcher('cloudbaseinit.utils.dhcp') as snatcher: with self.assertRaises(socket.error): dhcp._bind_dhcp_client_socket( mock_socket, max_bind_attempts=4, bind_retry_interval=mock.sentinel.bind_retry_interval) expected_occurences = sum( 1 for item in snatcher.output if item.startswith("Retrying to bind DHCP client port in ")) self.assertEqual(3, expected_occurences)
def test_old_plugin_mapping(self, mock_load_class): with testutils.LogSnatcher('cloudbaseinit.plugins.' 'factory') as snatcher: factory.load_plugins(None) expected = [ "Old plugin module 'cloudbaseinit.plugins.windows." "localscripts.LocalScriptsPlugin' was found. " "The new name is 'cloudbaseinit.plugins.common." "localscripts.LocalScriptsPlugin'. The old name will not " "be supported starting with cloudbaseinit 1.0", ] expected_call = mock.call('cloudbaseinit.plugins.common.' 'localscripts.LocalScriptsPlugin') self.assertEqual(expected, snatcher.output) called = mock_load_class.mock_calls[0] self.assertEqual(expected_call, called)
def setUp(self): self.mock_wmi = mock.MagicMock() self._moves_mock = mock.MagicMock() patcher = mock.patch.dict( "sys.modules", { "wmi": self.mock_wmi, "six.moves": self._moves_mock } ) patcher.start() self.addCleanup(patcher.stop) rdp = importlib.import_module( "cloudbaseinit.plugins.windows.rdp") self.rdp_settings = rdp.RDPSettingsPlugin() self.rdp_post = rdp.RDPPostCertificateThumbprintPlugin() self.snatcher = testutils.LogSnatcher(MODPATH)
def test__create_user_logon_fails(self): mock_osutils = mock.Mock() mock_osutils.create_user_logon_session.side_effect = Exception with testutils.LogSnatcher('cloudbaseinit.plugins.windows.' 'createuser') as snatcher: self._create_user._create_user_logon(mock.sentinel.user_name, mock.sentinel.password, mock_osutils) mock_osutils.create_user_logon_session.assert_called_once_with( mock.sentinel.user_name, mock.sentinel.password, True) self.assertFalse(mock_osutils.close_user_logon_session.called) logging_message = ( "Cannot create a user logon session for user: \"%s\"" % mock.sentinel.user_name) self.assertTrue(snatcher.output[0].startswith(logging_message))
def test_get_password(self, mock_password_client): headers = {"DomU_Request": "send_my_password"} expected_password = "******" mock_password_client.return_value = expected_password expected_output = [ "Try to get password from the Password Server.", "The password server returned a valid password " "for the current instance." ] with testutils.LogSnatcher('cloudbaseinit.metadata.services.' 'cloudstack') as snatcher: password = self._service._get_password() mock_password_client.assert_called_once_with(headers=headers) self.assertEqual(expected_password, password) self.assertEqual(expected_output, snatcher.output)
def test_process_user(self, mock_get_os_utils, mock_create_user): fake_data = [ { 'name': 'fake_user', 'gecos': 'fake user name', 'primary_group': 'Users', 'groups': 'test', 'ssh_authorized_keys': ["test2", "test1"], 'inactive': False, 'expiredate': '2020-09-01', 'passwd': 'Passw0rd' } ] with testutils.LogSnatcher(MODPATH) as snatcher: res = self.users_plugin.process(fake_data) self.assertEqual([], snatcher.output) self.assertEqual(res, False)
def test_process_non_multipart_dont_process_x509( self, mock_execute_user_data_script): user_data = textwrap.dedent(''' -----BEGIN CERTIFICATE----- MIIC9zCCAd8CAgPoMA0GCSqGSIb3DQEBBQUAMBsxGTAXBgNVBAMUEHVidW50dUBs b2NhbGhvc3QwHhcNMTUwNjE1MTAyODUxWhcNMjUwNjEyMTAyODUxWjAbMRkwFwYD -----END CERTIFICATE----- ''').encode() with testutils.LogSnatcher('cloudbaseinit.plugins.' 'common.userdata') as snatcher: status, reboot = self._userdata._process_non_multi_part(user_data=user_data) expected_logging = ['Found X509 certificate in userdata'] self.assertFalse(mock_execute_user_data_script.called) self.assertEqual(expected_logging, snatcher.output) self.assertEqual(1, status) self.assertFalse(reboot)
def _test_process(self, mock_write_file, mock_exec_file, mock_gettempdir, mock_get_os_utils, mock_os_remove, mock_path_exists, exception=False): mock_path_exists.return_value = True fake_dir_path = os.path.join("fake", "dir") mock_osutils = mock.MagicMock() mock_part = mock.MagicMock() mock_part.get_filename.return_value = "fake_filename" mock_gettempdir.return_value = fake_dir_path mock_get_os_utils.return_value = mock_osutils fake_target = os.path.join(fake_dir_path, "fake_filename") mock_exec_file.return_value = 'fake response' if exception: mock_exec_file.side_effect = [Exception] with mock.patch( "cloudbaseinit.plugins.common.userdataplugins." "shellscript.open", mock.mock_open(), create=True): with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.' 'shellscript') as snatcher: response = self._shellscript.process(mock_part) mock_part.get_filename.assert_called_once_with() mock_write_file.assert_called_once_with( fake_target, mock_part.get_payload.return_value) mock_exec_file.assert_called_once_with(fake_target) mock_part.get_payload.assert_called_once_with(decode=True) mock_gettempdir.assert_called_once_with() if not exception: self.assertEqual('fake response', response) else: expected_logging = 'An error occurred during user_data execution' self.assertTrue(snatcher.output[0].startswith(expected_logging)) mock_os_remove.assert_called_once_with(fake_target) mock_path_exists.assert_called_once_with(fake_target)
def setUp(self): self.mock_wmi = mock.MagicMock() self._moves_mock = mock.MagicMock() patcher = mock.patch.dict( "sys.modules", { "wmi": self.mock_wmi, "six.moves": self._moves_mock, 'ctypes': mock.MagicMock(), 'ctypes.windll': mock.MagicMock(), 'ctypes.wintypes': mock.MagicMock(), 'winioctlcon': mock.MagicMock() }) patcher.start() self.addCleanup(patcher.stop) bootconfig = importlib.import_module(MODPATH) self.boot_policy_plugin = bootconfig.BootStatusPolicyPlugin() self.bcd_config = bootconfig.BCDConfigPlugin() self.snatcher = testutils.LogSnatcher(MODPATH)
def test_exec_file_no_executor(self, mock_execute_user_data_script, mock_get_command, _): mock_get_command.return_value = None with testutils.create_tempfile() as temp: with mock.patch( 'cloudbaseinit.plugins.common.userdatautils' '.open', create=True): with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'fileexecutils') as snatcher: retval = fileexecutils.exec_file(temp) expected_logging = [ 'No valid extension or header found' ' in the userdata: %s' % temp ] self.assertEqual(0, retval) self.assertEqual(expected_logging, snatcher.output)
def test_process_basic_data(self, mock_os_utils, mock_userdata): run_commands = ['echo 1', 'echo 2', ['echo', '1'], 'exit 1003'] mock_userdata.return_value = 1003 mock_utils = mock.MagicMock() mock_utils.get_default_script_exec_header.return_value = 'fake_header' mock_os_utils.return_value = mock_utils expected_logging = [ "Running cloud-config runcmd entries.", "Found 4 cloud-config runcmd entries.", ] with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfigplugins.' 'runcmd') as snatcher: result_process = self._runcmd_plugin.process(run_commands) mock_utils.get_default_script_exec_header.assert_called_with() self.assertEqual(expected_logging, snatcher.output) self.assertEqual(result_process, True)
def test_unknown_encoding(self): tmp = self._get_tempfile() code = textwrap.dedent(""" write_files: - content: NDI= path: {} permissions: '0o466' """.format(tmp)) with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdataplugins.cloudconfigplugins.' 'write_files') as snatcher: self.plugin.process_non_multipart(code) self.assertTrue(os.path.exists(tmp), "Expected path does not exist.") with open(tmp) as stream: self.assertEqual('NDI=', stream.read()) self.assertEqual(["Unknown encoding, doing nothing."], snatcher.output)
def test_parse_mime(self, mock_get_as_string, mock_message_from_string): fake_user_data = textwrap.dedent(''' -----BEGIN CERTIFICATE----- MIIDGTCCAgGgAwIBAgIJAN5fj7R5dNrMMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV BAMTFmNsb3VkYmFzZS1pbml0LWV4YW1wbGUwHhcNMTUwNDA4MTIyNDI1WhcNMjUw ''') expected_logging = ['User data content:\n%s' % fake_user_data] mock_get_as_string.return_value = fake_user_data with testutils.LogSnatcher('cloudbaseinit.plugins.common.' 'userdata') as snatcher: response = self._userdata._parse_mime(user_data=fake_user_data) mock_get_as_string.assert_called_once_with(fake_user_data) mock_message_from_string.assert_called_once_with( mock_get_as_string.return_value) self.assertEqual(response, mock_message_from_string().walk()) self.assertEqual(expected_logging, snatcher.output)
def test_delete_password(self, mock_password_client): fake_url_error = urllib.error.HTTPError(url='127.0.0.1', code=404, hdrs={}, fp=None, msg='error') fake_connection_error = OSError(10061, "Connection error") mock_password_client.side_effect = [ cloudstack.SAVED_PASSWORD, cloudstack.BAD_REQUEST, fake_url_error, fake_connection_error ] expected_output = [ [ 'Remove the password for this instance from the ' 'Password Server.', 'Removing password failed due to a connection failure.', 'Failed to remove the password from the Password Server.' ], [ 'Remove the password for this instance from the ' 'Password Server.', 'Removing password failed: 404', 'Failed to remove the password from the Password Server.' ], [ 'Remove the password for this instance from the ' 'Password Server.', 'Failed to remove the password from the Password Server.' ], [ 'Remove the password for this instance from the ' 'Password Server.', 'The password was removed from the Password Server.' ], ] expected_output_len = len(expected_output) for _ in range(expected_output_len): with testutils.LogSnatcher('cloudbaseinit.metadata.services.' 'cloudstack') as snatcher: self.assertIsNone(self._service._delete_password()) self.assertEqual(expected_output.pop(), snatcher.output) self.assertEqual(expected_output_len, mock_password_client.call_count)
def _test_load(self, mock_get_cache_data, ip, cache_data_fails=False): if cache_data_fails: mock_get_cache_data.side_effect = Exception with testutils.ConfPatcher('metadata_base_url', ip, "maas"): with testutils.LogSnatcher('cloudbaseinit.metadata.services.' 'maasservice') as snatcher: response = self._maasservice.load() if ip is not None: if not cache_data_fails: mock_get_cache_data.assert_called_once_with( '%s/meta-data/' % self._maasservice._metadata_version) self.assertTrue(response) else: expected_logging = 'Metadata not found at URL \'%s\'' % ip self.assertEqual(expected_logging, snatcher.output[-1]) else: self.assertFalse(response)
def setUp(self): self._win32com_mock = mock.MagicMock() self._ctypes_mock = mock.MagicMock() self._ctypes_util_mock = mock.MagicMock() self._win32com_client_mock = mock.MagicMock() self._pywintypes_mock = mock.MagicMock() self._module_patcher = mock.patch.dict( 'sys.modules', {'win32com': self._win32com_mock, 'ctypes': self._ctypes_mock, 'ctypes.util': self._ctypes_util_mock, 'win32com.client': self._win32com_client_mock, 'pywintypes': self._pywintypes_mock}) self._module_patcher.start() self.addCleanup(self._module_patcher.stop) self._packet_module = importlib.import_module(MODULE_PATH) self._packet_service = self._packet_module.PacketService() self.snatcher = testutils.LogSnatcher(MODULE_PATH)
def _test_is_vfat_drive(self, execute_process_value, expected_logging, expected_response): mock_osutils = mock.Mock() mock_osutils.execute_process.return_value = execute_process_value with testutils.LogSnatcher('cloudbaseinit.utils.windows.' 'vfat') as snatcher: with testutils.ConfPatcher('mtools_path', 'mtools_path'): response = vfat.is_vfat_drive(mock_osutils, mock.sentinel.drive) mdir = os.path.join(CONF.mtools_path, "mlabel.exe") mock_osutils.execute_process.assert_called_once_with( [mdir, "-i", mock.sentinel.drive, "-s"], shell=False) self.assertEqual(expected_logging, snatcher.output) self.assertEqual(expected_response, response)