S-18b · Objecten API up in compose, wired to Objecttypen (closes #140) #143
@@ -280,7 +280,7 @@ jobs:
|
|||||||
# Log dump must precede teardown (which removes the containers).
|
# Log dump must precede teardown (which removes the containers).
|
||||||
- name: Dump container logs on failure
|
- name: Dump container logs on failure
|
||||||
if: failure()
|
if: failure()
|
||||||
run: docker compose -f infra/docker-compose.yml logs --no-color --tail=100 oz-init openzaak nrc-init nrc-web nrc-celery nrc-beat flowable-db flowable-rest flowable-init keycloak acl bff domain projection-db event-subscriber projection-api self-service openbaar behandel beheer objecttypen-db objecttypen-redis objecttypen-init objecttypen tempo prometheus grafana 2>&1 || true
|
run: docker compose -f infra/docker-compose.yml logs --no-color --tail=100 oz-init openzaak nrc-init nrc-web nrc-celery nrc-beat flowable-db flowable-rest flowable-init keycloak acl bff domain projection-db event-subscriber projection-api self-service openbaar behandel beheer objecttypen-db objecttypen-redis objecttypen-init objecttypen objecten-db objecten-redis objecten-init objecten tempo prometheus grafana 2>&1 || true
|
||||||
- name: Tear down
|
- name: Tear down
|
||||||
if: always()
|
if: always()
|
||||||
run: make down
|
run: make down
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ COMPOSE := infra/docker-compose.yml
|
|||||||
# Long-running services with a healthcheck — the smoke polls these for readiness
|
# Long-running services with a healthcheck — the smoke polls these for readiness
|
||||||
# (infra/wait-healthy.sh). One-shot init jobs (oz-init, nrc-init, flowable-init)
|
# (infra/wait-healthy.sh). One-shot init jobs (oz-init, nrc-init, flowable-init)
|
||||||
# are not polled; they only need to have run. See docs/runbooks/gitea-actions-gotchas.md.
|
# are not polled; they only need to have run. See docs/runbooks/gitea-actions-gotchas.md.
|
||||||
WAIT_SVCS := openzaak nrc-web acl bff domain event-subscriber projection-api self-service openbaar behandel beheer objecttypen
|
WAIT_SVCS := openzaak nrc-web acl bff domain event-subscriber projection-api self-service openbaar behandel beheer objecttypen objecten
|
||||||
# Config files (OpenZaak data.yaml, Keycloak realms, Flowable BPMN) are streamed
|
# Config files (OpenZaak data.yaml, Keycloak realms, Flowable BPMN) are streamed
|
||||||
# into external named volumes via `docker cp` (infra/seed-config.sh) instead of
|
# into external named volumes via `docker cp` (infra/seed-config.sh) instead of
|
||||||
# bind-mounted, because bind mounts don't reach sibling containers on the
|
# bind-mounted, because bind mounts don't reach sibling containers on the
|
||||||
@@ -18,7 +18,7 @@ WAIT_SVCS := openzaak nrc-web acl bff domain event-subscriber projection-api se
|
|||||||
# volumes are `external`, so compose won't remove them — CFG_VOLS lists them for
|
# volumes are `external`, so compose won't remove them — CFG_VOLS lists them for
|
||||||
# explicit teardown. See docs/runbooks/gitea-actions-gotchas.md.
|
# explicit teardown. See docs/runbooks/gitea-actions-gotchas.md.
|
||||||
SEED := bash infra/seed-config.sh
|
SEED := bash infra/seed-config.sh
|
||||||
CFG_VOLS := rr-oz-config rr-nrc-config rr-kc-realms rr-fl-bpmn rr-objecttypen-config
|
CFG_VOLS := rr-oz-config rr-nrc-config rr-kc-realms rr-fl-bpmn rr-objecttypen-config rr-objecten-config
|
||||||
# Local-only stack: same services but config is bind-mounted (no seed step), so a
|
# Local-only stack: same services but config is bind-mounted (no seed step), so a
|
||||||
# plain `docker compose -f infra/docker-compose.local.yml up` works on any local
|
# plain `docker compose -f infra/docker-compose.local.yml up` works on any local
|
||||||
# engine. This is the no-make / Windows-friendly path. See that file's header.
|
# engine. This is the no-make / Windows-friendly path. See that file's header.
|
||||||
@@ -94,14 +94,14 @@ mutation:
|
|||||||
# podman-compose, and needing no `--wait` flag or host port access. The one-shots
|
# podman-compose, and needing no `--wait` flag or host port access. The one-shots
|
||||||
# (oz-init, flowable-init) aren't polled; they just need to have run.
|
# (oz-init, flowable-init) aren't polled; they just need to have run.
|
||||||
smoke:
|
smoke:
|
||||||
$(SEED) oz nrc kc fl objecttypen
|
$(SEED) oz nrc kc fl objecttypen objecten
|
||||||
docker compose -f $(COMPOSE) up -d --build
|
docker compose -f $(COMPOSE) up -d --build
|
||||||
bash -c 'WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS); rc=$$?; docker compose -f $(COMPOSE) down --volumes; docker volume rm -f $(CFG_VOLS) >/dev/null 2>&1; exit $$rc'
|
bash -c 'WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS); rc=$$?; docker compose -f $(COMPOSE) down --volumes; docker volume rm -f $(CFG_VOLS) >/dev/null 2>&1; exit $$rc'
|
||||||
|
|
||||||
## up: seed config volumes and start the full stack (use instead of bare
|
## up: seed config volumes and start the full stack (use instead of bare
|
||||||
## `docker compose up`, which can't self-seed the external config volumes)
|
## `docker compose up`, which can't self-seed the external config volumes)
|
||||||
up:
|
up:
|
||||||
$(SEED) oz nrc kc fl objecttypen
|
$(SEED) oz nrc kc fl objecttypen objecten
|
||||||
docker compose -f $(COMPOSE) up -d --build
|
docker compose -f $(COMPOSE) up -d --build
|
||||||
|
|
||||||
## down: stop and remove the local stack (incl. the external config volumes)
|
## down: stop and remove the local stack (incl. the external config volumes)
|
||||||
@@ -139,7 +139,7 @@ changelog:
|
|||||||
## verify-up: bring the FULL stack up and wait for health (CI verify-stack step 1;
|
## verify-up: bring the FULL stack up and wait for health (CI verify-stack step 1;
|
||||||
## subsumes the old compose-smoke health gate — the DoD "up reaches green" check).
|
## subsumes the old compose-smoke health gate — the DoD "up reaches green" check).
|
||||||
verify-up:
|
verify-up:
|
||||||
$(SEED) oz nrc kc fl objecttypen
|
$(SEED) oz nrc kc fl objecttypen objecten
|
||||||
docker compose -f $(COMPOSE) up -d --build
|
docker compose -f $(COMPOSE) up -d --build
|
||||||
WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS)
|
WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS)
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ verify-objecten:
|
|||||||
## tear down (always). For fast single-concern local iteration use `integration`
|
## tear down (always). For fast single-concern local iteration use `integration`
|
||||||
## (oz-only) or `verify-notifications` (oz+nrc) instead.
|
## (oz-only) or `verify-notifications` (oz+nrc) instead.
|
||||||
verify:
|
verify:
|
||||||
$(SEED) oz nrc kc fl objecttypen
|
$(SEED) oz nrc kc fl objecttypen objecten
|
||||||
docker compose -f $(COMPOSE) up -d --build
|
docker compose -f $(COMPOSE) up -d --build
|
||||||
@bash -c 'set -e; rc=0; \
|
@bash -c 'set -e; rc=0; \
|
||||||
WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS) \
|
WAIT_TIMEOUT=420 bash infra/wait-healthy.sh $(WAIT_SVCS) \
|
||||||
|
|||||||
@@ -621,12 +621,76 @@ services:
|
|||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
networks: [cg]
|
networks: [cg]
|
||||||
|
|
||||||
|
# ── Objecten API (S-18b) — bind-mounted config (local variant) ─────────────
|
||||||
|
objecten-db:
|
||||||
|
image: docker.io/postgis/postgis:17-3.5
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: objects
|
||||||
|
POSTGRES_PASSWORD: objects
|
||||||
|
POSTGRES_DB: objects
|
||||||
|
volumes:
|
||||||
|
- objecten-db:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U objects"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 10
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten-redis:
|
||||||
|
image: docker.io/library/redis:7
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten-init:
|
||||||
|
image: docker.io/maykinmedia/objects-api:${OBJECTS_TAG:-3.4.0}
|
||||||
|
environment: &objecten-env-local
|
||||||
|
DJANGO_SETTINGS_MODULE: objects.conf.docker
|
||||||
|
SECRET_KEY: ${OBJECTS_SECRET_KEY:-dev-only-not-for-production}
|
||||||
|
DB_HOST: objecten-db
|
||||||
|
DB_NAME: objects
|
||||||
|
DB_USER: objects
|
||||||
|
DB_PASSWORD: objects
|
||||||
|
ALLOWED_HOSTS: "*"
|
||||||
|
CACHE_DEFAULT: objecten-redis:6379/0
|
||||||
|
CACHE_AXES: objecten-redis:6379/0
|
||||||
|
DISABLE_2FA: "true"
|
||||||
|
OTEL_SDK_DISABLED: "true"
|
||||||
|
RUN_SETUP_CONFIG: "true"
|
||||||
|
command: /setup_configuration.sh
|
||||||
|
volumes:
|
||||||
|
- ./objecten/setup_configuration:/app/setup_configuration:ro,z
|
||||||
|
depends_on:
|
||||||
|
objecten-db:
|
||||||
|
condition: service_healthy
|
||||||
|
objecten-redis:
|
||||||
|
condition: service_started
|
||||||
|
objecttypen:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten:
|
||||||
|
image: docker.io/maykinmedia/objects-api:${OBJECTS_TAG:-3.4.0}
|
||||||
|
environment: *objecten-env-local
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.head('http://localhost:8000/admin/').status_code in (200,302) else 1)"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
ports:
|
||||||
|
- "8021:8000"
|
||||||
|
depends_on:
|
||||||
|
objecten-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
oz-db:
|
oz-db:
|
||||||
nrc-db:
|
nrc-db:
|
||||||
flowable-db:
|
flowable-db:
|
||||||
projection-db:
|
projection-db:
|
||||||
objecttypen-db:
|
objecttypen-db:
|
||||||
|
objecten-db:
|
||||||
# Carries the seed-generated acl.env (server-assigned zaaktype URLs) from local-seed to the ACL.
|
# Carries the seed-generated acl.env (server-assigned zaaktype URLs) from local-seed to the ACL.
|
||||||
seed-env:
|
seed-env:
|
||||||
|
|
||||||
|
|||||||
@@ -635,6 +635,76 @@ services:
|
|||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
networks: [cg]
|
networks: [cg]
|
||||||
|
|
||||||
|
# ── Objecten API (S-18b) — upstream Maykin image, verbatim ─────────────────
|
||||||
|
# The authoritative object store. Same shape as Objecttypen (own DB + redis, an `-init` that runs
|
||||||
|
# setup_configuration from the external config volume, a health-checked web). Two differences: the
|
||||||
|
# DB is PostGIS (objects carry geometry), and setup_configuration registers the Objecttypen API
|
||||||
|
# (S-18a) as a trusted service so an object can reference its objecttype.
|
||||||
|
objecten-db:
|
||||||
|
image: docker.io/postgis/postgis:17-3.5
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: objects
|
||||||
|
POSTGRES_PASSWORD: objects
|
||||||
|
POSTGRES_DB: objects
|
||||||
|
volumes:
|
||||||
|
- objecten-db:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U objects"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 10
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten-redis:
|
||||||
|
image: docker.io/library/redis:7
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten-init:
|
||||||
|
image: docker.io/maykinmedia/objects-api:${OBJECTS_TAG:-3.4.0}
|
||||||
|
environment: &objecten-env
|
||||||
|
DJANGO_SETTINGS_MODULE: objects.conf.docker
|
||||||
|
SECRET_KEY: ${OBJECTS_SECRET_KEY:-dev-only-not-for-production}
|
||||||
|
DB_HOST: objecten-db
|
||||||
|
DB_NAME: objects
|
||||||
|
DB_USER: objects
|
||||||
|
DB_PASSWORD: objects
|
||||||
|
ALLOWED_HOSTS: "*"
|
||||||
|
CACHE_DEFAULT: objecten-redis:6379/0
|
||||||
|
CACHE_AXES: objecten-redis:6379/0
|
||||||
|
DISABLE_2FA: "true"
|
||||||
|
OTEL_SDK_DISABLED: "true"
|
||||||
|
RUN_SETUP_CONFIG: "true"
|
||||||
|
command: /setup_configuration.sh
|
||||||
|
# data.yaml is streamed into this external volume by infra/seed-config.sh before start.
|
||||||
|
volumes:
|
||||||
|
- objecten-config:/app/setup_configuration:ro
|
||||||
|
depends_on:
|
||||||
|
objecten-db:
|
||||||
|
condition: service_healthy
|
||||||
|
objecten-redis:
|
||||||
|
condition: service_started
|
||||||
|
# Objecten's setup_configuration registers the Objecttypen service; that service only needs to
|
||||||
|
# exist as config, but wait for Objecttypen to be up so the register is meaningful end to end.
|
||||||
|
objecttypen:
|
||||||
|
condition: service_healthy
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
|
objecten:
|
||||||
|
image: docker.io/maykinmedia/objects-api:${OBJECTS_TAG:-3.4.0}
|
||||||
|
environment: *objecten-env
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.head('http://localhost:8000/admin/').status_code in (200,302) else 1)"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
ports:
|
||||||
|
- "8021:8000"
|
||||||
|
depends_on:
|
||||||
|
objecten-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
networks: [cg]
|
||||||
|
|
||||||
# ── Observability backplane (S-16a, ADR-0023) ──────────────────────────────
|
# ── Observability backplane (S-16a, ADR-0023) ──────────────────────────────
|
||||||
# Grafana-native stack: Tempo ingests OTLP traces (the .NET services export
|
# Grafana-native stack: Tempo ingests OTLP traces (the .NET services export
|
||||||
# straight to it — no collector hop, S-16b), Prometheus scrapes service
|
# straight to it — no collector hop, S-16b), Prometheus scrapes service
|
||||||
@@ -685,6 +755,7 @@ volumes:
|
|||||||
flowable-db:
|
flowable-db:
|
||||||
projection-db:
|
projection-db:
|
||||||
objecttypen-db:
|
objecttypen-db:
|
||||||
|
objecten-db:
|
||||||
# Config volumes — created and populated out-of-band by infra/seed-config.sh
|
# Config volumes — created and populated out-of-band by infra/seed-config.sh
|
||||||
# (docker cp), because bind mounts don't reach sibling containers on the CI
|
# (docker cp), because bind mounts don't reach sibling containers on the CI
|
||||||
# runner. `external` keeps the names deterministic; the seed step manages them.
|
# runner. `external` keeps the names deterministic; the seed step manages them.
|
||||||
@@ -703,6 +774,9 @@ volumes:
|
|||||||
objecttypen-config:
|
objecttypen-config:
|
||||||
external: true
|
external: true
|
||||||
name: rr-objecttypen-config
|
name: rr-objecttypen-config
|
||||||
|
objecten-config:
|
||||||
|
external: true
|
||||||
|
name: rr-objecten-config
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
cg:
|
cg:
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Objecten API setup_configuration (S-18b). Streamed into the external rr-objecten-config volume by
|
||||||
|
# infra/seed-config.sh and applied by objecten-init (RUN_SETUP_CONFIG). Declarative + idempotent.
|
||||||
|
#
|
||||||
|
# Two things: (1) register the Objecttypen API (S-18a) as a trusted service so an object can
|
||||||
|
# reference its objecttype — authenticating with the dev static token Objecttypen provisioned; and
|
||||||
|
# (2) a dev static token so peers (the ACL, S-19) can write objects here. Dev-only, not for prod.
|
||||||
|
|
||||||
|
# (1) Trust the Objecttypen API. `orc` = overige RESTful component (how zgw_consumers classifies the
|
||||||
|
# Objecttypen API). The RegisterRecord objecttype (S-18c) will reference an objecttype under this
|
||||||
|
# service by uuid.
|
||||||
|
zgw_consumers_config_enable: true
|
||||||
|
zgw_consumers:
|
||||||
|
services:
|
||||||
|
- identifier: objecttypen
|
||||||
|
label: Objecttypen API
|
||||||
|
api_type: orc
|
||||||
|
api_root: http://objecttypen:8000/api/v2/
|
||||||
|
auth_type: api_key
|
||||||
|
header_key: Authorization
|
||||||
|
header_value: Token 0123456789abcdef0123456789abcdef01234567
|
||||||
|
|
||||||
|
# (2) Static API token peers use to write/read objects.
|
||||||
|
tokenauth_config_enable: true
|
||||||
|
tokenauth:
|
||||||
|
items:
|
||||||
|
- identifier: register-referentie
|
||||||
|
token: 1234567890abcdef1234567890abcdef12345678
|
||||||
|
contact_person: Register Referentie
|
||||||
|
email: admin@localhost
|
||||||
|
organization: Respellion
|
||||||
|
is_superuser: true
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
# subcommand. Fixed-name `external` volumes keep the names deterministic across
|
# subcommand. Fixed-name `external` volumes keep the names deterministic across
|
||||||
# both runtimes. See docs/runbooks/gitea-actions-gotchas.md.
|
# both runtimes. See docs/runbooks/gitea-actions-gotchas.md.
|
||||||
#
|
#
|
||||||
# Usage: seed-config.sh <key> [<key> ...] where key ∈ { oz, kc, fl }
|
# Usage: seed-config.sh <key> [<key> ...] where key ∈ { oz, nrc, kc, fl, objecttypen, objecten }
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
@@ -33,7 +33,7 @@ populate() { # volume source(file or dir/.)
|
|||||||
echo " seeded $vol"
|
echo " seeded $vol"
|
||||||
}
|
}
|
||||||
|
|
||||||
[ "$#" -gt 0 ] || { echo "usage: seed-config.sh <oz|nrc|kc|fl|objecttypen> ..." >&2; exit 2; }
|
[ "$#" -gt 0 ] || { echo "usage: seed-config.sh <oz|nrc|kc|fl|objecttypen|objecten> ..." >&2; exit 2; }
|
||||||
|
|
||||||
# The registratie process (BPMN) and its diploma-eligibility DMN are deployed as SEPARATE Flowable
|
# The registratie process (BPMN) and its diploma-eligibility DMN are deployed as SEPARATE Flowable
|
||||||
# deployments — the process engine and the DMN engine each own theirs (S-13, ADR-0016). flowable-rest
|
# deployments — the process engine and the DMN engine each own theirs (S-13, ADR-0016). flowable-rest
|
||||||
@@ -50,6 +50,7 @@ for key in "$@"; do
|
|||||||
nrc) populate rr-nrc-config "$here/opennotificaties/setup_configuration/." ;;
|
nrc) populate rr-nrc-config "$here/opennotificaties/setup_configuration/." ;;
|
||||||
kc) populate rr-kc-realms "$here/keycloak/realms/." ;;
|
kc) populate rr-kc-realms "$here/keycloak/realms/." ;;
|
||||||
objecttypen) populate rr-objecttypen-config "$here/objecttypen/setup_configuration/." ;;
|
objecttypen) populate rr-objecttypen-config "$here/objecttypen/setup_configuration/." ;;
|
||||||
|
objecten) populate rr-objecten-config "$here/objecten/setup_configuration/." ;;
|
||||||
fl) d="$(mktemp -d)"; stage_flowable_workflows "$d"; populate rr-fl-bpmn "$d/." ;;
|
fl) d="$(mktemp -d)"; stage_flowable_workflows "$d"; populate rr-fl-bpmn "$d/." ;;
|
||||||
*) echo "unknown seed key: $key" >&2; exit 2 ;;
|
*) echo "unknown seed key: $key" >&2; exit 2 ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user