Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
264edd2e3a | ||
|
|
cd2cbe7be6 | ||
|
|
73182d0c0c |
No files matched your search
@@ -18,7 +18,10 @@
|
|||||||
# TYPESENSE_SEARCH_KEY — Typesense search-only key (exposed to frontend)
|
# TYPESENSE_SEARCH_KEY — Typesense search-only key (exposed to frontend)
|
||||||
# UNLEASH_URL — http://<unleash-ip>:4242/api (empty = all flags off)
|
# UNLEASH_URL — http://<unleash-ip>:4242/api (empty = all flags off)
|
||||||
# UNLEASH_API_TOKEN — Unleash *client* token, environment: development
|
# UNLEASH_API_TOKEN — Unleash *client* token, environment: development
|
||||||
# AIRFLOW_ADMIN_USER — Airflow admin username (password auto-generated, see api-server logs)
|
# AIRFLOW_ADMIN_USER — Airflow admin username (default: admin)
|
||||||
|
# AIRFLOW_ADMIN_PASSWORD — Airflow admin password. REQUIRED: the api-server
|
||||||
|
# refuses to start without it, rather than falling
|
||||||
|
# back to a generated one that changes on restart.
|
||||||
# STAGING_DB_IP — macvlan IP for staging Postgres (default 10.0.1.190)
|
# STAGING_DB_IP — macvlan IP for staging Postgres (default 10.0.1.190)
|
||||||
# STAGING_FRONTEND_IP — macvlan IP for staging frontend (default 10.0.1.151)
|
# STAGING_FRONTEND_IP — macvlan IP for staging frontend (default 10.0.1.151)
|
||||||
|
|
||||||
@@ -124,7 +127,23 @@ services:
|
|||||||
airflow-api-server:
|
airflow-api-server:
|
||||||
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:staging
|
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:staging
|
||||||
container_name: sc_staging_airflow_api
|
container_name: sc_staging_airflow_api
|
||||||
command: airflow api-server --port 8080
|
# The simple auth manager generates a random password on first start and
|
||||||
|
# writes it to a file, so every container restart invalidates the last one.
|
||||||
|
# Writing the file ourselves from an environment variable makes the login
|
||||||
|
# deterministic. Airflow does not generate anything when the file exists.
|
||||||
|
#
|
||||||
|
# Built with python rather than echo/printf so a password containing quotes,
|
||||||
|
# backslashes or spaces is escaped correctly by json.dumps. An unset
|
||||||
|
# AIRFLOW_ADMIN_PASSWORD raises KeyError and the container exits: falling
|
||||||
|
# back to a generated password would silently undo the point of this.
|
||||||
|
command:
|
||||||
|
- bash
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p /opt/airflow
|
||||||
|
python -c "import json, os, pathlib; pathlib.Path('/opt/airflow/simple_auth_manager_passwords.json').write_text(json.dumps({os.environ.get('AIRFLOW_ADMIN_USER', 'admin'): os.environ['AIRFLOW_ADMIN_PASSWORD']}))"
|
||||||
|
exec airflow api-server --port 8080
|
||||||
ports:
|
ports:
|
||||||
- "8081:8080"
|
- "8081:8080"
|
||||||
environment:
|
environment:
|
||||||
@@ -136,6 +155,8 @@ services:
|
|||||||
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-staging-airflow-jwt-secret-key-long-enough-for-sha512"
|
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-staging-airflow-jwt-secret-key-long-enough-for-sha512"
|
||||||
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
||||||
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "${AIRFLOW_ADMIN_USER:-admin}:admin"
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "${AIRFLOW_ADMIN_USER:-admin}:admin"
|
||||||
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE: /opt/airflow/simple_auth_manager_passwords.json
|
||||||
|
AIRFLOW_ADMIN_PASSWORD: ${AIRFLOW_ADMIN_PASSWORD:?set AIRFLOW_ADMIN_PASSWORD in the Portainer stack environment}
|
||||||
AIRFLOW__LOGGING__BASE_LOG_FOLDER: /opt/airflow/logs
|
AIRFLOW__LOGGING__BASE_LOG_FOLDER: /opt/airflow/logs
|
||||||
PG_HOST: sc_database
|
PG_HOST: sc_database
|
||||||
PG_PORT: "5432"
|
PG_PORT: "5432"
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
# TYPESENSE_SEARCH_KEY — Typesense search-only key (exposed to frontend)
|
# TYPESENSE_SEARCH_KEY — Typesense search-only key (exposed to frontend)
|
||||||
# UNLEASH_URL — http://<unleash-ip>:4242/api (empty = all flags off)
|
# UNLEASH_URL — http://<unleash-ip>:4242/api (empty = all flags off)
|
||||||
# UNLEASH_API_TOKEN — Unleash *client* token, environment: production
|
# UNLEASH_API_TOKEN — Unleash *client* token, environment: production
|
||||||
# AIRFLOW_ADMIN_USER — Airflow admin username (password auto-generated, see api-server logs)
|
# AIRFLOW_ADMIN_USER — Airflow admin username (default: admin)
|
||||||
|
# AIRFLOW_ADMIN_PASSWORD — Airflow admin password. REQUIRED: the api-server
|
||||||
|
# refuses to start without it, rather than falling
|
||||||
|
# back to a generated one that changes on restart.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
@@ -113,7 +116,23 @@ services:
|
|||||||
airflow-api-server:
|
airflow-api-server:
|
||||||
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:prod
|
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:prod
|
||||||
container_name: schoolcompare_airflow_api
|
container_name: schoolcompare_airflow_api
|
||||||
command: airflow api-server --port 8080
|
# The simple auth manager generates a random password on first start and
|
||||||
|
# writes it to a file, so every container restart invalidates the last one.
|
||||||
|
# Writing the file ourselves from an environment variable makes the login
|
||||||
|
# deterministic. Airflow does not generate anything when the file exists.
|
||||||
|
#
|
||||||
|
# Built with python rather than echo/printf so a password containing quotes,
|
||||||
|
# backslashes or spaces is escaped correctly by json.dumps. An unset
|
||||||
|
# AIRFLOW_ADMIN_PASSWORD raises KeyError and the container exits: falling
|
||||||
|
# back to a generated password would silently undo the point of this.
|
||||||
|
command:
|
||||||
|
- bash
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p /opt/airflow
|
||||||
|
python -c "import json, os, pathlib; pathlib.Path('/opt/airflow/simple_auth_manager_passwords.json').write_text(json.dumps({os.environ.get('AIRFLOW_ADMIN_USER', 'admin'): os.environ['AIRFLOW_ADMIN_PASSWORD']}))"
|
||||||
|
exec airflow api-server --port 8080
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
environment:
|
environment:
|
||||||
@@ -125,6 +144,8 @@ services:
|
|||||||
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-airflow-jwt-secret-key-long-enough-for-sha512"
|
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-airflow-jwt-secret-key-long-enough-for-sha512"
|
||||||
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
||||||
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "${AIRFLOW_ADMIN_USER:-admin}:admin"
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "${AIRFLOW_ADMIN_USER:-admin}:admin"
|
||||||
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE: /opt/airflow/simple_auth_manager_passwords.json
|
||||||
|
AIRFLOW_ADMIN_PASSWORD: ${AIRFLOW_ADMIN_PASSWORD:?set AIRFLOW_ADMIN_PASSWORD in the Portainer stack environment}
|
||||||
AIRFLOW__LOGGING__BASE_LOG_FOLDER: /opt/airflow/logs
|
AIRFLOW__LOGGING__BASE_LOG_FOLDER: /opt/airflow/logs
|
||||||
PG_HOST: sc_database
|
PG_HOST: sc_database
|
||||||
PG_PORT: "5432"
|
PG_PORT: "5432"
|
||||||
|
|||||||
+19
-1
@@ -105,7 +105,23 @@ services:
|
|||||||
airflow-api-server:
|
airflow-api-server:
|
||||||
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:latest
|
image: privaterepo.sitaru.org/tudor/school_compare-pipeline:latest
|
||||||
container_name: schoolcompare_airflow_api
|
container_name: schoolcompare_airflow_api
|
||||||
command: airflow api-server --port 8080
|
# The simple auth manager generates a random password on first start and
|
||||||
|
# writes it to a file, so every container restart invalidates the last one.
|
||||||
|
# Writing the file ourselves from an environment variable makes the login
|
||||||
|
# deterministic. Airflow does not generate anything when the file exists.
|
||||||
|
#
|
||||||
|
# Built with python rather than echo/printf so a password containing quotes,
|
||||||
|
# backslashes or spaces is escaped correctly by json.dumps. An unset
|
||||||
|
# AIRFLOW_ADMIN_PASSWORD raises KeyError and the container exits: falling
|
||||||
|
# back to a generated password would silently undo the point of this.
|
||||||
|
command:
|
||||||
|
- bash
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p /opt/airflow
|
||||||
|
python -c "import json, os, pathlib; pathlib.Path('/opt/airflow/simple_auth_manager_passwords.json').write_text(json.dumps({os.environ.get('AIRFLOW_ADMIN_USER', 'admin'): os.environ['AIRFLOW_ADMIN_PASSWORD']}))"
|
||||||
|
exec airflow api-server --port 8080
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
environment: &airflow-env
|
environment: &airflow-env
|
||||||
@@ -117,6 +133,8 @@ services:
|
|||||||
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-airflow-jwt-secret-key-long-enough-for-sha512"
|
AIRFLOW__API_AUTH__JWT_SECRET: "school-compare-airflow-jwt-secret-key-long-enough-for-sha512"
|
||||||
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
AIRFLOW__API_AUTH__JWT_ISSUER: airflow
|
||||||
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "admin:admin"
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: "admin:admin"
|
||||||
|
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE: /opt/airflow/simple_auth_manager_passwords.json
|
||||||
|
AIRFLOW_ADMIN_PASSWORD: ${AIRFLOW_ADMIN_PASSWORD:-admin}
|
||||||
PG_HOST: db
|
PG_HOST: db
|
||||||
PG_PORT: "5432"
|
PG_PORT: "5432"
|
||||||
PG_USER: schoolcompare
|
PG_USER: schoolcompare
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ fail the E2E gate. That's the point: staging absorbs the risk.
|
|||||||
pr-checks status checks (frontend, backend, builds, ai-review) to pass.
|
pr-checks status checks (frontend, backend, builds, ai-review) to pass.
|
||||||
5. **Bootstrap staging data via Airflow** (no prod dump — staging populates
|
5. **Bootstrap staging data via Airflow** (no prod dump — staging populates
|
||||||
itself from source, exercising the pipeline image end-to-end):
|
itself from source, exercising the pipeline image end-to-end):
|
||||||
|
- Set `AIRFLOW_ADMIN_PASSWORD` in the stack environment first. The
|
||||||
|
api-server refuses to start without it. Airflow's simple auth manager
|
||||||
|
otherwise generates a password on first start and writes it to a file, so
|
||||||
|
the login changes every time the container restarts; the stack writes that
|
||||||
|
file itself from this variable instead. `AIRFLOW_ADMIN_USER` defaults to
|
||||||
|
`admin`.
|
||||||
- Open the staging Airflow UI (`http://<host>:8081`) and trigger, in order:
|
- Open the staging Airflow UI (`http://<host>:8081`) and trigger, in order:
|
||||||
`school_data_daily`, `school_data_monthly_ofsted`, then the manual-schedule
|
`school_data_daily`, `school_data_monthly_ofsted`, then the manual-schedule
|
||||||
`school_data_annual_ees` and `school_data_annual_idaci`.
|
`school_data_annual_ees` and `school_data_annual_idaci`.
|
||||||
|
|||||||
Reference in new issue
Block a user