def init_app(settings: Optional[AppSettings] = None) -> FastAPI: if settings is None: settings = AppSettings.create_from_envs() assert settings # nosec logging.basicConfig(level=settings.LOG_LEVEL.value) logging.root.setLevel(settings.LOG_LEVEL.value) logger.debug(settings.json(indent=2)) app = FastAPI( debug=settings.SC_BOOT_MODE in [BootModeEnum.DEBUG, BootModeEnum.DEVELOPMENT, BootModeEnum.LOCAL], title=PROJECT_NAME, description=SUMMARY, version=API_VERSION, openapi_url=f"/api/{API_VTAG}/openapi.json", docs_url="/dev/doc", redoc_url=None, # default disabled ) override_fastapi_openapi_method(app) app.state.settings = settings if settings.SC_BOOT_MODE == BootModeEnum.DEBUG: remote_debug.setup(app) if settings.DIRECTOR_V0.DIRECTOR_V0_ENABLED: director_v0.setup(app, settings.DIRECTOR_V0) if settings.POSTGRES.DIRECTOR_V2_POSTGRES_ENABLED: db.setup(app, settings.POSTGRES) if settings.DYNAMIC_SERVICES.DIRECTOR_V2_DYNAMIC_SERVICES_ENABLED: dynamic_services.setup(app, settings.DYNAMIC_SERVICES) if settings.DYNAMIC_SERVICES.DYNAMIC_SIDECAR and ( settings.DYNAMIC_SERVICES.DYNAMIC_SCHEDULER and settings.DYNAMIC_SERVICES.DYNAMIC_SCHEDULER. DIRECTOR_V2_DYNAMIC_SCHEDULER_ENABLED): dynamic_sidecar.setup(app) if settings.DASK_SCHEDULER.DIRECTOR_V2_DASK_CLIENT_ENABLED: dask_clients_pool.setup(app, settings.DASK_SCHEDULER) if settings.DASK_SCHEDULER.DIRECTOR_V2_DASK_SCHEDULER_ENABLED: rabbitmq.setup(app) comp_scheduler.setup(app) if settings.DIRECTOR_V2_TRACING: setup_tracing(app, settings.DIRECTOR_V2_TRACING) # setup app -- app.add_event_handler("startup", on_startup) app.add_event_handler("shutdown", on_shutdown) _set_exception_handlers(app) app.include_router(api_router) config_all_loggers() return app
def assemble_application() -> FastAPI: """ Creates the application from using the env vars as a context Also stores inside the state all instances of classes needed in other requests and used to share data. """ dynamic_sidecar_settings = DynamicSidecarSettings.create_from_envs() logging.basicConfig(level=dynamic_sidecar_settings.loglevel) logging.root.setLevel(dynamic_sidecar_settings.loglevel) logger.debug(dynamic_sidecar_settings.json(indent=2)) application = FastAPI( debug=dynamic_sidecar_settings.DEBUG, openapi_url=f"/api/{API_VTAG}/openapi.json", docs_url="/dev/doc", ) override_fastapi_openapi_method(application) # store "settings" and "shared_store" for later usage application.state.settings = dynamic_sidecar_settings application.state.shared_store = SharedStore( settings=dynamic_sidecar_settings) # type: ignore # used to keep track of the health of the application # also will be used in the /health endpoint application.state.application_health = ApplicationHealth() # enable debug if required if dynamic_sidecar_settings.is_development_mode: remote_debug_setup(application) if dynamic_sidecar_settings.RABBIT_SETTINGS: setup_rabbitmq(application) # requires rabbitmq to be in place setup_background_log_fetcher(application) # add routing paths application.include_router(main_router) setup_directory_watcher(application) def create_start_app_handler() -> Callable[[], Coroutine[Any, Any, None]]: async def on_startup() -> None: await login_registry(application.state.settings.REGISTRY_SETTINGS) print(WELCOME_MSG, flush=True) return on_startup def create_stop_app_handler() -> Callable[[], Coroutine[Any, Any, None]]: async def on_shutdown() -> None: await on_shutdown_handler(application) logger.info("shutdown cleanup completed") return on_shutdown application.add_event_handler("startup", create_start_app_handler()) application.add_event_handler("shutdown", create_stop_app_handler()) return application
def test_overriding_openapi_method(app: FastAPI): assert not hasattr(app, "_original_openapi") assert app.openapi.__doc__ is None override_fastapi_openapi_method(app) assert hasattr(app, "_original_openapi") assert "Overrides FastAPI.openapi member function" in str( app.openapi.__doc__) # override patches should now work openapi = app.openapi() assert openapi and isinstance(openapi, dict) validate_spec(openapi) params = openapi["paths"]["/data"]["get"]["parameters"] assert params == [ { "required": True, "schema": { "title": "X", "exclusiveMinimum": True, "type": "number", "minimum": 0.0, }, "name": "x", "in": "query", }, { "required": True, "schema": { "title": "Y", "exclusiveMaximum": True, "exclusiveMinimum": True, "type": "integer", "maximum": 4, "minimum": 3, }, "name": "y", "in": "query", }, ]
def init_app(settings: Optional[AppSettings] = None) -> FastAPI: if settings is None: settings = AppSettings.create_from_envs() assert settings # nosec logging.basicConfig(level=settings.LOG_LEVEL.value) logging.root.setLevel(settings.LOG_LEVEL.value) logger.debug(settings.json(indent=2)) app = FastAPI( debug=settings.SC_BOOT_MODE in [BootModeEnum.DEBUG, BootModeEnum.DEVELOPMENT, BootModeEnum.LOCAL], title=PROJECT_NAME, description=SUMMARY, version=API_VERSION, openapi_url=f"/api/{API_VTAG}/openapi.json", docs_url="/dev/doc", redoc_url=None, # default disabled ) override_fastapi_openapi_method(app) app.state.settings = settings if settings.SC_BOOT_MODE == BootModeEnum.DEBUG: remote_debug.setup(app) if settings.DIRECTOR_V0.DIRECTOR_V0_ENABLED: director_v0.setup(app, settings.DIRECTOR_V0) if settings.POSTGRES.DIRECTOR_V2_POSTGRES_ENABLED: db.setup(app, settings.POSTGRES) if settings.DYNAMIC_SERVICES.DIRECTOR_V2_DYNAMIC_SERVICES_ENABLED: dynamic_services.setup(app, settings.DYNAMIC_SERVICES) if settings.DYNAMIC_SERVICES.DYNAMIC_SIDECAR and ( settings.DYNAMIC_SERVICES.DYNAMIC_SCHEDULER and settings.DYNAMIC_SERVICES.DYNAMIC_SCHEDULER. DIRECTOR_V2_DYNAMIC_SCHEDULER_ENABLED): dynamic_sidecar.setup(app) if settings.DASK_SCHEDULER.DIRECTOR_V2_DASK_CLIENT_ENABLED: dask_clients_pool.setup(app, settings.DASK_SCHEDULER) if settings.DASK_SCHEDULER.DIRECTOR_V2_DASK_SCHEDULER_ENABLED: rabbitmq.setup(app) comp_scheduler.setup(app) if settings.DIRECTOR_V2_TRACING: setup_tracing(app, settings.DIRECTOR_V2_TRACING) # setup app -- app.add_event_handler("startup", on_startup) app.add_event_handler("shutdown", on_shutdown) app.add_exception_handler(HTTPException, http_error_handler) app.add_exception_handler(RequestValidationError, http422_error_handler) # director-v2 core.errors mappend into HTTP errors app.add_exception_handler( ProjectNotFoundError, make_http_error_handler_for_exception(status.HTTP_404_NOT_FOUND, ProjectNotFoundError), ) app.add_exception_handler( PipelineNotFoundError, make_http_error_handler_for_exception(status.HTTP_404_NOT_FOUND, PipelineNotFoundError), ) # SEE https://docs.python.org/3/library/exceptions.html#exception-hierarchy app.add_exception_handler( NotImplementedError, make_http_error_handler_for_exception(status.HTTP_501_NOT_IMPLEMENTED, NotImplementedError), ) app.add_exception_handler( Exception, make_http_error_handler_for_exception( status.HTTP_500_INTERNAL_SERVER_ERROR, Exception), ) app.include_router(api_router) config_all_loggers() return app
def init_app(settings: Optional[AppSettings] = None) -> FastAPI: if settings is None: settings = AppSettings.create_from_envs() assert settings # nosec logging.basicConfig(level=settings.CATALOG_LOG_LEVEL.value) logging.root.setLevel(settings.CATALOG_LOG_LEVEL.value) logger.debug(settings.json(indent=2)) app = FastAPI( debug=settings.SC_BOOT_MODE in [BootModeEnum.DEBUG, BootModeEnum.DEVELOPMENT, BootModeEnum.LOCAL], title=PROJECT_NAME, description=SUMMARY, version=API_VERSION, openapi_url=f"/api/{API_VTAG}/openapi.json", docs_url="/dev/doc", redoc_url=None, # default disabled ) override_fastapi_openapi_method(app) app.state.settings = settings setup_function_services(app) # events app.add_event_handler("startup", on_startup) app.add_event_handler("startup", create_start_app_handler(app)) app.add_event_handler("shutdown", on_shutdown) app.add_event_handler("shutdown", create_stop_app_handler(app)) # exception handlers app.add_exception_handler(HTTPException, http_error_handler) app.add_exception_handler(RequestValidationError, http422_error_handler) # SEE https://docs.python.org/3/library/exceptions.html#exception-hierarchy app.add_exception_handler( NotImplementedError, make_http_error_handler_for_exception(status.HTTP_501_NOT_IMPLEMENTED, NotImplementedError), ) app.add_exception_handler( Exception, make_http_error_handler_for_exception( status.HTTP_500_INTERNAL_SERVER_ERROR, Exception), ) # Routing # healthcheck at / and at /v0/ app.include_router(health_router) # api under /v* app.include_router(api_router, prefix=f"/{API_VTAG}") # middleware to time requests (ONLY for development) if settings.SC_BOOT_MODE != BootModeEnum.PRODUCTION: async def _add_process_time_header(request: Request, call_next: Callable): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(process_time) return response app.add_middleware(BaseHTTPMiddleware, dispatch=_add_process_time_header) # gzip middleware app.add_middleware(GZipMiddleware) return app
def init_app(settings: Optional[AppSettings] = None) -> FastAPI: if settings is None: settings = AppSettings.create_default() logging.basicConfig(level=settings.loglevel) logging.root.setLevel(settings.loglevel) app = FastAPI( debug=settings.debug, title="Components Catalog Service", description= "Manages and maintains a **catalog** of all published components (e.g. macro-algorithms, scripts, etc)", version=api_version, openapi_url=f"/api/{api_vtag}/openapi.json", docs_url="/dev/doc", redoc_url=None, # default disabled ) override_fastapi_openapi_method(app) logger.debug("App settings:%s", settings.json(indent=2)) app.state.settings = settings setup_frontend_services(app) # events app.add_event_handler("startup", on_startup) app.add_event_handler("startup", create_start_app_handler(app)) app.add_event_handler("shutdown", on_shutdown) app.add_event_handler("shutdown", create_stop_app_handler(app)) # exception handlers app.add_exception_handler(HTTPException, http_error_handler) app.add_exception_handler(RequestValidationError, http422_error_handler) # SEE https://docs.python.org/3/library/exceptions.html#exception-hierarchy app.add_exception_handler( NotImplementedError, make_http_error_handler_for_exception(status.HTTP_501_NOT_IMPLEMENTED, NotImplementedError), ) app.add_exception_handler( Exception, make_http_error_handler_for_exception( status.HTTP_500_INTERNAL_SERVER_ERROR, Exception), ) # Routing # healthcheck at / and at /v0/ app.include_router(health_router) # api under /v* app.include_router(api_router, prefix=f"/{api_vtag}") # middleware to time requests (ONLY for development) if settings.boot_mode != BootModeEnum.PRODUCTION: @app.middleware("http") async def _add_process_time_header(request: Request, call_next: Callable): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time response.headers["X-Process-Time"] = str(process_time) return response # gzip middleware app.add_middleware(GZipMiddleware) return app