From 2b3b5b326475b37d6810c753dee82e974786ffb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Wed, 9 Sep 2026 22:13:38 +0200 Subject: [PATCH] Fix passing kiwi options For the typer cli, fix how kiwi options are passed to the commandline. --- kiwi_stackbuild_plugin/cli.py | 21 +-- .../tasks/system_stackbuild.py | 81 ++++++----- test/unit/tasks/system_stackbuild_test.py | 136 ++---------------- 3 files changed, 63 insertions(+), 175 deletions(-) diff --git a/kiwi_stackbuild_plugin/cli.py b/kiwi_stackbuild_plugin/cli.py index a701776..df4d04e 100644 --- a/kiwi_stackbuild_plugin/cli.py +++ b/kiwi_stackbuild_plugin/cli.py @@ -16,10 +16,9 @@ # along with kiwi-stackbuild. If not, see # import typer -import itertools from pathlib import Path from typing import ( - Annotated, Optional, List, Union, no_type_check + Annotated, Optional, List, no_type_check ) typers = { @@ -53,23 +52,7 @@ def kiwi( option. """ Cli = ctx.obj - args = ctx.args - for option in list(set(args)): - if type(option) is not str or not option.startswith('-'): - continue - k: List[Union[str, List]] = [option] - v = [] - indexes = [n for n, x in enumerate(args) if x == option] - if len(indexes) > 1: - for index in indexes: - v.append(args[index + 1]) - for index in sorted(indexes, reverse=True): - del args[index + 1] - del args[index] - k.append(v) - args += k - Cli.subcommand_args['stackbuild']['system_build_or_create'] = \ - dict(itertools.zip_longest(*[iter(args)] * 2)) + Cli.subcommand_args['stackbuild']['system_build_or_create'] = ctx.args Cli.global_args['command'] = 'stackbuild' Cli.global_args['system'] = True Cli.cli_ok = True diff --git a/kiwi_stackbuild_plugin/tasks/system_stackbuild.py b/kiwi_stackbuild_plugin/tasks/system_stackbuild.py index 55e4b77..95d90d7 100644 --- a/kiwi_stackbuild_plugin/tasks/system_stackbuild.py +++ b/kiwi_stackbuild_plugin/tasks/system_stackbuild.py @@ -65,9 +65,7 @@ import logging from unittest.mock import patch from docopt import docopt -from typing import ( - Dict, List -) +from typing import List import kiwi.tasks.system_build import kiwi.tasks.system_create @@ -182,7 +180,7 @@ def process(self) -> None: def _validate_kiwi_create_command( self, kiwi_create_command: List[str] ) -> List[str]: - if self.command_args.get(''): + if self.command_args.get(''): # pragma: nocover # construct create command from docopt command line kiwi_create_command += self.command_args.get( '' @@ -200,19 +198,44 @@ def _validate_kiwi_create_command( kiwi.tasks.system_create.__doc__, argv=kiwi_create_command ) + kiwi_command = [ + 'system', 'create' + ] + for option, value in validated_create_command.items(): + if option.startswith('-') and value: + if isinstance(value, bool): + kiwi_command.append(option) + elif isinstance(value, str): + kiwi_command.extend([option, value]) + elif isinstance(value, list): + for element in value: + kiwi_command.extend([option, element]) else: - validated_create_command = \ - self.command_args.get('system_build_or_create') + kiwi_command = [ + 'system', 'create' + ] + self.command_args.get('system_build_or_create') - # rebuild kiwi create command from validated docopt parser result - return self._rebuild_kiwi_command( - validated_create_command, 'create' + # rebuild kiwi create command + final_kiwi_command = ['kiwi-ng'] + if self.global_args.get('--type'): + final_kiwi_command.append('--type') + final_kiwi_command.append(self.global_args.get('--type')) + if self.global_args.get('--profile'): + for profile in sorted(set(self.global_args.get('--profile'))): + final_kiwi_command.append('--profile') + final_kiwi_command.append(profile) + final_kiwi_command += kiwi_command + log.debug( + 'Building with:{0} {1}'.format( + os.linesep, final_kiwi_command + ) ) + return final_kiwi_command def _validate_kiwi_build_command( self, kiwi_build_command: List[str] ) -> List[str]: - if self.command_args.get(''): + if self.command_args.get(''): # pragma: nocover # construct build command from given command line kiwi_build_command += self.command_args.get( '' @@ -230,30 +253,24 @@ def _validate_kiwi_build_command( kiwi.tasks.system_build.__doc__, argv=kiwi_build_command ) + kiwi_command = [ + 'system', 'build' + ] + for option, value in validated_build_command.items(): + if option.startswith('-') and value: + if isinstance(value, bool): + kiwi_command.append(option) + elif isinstance(value, str): + kiwi_command.extend([option, value]) + elif isinstance(value, list): + for element in value: + kiwi_command.extend([option, element]) else: - validated_build_command = \ - self.command_args.get('system_build_or_create') - - # rebuild kiwi build command from validated parser result - return self._rebuild_kiwi_command( - validated_build_command, 'build' - ) + kiwi_command = [ + 'system', 'build' + ] + self.command_args.get('system_build_or_create') - def _rebuild_kiwi_command( - self, validated_options_dict: Dict, command: str - ) -> List[str]: - kiwi_command = [ - 'system', command - ] - for option, value in validated_options_dict.items(): - if option.startswith('-') and value: - if isinstance(value, bool): - kiwi_command.append(option) - elif isinstance(value, str): - kiwi_command.extend([option, value]) - elif isinstance(value, list): - for element in value: - kiwi_command.extend([option, element]) + # rebuild kiwi build command final_kiwi_command = ['kiwi-ng'] if self.global_args.get('--type'): final_kiwi_command.append('--type') diff --git a/test/unit/tasks/system_stackbuild_test.py b/test/unit/tasks/system_stackbuild_test.py index 137a0a7..57e5dd9 100644 --- a/test/unit/tasks/system_stackbuild_test.py +++ b/test/unit/tasks/system_stackbuild_test.py @@ -16,7 +16,7 @@ def setup(self): sys.argv = [ sys.argv[0], '--profile', 'a', '--profile', 'b', '--type', 'iso', 'system', 'stackbuild', - '--stash', 'name', '--target-dir', 'some-target-dir', '--', + '--stash', 'name', '--target-dir', 'some-target-dir', 'kiwi', '--signing-key', 'some-key' ] self.task = SystemStackbuildTask() @@ -32,11 +32,8 @@ def _init_command_args(self): self.task.command_args['--from-registry'] = None self.task.command_args['--target-dir'] = None self.task.command_args['--description'] = None - self.task.command_args[''] = [ - '--', '--signing-key', 'some-key' - ] - self.task.command_args[''] = [ - '--', '--signing-key', 'some-key' + self.task.command_args['system_build_or_create'] = [ + '--signing-key', 'some-key' ] @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Help') @@ -99,65 +96,11 @@ def test_process_rebuild_typer_commandline( mock_Path_create, mock_Privileges ): self._init_command_args() - self.task.command_args[''] = None - self.task.command_args[''] = None - self.task.command_args['system_build_or_create'] = { - '--root': '/some/target-dir/build/image-root', - '--target-dir': '/some/target-dir', - '--signing-key': 'some-key' - } - self.task.command_args['stackbuild'] = True - self.task.command_args['--stash'] = ['name'] - self.task.command_args['--target-dir'] = '/some/target-dir' - self.task.command_args['--from-registry'] = 'registry.uri' - mock_os_path_exists.return_value = False - mock_Command_run.return_value.output = '/podman/mount/path' - kiwi_task = Mock() - mock_SystemCreateTask.return_value = kiwi_task - self.task.process() - assert mock_Command_run.call_args_list == [ - call(['podman', 'pull', 'registry.uri/name']), - call(['podman', 'image', 'mount', 'name']), - call( - [ - 'rsync', '--archive', '--hard-links', '--xattrs', - '--acls', '--one-file-system', '--inplace', - '/podman/mount/path/', - '/some/target-dir/build/image-root' - ] - ), - call( - ['podman', 'image', 'umount', '--force', 'name'], - raise_on_error=False - ) + self.task.command_args['system_build_or_create'] = [ + '--root', '/some/target-dir/build/image-root', + '--target-dir', '/some/target-dir', + '--signing-key', 'some-key' ] - mock_SystemCreateTask.assert_called_once_with( - should_perform_task_setup=False - ) - kiwi_task.process.assert_called_once_with() - mock_patch_object.assert_called_once_with( - sys, 'argv', [ - 'kiwi-ng', '--type', 'iso', - '--profile', 'a', '--profile', 'b', - 'system', 'create', - '--root', '/some/target-dir/build/image-root', - '--target-dir', '/some/target-dir', - '--signing-key', 'some-key' - ] - ) - - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Privileges') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Path.create') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Command.run') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.SystemCreateTask') - @patch('os.path.exists') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.patch.object') - def test_process_rebuild( - self, mock_patch_object, mock_os_path_exists, - mock_SystemCreateTask, mock_Command_run, - mock_Path_create, mock_Privileges - ): - self._init_command_args() self.task.command_args['stackbuild'] = True self.task.command_args['--stash'] = ['name'] self.task.command_args['--target-dir'] = '/some/target-dir' @@ -210,67 +153,12 @@ def test_process_new_build_typer_commandline( mock_Path_create, mock_Privileges ): self._init_command_args() - self.task.command_args[''] = None - self.task.command_args[''] = None - self.task.command_args['system_build_or_create'] = { - '--description': '/path/to/kiwi/description', - '--target-dir': '/some/target-dir', - '--allow-existing-root': True, - '--signing-key': 'some-key' - } - self.task.command_args['stackbuild'] = True - self.task.command_args['--stash'] = ['name'] - self.task.command_args['--target-dir'] = '/some/target-dir' - self.task.command_args['--description'] = '/path/to/kiwi/description' - self.task.command_args['--from-registry'] = 'registry.uri' - mock_os_path_exists.return_value = False - mock_Command_run.return_value.output = '/podman/mount/path' - kiwi_task = Mock() - mock_SystemBuildTask.return_value = kiwi_task - self.task.process() - assert mock_Command_run.call_args_list == [ - call(['podman', 'pull', 'registry.uri/name']), - call(['podman', 'image', 'mount', 'name']), - call( - [ - 'rsync', '--archive', '--hard-links', '--xattrs', - '--acls', '--one-file-system', '--inplace', - '/podman/mount/path/', - '/some/target-dir/build/image-root' - ] - ), - call( - ['podman', 'image', 'umount', '--force', 'name'], - raise_on_error=False - ) + self.task.command_args['system_build_or_create'] = [ + '--description', '/path/to/kiwi/description', + '--target-dir', '/some/target-dir', + '--allow-existing-root', + '--signing-key', 'some-key' ] - mock_SystemBuildTask.assert_called_once_with( - should_perform_task_setup=False - ) - kiwi_task.process.assert_called_once_with() - mock_patch_object.assert_called_once_with( - sys, 'argv', [ - 'kiwi-ng', '--type', 'iso', - '--profile', 'a', '--profile', 'b', - 'system', 'build', - '--description', '/path/to/kiwi/description', - '--target-dir', '/some/target-dir', - '--allow-existing-root', '--signing-key', 'some-key' - ] - ) - - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Privileges') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Path.create') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.Command.run') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.SystemBuildTask') - @patch('os.path.exists') - @patch('kiwi_stackbuild_plugin.tasks.system_stackbuild.patch.object') - def test_process_new_build( - self, mock_patch_object, mock_os_path_exists, - mock_SystemBuildTask, mock_Command_run, - mock_Path_create, mock_Privileges - ): - self._init_command_args() self.task.command_args['stackbuild'] = True self.task.command_args['--stash'] = ['name'] self.task.command_args['--target-dir'] = '/some/target-dir'