Skip to content
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

Support container provisioner in toolbox #3228

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
7 changes: 7 additions & 0 deletions tests/provision/container/toolbox/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
summary: Test container provisioner in toolbox
description:
Make sure that container provisioner works well
in a toolbox container.
tag+:
- provision-only
- provision-container
2 changes: 2 additions & 0 deletions tests/provision/container/toolbox/podman_wrapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
flatpak-spawn --host podman "$@"
48 changes: 48 additions & 0 deletions tests/provision/container/toolbox/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlJournalStart
rlPhaseStartSetup
rlRun "toolbox_container_name=\$(uuidgen)" 0 "Generate toolbox container name"
rlPhaseEnd

rlPhaseStartTest "Create toolbox container"
rlRun "toolbox create -y $toolbox_container_name"
rlPhaseEnd

toolbox_run() {
toolbox run --container "$toolbox_container_name" "$@"
}

if env | grep -q PACKIT_COPR_PROJECT; then
rlPhaseStartTest "Install tmt in from copr repository"
TMT_COMMAND="tmt"
rlRun "toolbox_run dnf -y install dnf-plugins-core"
rlRun "toolbox_run dnf -y copr enable $PACKIT_COPR_PROJECT"
rlRun "toolbox_run dnf -y install tmt-provision-container"
rlPhaseEnd
else
rlPhaseStartTest "Install hatch, expecting local execution"
TMT_COMMAND="hatch run dev:tmt"
rlRun "toolbox_run dnf -y install hatch"
rlPhaseEnd
fi

rlPhaseStartTest "Print tmt version installed in toolbox"
rlRun "toolbox_run $TMT_COMMAND --version"
rlPhaseEnd

rlPhaseStartTest "Add podman wrapper"
rlRun "podman cp podman_wrapper $toolbox_container_name:/usr/bin/podman"
rlRun "toolbox_run podman --version"
rlPhaseEnd

rlPhaseStartTest "Verify container provisioner works from toolbox"
rlRun -s "toolbox_run tmt run -a -vvv provision -h container execute -h tmt -s 'echo hello from container'"
rlAssertGrep "content: hello from container" $rlRun_LOG
rlPhaseEnd

rlPhaseStartCleanup
rlRun "toolbox rm -f $toolbox_container_name" 0 "Remove toolbox container"
rlPhaseEnd
rlJournalEnd
41 changes: 39 additions & 2 deletions tmt/steps/provision/podman.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dataclasses
import functools
import os
from shlex import quote
from typing import Any, Optional, Union, cast
Expand Down Expand Up @@ -283,6 +284,33 @@ def _run_ansible(
log=log,
silent=silent)

@functools.cached_property
def _is_toolbox(self) -> bool:
""" Return ``True`` if running in toolbox, ``False`` otherwise. """
if os.path.exists('/run/.toolboxenv'):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.path should be replaced with Path().exists()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to remember we use pathlib here :)

return True

return False

@functools.cached_property
def _toolbox_container_name(self) -> Optional[str]:
""" Returns toolbox container name if running in toolbox, ``None`` otherwise. """
if not self._is_toolbox:
return None

if not os.path.exists('/run/.containerenv'):
self.logger.warning(
"Unable to detect toolbox container name, '/run/.containerenv' not found."
)
return None

with open('/run/.containerenv') as envfile:
for line in envfile.readline():
if line.startswith('name="'):
return line[6:-1]

return None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two look like they belong to guest facts, as they are properties of a machine similar to has_selinux or arch, for example. Once moved, you would reach them via self.parent.plan.my_run.runner.facts.*.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the pointers


def podman(
self,
command: Command,
Expand Down Expand Up @@ -376,10 +404,19 @@ def push(
self._run_guest_command(Command(
"chcon", "--recursive", "--type=container_file_t", self.parent.plan.workdir
), shell=False, silent=True)

# In case explicit destination is given, use `podman cp` to copy data
# to the container
# to the container. If running in toolbox, make sure to copy from the toolbox
# container instead of localhost.
if source and destination:
self.podman(Command("cp", source, f"{self.container}:{destination}"))
self.podman(
Command(
"cp",
f"{self._toolbox_container_name}:{source}"
if self._toolbox_container_name else source,
f"{self.container}:{destination}"
)
)

def pull(
self,
Expand Down
Loading