Skip to content

Commit

Permalink
Support Fedora Image Mode
Browse files Browse the repository at this point in the history
To support Fedora Image mode the following changes were required:

* Fix `rsync` installation. The tool is not included in the distribution and
  the installation method was completely broken, i.e. `rpm-ostree` has
  no `--install-root` option. We did not hit it as there is no good
  testing environment available that would cover this.

* Introduce `TMT_SCRIPTS_DEST_DIR` environment variable set by default
  to `/var/tmp/tmt/bin` which hosts the `tmt` scripts. The original path
  is not writable on these systems. The `PATH` is set system wide via a
  new `/etc/profile.d/tmt.sh` script.

Signed-off-by: Miroslav Vadkerti <[email protected]>
  • Loading branch information
thrix committed Oct 1, 2024
1 parent 4d0abe1 commit 0b923ee
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
exclude-path: |
tests/**
examples/**/test.sh
tmt/steps/execute/scripts/tmt.sh.j2
tmt/steps/execute/scripts/*.sh.j2
tmt/templates/**
token: ${{ secrets.GITHUB_TOKEN }}

Expand Down
86 changes: 58 additions & 28 deletions tmt/steps/execute/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# Metadata file with details about the current test
TEST_METADATA_FILENAME = 'metadata.yaml'

# Scripts source directory
#: Scripts source directory
SCRIPTS_SRC_DIR = tmt.utils.resource_files('steps/execute/scripts')

#: The default scripts destination directory
Expand All @@ -67,16 +67,35 @@

@dataclass
class Script:
""" Represents a script provided by the internal executor """
"""
Represents a script provided by the internal executor.
Must be used as a context manager. The context manager returns
the source file path.
The source file name matches the name of the file specified via
the ``path` attribute and must be located in the directory specified
via :py:data:`SCRIPTS_SRC_DIR` variable.
"""

path: Path
aliases: list[Path]
related_variables: list[str]

def __enter__(self) -> Path:
return SCRIPTS_SRC_DIR / self.path.name

def __exit__(self, *args: object) -> None:
pass


@dataclass
class ScriptCreatingFile(Script):
""" Represents a script which creates a file """
"""
Represents a script which creates a file.
See :py:class:`Script` for more details.
"""

created_file: str

Expand All @@ -85,18 +104,41 @@ class ScriptCreatingFile(Script):
class ScriptTemplate(Script):
"""
Represents a Jinja2 templated script.
The source filename must have a ``.j2`` suffix.
Must be used as a context manager. The context manager returns
the source file path.
The source file name is constructed from the name of the file specified
via the ``path` attribute that is extended with the ``.j2`` suffix.
The template file must be located in the directory specified
via :py:data:`SCRIPTS_SRC_DIR` variable.
"""

context: dict[str, str]

_rendered_script_path: Optional[Path] = None

def __enter__(self) -> Path:
with tempfile.NamedTemporaryFile(mode='w', delete=False) as rendered_script:
rendered_script.write(render_template_file(
SCRIPTS_SRC_DIR / f"{self.path.name}.j2", None, **self.context))

self._rendered_script_path = Path(rendered_script.name)

return self._rendered_script_path

def __exit__(self, *args: object) -> None:
assert self._rendered_script_path
os.unlink(self._rendered_script_path)


def effective_scripts_dest_dir() -> Path:
"""
Find out what the actual scripts destination directory is.
If ``TMT_SCRIPTS_DEST_DIR`` variable is set, it is used as the scripts destination
directory. Otherwise, the default of :py:data:`SCRIPTS_DEST_DIR` is used.
If the ``TMT_SCRIPTS_DEST_DIR`` variable is set, it is used as the scripts
destination directory. Otherwise, the default of :py:data:`SCRIPTS_DEST_DIR`
is used.
"""

if 'TMT_SCRIPTS_DEST_DIR' in os.environ:
Expand Down Expand Up @@ -153,13 +195,13 @@ def effective_scripts_dest_dir() -> Path:
created_file="abort"
)

# Profile script for adding SCRIPTS_DEST_DIR to executable pats system-wide
# Profile script for adding SCRIPTS_DEST_DIR to executable paths system-wide
TMT_ETC_PROFILE_D = ScriptTemplate(
path=Path("/etc/profile.d/tmt.sh"),
aliases=[],
related_variables=[],
context={
'scripts_dest_dir': str(effective_scripts_dest_dir())
'SCRIPTS_DEST_DIR': str(effective_scripts_dest_dir())
})


Expand Down Expand Up @@ -647,29 +689,17 @@ def _render_script_template(self, source: Path, context: dict[str, str]) -> Path
def prepare_scripts(self, guest: "tmt.steps.provision.Guest") -> None:
""" Prepare additional scripts for testing """
# Create scripts directory
guest.execute(Command("mkdir", "-p", str(SCRIPTS_DEST_DIR)))
guest.execute(Command("mkdir", "-p", str(effective_scripts_dest_dir())))

# Install all scripts on guest
for script in self.scripts:
source = SCRIPTS_SRC_DIR / script.path.name

# Render script template
if isinstance(script, ScriptTemplate):
source = self._render_script_template(
SCRIPTS_SRC_DIR / f"{script.path.name}.j2",
context=script.context
)

for dest in [script.path, *script.aliases]:
guest.push(
source=source,
destination=dest,
options=["-p", "--chmod=755"],
superuser=guest.facts.is_superuser is not True)

# Remove script template source
if isinstance(script, ScriptTemplate):
os.unlink(source)
with script as source:
for dest in [script.path, *script.aliases]:
guest.push(
source=source,
destination=dest,
options=["-p", "--chmod=755"],
superuser=guest.facts.is_superuser is not True)

def _tmt_report_results_filepath(self, invocation: TestInvocation) -> Path:
""" Create path to test's ``tmt-report-result`` file """
Expand Down
2 changes: 1 addition & 1 deletion tmt/steps/execute/scripts/tmt.sh.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# shellcheck shell=bash

# tmt provides executable scripts under this path
export PATH={{ scripts_dest_dir }}:$PATH
export PATH={{ SCRIPTS_DEST_DIR }}:$PATH

0 comments on commit 0b923ee

Please sign in to comment.