Skip to content
Open
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
34 changes: 34 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import guzzle_sphinx_theme

from pyinfra import __version__, local
from pyinfra.api import metadata

copyright = "Nick Barrett {0} — pyinfra v{1}".format(
date.today().year,
Expand Down Expand Up @@ -57,9 +58,42 @@
]


def rstjinja(app, docname, source):
"""
Render certain pages as a jinja templates.
"""
# this should only be run when building html
if app.builder.format != "html":
return
# We currently only render docs/operations.rst
# and docs/facts.rst as jinja2 templates
if docname in ["operations", "facts"]:
src = source[0]
rendered = app.builder.templates.render_string(src, app.config.html_context)
source[0] = rendered


def setup(app):
app.connect("source-read", rstjinja)
this_dir = path.dirname(path.realpath(__file__))
scripts_dir = path.abspath(path.join(this_dir, "..", "scripts"))
metadata_file = path.abspath(path.join(this_dir, "..", "pyinfra-metadata.toml"))
if not path.exists(metadata_file):
raise ValueError("No pyinfra-metadata.toml in project root")
with open(metadata_file, "r") as file:
metadata_text = file.read()
plugins = metadata.parse_plugins(metadata_text)

operation_plugins = [p for p in plugins if p.type == "operation"]
fact_plugins = [p for p in plugins if p.type == "fact"]
html_context = {
"operation_plugins": operation_plugins,
"fact_plugins": fact_plugins,
"tags": metadata.ALLOWED_TAGS,
"docs_language": language,
"docs_version": version,
}
app.config.html_context = html_context

for auto_docs_name in ("operations", "facts", "apidoc", "connectors"):
auto_docs_path = path.join(this_dir, auto_docs_name)
Expand Down
69 changes: 48 additions & 21 deletions docs/facts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,53 @@ You can leverage facts within :doc:`operations <using-operations>` like this:

**Want a new fact?** Check out :doc:`the writing facts guide <./api/operations>`.

Facts, like :doc:`operations <operations>`, are namespaced as different modules - shortcuts to each of these can be found in the sidebar.

.. raw:: html

<style type="text/css">
#facts-index .toctree-wrapper > ul {
padding: 0;
}
#facts-index .toctree-wrapper > ul > li {
padding: 0;
list-style: none;
margin: 20px 0;
}
#facts-index .toctree-wrapper > ul > li > ul > li {
display: inline-block;
}
</style>

.. toctree::
:maxdepth: 2
:glob:

facts/*
<div class="container my-4">
<!-- Dropdown Filter -->
<div class="mb-4">
<label for="tag-dropdown" class="form-label">Filter by Tag:</label>
<select class="form-select" id="tag-dropdown">
<option value="All">All</option>
{% for tag in tags %}
<option value="{{ tag.title_case }}">{{ tag.title_case }}</option>
{% endfor %}
</select>
</div>

<!-- Cards Grid -->
<div class="row" id="card-container">
{% for plugin in fact_plugins %}
<div class="col-md-4 mb-4 card-item">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">
<a href="{{ docs_language }}/{{ docs_version }}/facts/{{ plugin.name }}.html">
{{ plugin.name }}
</a>
<p class="card-text">{{ plugin.description }}</p>
{% for tag in plugin.tags %}
<span class="badge bg-secondary">{{ tag.title_case }}</span>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script>
document.getElementById('tag-dropdown').addEventListener('change', function () {
const selectedTag = this.value;
const cards = document.querySelectorAll('.card-item');

cards.forEach(card => {
const tags = Array.from(card.querySelectorAll('.badge')).map(badge => badge.textContent.trim());

if (selectedTag === 'All' || tags.includes(selectedTag)) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});
</script>
96 changes: 49 additions & 47 deletions docs/operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,52 @@ Operations are used to describe changes to make to systems in the inventory. Use

.. raw:: html

<h3>Popular operations by category</h3>

.. admonition:: Basics
:class: note inline

:doc:`operations/files`, :doc:`operations/server`, :doc:`operations/git`, :doc:`operations/systemd`

.. admonition:: System Packages
:class: note inline

:doc:`operations/apt`, :doc:`operations/apk`, :doc:`operations/brew`, :doc:`operations/dnf`, :doc:`operations/yum`

.. admonition:: Language Packages
:class: note inline

:doc:`operations/gem`, :doc:`operations/npm`, :doc:`operations/pip`

.. admonition:: Databases
:class: note inline

:doc:`operations/postgresql`, :doc:`operations/mysql`

.. raw:: html

<h3>All operations alphabetically</h3>

.. raw:: html

<style type="text/css">
#operations-index .toctree-wrapper > ul {
padding: 0;
}
#operations-index .toctree-wrapper > ul > li {
padding: 0;
list-style: none;
margin: 20px 0;
}
#operations-index .toctree-wrapper > ul > li > ul > li {
display: inline-block;
}
</style>

.. toctree::
:maxdepth: 2
:glob:

operations/*
<div class="container my-4">
<!-- Dropdown Filter -->
<div class="mb-4">
<label for="tag-dropdown" class="form-label">Filter by Tag:</label>
<select class="form-select" id="tag-dropdown">
<option value="All">All</option>
{% for tag in tags %}
<option value="{{ tag.title_case }}">{{ tag.title_case }}</option>
{% endfor %}
</select>
</div>

<!-- Cards Grid -->
<div class="row" id="card-container">
{% for plugin in operation_plugins %}
<div class="col-md-4 mb-4 card-item">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">
<a href="{{ docs_language }}/{{ docs_version }}/operations/{{ plugin.name }}.html">
{{ plugin.name }}
</a>
</h5>
<p class="card-text">{{ plugin.description }}</p>
{% for tag in plugin.tags %}
<span class="badge bg-secondary">{{ tag.title_case }}</span>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script>
document.getElementById('tag-dropdown').addEventListener('change', function () {
const selectedTag = this.value;
const cards = document.querySelectorAll('.card-item');

cards.forEach(card => {
const tags = Array.from(card.querySelectorAll('.badge')).map(badge => badge.textContent.trim());

if (selectedTag === 'All' || tags.includes(selectedTag)) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});
</script>
57 changes: 57 additions & 0 deletions pyinfra-metadata-schema-1.0.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "pyinfra-metadata Configuration",
"type": "object",
"properties": {
"$schema": {
"type": "string"
},
"pyinfra": {
"type": "object",
"properties": {
"plugins": {
"type": "object",
"minProperties": 1,
"patternProperties": {
"^.*$": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"operation",
"fact",
"connector"
]
},
"path": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"type",
"path",
"tags"
],
"additionalProperties": false
}
}
}},
"required": [
"plugins"
],
"additionalProperties": false
}
},
"required": ["pyinfra"]
}
Loading