Skip to content

Commit

Permalink
Add HW requirement support matrix to docs (#3025)
Browse files Browse the repository at this point in the history
Generated from HW requriement stories and their links, it should be the
most up-to-date picture of what's supported by plugins shipped with tmt.
  • Loading branch information
happz authored Jul 23, 2024
1 parent 3ec64e6 commit f73dd7a
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ docs/plugins/prepare.rst
docs/plugins/provision.rst
docs/plugins/report.rst
docs/plugins/test-checks.rst
docs/plugins/hardware-matrix.rst
docs/_build
docs/spec
docs/stories
Expand Down
11 changes: 9 additions & 2 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ plugins/report.rst: $(call plugins-dependencies)
plugins/test-checks.rst: $(call plugins-checks-dependencies)
$(call build-plugins)

plugins/hardware-matrix.rst: $(SCRIPTSDIR)/generate-hardware-matrix.py \
$(TEMPLATESDIR)/hardware-matrix.rst.j2 \
$(shell find $(REPODIR)/spec/hardware -name '*.fmf')
$(SCRIPTSDIR)/generate-hardware-matrix.py $(TEMPLATESDIR)/hardware-matrix.rst.j2 $@

spec/lint.rst: $(SCRIPTSDIR)/generate-lint-checks.py \
$(TEMPLATESDIR)/lint-checks.rst.j2 \
$(TMTDIR)/base.py
Expand All @@ -121,15 +126,17 @@ generate-autodocs: ## Generate autodocs from source docstrings

generate-lint-checks: spec spec/lint.rst ## Generate documentation sources for lint checks

generate-plugins: $(PLUGIN_TARGETS) ## Generate documentation sources for plugins
generate-plugins: $(PLUGIN_TARGETS) generate-hardware-matrix ## Generate documentation sources for plugins

generate-hardware-matrix: plugins/hardware-matrix.rst ## Generate HW requirement support matrix

generate-stories: stories $(TEMPLATESDIR)/story.rst.j2 ## Generate documentation sources for stories
$(SCRIPTSDIR)/generate-stories.py $(TEMPLATESDIR)/story.rst.j2

generate-template-filters: code/template-filters.rst ## Generate documentation sources for Jinja2 template filters

clean: ## Remove all generated content
rm -rf _build $(GENERATED_DIRECTORIES) code/autodocs/*.rst code/template-filters.rst $(PLUGIN_TARGETS) $(LOGO_DST)
rm -rf _build $(GENERATED_DIRECTORIES) code/autodocs/*.rst code/template-filters.rst plugins/hardware-matrix.rst $(PLUGIN_TARGETS) $(LOGO_DST)

##
## Help!
Expand Down
Empty file removed docs/_static/.empty
Empty file.
5 changes: 5 additions & 0 deletions docs/_static/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import 'css/theme.css';

/* Used for HW requirement support matrix */
.supported { color: green; }
.unsupported { color: red; }
5 changes: 4 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def _load_theme(

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build', '**/*.inc.rst']
exclude_patterns = ['_build', '**/*.inc.rst', 'plugins/hardware-matrix.rst']

# The reST default role (used for this markup: `text`) to use for all
# documents.
Expand Down Expand Up @@ -229,6 +229,9 @@ def _load_theme(
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Include custom style.
html_style = 'custom.css'

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
Expand Down
2 changes: 2 additions & 0 deletions docs/plugins/provision-header.inc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ Following plugins fully implement hard reboot:
* :ref:`plugins/provision/beaker`
* :ref:`plugins/provision/container`
* :ref:`virtual<plugins/provision/virtual.testcloud>`

.. include:: hardware-matrix.rst
84 changes: 84 additions & 0 deletions docs/scripts/generate-hardware-matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3

import sys
import textwrap

import tmt.plugins
import tmt.steps.provision
from tmt.utils import Path, render_template_file

HELP = textwrap.dedent("""
Usage: generate-hardware-matrix.py <TEMPLATE-PATH> <OUTPUT-PATH>
Generate page with HW requirement support matrix from stories.
""").strip()


def main() -> None:
if len(sys.argv) != 3:
print(HELP)

sys.exit(1)

template_filepath = Path(sys.argv[1])
output_filepath = Path(sys.argv[2])

# We will need a logger...
logger = tmt.Logger.create()
logger.add_console_handler()

# Explore available *export* plugins - do not import other plugins, we don't need them.
tmt.plugins._explore_packages(logger)

known_methods = sorted(
tmt.steps.provision.ProvisionPlugin._supported_methods.iter_plugin_ids())

tree = tmt.Tree(logger=logger, path=Path.cwd())

logger.info('Generating reST file for HW requirement support matrix')

matrix: dict[str, dict[str, tuple[bool, str]]] = {}
notes: list[str] = []

for story in tree.stories(logger=logger, names=['^/spec/hardware/.*'], whole=True):
hw_requirement = story.name.replace('/spec/hardware/', '')

if hw_requirement == 'arch':
continue

matrix[hw_requirement] = {
method: (False, int) for method in known_methods
}

if not story.link:
pass

for link in story.link.get(relation='implemented-by'):
implemented_by_method = Path(link.target).stem

if implemented_by_method == 'mrack':
implemented_by_method = 'beaker'

elif implemented_by_method == 'testcloud':
implemented_by_method = 'virtual.testcloud'

if implemented_by_method not in matrix[hw_requirement]:
raise Exception(f'{implemented_by_method} unknown')

if link.note:
notes.append(f'``{hw_requirement}`` with ``{implemented_by_method}``: {link.note}')

matrix[hw_requirement][implemented_by_method] = (True, len(notes))

else:
matrix[hw_requirement][implemented_by_method] = (True, None)

output_filepath.write_text(render_template_file(
template_filepath,
LOGGER=logger,
MATRIX=matrix,
NOTES=notes))


if __name__ == '__main__':
main()
44 changes: 44 additions & 0 deletions docs/templates/hardware-matrix.rst.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{#
A Jinja2 template for rendering HW requirement support matrix in tmt's own docs.
#}

.. _/plugins/provision/hardware-requirement-support-matrix:

Hardware requirement support
----------------------------

Below you can find a matrix documenting which hardware requirement are
supported by plugins bundled with tmt.

.. role:: supported

.. role:: unsupported

.. list-table::
:header-rows: 1

* - Requirement
{% for plugin in MATRIX['memory'].keys() %}
{% if plugin == 'virtual.testcloud' %}
- ``virtual``
{% else %}
- ``{{ plugin }}``
{% endif %}
{% endfor %}

{% for requirement, plugins in MATRIX.items() %}
* - :ref:`{{ requirement }}{# djlint:off #}</spec/hardware/{# djlint:on H025 #}{{ requirement }}>`
{% for plugin, (enabled, note_id) in plugins.items() %}
{% if enabled %}
- :supported:`yes`{% if note_id %} [{{ note_id }}]_{% endif %}

{% else %}
- :unsupported:`no`

{% endif %}
{% endfor %}
{% endfor %}

{% for note in NOTES %}
.. [{{ loop.index }}] {{ note }}
{% endfor %}
4 changes: 4 additions & 0 deletions spec/hardware/main.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ description: |
requirements. For example one consistent way how to specify
`at least 2 GB of RAM` for all supported provisioners.

The current state of support of HW requirements among plugins
bundled with tmt is available at
:ref:`/plugins/provision/hardware-requirement-support-matrix`.

Introduction
^^^^^^^^^^^^

Expand Down

0 comments on commit f73dd7a

Please sign in to comment.