Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .streamlit/secrets.toml
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
auth_type='oidc'
auth_type='simple'

user='admin'
password='password'
Expand Down
18 changes: 18 additions & 0 deletions Makefile
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
#!make
include .env

build:
docker build -f oasisui_st_app.Dockerfile . -t ${PYTHONUI_IMG}:${VERS_UI}

push:
docker push ${PYTHONUI_IMG}:${VERS_UI}

scenarios_portfolios:
python ./scripts/add_test_portfolios.py -c ./scenarios/portfolios.json

scenarios_settings:
python ./scripts/add_settings_template.py -c ./scenarios/a_settings.json

scenarios: scenarios_portfolios scenarios_settings

build_and_push: build push
109 changes: 101 additions & 8 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,9 +65,16 @@ echo "127.0.0.1 ui.oasis.local" | sudo tee -a /etc/hosts
./install.sh
```

The installer clones the PiWind demo model, processes OIDC templates (if
applicable), builds the UI image, and starts all services. It will prompt
before redeploying if a previous installation is detected.
The installer stages the model data for the selected model set, processes OIDC
templates (if applicable), pulls the images, and starts all services. It will
prompt before redeploying if a previous installation is detected.

| Option | Description |
|--------|-------------|
| `-m`, `--model-set <name>` | Model set to deploy. Defaults to `MODEL_SET` from `.env`, or `piwind`. |
| `--build-ui` | Build the UI image locally instead of pulling `PYTHONUI_IMG:VERS_UI`. |
| `-u`, `--uninstall` | Bring the stack down and delete its volumes. |
| `-h`, `--help` | Show usage. |

To tear everything down (removes containers and volumes):

Expand DownExpand Up@@ -104,19 +111,82 @@ All services are reachable on port 80 via Traefik after a successful install:

## Docker Compose Architecture

The stack is assembled from multiple Compose files depending on auth type:
`install.sh` layers several Compose files into a single `docker compose`
command. The model workers live in a file of their own, so the core platform,
the UI and the auth stack stay model-agnostic:

```
Always loaded:
docker-compose.yml # Core platform: server, worker, databases, broker
docker-compose.ui.yml # Streamlit UI + Traefik reverse proxy
docker-compose.yml # Core platform: Traefik, server, websocket, databases, broker, filestore
docker-compose.models.<model-set>.yml # Model workers and model registration for one model set
docker-compose.ui.yml # Streamlit UI

