Skip to content

Commit

Permalink
Implement --last, --id and --skip for tmt clean (#2806)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Hoyer <mhoyer@redhat.com>
Co-authored-by: Miloš Prchlík <mprchlik@redhat.com>
Co-authored-by: Petr Šplíchal <psplicha@redhat.com>
  • Loading branch information
4 people authored Aug 9, 2024
1 parent 06e21de commit b98dbd1
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 10 deletions.
37 changes: 37 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,43 @@ to see what would actually happen using ``--dry`` mode:
testcloud
warn: Directory '/var/tmp/tmt/testcloud/images' does not exist.
You may also want to clean everything in only one run using
the ``--id`` or ``--last`` options.
.. code-block:: shell
$ tmt clean -v --last
clean
guests
Stopping guests in run '/var/tmp/tmt/run-001' plan '/plans/testcloud'.
finish
guest: stopped
guest: removed
summary: 0 tasks completed
runs
Removing workdir '/var/tmp/tmt/run-001'.
images
testcloud
warn: Directory '/var/tmp/tmt/testcloud/images' does not exist.
You can also skip cleaning selected resources using the ``--skip``
option.
.. code-block:: shell
$ tmt clean -v --last --skip images
clean
guests
Stopping guests in run '/var/tmp/tmt/run-001' plan '/plans/testcloud'.
finish
guest: stopped
guest: removed
summary: 0 tasks completed
runs
Removing workdir '/var/tmp/tmt/run-001'.
In some cases, you may want to have a bit more control over the
behaviour which can be achieved using subcommands and their
options. All of the options described above can be used with
Expand Down
6 changes: 6 additions & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ overall result is determined by selecting the result with the
value which resides highest on the hierarchy of `skip`, `pass`,
`warn`, `fail`).

Add support for ``--last``, ``--id``, and ``--skip`` params for
the ``clean`` subcommand. Users can clean resources from the last
run or from a run with a given id. Users can also choose to skip
cleaning ``guests``, ``runs`` or ``images``.


tmt-1.34
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions tests/clean/basic/data/.fmf/version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
10 changes: 10 additions & 0 deletions tests/clean/basic/data/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/plan:
discover:
how: fmf
provision:
how: local
execute:
how: tmt

/test:
test: /bin/true
1 change: 1 addition & 0 deletions tests/clean/basic/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
summary: Check the basic functionality of 'tmt clean'
44 changes: 44 additions & 0 deletions tests/clean/basic/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartSetup
rlRun "root=/var/tmp/tmt"
rlRun "pushd data"
rlPhaseEnd

rlPhaseStartTest "Create a couple of runs"
for id in {001..004}; do
rlRun "tmt --feeling-safe run --id clean-$id"
rlAssertExists "$root/clean-$id"
done
rlPhaseEnd

rlPhaseStartTest "Remove last"
rlRun "tmt clean -v --last"
rlAssertExists "$root/clean-001"
rlAssertExists "$root/clean-002"
rlAssertExists "$root/clean-003"
rlAssertNotExists "$root/clean-004"
rlPhaseEnd

rlPhaseStartTest "Remove selected (full path)"
rlRun "tmt clean -v --id $root/clean-001"
rlAssertNotExists "$root/clean-001"
rlAssertExists "$root/clean-002"
rlAssertExists "$root/clean-003"
rlAssertNotExists "$root/clean-004"
rlPhaseEnd

rlPhaseStartTest "Remove selected (name)"
rlRun "tmt clean -v --id clean-002"
rlAssertNotExists "$root/clean-001"
rlAssertNotExists "$root/clean-002"
rlAssertExists "$root/clean-003"
rlAssertNotExists "$root/clean-004"
rlPhaseEnd

rlPhaseStartCleanup
rlRun "popd"
rlPhaseEnd
rlJournalEnd
4 changes: 2 additions & 2 deletions tmt/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3933,7 +3933,7 @@ def _clean_workdir(self, path: Path) -> bool:
return False
return True

def runs(self) -> bool:
def runs(self, id_: tuple[str, ...]) -> bool:
""" Clean workdirs of runs """
self.info('runs', color='blue')
root_path = Path(self.opt('workdir-root'))
Expand All @@ -3944,7 +3944,7 @@ def runs(self) -> bool:
last_run._workdir_load(last_run._workdir_path)
assert last_run.workdir is not None # narrow type
return self._clean_workdir(last_run.workdir)
all_workdirs = list(tmt.utils.generate_runs(root_path, self.opt('id_')))
all_workdirs = list(tmt.utils.generate_runs(root_path, id_))
keep = self.opt('keep')
if keep is not None:
# Sort by modify time of the workdirs and keep the newest workdirs
Expand Down
36 changes: 28 additions & 8 deletions tmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1865,14 +1865,28 @@ def status(
# Clean
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Supported clean resources
CLEAN_RESOURCES: list[str] = ["guests", "runs", "images"]

# ignore[arg-type]: click code expects click.Context, but we use our own type for better type
# inference. See Context and ContextObjects above.
@main.group(chain=True, invoke_without_command=True, cls=CustomGroup) # type: ignore[arg-type]

@main.group(chain=True, invoke_without_command=True, cls=CustomGroup)
@pass_context
@option(
'-l', '--last', is_flag=True,
help='Clean resources related to the last run.')
@option(
'-i', '--id', 'id_', metavar="ID", multiple=True,
help='Identifier (name or directory path) of the run to be cleaned.')
@option(
'-s', '--skip', choices=CLEAN_RESOURCES,
help='The resources which should be kept on the disk.', multiple=True)
@verbosity_options
@dry_options
def clean(context: Context, **kwargs: Any) -> None:
def clean(context: Context,
last: bool,
id_: tuple[str, ...],
skip: list[str],
**kwargs: Any) -> None:
"""
Clean workdirs, guests or images.
Expand All @@ -1885,6 +1899,9 @@ def clean(context: Context, **kwargs: Any) -> None:
the same, irrespective of the order on the command line. First, all
the guests are cleaned, followed by runs and images.
"""
if last and id_:
raise tmt.utils.GeneralError(
"Options --last and --id cannot be used together.")

context.obj.clean_logger = context.obj.logger \
.descend(logger_name='clean', extra_shift=0) \
Expand All @@ -1911,15 +1928,16 @@ def clean(context: Context, **kwargs: Any) -> None:
parent=clean_obj,
cli_invocation=CliInvocation.from_context(context))
if tmt.utils.WORKDIR_ROOT.exists():
if not clean_obj.guests():
if 'guests' not in skip and not clean_obj.guests():
exit_code = 1
if not clean_obj.runs():
if 'runs' not in skip and not clean_obj.runs(id_):
exit_code = 1
else:
clean_obj.warn(
f"Directory '{tmt.utils.WORKDIR_ROOT}' does not exist, "
f"skipping guest and run cleanup.")
clean_obj.images()
if 'images' not in skip and not clean_obj.images():
exit_code = 1
raise SystemExit(exit_code)


Expand Down Expand Up @@ -1989,7 +2007,9 @@ def clean_runs(
.apply_verbosity_options(**kwargs),
parent=context.obj.clean,
cli_invocation=CliInvocation.from_context(context))
context.obj.clean_partials["runs"].append(clean_obj.runs)
context.obj.clean_partials["runs"].append(
lambda: clean_obj.runs(
(context.parent and context.parent.params.get('id_', [])) or id_))


@clean.command(name='guests')
Expand Down

0 comments on commit b98dbd1

Please sign in to comment.