diff --git a/src/pulp_docs/constants.py b/src/pulp_docs/constants.py index ed33eed..a51349e 100644 --- a/src/pulp_docs/constants.py +++ b/src/pulp_docs/constants.py @@ -1,5 +1,12 @@ """Project constants.""" +BASE_TMPDIR_NAME = "pulpdocs_tmp" +"""Base temporary directory name for all pulp-docs operations.""" + +OPENAPI_JSON_DIR = "openapi" +"""Relative to src/pulp_docs/.""" + + SECTION_REPO = "pulp-docs" """The repository which contains section pages""" diff --git a/src/pulp_docs/data/openapi_json/.gitkeep b/src/pulp_docs/data/openapi_json/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/pulp_docs/openapi.py b/src/pulp_docs/openapi.py new file mode 100644 index 0000000..7fdf6bb --- /dev/null +++ b/src/pulp_docs/openapi.py @@ -0,0 +1,118 @@ +""" +Module for generating open-api json files for selected Pulp plugins. +""" +import os +import shutil +import subprocess +import tempfile +from pathlib import Path +from typing import NamedTuple + +from importlib_resources import files + +from pulp_docs.constants import BASE_TMPDIR_NAME +from pulp_docs.repository import Repo, Repos + + +class PulpPlugin(NamedTuple): + """ + A Pulp plugin. + + Args: + name: The repository name for plugin as it exists in github.com + label: The label of the plugin as its used in django (e.g, pulpcore.label == core) + """ + + name: str + label: str + + +class OpenAPIGenerator: + """ + Responsible for seting up a python environment with the required + Pulp packages to generate openapi schemas for all registered plugins. + + Args: + plugin_remotes: A list of git remote urls of the required Pulp packages. + target_dir: The path to where the {plugin-label}-api.json files should be saved. + """ + + def __init__(self, plugins: list[PulpPlugin], target_dir: Path): + URL_TEMPLATE = "https://github.com/pulp/{}" + self.plugin_remotes = [URL_TEMPLATE.format(p.name) for p in plugins] + self.plugin_labels = [p.label for p in plugins] + self.target_dir = target_dir + self.tmpdir = Path(tempfile.gettempdir()) / BASE_TMPDIR_NAME / "openapi" + shutil.rmtree(self.tmpdir, ignore_errors=True) + os.makedirs(self.tmpdir, exist_ok=True) + + def generate(self): + """Generate openapi json files at target directory.""" + self.setup_environemnt() + + origin_dir = os.getcwd() + os.chdir(self.tmpdir) + for component in self.plugin_labels: + outfile = str(self.target_dir / f"{component}-api.json") + cmd = ( + "venv/bin/pulpcore-manager", + "openapi", + "--component", + component, + "--file", + outfile, + ) + subprocess.run(cmd, check=True) + with open(outfile, "r") as fd: + print(fd.read()) + + os.chdir(origin_dir) + + def setup_environemnt(self): + """ + Creates virtualenv and install required packages. + """ + # create venv + origin_dir = os.getcwd() + os.chdir(self.tmpdir) + cmd = ("python", "-m", "venv", "venv") + subprocess.run(cmd, check=True) + + # install plugins + for plugin_remote in self.plugin_remotes: + url = f"git+{plugin_remote}" + cmd = ("venv/bin/pip", "install", url) + subprocess.run(cmd, check=True) + + cmd = ("venv/bin/pip", "list") + result = subprocess.run(cmd, capture_output=True, check=True) + print(result.stdout.decode()) + os.chdir(origin_dir) + + +if __name__ == "__main__": + # pulp_ostree requires: + # sudo dnf install cairo-devel gobject-introspection-devel cairo-gobject-devel + repolist = files("pulp_docs").joinpath("data/repolist.yml").absolute() + repos = Repos.from_yaml(repolist).get_repos(["content", "core"]) + repos = [r for r in repos if isinstance(r, Repo)] + pulp_plugins = [] + for repo in repos: + # pulp_container: is pinned to pulpcore<3.55 + # pulp_ansible: importlib-resource pinned to around v5, and rpm requires ~=6 something + # pulp_python: requires settings.CONTENT_ORIGIN on module load + # * https://github.com/pulp/pulp_python/blob/5f5854492f631d670c545ffcd61ae9f020d15d0c/pulp_python/app/pypi/views.py#L55 + if repo.name in ("pulp_ansible", "pulp_container", "pulp_python"): + continue + + name = repo.name + label = name.split("_")[-1] + if name == "pulpcore": + label = "core" + pulp_plugins.append(PulpPlugin(name, label)) + print(pulp_plugins) + + # dest = Path("data/openapi") + dest = Path(tempfile.gettempdir()) / "pulpdocs_tmp" + openapi = OpenAPIGenerator(pulp_plugins, dest) + openapi.generate()