6033967e6a
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
79 lines
2.8 KiB
Python
79 lines
2.8 KiB
Python
"""Mount OpenStack service routers onto the FastAPI application."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import FastAPI
|
|
|
|
from app.openstack.contract_loader import ensure_loaded, load_series_pack
|
|
from app.openstack.dispatch import ServiceDispatchMiddleware, ServiceStateMiddleware
|
|
from app.openstack.engine import mount_generic_services
|
|
from app.openstack.errors import OpenStackError, openstack_error_handler
|
|
from app.openstack.microversions import MicroversionMiddleware
|
|
from app.openstack.registry import HandlerRegistry, register_specialized_handlers
|
|
from app.openstack.routes import (
|
|
cinder,
|
|
glance,
|
|
heat,
|
|
ironic,
|
|
keystone,
|
|
neutron,
|
|
nova,
|
|
octavia,
|
|
placement,
|
|
root,
|
|
swift,
|
|
)
|
|
from app.openstack.schema_engine import mount_schema_services
|
|
|
|
|
|
# Specialized routers provide stateful handlers; contract packs register every
|
|
# path. Legacy generic engine remains as a final fallback for undeclared services.
|
|
_SPECIALIZED_ROUTERS: list[tuple[str, object]] = [
|
|
("keystone", keystone.router),
|
|
("nova", nova.router),
|
|
("neutron", neutron.router),
|
|
("glance", glance.router),
|
|
("cinder", cinder.router),
|
|
("placement", placement.router),
|
|
("heat", heat.router),
|
|
("swift", swift.router),
|
|
("ironic", ironic.router),
|
|
("octavia", octavia.router),
|
|
]
|
|
|
|
|
|
def build_openstack_handlers() -> HandlerRegistry:
|
|
"""Collect stateful handlers from specialized routers into a registry."""
|
|
|
|
registry = HandlerRegistry()
|
|
for name, router in _SPECIALIZED_ROUTERS:
|
|
register_specialized_handlers(registry, name, router) # type: ignore[arg-type]
|
|
return registry
|
|
|
|
|
|
def mount_openstack_routes(app: FastAPI, *, series: str = "dalmatian") -> None:
|
|
"""Register all OpenStack Identity + IaaS + schema-complete APIs."""
|
|
|
|
app.add_exception_handler(OpenStackError, openstack_error_handler)
|
|
|
|
# Order matters: last added = outermost. Dispatch must be outermost so
|
|
# rewritten paths reach routers; microversions see original headers.
|
|
app.add_middleware(MicroversionMiddleware)
|
|
app.add_middleware(ServiceStateMiddleware)
|
|
app.add_middleware(ServiceDispatchMiddleware)
|
|
|
|
# Port-aware version discovery stays on bare "/".
|
|
app.include_router(root.router)
|
|
|
|
# Contract is the sole path source; specialized routers contribute handlers only.
|
|
handlers = build_openstack_handlers()
|
|
ensure_loaded(series)
|
|
mounted = mount_schema_services(app, series=series, handlers=handlers)
|
|
app.state.openstack_schema_ops = mounted
|
|
app.state.openstack_handlers = handlers
|
|
|
|
# Legacy generic CRUD only for services without a schema pack (avoid
|
|
# /{item_id} stealing /detail and other static schema paths).
|
|
schema_services = set(load_series_pack(series).keys())
|
|
mount_generic_services(app, skip=schema_services)
|