64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Export the API schema without depending on operator configuration or network I/O."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import asyncio
|
|
import json
|
|
import os
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from backup_tool.api.app import create_app
|
|
from backup_tool.config import Settings
|
|
|
|
|
|
def export_schema() -> dict[str, object]:
|
|
"""Build the FastAPI schema with disposable, valid settings."""
|
|
with tempfile.TemporaryDirectory(prefix="backup-tool-openapi-") as temporary:
|
|
root = Path(temporary)
|
|
key = root / "master.key"
|
|
key.write_bytes(b"openapi-export-key-material-must-be-at-least-32-bytes")
|
|
key.chmod(0o600)
|
|
for name in ("data", "repositories", "sources", "restores"):
|
|
(root / name).mkdir()
|
|
settings = Settings(
|
|
data_dir=root / "data",
|
|
database_url=f"sqlite+aiosqlite:///{root / 'data' / 'metadata.db'}",
|
|
repository_roots=(root / "repositories",),
|
|
local_source_roots=(root / "sources",),
|
|
restore_roots=(root / "restores",),
|
|
master_key_file=key,
|
|
)
|
|
app = create_app(settings)
|
|
schema = app.openapi()
|
|
# Engine construction is lazy, but dispose defensively if that changes.
|
|
asyncio.run(app.state.engine.dispose())
|
|
return schema
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Export the deterministic v2 OpenAPI document.")
|
|
parser.add_argument("--output", type=Path, default=Path("openapi/v2.json"))
|
|
parser.add_argument("--check", type=Path, metavar="PATH", help="fail when PATH differs")
|
|
arguments = parser.parse_args()
|
|
output = arguments.check or arguments.output
|
|
rendered = json.dumps(export_schema(), indent=2, sort_keys=True, ensure_ascii=False) + "\n"
|
|
if arguments.check:
|
|
if not output.is_file() or output.read_text(encoding="utf-8") != rendered:
|
|
print(f"OpenAPI drift: regenerate {output}")
|
|
return 1
|
|
print(f"OpenAPI is current: {output}")
|
|
return 0
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
output.write_text(rendered, encoding="utf-8")
|
|
# The schema is public source, not executable configuration.
|
|
os.chmod(output, 0o644)
|
|
print(f"Exported OpenAPI: {output}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|