OCI tenancy map (live service)¶
The next-generation source of truth for what's in our OCI tenancies and what it costs, succeeding the static oci-resource-map.md page.
Lives in its own repo: https://git.projecteidos.com/internal/oci-tenancy-map
What it is¶
A small self-hosted FastAPI service that:
- Holds read-only OCI API keys for one or more tenancies (currently ORA448Global; EIDOSDev1 pending IAM setup)
- Continuously enumerates every resource per compartment via the OCI Resource Search API
- Pulls last-30-day cost per compartment / service / SKU / resource via the OCI Usage API
- Caches everything in SQLite and serves a versioned JSON REST API
- Cross-references resources against this repo's
apps/*.mdso cost rolls up per business application
The docs site fetches numbers from it on page load (planned: Phase 4 below). Same container is the blueprint for per-client FinOps deployments.
Where it sits¶
| Layer | Detail |
|---|---|
| Code | internal/oci-tenancy-map GitLab repo |
| Container | python:3.12-slim, ~120 MB image, ~80 MB idle RAM |
| Public URL | https://cost.448.global (planned) |
| Host | O1 via Dokploy (planned) |
| Auth | Authentik forward-auth at Caddy (planned) |
| Cache | SQLite, single file, bind-mounted volume |
Status¶
| Phase | Scope | Status |
|---|---|---|
| 1 | Scaffold FastAPI + SQLite + OCI session reuse | done — pushed |
| 2 | APScheduler + caching + multi-tenant config | done — smoke-tested against ORA448Global; cost matches static script within £0.01 |
| 3 | Dokploy deploy on O1 + Caddy + Authentik on cost.448.global |
pending |
| 4 | Docs JS + Parallax pilot page | pending |
| 5 | Roll-out across all app pages + monitoring | pending |
| 6 | Dashboard SPA (drill-down UI) | future |
| 7 | Per-client deployment blueprint | future |
Relationship to the static script¶
The static script at infra/scripts/oci-resource-map.py is now the offline fallback — useful for ad-hoc CLI runs and as a recovery tool if the container is down. The container is the live source of truth.
Both share the same categorisation + system-vs-user heuristics (the container imports them from its own app/categorise.py, mirroring the script's logic to keep them consistent).
Why we built it instead of adopting an existing tool¶
Reviewed in May 2026: Komiser is effectively dormant (last real commit Jan 2025), Steampipe's OCI plugin has 166 tables but zero cost tables, CloudQuery has no OCI plugin at all, InfraCost is estimates not actuals, OpenCost is K8s-only. No OSS tool exposes the OCI Usage API for cost actuals as queryable JSON. Combined with the principle "every adopted dependency is another maintenance + abandonment risk," rolling our own was the right call. See the new repo's ARCHITECTURE.md for the full reasoning.
Ad-hoc cost queries¶
ADB daily cost report¶
To get a per-day breakdown of paid ADB (Autonomous Database / APEX / Exadata) costs for the last 30 days across both tenancies:
Options:
| Flag | Default | Example |
|---|---|---|
--days N |
30 | --days 7 |
--profile NAME |
all tenancies | --profile EIDOSDev1 |
The script uses the OCI Usage API with DAILY granularity and filters to ADB-related SKUs (Autonomous, APEX Application Development, Exadata Storage). Output is a detail table followed by a per-day total and a 30-day sum.
The same .venv is used by the live oci-tenancy-map service — no separate install needed. Both OCI profiles (ORA448Global, EIDOSDev1) are hardcoded in the script alongside their tenancy OCIDs; update them if profiles are renamed.
Operating it¶
See the new repo's deploy/RUNBOOK.md: adding a tenancy, rotating API keys, forcing a refresh, inspecting freshness, common failure modes.