Skip to content

Guest fact discovery via a single script#4438

Open
happz wants to merge 8 commits intomainfrom
guest-facts-discovery-single-script
Open

Guest fact discovery via a single script#4438
happz wants to merge 8 commits intomainfrom
guest-facts-discovery-single-script

Conversation

@happz
Copy link
Copy Markdown
Contributor

@happz happz commented Dec 17, 2025

TL;DR: guest fact discovery now runs as a single remote command, whose
output is then parsed into values of individual facts.

  • Each fact attribute is now defined with a descriptor (see [1]). It
    keeps the proper type annotation, but we can attach more information.
  • Each probe is now a shell script snippet, and is attached to its
    owning fact.
  • Snippets are collected, joined, and the resulting script is executed.
    GuestFacts then processes the output, delivers discovered values to
    the right attributes.
  • No Python code in probes, custom Python code to handle decoding of the
    script output fully supported (and used, see package manager facts).

For the tmt code, nothing changes, GuestFacts API remains the same.

[1] https://docs.python.org/3/howto/descriptor.html

Pull Request Checklist

  • implement the feature
  • write the documentation

@happz happz added this to planning Dec 17, 2025
@happz happz added step | provision Stuff related to the provision step ci | full test Pull request is ready for the full test execution labels Dec 17, 2025
@github-project-automation github-project-automation Bot moved this to backlog in planning Dec 17, 2025
@happz
Copy link
Copy Markdown
Contributor Author

happz commented Dec 17, 2025

Blocked on #4443

@happz happz force-pushed the guest-facts-discovery-single-script branch from 518614c to 4bde734 Compare December 30, 2025 21:50
@happz happz moved this from backlog to implement in planning Dec 30, 2025
Comment thread tmt/steps/provision/__init__.py Outdated
@happz happz force-pushed the guest-facts-discovery-single-script branch from 4bde734 to 51f8a18 Compare January 5, 2026 14:16
Comment thread tmt/steps/provision/__init__.py Outdated
Comment thread tmt/steps/provision/__init__.py Outdated
@happz happz force-pushed the guest-facts-discovery-single-script branch from 44acca0 to aa53188 Compare February 13, 2026 10:19
Comment thread tmt/steps/provision/__init__.py Outdated
Comment thread tmt/steps/provision/__init__.py Outdated
@happz happz moved this from implement to review in planning Feb 13, 2026
@happz happz moved this from review to implement in planning Feb 13, 2026
Comment thread tmt/steps/provision/__init__.py Outdated
@happz happz force-pushed the guest-facts-discovery-single-script branch from 1efb436 to 919a85a Compare February 23, 2026 12:57
@happz happz added the status | blocked The merging of PR is blocked on some other issue label Feb 23, 2026
@happz happz force-pushed the guest-facts-discovery-single-script branch from 945eb56 to c10ce07 Compare March 1, 2026 09:44
Comment thread tmt/guest/__init__.py
Comment on lines +1030 to +1041
#: A prefix to use when invoking commands with ``sudo``.
sudo_prefix = string_guest_fact(
"""
Format facts for pretty printing.
if [ "$(whoami)" = "root" ]; then
echo ''
elif sudo -n true 1>&2; then
echo 'sudo'
else
echo ''
fi
"""
)
Copy link
Copy Markdown
Member

@LecrisUT LecrisUT Mar 3, 2026

Choose a reason for hiding this comment

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

I think we should keep the original design with each _query_* methods and have these functions contribute to an unordered dict for the actual string_guest_fact. The return of those could then be the variable from where it is accessed. So for sudo_prefix it can look like

    def _query_sudo_prefix(self) -> str:
        is_superuser = self._query_is_superuser()
        can_sudo = self._query_can_sudo()
        self.query_script["sudo_prefix"] = string_guest_fact(f"""
        if [ "${is_superuser}" = true ]; then
            sudo_prefix=""
        elif [ "${can_sudo}" = true ]; then
            sudo_prefix="sudo"
        else
            sudo_prefix=""
        fi
        """)
        return "sudo_prefix"

assignment vs echo here are interchangeable, just used the latter for logic clarity.

Using the unordered dict would help here to guarantee there is no duplicates of the query scripts while still guaranteeing that all query scripts were performed before it was requested.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do we even have to have an actual shell probe for "sudo prefix"? Seems like a mistake I haven't noticed before. It's derived from probes that do have actual stuff to discover, and this one seems like a mere crossroad once the rest is discovered. Might be just a (cached) property on top of is_superuser and can_sudo facts. I'll see what I can do.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well, not about sudo_prefix explicitly, but to figure out how to do probes that have dependencies on other probes, is_image_mode being the primary case where we hit it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added "required probes" in 41e3dbec. Probes can now hint the script to emit some probes first, each probe is saved in a variable, later probes can use them in their snippets. I don't want to go back to _query_* methods, it's cumbersome and blocks fact collection in one go.

@happz happz force-pushed the guest-facts-discovery-single-script branch from c10ce07 to 41e3dbe Compare April 6, 2026 18:30
Comment thread tmt/guest/__init__.py
happz added 7 commits April 20, 2026 13:02
TL;DR: guest fact discovery now runs as a single remote command, whose
output is then parsed into values of individual facts.

* Each fact attribute is now defined with a descriptor (see [1]). It
  keeps the proper type annotation, but we can attach more information.
* Each probe is now a shell script snippet, and is attached to its
  owning fact.
* Snippets are collected, joined, and the resulting script is executed.
  `GuestFacts` then processes the output, delivers discovered values to
  the right attributes.
* No Python code in probes, custom Python code to handle decoding of the
  script output fully supported (and used, see package manager facts).

For the tmt code, nothing changes, `GuestFacts` API remains the same.

[1] https://docs.python.org/3/howto/descriptor.html
@happz happz force-pushed the guest-facts-discovery-single-script branch from c16dbb7 to 26e8166 Compare April 20, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci | full test Pull request is ready for the full test execution status | blocked The merging of PR is blocked on some other issue step | provision Stuff related to the provision step

Projects

Status: implement

Development

Successfully merging this pull request may close these issues.

2 participants