Skip to content

Split monolithic module into several collection modules #34

Merged
marmarek merged 15 commits intoQubesOS:mainfrom
Guiiix:refactor_new
Apr 24, 2026
Merged

Split monolithic module into several collection modules #34
marmarek merged 15 commits intoQubesOS:mainfrom
Guiiix:refactor_new

Conversation

@Guiiix
Copy link
Copy Markdown
Member

@Guiiix Guiiix commented Mar 29, 2026

Fixes QubesOS/qubes-issues#10670

This PR brings some architectural changes to this repository.

1. Introduction of collections

Ansible collections allow to distribute a set of plugins, roles and modules into a self-contained, reusable and versioned package.

The qubesos module allow to do a lot of different things, many of which are not directly related. Splitting it into 3 modules helps for maintenance and for usage in playbooks.
2 collections are introduced:

  • qubesos.core for everything related to QubesOS management
  • qubesos.security for Ansible-related security features (basically, the qubes-proxy and the qubesos_strategy_guard)

The qubesos module has been splitted into 3 different modules:

  • qubesos.core.qube: to manage the qubes
  • qubesos.core.command: non indempotent commands (required to keep compatibility with the old module)
  • qubesos.core.host_devices_facts: gather facts about available devices on the host

Other plugins (connection, strategy and callback) have been moved into a collection but may still be called using their old name.

Plugin type Old name New name
Connection qubes qubesos.core.qubes
Strategy qubes_proxy qubesos.security.qubes_proxy
Callback qubes_strategy_guard qubesos.security.qubes_strategy_guard 

2. Legacy module

To prevent breaking changes, the qubesos module is still present but is considered deprecated and may be removed in a future release.

The module takes the same options and will try to translate to calls to the new
modules with the appropriate options.

Option wait has no more effect. The module will always wait for the actions (qube start, stop...)
to finish before starting a new task to prevent unexpected behaviors.

3. A word about module_utils

The files in the modules directory contains only the module documentation while the entire module code is stored in the directory module_utils. The reason of that split is the legacy module qubesos. As described above, this module is responsible of taking the same input as the previous module and based on the input, it will call the new modules.

However, Ansiballz framework doesn't include other modules in the generated archive making imports fail. Putting modules logic into module_utils make the code available to other modules, and so available to qubesos module.

4. Documentation

The documentation is now automatically generated based on modules docstrings and is available in the project Gitlab Pages.

Focusing on documenting modules using the official way allow to generate the documentation with the common Ansible format while also making it available using ansible-docs command.

@Guiiix Guiiix marked this pull request as draft March 29, 2026 08:13
Keep a symlink in old locations to avoid breaking changes
@Guiiix Guiiix force-pushed the refactor_new branch 3 times, most recently from 2dd94cd to 9a8d92e Compare March 29, 2026 09:36
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 29, 2026

Codecov Report

❌ Patch coverage is 90.20979% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.30%. Comparing base (6072fde) to head (6dee747).
⚠️ Report is 16 commits behind head on main.

Files with missing lines Patch % Lines
plugins/modules/qubesos.py 90.20% 14 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #34      +/-   ##
==========================================
+ Coverage   73.34%   81.30%   +7.96%     
==========================================
  Files           1        1              
  Lines         529      214     -315     
==========================================
- Hits          388      174     -214     
+ Misses        141       40     -101     
Flag Coverage Δ
unittests 81.30% <90.20%> (+7.96%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Guiiix Guiiix force-pushed the refactor_new branch 3 times, most recently from 9a58c91 to bd2ece0 Compare March 29, 2026 12:46
@Guiiix Guiiix changed the title Draft: Module refactoring Draft: Split monolithic module into several collection modules Mar 29, 2026
@Guiiix Guiiix force-pushed the refactor_new branch 8 times, most recently from b1db702 to 25600a3 Compare April 1, 2026 10:25
@Guiiix
Copy link
Copy Markdown
Member Author

Guiiix commented Apr 1, 2026

PipelineRetry

@Guiiix Guiiix force-pushed the refactor_new branch 2 times, most recently from deddfe6 to 967ad2f Compare April 4, 2026 06:59
Guiiix added 3 commits April 5, 2026 11:47
All tests must still work without any modification to prevent breaking changes.
Currently, the only identified braking change is the wait param which is no more supported (it will not fail but if using wait: false, the module will ignore the option)
@Guiiix Guiiix force-pushed the refactor_new branch 2 times, most recently from 2c63a95 to 608d218 Compare April 5, 2026 10:02
@Guiiix Guiiix changed the title Draft: Split monolithic module into several collection modules Split monolithic module into several collection modules Apr 5, 2026
@Guiiix Guiiix marked this pull request as ready for review April 5, 2026 10:38
@marmarek
Copy link
Copy Markdown
Member

  • gpu_passthrough: Failed (test died)
    # Test died: command 'ansible-playbook -i inventory -e pci_devices=...

Old playbook stopped working. It's here: https://github.com/QubesOS/openqa-tests-qubesos/tree/main/extra-files/ansible

"netvm",
]:
value = self.wants.properties.get(property)
if value in (None, "dom0", "*default*"):
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.

It used to accept also empty string as None (existing playbooks rely on that).

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.

This probably also wants a test for setting any of the VM-type properties to None.

Comment thread plugins/modules/qubesos.py Outdated
if key not in PROPS:
return VIRT_FAILED, {"Invalid property": key}
raise ValidationFailure({"Invalid property": key})
if type(val) != PROPS[key]:
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.

This is unfortunate given the new module doesn't accept empty string as None anymore, yet this line rejects real None...

continue

try:
vm = self.helper.get_vm(value)
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.

This validation is too early. This prevents creating a (disposable template) qube that has itself as its default_dispvm. It used to be possible.

@Guiiix
Copy link
Copy Markdown
Member Author

Guiiix commented Apr 21, 2026

Thanks for the review @marmarek.

Should be good for the openqa playbook. Ansible doesn't like Enum in returned data...

Now we can set an empty string or None in a qube property and qube existence is skipped when specifying the managed qube in a property.

Some tests added too.

@marmarek marmarek merged commit 587ef7c into QubesOS:main Apr 24, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split QubesOS Ansible module into multiple modules

4 participants