def test_config_sections_from_home_base_config(self, mock_Cli): cli = Mock() cli.get_global_args.return_value = {} mock_Cli.return_value = cli with patch.dict('os.environ', {'HOME': '../data/kiwi_config/ok'}): runtime_config = RuntimeConfig(reread=True) assert runtime_config.get_xz_options() == ['-a', '-b', 'xxx'] assert runtime_config.is_obs_public() is True assert runtime_config.get_bundle_compression() is True assert runtime_config.get_obs_download_server_url() == \ 'http://example.com' assert runtime_config.get_obs_api_server_url() == \ 'https://api.example.com' assert runtime_config.get_container_compression() is None assert runtime_config.get_iso_tool_category() == 'cdrtools' assert runtime_config.get_oci_archive_tool() == 'umoci' assert runtime_config.get_package_changes() is True assert runtime_config.get_disabled_runtime_checks() == [ 'check_dracut_module_for_oem_install_in_package_list', 'check_container_tool_chain_installed' ] assert runtime_config.get_obs_api_credentials() == [{ 'user_name': 'user_credentials' }]
class TestRuntimeConfig: def setup(self): with patch.dict('os.environ', {'HOME': '../data'}): self.runtime_config = RuntimeConfig() # pretend that none of the runtime config files exist, even if they do # (e.g. the system wide config file in /etc/kiwi.yml) # => this will give us the defaults with patch('os.path.exists', return_value=False): self.default_runtime_config = RuntimeConfig() @patch('os.path.exists') @patch('yaml.safe_load') def test_reading_system_wide_config_file(self, mock_yaml, mock_exists): exists_call_results = [True, False] def os_path_exists(config): return exists_call_results.pop() mock_exists.side_effect = os_path_exists with patch('builtins.open') as m_open: self.runtime_config = RuntimeConfig() m_open.assert_called_once_with('/etc/kiwi.yml', 'r') def test_invalid_yaml_format(self): self.runtime_config.config_data = {'xz': None} with raises(KiwiRuntimeConfigFormatError): self.runtime_config.get_xz_options() def test_get_xz_options(self): assert self.runtime_config.get_xz_options() == ['-a', '-b', 'xxx'] def test_is_obs_public(self): assert self.runtime_config.is_obs_public() is True def test_get_bundle_compression(self): assert self.runtime_config.get_bundle_compression() is True def test_get_bundle_compression_default(self): assert self.default_runtime_config.get_bundle_compression( default=True) is True assert self.default_runtime_config.get_bundle_compression( default=False) is False def test_is_obs_public_default(self): assert self.default_runtime_config.is_obs_public() is True def test_get_obs_download_server_url(self): assert self.runtime_config.get_obs_download_server_url() == \ 'http://example.com' def test_get_obs_download_server_url_default(self): assert self.default_runtime_config.get_obs_download_server_url() == \ Defaults.get_obs_download_server_url() def test_get_container_compression(self): assert self.runtime_config.get_container_compression() is None def test_get_container_compression_default(self): assert self.default_runtime_config.get_container_compression() == 'xz' @patch.object(RuntimeConfig, '_get_attribute') @patch('kiwi.logger.log.warning') def test_get_container_compression_invalid(self, mock_warning, mock_get_attribute): mock_get_attribute.return_value = 'foo' assert self.runtime_config.get_container_compression() == 'xz' mock_warning.assert_called_once_with( 'Skipping invalid container compression: foo') @patch.object(RuntimeConfig, '_get_attribute') def test_get_container_compression_xz(self, mock_get_attribute): mock_get_attribute.return_value = 'xz' assert self.runtime_config.get_container_compression() == 'xz' def test_get_iso_tool_category(self): assert self.runtime_config.get_iso_tool_category() == 'cdrtools' def test_get_iso_tool_category_default(self): assert self.default_runtime_config.get_iso_tool_category() == 'xorriso' @patch.object(RuntimeConfig, '_get_attribute') @patch('kiwi.logger.log.warning') def test_get_iso_tool_category_invalid(self, mock_warning, mock_get_attribute): mock_get_attribute.return_value = 'foo' assert self.runtime_config.get_iso_tool_category() == 'xorriso' mock_warning.assert_called_once_with( 'Skipping invalid iso tool category: foo') def test_get_oci_archive_tool(self): assert self.runtime_config.get_oci_archive_tool() == 'umoci' def test_get_oci_archive_tool_default(self): assert self.default_runtime_config.get_oci_archive_tool() == 'umoci' def test_get_disabled_runtime_checks(self): assert self.runtime_config.get_disabled_runtime_checks() == [ 'check_dracut_module_for_oem_install_in_package_list', 'check_container_tool_chain_installed' ]
class CliTask: """ Base class for all task classes, loads the task and provides the interface to the command options and the XML description Attributes * :attr:`should_perform_task_setup` Indicates if the task should perform the setup steps which covers the following task configurations: * setup debug level * setup logfile * setup color output """ def __init__(self, should_perform_task_setup=True): self.cli = Cli() # initialize runtime checker self.runtime_checker = None # initialize runtime configuration self.runtime_config = RuntimeConfig() # help requested self.cli.show_and_exit_on_help_request() # load/import task module self.task = self.cli.load_command() # get command specific args self.command_args = self.cli.get_command_args() # get global args self.global_args = self.cli.get_global_args() # initialize generic runtime check dicts self.checks_before_command_args = { 'check_minimal_required_preferences': [], 'check_efi_mode_for_disk_overlay_correctly_setup': [], 'check_initrd_selection_required': [], 'check_boot_description_exists': [], 'check_consistent_kernel_in_boot_and_system_image': [], 'check_container_tool_chain_installed': [], 'check_volume_setup_defines_reserved_labels': [], 'check_volume_setup_defines_multiple_fullsize_volumes': [], 'check_volume_setup_has_no_root_definition': [], 'check_volume_label_used_with_lvm': [], 'check_xen_uniquely_setup_as_server_or_guest': [], 'check_mediacheck_installed': [], 'check_dracut_module_for_live_iso_in_package_list': [], 'check_dracut_module_for_disk_overlay_in_package_list': [], 'check_dracut_module_for_disk_oem_in_package_list': [], 'check_dracut_module_for_oem_install_in_package_list': [], 'check_architecture_supports_iso_firmware_setup': [], 'check_appx_naming_conventions_valid': [], 'check_syslinux_installed_if_isolinux_is_used': [], 'check_image_type_unique': [] } self.checks_after_command_args = { 'check_repositories_configured': [], 'check_image_include_repos_publicly_resolvable': [] } if should_perform_task_setup: # set log level if self.global_args['--debug']: log.setLogLevel(logging.DEBUG) else: log.setLogLevel(logging.INFO) # set log file if self.global_args['--logfile']: log.set_logfile(self.global_args['--logfile']) if self.global_args['--color-output']: log.set_color_format() def load_xml_description(self, description_directory): """ Load, upgrade, validate XML description Attributes * :attr:`xml_data` instance of XML data toplevel domain (image), stateless data * :attr:`config_file` used config file path * :attr:`xml_state` Instance of XMLState, stateful data """ log.info('Loading XML description') config_file = description_directory + '/config.xml' if not os.path.exists(config_file): # alternative config file lookup location config_file = description_directory + '/image/config.xml' if not os.path.exists(config_file): # glob config file search, first match wins glob_match = description_directory + '/*.kiwi' for kiwi_file in sorted(glob.iglob(glob_match)): config_file = kiwi_file break if not os.path.exists(config_file): raise KiwiConfigFileNotFound('no XML description found in %s' % description_directory) self.description = XMLDescription(config_file) self.xml_data = self.description.load() self.config_file = config_file.replace('//', '/') self.xml_state = XMLState(self.xml_data, self.global_args['--profile'], self.global_args['--type']) log.info('--> loaded %s', self.config_file) if self.xml_state.build_type: log.info('--> Selected build type: %s', self.xml_state.get_build_type_name()) if self.xml_state.profiles: log.info('--> Selected profiles: %s', ','.join(self.xml_state.profiles)) self.runtime_checker = RuntimeChecker(self.xml_state) def quadruple_token(self, option): """ Helper method for commandline options of the form --option a,b,c,d Make sure to provide a common result for option values which separates the information in a comma separated list of values :return: common option value representation :rtype: str """ tokens = option.split(',', 3) return [ self._pop_token(tokens) if len(tokens) else None for _ in range(0, 4) ] def sextuple_token(self, option): """ Helper method for commandline options of the form --option a,b,c,d,e,f Make sure to provide a common result for option values which separates the information in a comma separated list of values :return: common option value representation :rtype: str """ tokens = option.split(',', 5) return [ self._pop_token(tokens) if len(tokens) else None for _ in range(0, 6) ] def run_checks(self, checks): """ This method runs the given runtime checks excluding the ones disabled in the runtime configuration file. :param dict checks: A dictionary with the runtime method names as keys and their arguments list as the values. """ exclude_list = self.runtime_config.get_disabled_runtime_checks() if self.runtime_checker is not None: for method, args in { key: value for key, value in checks.items() if key not in exclude_list }.items(): attrgetter(method)(self.runtime_checker)(*args) def _pop_token(self, tokens): token = tokens.pop(0) if len(token) > 0 and token == 'true': return True elif len(token) > 0 and token == 'false': return False else: return token