-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5ab59c6
Showing
49 changed files
with
6,815 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Sphinx build info version 1 | ||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. | ||
config: 4708ca9c6c7e6a8e388805bb983110da | ||
tags: 645f666f9bcd5a90fca523b33c5a78b7 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Empty file.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
|
||
# The openEO Aggregator: federated openEO processing | ||
|
||
The openEO Aggregator is a software component to group multiple openEO back-ends together | ||
into a unified, federated openEO processing platform. | ||
|
||
|
||
```{mermaid} | ||
flowchart LR | ||
|
||
U("👤 User") --> A("openEO Aggregator") | ||
|
||
subgraph federation ["Federated openEO Processing"] | ||
|
||
A --> B1("openEO Back-end 1") | ||
A --> B2("openEO Back-end 2") | ||
A --> B3("openEO Back-end 3") | ||
end | ||
``` | ||
|
||
|
||
## Core openEO API | ||
|
||
The [openEO API](https://openeo.org/) is an open, standardized API for Earth Observation data processing, | ||
connecting openEO-capable clients at the user side with openEO-capable back-ends at the (cloud) processing side. | ||
Not only does it decouple the clients requirements from the technology stack of the back-ends, | ||
it also allows the user or client to switch between back-ends with minimal or even no code changes. | ||
Multiple openEO back-end implementations have been developed and are available today, | ||
each based on different processing technologies and each providing a different set of data collections. | ||
|
||
The freedom to choose a back-end and avoiding lock-in is one of the key features of openEO, | ||
but it also implies that the user is required to make a choice, as there is no default back-end. | ||
Moreover, the user might want to combine data or processing functionality from different back-ends, | ||
which is not directly supported by openEO's core API. | ||
Note that Earth Observation data is fast-growing and diverse, | ||
making it unsafe to assume that a single provider will be able to host all EO data. | ||
|
||
## Federated openEO processing | ||
|
||
The "openEO Aggregator" project aims to address this problem through a proxy-like component to | ||
build a federated openEO processing platform. | ||
The openEO Aggregator allows to group multiple openEO back-ends together | ||
and to and expose their combined power as a single, openEO-compliant API endpoint to the user, | ||
including, but not limited to: | ||
|
||
- merging and unification of general resource metadata such as data collections and openEO processes | ||
- unified listing of batch jobs of a user across multiple back-ends | ||
- dispatching of simple processing requests (both for synchronous processing and batch jobs) to the appropriate back-end | ||
- handling of more complex processing requests that require data from multiple back-ends | ||
|
||
|
||
|
||
```{toctree} | ||
:caption: Documentation | ||
:hidden: | ||
pages/installation.md | ||
pages/configuration.md | ||
pages/usage.md | ||
``` | ||
|
||
```{toctree} | ||
:caption: Development | ||
:hidden: | ||
pages/changelog | ||
GitHub <https://github.com/Open-EO/openeo-aggregator> | ||
openEO.org <https://openeo.org/> | ||
pages/license | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Changelog | ||
|
||
|
||
```{include} ../../CHANGELOG.md | ||
:start-after: <!-- start-of-changelog --> | ||
:end-before: <!-- end-of-changelog --> | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Configuration | ||
|
||
## Essential configuration | ||
|
||
The openEO-Aggregator specific configuration, | ||
is grouped by an `AggregatorBackendConfig` container object | ||
(subclass of [`OpenEoBackendConfig`](https://github.com/Open-EO/openeo-python-driver/blob/master/openeo_driver/config/config.py) | ||
as defined in the [`openeo-python-driver`](https://github.com/Open-EO/openeo-python-driver) framework project). | ||
|
||
The most important config value is `aggregator_backends`, which | ||
defines the backends to "aggregate". | ||
|
||
```python | ||
config = AggregatorBackendConfig( | ||
..., | ||
aggregator_backends={ | ||
"dummy": "https://openeo.example/", | ||
}, | ||
... | ||
) | ||
``` | ||
|
||
|
||
|
||
See [`src/openeo_aggregator/config/config.py`](https://github.com/Open-EO/openeo-aggregator/blob/master/src/openeo_aggregator/config/config.py) | ||
for more details and other available configuration options. | ||
|
||
Use the env var `OPENEO_BACKEND_CONFIG` to point to the desired config path. | ||
For example, using the example [dummy config](https://github.com/Open-EO/openeo-aggregator/blob/master/src/openeo_aggregator/config/examples/aggregator.dummy.py) | ||
from the repo: | ||
|
||
```shell | ||
export OPENEO_BACKEND_CONFIG=src/openeo_aggregator/config/examples/aggregator.dummy.py | ||
``` | ||
|
||
|
||
When no valid openEO-Aggregator configuration is set that way, you typically get this error: | ||
|
||
```text | ||
ConfigException: Expected AggregatorBackendConfig but got OpenEoBackendConfig | ||
``` | ||
|
||
|
||
## Further configuration | ||
|
||
The flask/gunicorn related configuration can be set through | ||
standard flask/gunicorn configuration means | ||
like command line options or env variables, as shown in the [usage docs](usage.md). | ||
|
||
### Gunicorn config | ||
|
||
For running with gunicorn, there is an example config at `src/openeo_aggregator/config/examples/gunicorn-config.py`, | ||
for example to be used like this: | ||
|
||
```shell | ||
gunicorn \ | ||
--config=src/openeo_aggregator/config/examples/gunicorn-config.py \ | ||
'openeo_aggregator.app:create_app()' | ||
``` | ||
|
||
### Logging | ||
|
||
By default, logging is done in JSON format. | ||
You can switch to a simple text-based logging with this env var: | ||
|
||
```shell | ||
export OPENEO_AGGREGATOR_SIMPLE_LOGGING=1 | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Installation | ||
|
||
The openEO Aggregator is a Python package and can be installed via standard tooling like `pip`. | ||
While it's possible to install it with a naive `pip install openeo-aggregator`, | ||
the current build workflows push the related packages to a dedicated repository (instead of PyPI), | ||
so to install a recent version it is generally recommended to install with | ||
|
||
```shell | ||
python -m pip install openeo-aggregator \ | ||
--extra-index-url https://artifactory.vgt.vito.be/api/pypi/python-openeo/simple | ||
``` | ||
|
||
At the time of this writing it is recommended to work with Python 3.11 | ||
(as done in the Docker image used in various production deployments). | ||
|
||
|
||
## Installation from source | ||
|
||
If desired, it is also possible to install from source. | ||
As usual, run something like this from the project root in some kind of virtual environment: | ||
|
||
```shell | ||
pip install . | ||
``` | ||
|
||
When planning to do development, it is recommended to install it in development mode (option `-e`) with the `dev` "extra": | ||
|
||
```shell | ||
pip install -e .[dev] | ||
``` | ||
|
||
|
||
## Requirements | ||
|
||
Some (optional) features have some additional requirements: | ||
|
||
- Optional: a Zookeeper cluster for caching and partitioned job db |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# License | ||
|
||
```{literalinclude} ../../LICENSE.txt | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Usage | ||
|
||
How to run the aggregator (flask based) webapp? | ||
|
||
|
||
Note: make sure you [point to a valid configuration file](configuration.md) | ||
before trying to run the web app. | ||
|
||
|
||
### Flask dev mode | ||
|
||
To run locally in development mode, with standard Flask workflow, | ||
for example (also see `./scripts/run-flask-dev.sh`): | ||
|
||
```shell | ||
export FLASK_APP=openeo_aggregator.app | ||
export FLASK_ENV=development | ||
flask run | ||
``` | ||
|
||
The webapp should be available at [http://localhost:5000/openeo/1.2](http://localhost:5000/openeo/1.2). | ||
|
||
|
||
### With gunicorn | ||
|
||
To run the app as gunicorn application, with desired options, | ||
for example (also see `./scripts/run-gunicorn.sh`): | ||
|
||
```shell | ||
gunicorn --workers=4 --bind 0.0.0.0:8080 'openeo_aggregator.app:create_app()' | ||
``` | ||
|
||
The webapp should be available at [http://localhost:8080/openeo/1.2](http://localhost:8080/openeo/1.2). | ||
|
||
|
||
## Docker image | ||
|
||
The [docker](https://github.com/Open-EO/openeo-aggregator/blob/master/docker) folder has a `Dockerfile` to build a Docker image, e.g.: | ||
|
||
```shell | ||
docker build -t openeo-aggregator -f docker/Dockerfile . | ||
``` | ||
|
||
This image is built automatically and hosted by VITO at `vito-docker.artifactory.vgt.vito.be/openeo-aggregator` | ||
|
||
The image runs the app in gunicorn by default (serving on `127.0.0.1:8000`). | ||
|
||
Example usage, with some extra gunicorn settings and the built-in dummy config: | ||
|
||
docker run \ | ||
--rm \ | ||
-p 8080:8080 \ | ||
-e GUNICORN_CMD_ARGS='--bind=0.0.0.0:8080 --workers=2' \ | ||
-e OPENEO_BACKEND_CONFIG=/home/openeo/venv/lib/python3.11/site-packages/openeo_aggregator/config/examples/aggregator.dummy.py \ | ||
vito-docker.artifactory.vgt.vito.be/openeo-aggregator:latest | ||
|
||
This webapp should be available at [http://localhost:8080/openeo/1.2](http://localhost:8080/openeo/1.2). |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// @ts-check | ||
|
||
// Extra JS capability for selected tabs to be synced | ||
// The selection is stored in local storage so that it persists across page loads. | ||
|
||
/** | ||
* @type {Record<string, HTMLElement[]>} | ||
*/ | ||
let sd_id_to_elements = {}; | ||
const storageKeyPrefix = "sphinx-design-tab-id-"; | ||
|
||
/** | ||
* Create a key for a tab element. | ||
* @param {HTMLElement} el - The tab element. | ||
* @returns {[string, string, string] | null} - The key. | ||
* | ||
*/ | ||
function create_key(el) { | ||
let syncId = el.getAttribute("data-sync-id"); | ||
let syncGroup = el.getAttribute("data-sync-group"); | ||
if (!syncId || !syncGroup) return null; | ||
return [syncGroup, syncId, syncGroup + "--" + syncId]; | ||
} | ||
|
||
/** | ||
* Initialize the tab selection. | ||
* | ||
*/ | ||
function ready() { | ||
// Find all tabs with sync data | ||
|
||
/** @type {string[]} */ | ||
let groups = []; | ||
|
||
document.querySelectorAll(".sd-tab-label").forEach((label) => { | ||
if (label instanceof HTMLElement) { | ||
let data = create_key(label); | ||
if (data) { | ||
let [group, id, key] = data; | ||
|
||
// add click event listener | ||
// @ts-ignore | ||
label.onclick = onSDLabelClick; | ||
|
||
// store map of key to elements | ||
if (!sd_id_to_elements[key]) { | ||
sd_id_to_elements[key] = []; | ||
} | ||
sd_id_to_elements[key].push(label); | ||
|
||
if (groups.indexOf(group) === -1) { | ||
groups.push(group); | ||
// Check if a specific tab has been selected via URL parameter | ||
const tabParam = new URLSearchParams(window.location.search).get( | ||
group | ||
); | ||
if (tabParam) { | ||
console.log( | ||
"sphinx-design: Selecting tab id for group '" + | ||
group + | ||
"' from URL parameter: " + | ||
tabParam | ||
); | ||
window.sessionStorage.setItem(storageKeyPrefix + group, tabParam); | ||
} | ||
} | ||
|
||
// Check is a specific tab has been selected previously | ||
let previousId = window.sessionStorage.getItem( | ||
storageKeyPrefix + group | ||
); | ||
if (previousId === id) { | ||
// console.log( | ||
// "sphinx-design: Selecting tab from session storage: " + id | ||
// ); | ||
// @ts-ignore | ||
label.previousElementSibling.checked = true; | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Activate other tabs with the same sync id. | ||
* | ||
* @this {HTMLElement} - The element that was clicked. | ||
*/ | ||
function onSDLabelClick() { | ||
let data = create_key(this); | ||
if (!data) return; | ||
let [group, id, key] = data; | ||
for (const label of sd_id_to_elements[key]) { | ||
if (label === this) continue; | ||
// @ts-ignore | ||
label.previousElementSibling.checked = true; | ||
} | ||
window.sessionStorage.setItem(storageKeyPrefix + group, id); | ||
} | ||
|
||
document.addEventListener("DOMContentLoaded", ready, false); |
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.