Skip to content

Add typer cli interface #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions kiwi_stackbuild_plugin/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# Copyright (c) 2025 SUSE LLC. All rights reserved.
#
# This file is part of kiwi-stackbuild.
#
# kiwi-stackbuild is free software: you can redistribute it and/or modify
# it under the terms owf the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# kiwi-stackbuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with kiwi-stackbuild. If not, see <http://www.gnu.org/licenses/>
#
import typer
import itertools
from pathlib import Path
from typing import (
Annotated, Optional, List, Union, no_type_check
)

typers = {
'stackbuild': typer.Typer(
add_completion=False
),
'stash': typer.Typer(
add_completion=False
)
}

system_stackbuild = typers['stackbuild']
system_stash = typers['stash']


@no_type_check
@system_stackbuild.command(
context_settings={
'allow_extra_args': True,
'ignore_unknown_options': True
}
)
def kiwi(
ctx: typer.Context
):
"""
List of command parameters as supported by the kiwi-ng
build or create command. The information given here is passed
along to the kiwi-ng system build or the kiwi-ng system create
command depending on the presence of the --description
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.global_args['command'] = 'stackbuild'
Cli.global_args['system'] = True
Cli.cli_ok = True


@system_stackbuild.callback(
help='Build an image based on a given stash container root. '
'If no KIWI --description parameter is provided, '
'stackbuild rebuilds the image from the stash container. '
'In this case, the given kiwi parameters are passed to the '
'kiwi-ng system create command. If a KIWI description is '
'provided, this description takes over precedence and a new '
'image from this description based on the given stash container '
'root will be built. In this case, the given kiwi parameters '
'are passed to the kiwi-ng system build command.',
invoke_without_command=False,
subcommand_metavar='kiwi [OPTIONS]'
)
def stackbuild(
ctx: typer.Context,
stash: Annotated[
List[str], typer.Option(
help='<name> Name of the stash container. See system stash --list '
'for available stashes. Multiple --stash options will be stacked '
'together in the given order'
)
],
target_dir: Annotated[
Path, typer.Option(
help='<directory> The target directory to store the '
'system image file(s)'
)
],
description: Annotated[
Optional[Path], typer.Option(
help='<directory> Path to KIWI image description'
)
] = None,
from_registry: Annotated[
Optional[str], typer.Option(
help='<URI> Pull given stash container name from the '
'provided registry URI'
)
] = None,
):
Cli = ctx.obj
Cli.subcommand_args['stackbuild'] = {
'--stash': stash,
'--target-dir': target_dir,
'--description': description,
'--from-registry': from_registry,
'help': False
}


@system_stash.callback(
help='Create a container from the given root directory',
invoke_without_command=True,
subcommand_metavar=''
)
def stash(
ctx: typer.Context,
root: Annotated[
Optional[Path], typer.Option(
help='<directory> The path to the root directory, '
'usually the result of a former system prepare or '
'build call'
)
] = None,
tag: Annotated[
Optional[str], typer.Option(
help='<name> The tag name for the container. '
'By default set to: latest'
)
] = None,
container_name: Annotated[
Optional[str], typer.Option(
help='<name> The name of the container. By default '
'set to the image name of the stash'
)
] = None,
stash_list: Annotated[
Optional[bool], typer.Option(
'--list',
help='List the available stashes'
)
] = False
):
Cli = ctx.obj
Cli.subcommand_args['stash'] = {
'--root': root,
'--tag': tag,
'--container-name': container_name,
'--list': stash_list,
'help': False
}
Cli.global_args['command'] = 'stash'
Cli.global_args['system'] = True
Cli.cli_ok = True
76 changes: 43 additions & 33 deletions kiwi_stackbuild_plugin/tasks/system_stackbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,23 +182,28 @@ def process(self) -> None:
def _validate_kiwi_create_command(
self, kiwi_create_command: List[str]
) -> List[str]:
# construct create command from given command line
kiwi_create_command += self.command_args.get(
'<kiwi_create_command_args>'
)
if '--' in kiwi_create_command:
kiwi_create_command.remove('--')
# validate create command through docopt from the original
# kiwi.tasks.system_create docopt information
log.debug(
'Validating kiwi_create_command_args:{0} {1}'.format(
os.linesep, kiwi_create_command
if self.command_args.get('<kiwi_create_command_args>'):
# construct create command from docopt command line
kiwi_create_command += self.command_args.get(
'<kiwi_create_command_args>'
)
)
validated_create_command = docopt(
kiwi.tasks.system_create.__doc__,
argv=kiwi_create_command
)
if '--' in kiwi_create_command:
kiwi_create_command.remove('--')
# validate create command through docopt from the original
# kiwi.tasks.system_create docopt information
log.debug(
'Validating kiwi_create_command_args:{0} {1}'.format(
os.linesep, kiwi_create_command
)
)
validated_create_command = docopt(
kiwi.tasks.system_create.__doc__,
argv=kiwi_create_command
)
else:
validated_create_command = \
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'
Expand All @@ -207,24 +212,29 @@ def _validate_kiwi_create_command(
def _validate_kiwi_build_command(
self, kiwi_build_command: List[str]
) -> List[str]:
# construct build command from given command line
kiwi_build_command += self.command_args.get(
'<kiwi_build_command_args>'
)
if '--' in kiwi_build_command:
kiwi_build_command.remove('--')
# validate build command through docopt from the original
# kiwi.tasks.system_build docopt information
log.debug(
'Validating kiwi_build_command_args:{0} {1}'.format(
os.linesep, kiwi_build_command
if self.command_args.get('<kiwi_build_command_args>'):
# construct build command from given command line
kiwi_build_command += self.command_args.get(
'<kiwi_build_command_args>'
)
)
validated_build_command = docopt(
kiwi.tasks.system_build.__doc__,
argv=kiwi_build_command
)
# rebuild kiwi build command from validated docopt parser result
if '--' in kiwi_build_command:
kiwi_build_command.remove('--')
# validate build command through docopt from the original
# kiwi.tasks.system_build docopt information
log.debug(
'Validating kiwi_build_command_args:{0} {1}'.format(
os.linesep, kiwi_build_command
)
)
validated_build_command = docopt(
kiwi.tasks.system_build.__doc__,
argv=kiwi_build_command
)
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'
)
Expand Down
Loading