diff --git a/autogen.sh b/autogen.sh index 5d26d18..ff9f226 100755 --- a/autogen.sh +++ b/autogen.sh @@ -28,9 +28,9 @@ for pvd in "${providers[@]}"; do fi done -# generate the module classes +# generate the module classes and docs for pvd in "${providers[@]}"; do - echo "generating the modules for provider '$pvd'" + echo "generating the modules & docs for provider '$pvd'" python -m scripts.generate "$pvd" done diff --git a/config.py b/config.py index dc0cca6..67f56a0 100644 --- a/config.py +++ b/config.py @@ -6,6 +6,7 @@ APP_NAME = "diagrams" +DIR_DOC_ROOT = "docs/nodes" DIR_APP_ROOT = "diagrams" DIR_RESOURCE = "resources" DIR_TEMPLATE = "templates" @@ -29,6 +30,12 @@ FILE_PREFIXES = { } ######################### +# Doc Auto Generation # +######################### + +TMPL_APIDOC = "apidoc.tmpl" + +######################### # Class Auto Generation # ######################### @@ -39,8 +46,9 @@ UPPER_WORDS = { "azure": ("ad", "b2c", "ai", "api", "cdn", "ddos", "dns", "fxt", "hana", "hd", "id", "sap", "sql", "vm"), "gcp": ("gcp", "ai", "api", "cdn", "dns", "gke", "gpu", "ml", "nat", "os", "sdk", "sql", "tpu", "vpn"), "k8s": ( - "api", "cm", "ccm", "crb", "crd", "ds", "etcd", "hpa", "ns", "psp", "pv", "pvc", "rb", "rs", "sa", "sc", "sts", - "svc"), + "api", "cm", "ccm", "crb", "crd", "ds", "etcd", "hpa", "k8s", "ns", "psp", "pv", "pvc", "rb", "rs", + "sa", "sc", "sts", "svc", + ), } # TODO: check if the classname exists diff --git a/scripts/__init__.py b/scripts/__init__.py index 285441b..da78298 100644 --- a/scripts/__init__.py +++ b/scripts/__init__.py @@ -9,6 +9,11 @@ def app_root_dir(pvd: str) -> str: return os.path.join(basedir.parent, cfg.DIR_APP_ROOT, pvd) +def doc_root_dir() -> str: + basedir = Path(os.path.abspath(os.path.dirname(__file__))) + return os.path.join(basedir.parent, cfg.DIR_DOC_ROOT) + + def resource_dir(pvd: str) -> str: basedir = Path(os.path.abspath(os.path.dirname(__file__))) return os.path.join(basedir.parent, cfg.DIR_RESOURCE, pvd) diff --git a/scripts/generate.py b/scripts/generate.py index 6c8cb70..dc28025 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -5,7 +5,7 @@ from typing import Iterable from jinja2 import Environment, FileSystemLoader, Template import config as cfg -from . import app_root_dir, resource_dir, template_dir +from . import app_root_dir, doc_root_dir, resource_dir, template_dir _usage = "Usage: generate.py " @@ -24,6 +24,8 @@ def gen_classes(pvd: str, typ: str, paths: Iterable[str]) -> str: """Generate all service node classes based on resources paths with class templates.""" tmpl = load_tmpl(cfg.TMPL_MODULE) + # TODO: extract the gen class metas for sharing + # TODO: independent function for generating all pvd/typ/paths pairs def _gen_class_meta(path: str) -> dict: base = os.path.splitext(path)[0] name = "".join([up_or_title(pvd, s) for s in base.split("-")]) @@ -34,6 +36,24 @@ def gen_classes(pvd: str, typ: str, paths: Iterable[str]) -> str: return tmpl.render(pvd=pvd, typ=typ, metas=metas, aliases=aliases) +def gen_apidoc(pvd: str, typ_paths: dict) -> str: + tmpl = load_tmpl(cfg.TMPL_APIDOC) + + # TODO: remove + def _gen_class_name(path: str) -> str: + base = os.path.splitext(path)[0] + name = "".join([up_or_title(pvd, s) for s in base.split("-")]) + return name + + typ_classes = {} + for typ, paths in typ_paths.items(): + typ_classes[typ] = [] + for name in map(_gen_class_name, paths): + alias = cfg.ALIASES[pvd].get(typ, {}).get(name) + typ_classes[typ].append({'name': name, 'alias': alias}) + return tmpl.render(pvd=pvd, typ_classes=typ_classes) + + def make_module(pvd: str, typ: str, classes: str) -> None: """Create a module file""" mod_path = os.path.join(app_root_dir(pvd), f"{typ}.py") @@ -41,13 +61,21 @@ def make_module(pvd: str, typ: str, classes: str) -> None: f.write(classes) +def make_apidoc(pvd: str, content: str) -> None: + """Create an api documentation file""" + mod_path = os.path.join(doc_root_dir(), f"{pvd}.md") + with open(mod_path, "w+") as f: + f.write(content) + + def generate(pvd: str) -> None: """Generates a service node classes.""" + typ_paths = {} for root, _, files in os.walk(resource_dir(pvd)): # Extract the names and paths from resources. files.sort() - pngs = filter(lambda f: f.endswith(".png"), files) - paths = filter(lambda f: "rounded" not in f, pngs) + pngs = list(filter(lambda f: f.endswith(".png"), files)) + paths = list(filter(lambda f: "rounded" not in f, pngs)) # Skip the top-root directory. typ = os.path.basename(root) @@ -57,6 +85,11 @@ def generate(pvd: str) -> None: classes = gen_classes(pvd, typ, paths) make_module(pvd, typ, classes) + typ_paths[typ] = paths + # Build API documentation + apidoc = gen_apidoc(pvd, typ_paths) + make_apidoc(pvd, apidoc) + if __name__ == "__main__": pvd = sys.argv[1] diff --git a/scripts/resource.py b/scripts/resource.py index 386f277..d9f130b 100644 --- a/scripts/resource.py +++ b/scripts/resource.py @@ -52,7 +52,7 @@ def cleaner_k8s(f): f = f.replace("-256", "") for p in cfg.FILE_PREFIXES["k8s"]: if f.startswith(p): - f = f[len(p):] + f = f[len(p) :] break return f.lower() diff --git a/templates/apidoc.tmpl b/templates/apidoc.tmpl new file mode 100644 index 0000000..af10ceb --- /dev/null +++ b/templates/apidoc.tmpl @@ -0,0 +1,11 @@ +--- +id: {{ pvd }} +title: {{ pvd|up_or_title(pvd) }} +--- + +Node classes list of {{ pvd }} provider. +{% for typ, classes in typ_classes.items() %} +## {{ pvd }}.{{ typ }} +{% for class in classes %} +- **diagrams.{{ pvd }}.{{ typ }}.{{ class['name'] }}**{% if class['alias'] %}, **{{ class['alias'] }}** (alias){% endif %}{% endfor %} +{% endfor %}