Conditionally loaded:
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.keycloak.yml # Keycloak + its PostgreSQL DB (API_AUTH_TYPE=keycloak)
docker-compose.authentik.yml # Authentik + its PostgreSQL DB (API_AUTH_TYPE=authentik)
```

`install.sh` builds the correct `docker compose -f ... up` command automatically.
### Model sets — `docker-compose.models.<model-set>.yml`

`docker-compose.yml` defines no model workers at all. Everything
model-specific is confined to a `docker-compose.models.<model-set>.yml` file:

- one worker service per model, carrying its `OASIS_MODEL_SUPPLIER_ID`,
`OASIS_MODEL_ID`, `OASIS_MODEL_VERSION_ID` and `OASIS_RUN_MODE`
- the volume mount that supplies that model's data
- any `model-registration` job needed to register the models with the API

Exactly one model set is loaded per deployment. Pick it with `-m/--model-set`,
or set `MODEL_SET` in `.env` so a bare `./install.sh` deploys it:

```bash
./install.sh -m piwind # default: the PiWind demo model
./install.sh -m scenarios # PiWind plus the public scenario models
```

Model sets shipped in this repository:

| File | Contents |
|------|----------|
| `docker-compose.models.piwind.yml` | A `model-registration` one-shot and `piwind-worker`, with model data from `./OasisPiWind/`. |
| `docker-compose.models.scenarios.yml` | `piwind-worker` plus the scenario workers (Impact Forecasting, JBA, ARA, IPE), with model data from `${SCENARIOS_PATH}`. |

Because the split is by filename, adding a model set means dropping two new
files into the root directory — no edits to `docker-compose.yml`, `install.sh`
or the auth files:

1. Write `docker-compose.models.<name>.yml` with the worker services. The
workers join the core stack, so they can depend on `server`, `celery-db` and
`broker` and mount the shared `filestore-data` volume directly.
2. Optionally add `get-<name>.sh` to fetch the model data (see below).
3. Deploy with `./install.sh -m <name>`.

`install.sh --uninstall` passes *every* `docker-compose.models.*.yml` to
`docker compose down`, so the model workers are torn down whichever set was
deployed.

#### Model data — `get-<model-set>.sh`

The Compose file describes how a model runs; the matching `get-<model-set>.sh`
puts its data on disk. Before bringing the stack up, `install.sh` runs
`get-$MODEL_SET.sh` if it exists, and otherwise assumes the data is already in
place.

| Script | What it does |
|--------|--------------|
| `get-piwind.sh` | Clones `OasisLMF/OasisPiWind` at `VERS_PIWIND` into `./OasisPiWind/`. No-ops once cloned. |
| `get-scenarios.sh` | Runs `get-piwind.sh`, clones `OasisLMF/Scenarios` into `$SCENARIOS_PATH`, then runs that repository's `get_s3_data_reduced.sh` to download the model files. Each step is skipped if it has already been done. |

The scripts are idempotent and safe to run on their own, which is the easy way
to pre-stage model data on a server before deploying, or to refresh it without
a redeploy:

```bash
SCENARIOS_PATH=/home/ubuntu/Scenarios ./get-scenarios.sh
```

When writing your own, keep it re-runnable: `install.sh` calls it on every
deploy, including redeploys over an existing installation.

## Key Environment Variables

Expand All@@ -131,6 +201,25 @@ Conditionally loaded:

See the `.env.*` templates for the full list with inline comments.

### Deployment overrides

These variables decide *what* gets deployed and *what the UI shows*, rather
than how the platform is wired together. They are read straight from `.env` by
`install.sh` and the Compose files, and each falls back to the layout in this
repository — so a plain checkout still deploys unchanged with none of them set.
They are not in the `.env.*` templates; add the ones a deployment needs.

| Variable | Default | Purpose |
|----------|---------|---------|
| `MODEL_SET` | `piwind` | Which `docker-compose.models.<name>.yml` / `get-<name>.sh` pair to deploy. `-m/--model-set` overrides it for one run. |
| `SCENARIOS_PATH` | *(unset)* | Host directory holding the scenario model data. Required by the `scenarios` model set — both `get-scenarios.sh` and the worker mounts read it. |
| `UI_CONFIG` | `./ui-config.json` | The UI's config file: pages, post-login page, model-to-exposure map, footer, and `skip_login`. |
| `UI_DEFAULTS` | `./defaults/` | Per-model default analysis settings the UI pre-fills when creating an analysis. |
| `UI_ASSETS` | `./ui_assets/` | Files `UI_CONFIG` refers to as `ui_assets/<file>` — footer text, logos, anything a deployment supplies. |
| `UI_STREAMLIT` | `./.streamlit/` | The Streamlit directory mounted read-only: `secrets.toml` and `config.toml`. |
| `PYTHONUI_IMG` / `VERS_UI` | `coreoasis/oasispythonui_app` / `latest` | UI image pulled at deploy time, and the tag `make build` / `make push` produce. |


## Adding Users

### Simple auth
Expand DownExpand Up@@ -166,6 +255,10 @@ Usually first thing to try before anything is clearing browser cache/cookies for
- The IdP database container must be healthy first: `docker compose ps`.
- First startup can take 2–3 minutes while blueprints and realms are imported.

**`install.sh` exits with `no model set '<name>'`**
- The model set has no `docker-compose.models.<name>.yml` in the root directory.
Check the spelling of `-m/--model-set` or `MODEL_SET`.

**Logs and status**
```bash
docker compose ps # service health
Expand Down
24 changes: 0 additions & 24 deletions defaults/10_ghana-e760461_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/11_nepal-e151185_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/12_nepal-e432557_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/13_nepal-e505423_jba-analysis_settings.json

This file was deleted.

24 changes: 0 additions & 24 deletions defaults/14_france-hail_ipe-analysis_settings.json

This file was deleted.

32 changes: 0 additions & 32 deletions defaults/2_maeq_impact-forecasting-analysis_settings.json

This file was deleted.

29 changes: 0 additions & 29 deletions defaults/3_euws_impact-forecasting-analysis_settings.json

This file was deleted.

34 changes: 0 additions & 34 deletions defaults/4_treq_impact-forecasting-analysis_settings.json

This file was deleted.

Loading