Platform and operations endpoints¶
Analytics reports, platform health and statistics, read-only mode, backup actions, and the Hub pod init container. Authorization for these routes is in Authentication and authorization.
Analytics report endpoints¶
The Site weekly/monthly endpoints serve the reports produced by the analytics service (15, 17):
- the caller must have the Site administrator role (platform administrators included);
- when the report file does not exist yet, the generation job is queued on
the single-worker FIFO queue and the answer is 202 "being generated in the
background"; the generation job holds a per-report lock, and while that
lock is held
exists()stays false, so further requests also answer 202; the single worker serializes the queued jobs; - when the report exists,
Acceptselects the attachment format (JSON default, HTML, or PDF); a report without a JSON body answers 404 "No data found to produce a report."; - periods come from
reference_dateor a fullstart_date/end_dateweek or month, and default to the previous period; - the platform endpoints (
stats/analytics/...) require the platform administrator role and answer 503 when the analytics integration is inactive.
Divergence, on purpose: the Site weekly endpoint does not gate on the
integration (its check is commented out in common.py), unlike the Site
monthly and both platform endpoints; see
13 — weekly reports. Neither Site analytics endpoint
checks whether the Site is archived; the report preloader simply skips
disabled Sites.
Platform and operations endpoints¶
| Endpoint | Access | Behaviour |
|---|---|---|
GET /health/ |
platform admin | Redis, Kubernetes API, and data-volume checks. ?deep= slows the storage check for a deeper probe; hub.health_timeout_status decides whether a slow check means NOK or a warning. Accept: text/plain or application/nagios returns the Nagios one-line format with performance data; otherwise JSON. The HTTP code stays 200 either way. |
GET /sites/health/ |
platform admin | Probes every enabled, monitored Site in parallel (45-second budget) through the Site health API with the Site master tokens. Any failing Site makes the answer 500: this endpoint is the monitoring hook and 500 is deliberate. |
POST /read-only/ |
platform admin | Toggles the stored state (below). |
GET /stats/system/, /stats/service/ |
platform admin | The dashboard data objects (node capacity and usage; Sites, storage, CPU, and memory against the ResourceQuota), Redis-cached on a short time to live (TTL). |
DELETE /cache/ |
platform admin | Deletes the Sites, spec, stats, and template cache prefixes and refreshes the directory cache. |
GET /logs/ |
platform admin | Hub or operator pod logs (?name=SITES_OPERATOR, default Hub), ?limit= tail lines. |
GET/POST /backup/ |
platform admin | Both return the current day's platform backup YAML file as an attachment; POST runs a fresh backup first. |
GET /version/ |
any | The Hub package version. |
GET /whoami/ |
any | Pretty name, username, policies, and role (Administrator, Staff, or Anonymous). |
POST /htpasswd/ |
a signed-in caller; an anonymous caller is refused before the hash runs | {username, password?}; without a password it generates an 8-byte secure token. The hash is bcrypt, so an anonymous caller is refused before hashing that would let a loop exhaust the Hub workers. Accept: text/plain returns the .htpasswd file and then requires the password. |
GET /users/, /groups/ |
staff | Directory users (?q=) and the configured group policies. |
GET /sites/users/, /sites/groups/ |
platform admin | Distinct Site owners (with Accept: text/plain as CSV) and Site groups. |
GET /sites/applications/, /sites/<s>/<n>/applications/ |
staff (platform-wide list); Site administrator (per-Site list) | The optional, on-demand application set (?q=, name lookup), platform-wide or as configured on one Site. |
GET/PUT/DELETE /sites/templates/[name/] |
staff GET; admin writes | The create-template files (HUI-02). PUT/DELETE answer 403 for platform templates (provided by the Helm value siteTemplates), 400 for an invalid name or content, and DELETE answers 404 for an unknown name. |
Read-only mode¶
The Hub stores read-only state in the sites-platform-state ConfigMap
(core/.../kubernetes/platform_state.py). The state update re-reads the
ConfigMap and retries up to five times on a resource-version conflict (409).
No API handler checks the state itself. Enforcement sits in front of the application, once per routing mode:
- Ingress mode: the toggle adds or removes an NGINX location snippet on the master Ingress. The snippet returns 405 (redirect to the Hub error page) for every method outside GET/OPTIONS/HEAD.
- Gateway mode: the Hub registers a
before_requestrule with the same policy and answers a plain 405 (hub/.../routing_rules.py). It reads the state through a five-second cache and keeps the last known value when the cluster read fails; it clears the cache right after a toggle through its own endpoint.
The allow-list is the same in both modes, and it is narrower than "the
read-only endpoint": GET/HEAD/OPTIONS everywhere, plus the v2 toggle
path, plus the /hub/list/ UI prefix (so list pages can still refresh their
fragments). While read-only is on, POST /hub/api/v1/read-only/ is itself
blocked; only the v2 path can change the state. API rejections surface as
405, which renders as JSON on API paths.
The Hub always runs a background thread that imports the state from a
legacy Ingress snippet and, in ingress mode only, keeps that snippet in sync
with the ConfigMap. The blocked-while-read-only rule, the conflict retries,
and the
legacy import are covered by hub/tests/test_routing_rules.py and
core/tests/test_routing.py. See
data storage and recovery.
Backup and restore actions¶
The Hub exposes platform-definition backup actions and Site administration pages. The backup job and the Hub backup action export Site resources without status or resource-version fields. They do not copy Site content from the persistent volume claim (PVC). The administration restore page is documented in 18 — Administration pages.
Site token-history backup and restore are separate Site API operations. Their storage and recovery contract is in data storage and recovery.
Hub pod initialisation¶
The Hub Deployment runs an init container, sites-hub-initializer, before
the Hub container starts (helm/ecmwf-sites/templates/deployment-hub.yaml).
It uses the Hub image and the command from hub.initializer (default
python -m ecmwf.sites.hub.initializer), the sites-secrets and OpenID Connect (OIDC)
client-secret environments (both via envFrom),
and the shared data volume. The module runs two ensurers
(hub/src/ecmwf/sites/hub/initializer/):
DirectoriesEnsurercreates the platform data directories for backups and analytics reports (BACKUPS_DIRandANALYTICS_DIRunder the namespace data directory on the data volume).OIDCSecretsFileEnsurerresolves the effective OIDC issuer and endpoint URLs through the shared discovery rules (explicit overrides first; see 10-security), then writes the OpenID client secrets JSON that the Hub's OpenID library reads at startup (OIDC_CLIENT_SECRETS,core/.../config/oidc.py). When an endpoint cannot be resolved, the init step fails before it writes the file.