From 94ac6cd084850f787bf631783e7df1d525f27620 Mon Sep 17 00:00:00 2001 From: sean Date: Mon, 8 Apr 2024 13:59:40 +0200 Subject: [PATCH] update docs and ci --- .github/workflows/release.yaml | 3 + docs/guide/adding.md | 0 docs/guide/auth.md | 1 + docs/guide/overriding.md | 0 docs/guide/registers.md | 108 +++++++++++++++++++++++++ docs/index.md | 1 - docs/setup.md | 96 +++++++++++++++++++++- mkdocs.yml | 4 +- openeo_fastapi/cli.py | 66 ++------------- openeo_fastapi/client/psql/settings.py | 2 +- openeo_fastapi/client/settings.py | 2 - openeo_fastapi/templates.py | 61 ++++++++++++++ 12 files changed, 278 insertions(+), 66 deletions(-) delete mode 100644 docs/guide/adding.md delete mode 100644 docs/guide/overriding.md create mode 100644 docs/guide/registers.md create mode 100644 openeo_fastapi/templates.py diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4383e73..2835211 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -39,3 +39,6 @@ jobs: - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + + - name: Build new documentation + run: mkdocs gh-deploy diff --git a/docs/guide/adding.md b/docs/guide/adding.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/guide/auth.md b/docs/guide/auth.md index e69de29..65e1cbb 100644 --- a/docs/guide/auth.md +++ b/docs/guide/auth.md @@ -0,0 +1 @@ +## To be defined \ No newline at end of file diff --git a/docs/guide/overriding.md b/docs/guide/overriding.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/guide/registers.md b/docs/guide/registers.md new file mode 100644 index 0000000..a1f6c18 --- /dev/null +++ b/docs/guide/registers.md @@ -0,0 +1,108 @@ +## Editing the registers. + +The endpoint registers are a loose abstraction defining what endpoints a register is responsible for, and also what code is expected to be executed for those endpoints. + +The available registers can be imported as follows. + + from openeo_fastapi.client.jobs import JobsRegister + from openeo_fastapi.client.files import FilesRegister + from openeo_fastapi.client.processes import ProcessesRegister + from openeo_fastapi.client.collections import CollectionsRegister + +You will need to know how you are expected to overwrite the functionality of these registers, as the openeo-fastapi package does not define functionality for all available endpoints. + +## How to overwrite an endpoint. + +In the following example, we import the FileRegister, and overwrite the functionality for the list_files method. This will define a new response for that endpoint. This is the framework for editing the functionality of the api endpoints. + + from openeo_fastapi.client.files import FilesRegister + + class OverwrittenFileRegister(FilesRegister): + def __init__(self, settings, links) -> None: + super().__init__(settings, links) + + def list_files( + self, + limit: Optional[int] = 10 + ): + """ """ + return FilesGetResponse( + files=[File(path="/somefile.txt", size=10)], + links=[ + Link( + href="https://eodc.eu/", + rel="about", + type="text/html", + title="Homepage of the service provider", + ) + ], + ) + +In order to use this overwritten file register, we instantiate the register, and parse this to the OpenEOCore object. Now, when the api is next deployed, we will return the FilesGetResponse, and not the default HTTPException. + + extended_register = OverwrittenFileRegister(app_settings, test_links) + + client = OpenEOCore( + ... + files=extended_register, + ... + ) + + api = OpenEOApi(client=client, app=FastAPI()) + +## How to add an endpoint + +The registers can also be extended to include extra functionality. In order to do this, we again need to define a new child class for the register you want to extend. + +We can define a new endpoint for the api as follows. + + from openeo_fastapi.api.types import Endpoint + new_endpoint = Endpoint( + path="/files/{path}", + methods=["HEAD"], + ) + +When defining the child register, the *_initialize_endpoints* method needs to be redefined to add the new_endpoint object. The new functionality can be defined under a new function, here *get_file_headers*. + + from openeo_fastapi.client.files import FilesRegister, FILE_ENDPOINTS + + class ExtendedFileRegister(FilesRegister): + def __init__(self, settings, links) -> None: + super().__init__(settings, links) + self.endpoints = self._initialize_endpoints() + + def _initialize_endpoints(self) -> list[Endpoint]: + endpoints = list(FILE_ENDPOINTS) + endpoints.append(new_endpoint) + return endpoints + + def get_file_headers( + self, path: str, user: User = Depends(Authenticator.validate) + ): + """ """ + return Response( + status_code=200, + headers={ + "Accept-Ranges": "bytes", + }, + ) + + client = OpenEOCore( + ... + files=extended_register, + ... + ) + + api = OpenEOApi(client=client, app=FastAPI()) + +So far, we have made the new code available to the api, but the api does not know how or when to execute the new code. The following snippet will register the new path to the api server, along with the functionality. + + api.app.router.add_api_route( + name="file_headers", + path=f"/{api.client.settings.OPENEO_VERSION}/files" + "/{path}", + response_model=None, + response_model_exclude_unset=False, + response_model_exclude_none=True, + methods=["HEAD"], + endpoint=api.client.files.get_file_headers, + ) \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index c4a1e16..1ca9552 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,4 +7,3 @@ to the database schema, and finally increase the offering of the baseline api wi would like to add. * [Getting Started](setup.md) -* [User Guide](setup.md) \ No newline at end of file diff --git a/docs/setup.md b/docs/setup.md index 54b0c97..3b8b5e3 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -1,5 +1,99 @@ +# Getting Started + +Everything on this page is all you need to go from 0 to having your OpenEO Api server running locally. + ## Environment Setup +The openeo-fastapi package comes with a couple of assumptions. The first assumption, is the package is used to build a server side application. The second assumption is that the user is able to provide a connection to a psql database. The final assumption, is the user has provided the set of required environment variables which are needed for the application to run. + +The following steps will explain how the user can get the application skeleton to run. + ## Installation - pip install openeo-fastapi \ No newline at end of file +Prior to installation, configure and activate a virtual environment for your new project, I can recommend using [poetry](https://python-poetry.org/docs/basic-usage/) for this. Once the environment is activate continue with installing openeo-fastapi. + + + pip install openeo-fastapi + +## Command line interface + +The openeo-fastapi CLI can be used to set up a quick source directory for your deployment. + + openeo_fastapi new /path/to/source/directory + +The command line interface will create the following directory tree. + + src/ + __init__.py + app.py + revise.py + /psql + alembic.ini + models.py + alembic/ + env.py + README + script.py.mako + versions/ + + +The **app.py** file defines the minimal code to define the FastApi application to deploy the API. + +The **revise.py** file defines steps that can be used to generate and apply +alembic revisions to the database deployment. This file is intended to be used after a new release of your deployment, but before your release has been deployed, i.e. as part of an initialization container. This file is optional and can be deleted if you want to complete these steps in a different way. + +The **/psql** directory is used for housing the alembic directory to record the alembic revision history and connectivity to the database. All files ( apart from models.py ) are generated from the alembic init command, so refer to the [alembic docs](https://alembic.sqlalchemy.org/en/latest/) for more information on those files. + +The **/psql/models.py** file defines the basis for importing the orm models from the OpenEO FastApi and defining the metadata class that can then be imported and used in the alembic *env.py* file. + +The **/psql/alembic/env.py** file needs a couple of edits. + +Set the main option for the psql connection. + + config.set_main_option( + "sqlalchemy.url", + f"postgresql://{environ.get('POSTGRES_USER')}:{environ.get('POSTGRES_PASSWORD')}" + f"@{environ.get('POSTGRESQL_HOST')}:{environ.get('POSTGRESQL_PORT')}" + f"/{environ.get('POSTGRES_DB')}", + ) + +Set the target metadata. In this example, I am importing from the **/psql/models.py** file. + + from openeo_api.psql.models import metadata + target_metadata = metadata + + +## Set the environment variables + +These variables need to be set in the environment of the deployment. Those marked required need to be set, and those set False, have some default value that only needs to be provided + +| Variable | Description | Required | +| -------- | ------- | ------- | +| API_DNS | The domain name hosting the API. | True | +| API_TLS | Whether the API http scheme should be http or https. | True | +| API_TITLE | The API title to be provided to FastAPI. | True | +| API_DESCRIPTION | The API description to be provided to FastAPI. | True | +| OPENEO_VERSION | The OpenEO Api specification version supported in this deployment of the API. Defaults to "1.1.0". | False | +| OPENEO_PREFIX | The OpenEO prefix to be used when creating the endpoint urls. Defaults to the value of the openeo_version | True | +| OIDC_URL | The URL of the OIDC provider used to authenticate tokens against. | True | +| OIDC_ORGANISATION | The abbreviation of the OIDC provider's organisation name. | True | +| OIDC_ROLES | The OIDC roles to check against when authenticating a user. | False | +| STAC_VERSION | The STAC Version that is being supported by this deployments data discovery endpoints. Defaults to "1.0.0". | False | +| STAC_API_URL | The STAC URL of the catalogue that the application deployment will proxy to. | True | +| STAC_COLLECTIONS_WHITELIST | The collection ids to filter by when proxying to the Stac catalogue. | False | +| POSTGRES_USER | The name of the postgres user. | True | +| POSTGRES_PASSWORD | The pasword for the postgres user. | True | +| POSTGRESQL_HOST | The host the database runs on. | True | +| POSTGRESQL_PORT | The post on the host the database is available on. | True | +| POSTGRES_DB | The name of the databse being used on the host. | True | +| ALEMBIC_DIR | The path to the alembic directory for applying revisions. | True | + +## Deploy the application. + +1. Revise the database. + + python -m revise.py + +2. Deploy the uvicorn server + + uvicorn openeo_app.main:app --reload diff --git a/mkdocs.yml b/mkdocs.yml index 0d4671d..f788885 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,8 +3,8 @@ nav: - Home: index.md - Getting Started: setup.md - User Guide: - - Override endpoints: guide/overriding.md - - Add new endpoints: guide/adding.md + - Manipulating endpoints: guide/registers.md + - Extend the object relational Models: guide/orms.md - Add your own auth: guide/auth.md - Extend the object relational Models: guide/orms.md - Reference: diff --git a/openeo_fastapi/cli.py b/openeo_fastapi/cli.py index f473921..eeaded4 100644 --- a/openeo_fastapi/cli.py +++ b/openeo_fastapi/cli.py @@ -6,66 +6,12 @@ from alembic.config import Config from pathlib import Path -def get_app_template(): - """ - Generate the default app file for an openeo api app. - """ - return """ -from fastapi import FastAPI - -from openeo_fastapi.api.app import OpenEOApi -from openeo_fastapi.api.types import Billing, FileFormat, GisDataType, Link, Plan -from openeo_fastapi.client.core import OpenEOCore - -formats = [] - -links = [] - -client = OpenEOCore( - input_formats=formats, - output_formats=formats, - links=links, - billing=Billing( - currency="credits", - default_plan="a-cloud", - plans=[Plan(name="user", description="Subscription plan.", paid=True)], - ) +from openeo_fastapi.templates import ( + get_app_template, + get_models_template, + get_revision_template ) -api = OpenEOApi(client=client, app=FastAPI()) - -app = api.app -""" - -def get_models_template(): - """ - Generate the default models file for an openeo api app. - """ - return """from openeo_fastapi.client.psql.settings import BASE -from openeo_fastapi.client.psql.models import * - -metadata = BASE.metadata -""" - -def get_revision_template(): - """ - Generate the default revision file for the openeo api app. - """ - return """import os -from alembic import command -from alembic.config import Config -from pathlib import Path - -from openeo_fastapi.client.psql.settings import DataBaseSettings - -settings=DataBaseSettings() - -os.chdir(Path(settings.ALEMBIC_DIR)) -alembic_cfg = Config("alembic.ini") - -command.revision(alembic_cfg, autogenerate=True) -command.upgrade(alembic_cfg, "head") -""" @click.group() def cli(): @@ -85,7 +31,7 @@ def new(path): else: path = Path(fs.get_mapper("").root) - openeo_dir = path / "openeo_api" + openeo_dir = path db_dir = openeo_dir / "psql" init_file = openeo_dir / "__init__.py" app_file = openeo_dir / "app.py" @@ -121,6 +67,8 @@ def new(path): revise_file = openeo_dir / "revise.py" fs.touch(revise_file) + with fs.open(revise_file, 'w') as f: + f.write(get_revision_template()) pass diff --git a/openeo_fastapi/client/psql/settings.py b/openeo_fastapi/client/psql/settings.py index f0d60a1..f9009e7 100644 --- a/openeo_fastapi/client/psql/settings.py +++ b/openeo_fastapi/client/psql/settings.py @@ -20,4 +20,4 @@ class DataBaseSettings(BaseSettings): """The name of the databse being used on the host.""" ALEMBIC_DIR: Path - """The path to the alembic directory for applying revisions.""" + """The path leading to the alembic directory to be used.""" diff --git a/openeo_fastapi/client/settings.py b/openeo_fastapi/client/settings.py index a3f9c9c..8060a55 100644 --- a/openeo_fastapi/client/settings.py +++ b/openeo_fastapi/client/settings.py @@ -12,8 +12,6 @@ class AppSettings(BaseSettings): """The domain name hosting the API.""" API_TLS: bool = True """Whether the API http scheme should be http or https.""" - ALEMBIC_DIR: Path - """The path leading to the alembic directory to be used.""" API_TITLE: str """The API title to be provided to FastAPI.""" API_DESCRIPTION: str diff --git a/openeo_fastapi/templates.py b/openeo_fastapi/templates.py new file mode 100644 index 0000000..20c37f3 --- /dev/null +++ b/openeo_fastapi/templates.py @@ -0,0 +1,61 @@ +def get_app_template(): + """ + Generate the default app file for an openeo api app. + """ + return """ +from fastapi import FastAPI + +from openeo_fastapi.api.app import OpenEOApi +from openeo_fastapi.api.types import Billing, FileFormat, GisDataType, Link, Plan +from openeo_fastapi.client.core import OpenEOCore + +formats = [] + +links = [] + +client = OpenEOCore( + input_formats=formats, + output_formats=formats, + links=links, + billing=Billing( + currency="credits", + default_plan="a-cloud", + plans=[Plan(name="user", description="Subscription plan.", paid=True)], + ) +) + +api = OpenEOApi(client=client, app=FastAPI()) + +app = api.app +""" + +def get_models_template(): + """ + Generate the default models file for an openeo api app. + """ + return """from openeo_fastapi.client.psql.settings import BASE +from openeo_fastapi.client.psql.models import * + +metadata = BASE.metadata +""" + +def get_revision_template(): + """ + Generate the default revision file for the openeo api app. + """ + return """import os +from alembic import command +from alembic.config import Config +from pathlib import Path + +from openeo_fastapi.client.psql.settings import DataBaseSettings + +settings=DataBaseSettings() + +os.chdir(Path(settings.ALEMBIC_DIR)) +alembic_cfg = Config("alembic.ini") + +command.revision(alembic_cfg, autogenerate=True) +command.upgrade(alembic_cfg, "head") +""" + \ No newline at end of file