Created
April 3, 2026 19:15
-
-
Save lennysh/58cadf2d8c9e59e61e3aea4899040769 to your computer and use it in GitHub Desktop.
Convert `oc explain ...` text to a commented YAML skeleton under `spec:`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Convert `oc explain ...` text to a commented YAML skeleton under `spec:`. | |
| Usage: | |
| oc explain automationcontrollers.spec --api-version=... | oc-explain-to-yaml-template | |
| oc explain ... | oc-explain-to-yaml-template --disabled | |
| With --disabled, assignment lines are commented as "#fieldname: placeholder" | |
| (no space after # so the key is easy to spot). Type stays a normal comment: | |
| "# <type>". | |
| Placeholders from explain types: string -> "", integer -> 0, boolean -> false, | |
| Object -> {}, []string / []Object -> [] | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import re | |
| import sys | |
| FIELD_LINE = re.compile(r"^ ([a-zA-Z0-9_]+)\s+<([^>]+)>\s*$") | |
| def placeholder_for_type(type_str: str) -> str: | |
| t = type_str.strip() | |
| if t == "string": | |
| return '""' | |
| if t == "integer": | |
| return "0" | |
| if t == "boolean": | |
| return "false" | |
| if t == "Object": | |
| return "{}" | |
| if t == "[]string": | |
| return "[]" | |
| if t == "[]Object": | |
| return "[]" | |
| return "null" | |
| def yaml_comment_block(text: str, indent: str) -> list[str]: | |
| lines = [] | |
| for raw in text.strip().splitlines(): | |
| line = raw.rstrip() | |
| if not line: | |
| continue | |
| safe = line | |
| if safe.startswith("#"): | |
| safe = " " + safe | |
| lines.append(f"{indent}# {safe}") | |
| return lines | |
| def parse_fields(body: str) -> list[tuple[str, str, str]]: | |
| """Return (name, type_str, comment_text) per field.""" | |
| if "FIELDS:" not in body: | |
| return [] | |
| _, rest = body.split("FIELDS:", 1) | |
| lines = rest.splitlines() | |
| fields: list[tuple[str, str, str]] = [] | |
| name: str | None = None | |
| typ: str | None = None | |
| buf: list[str] = [] | |
| def flush() -> None: | |
| nonlocal name, typ, buf | |
| if name is not None and typ is not None: | |
| fields.append((name, typ, "\n".join(buf))) | |
| name = None | |
| typ = None | |
| buf = [] | |
| for line in lines: | |
| m = FIELD_LINE.match(line) | |
| if m: | |
| flush() | |
| name, typ = m.group(1), m.group(2) | |
| continue | |
| if name is None: | |
| continue | |
| s = line.rstrip() | |
| if not s: | |
| continue | |
| if s.startswith(" "): | |
| buf.append(s[4:]) | |
| elif s.startswith(" enum:"): | |
| buf.append(s[2:]) | |
| else: | |
| buf.append(s.strip()) | |
| flush() | |
| return fields | |
| def emit_yaml(fields: list[tuple[str, str, str]], *, disabled: bool) -> str: | |
| out: list[str] = [ | |
| "# Generated from oc explain — fill in values.", | |
| "# For Object fields, run: oc explain automationcontrollers.spec.<field> \\", | |
| "# --api-version=automationcontroller.ansible.com/v1beta1", | |
| "", | |
| "spec:", | |
| ] | |
| for field_name, type_str, comment in fields: | |
| out.append("") | |
| if comment.strip(): | |
| out.extend(yaml_comment_block(comment, " ")) | |
| ph = placeholder_for_type(type_str) | |
| out.append(f" # <{type_str}>") | |
| if disabled: | |
| out.append(f" #{field_name}: {ph}") | |
| else: | |
| out.append(f" {field_name}: {ph}") | |
| out.append("") | |
| return "\n".join(out) | |
| def main() -> int: | |
| parser = argparse.ArgumentParser( | |
| description="Convert oc explain output to a spec YAML skeleton.", | |
| ) | |
| parser.add_argument( | |
| "--disabled", | |
| action="store_true", | |
| help="Comment out field: value lines (#name: placeholder); type stays # <type>", | |
| ) | |
| args = parser.parse_args() | |
| raw = sys.stdin.read() | |
| if not raw.strip(): | |
| print("oc-explain-to-yaml-template: empty stdin", file=sys.stderr) | |
| return 1 | |
| fields = parse_fields(raw) | |
| if not fields: | |
| print( | |
| "oc-explain-to-yaml-template: no FIELDS: section found", | |
| file=sys.stderr, | |
| ) | |
| return 1 | |
| sys.stdout.write(emit_yaml(fields, disabled=args.disabled)) | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment