Skip to content

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, Accept selects 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_date or a full start_date/end_date week 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_request rule 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/):

  • DirectoriesEnsurer creates the platform data directories for backups and analytics reports (BACKUPS_DIR and ANALYTICS_DIR under the namespace data directory on the data volume).
  • OIDCSecretsFileEnsurer resolves 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.