Rating (FinOps): usage collected from Prometheus, priced by hashmap rules and CEL scripts, rated history in InfluxDB; with openkeel-pricing (cost and carbon quotes), it feeds Skyline's FinOps / GreenOps page.
Go Prometheus, InfluxDBopenkeel-cloudkitty
The module
OpenKeel implementation in Go of OpenStack CloudKitty, the rating service (cloudkitty-api and cloudkitty-processor), generated from the reverse-specification of branch stable/2026.2 (reverse-spec-cloudkitty/, files 00–07 and _rewrite/) by the generate-go-from-spec skill. It replaces the Python service without its clients noticing (python-cloudkittyclient, cloudkitty-dashboard): same routes (66 operations of v1, hashmap, pyscripts and v2), status codes, WSME and flask-restful error bodies, and policies.
What it does: the processor lists the scopes (Keystone projects with the rating role, Prometheus label values or a static list), collects their usage from Prometheus every period, prices it with the enabled rating modules (hashmap rules, CEL scripts in place of PyScripts), and stores the rated data in InfluxDB (1.x or 2.x); the API manages the rules and returns summaries, rated data frames and instant quotes.
OpenKeel decisions (details and reasons in docs/CONFORMANCE.md):
PyScripts are CEL expressions, evaluated per data point, never Python (exec); tools/pyscript2cel.py translates the scripts written in the documented pattern; skip_datapoints_expression is CEL too.
Collector: Prometheus only (kube-prometheus-stack); storage: InfluxDB only; no RabbitMQ: quotes are computed in the API, scope resets go to the processor through the database; one active processor elected with a Kubernetes Lease.
Fixed upstream defects: scoped deletes, unprotected GET /v2/rating/modules, quotes with a flat desc, InfluxQL built from escaped literals, no unverified Keystone call, reprocessing and reset windows. What is reproduced and what differs is in docs/CONFORMANCE.md; the security checklist is in docs/SECURITY.md.
Go module: github.com/openkeel/openkeel-cloudkitty
Binaries: cloudkitty-api (API on port 8889, health and metrics on 9090) and cloudkitty-processor (health on 9090)
Configuration: YAML, see config/config.example.yaml
Setting up a development environment, the database and the tests: docs/GETTING-STARTED.md
Database schema, migrations and upgrades: docs/DATABASE.md
Excerpt from openkeel-cloudkitty/README.md (in English).
REST API
66 operations of the original REST API (routes and body actions), and their state in OpenKeel.
CloudKitty's three gabbi suites are replayed against the Go service, with hashmap vectors recorded from the Python tests and a lab deployment read back through the ingress.
Replay of recorded exchanges
E2E replay of the gabbi suites
223 exchanges of 19 gabbi files (v1, hashmap, pyscripts, v2) give the same status and body.
How it runs
make e2e, also on MariaDB 11.4 (E2E_MYSQL_DSN); strict mode passes with the known differences listed.
Latest result 153 / 223 identical; the 70 others are explained (Python test fakes, storage v1, CORS, Python scripts refused).
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Unit and golden tests
Hashmap vectors
24 hashmap rating vectors recorded from cloudkitty.tests.test_hashmap price to the digit, decimals checked against CPython.
How it runs
go test ./... (19 packages).
Latest result 24 / 24 identical.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
End to end on a lab
Lab deployment
Catalog type rating, modules, hashmap rules, quotes, a Python script refused and a CEL one accepted, dataframes pushed then read back by /v2/summary; the processor rates from the month start.
How it runs
okadm install --mode lab with cloudkitty, calls through the ingress with an admin token; Skyline's FinOps / GreenOps page.
Latest result Pass, 0 rating failure.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Client contract
Client expectations
python-cloudkittyclient, cloudkitty-dashboard and cloudkitty-tempest-plugin.
How it runs
Not reverse-specified yet.
Latest result Not run.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Left out of the rewrite
CloudKitty keeps its 66 API operations and its rating; it collects from Prometheus and stores in InfluxDB only, and PyScripts become CEL expressions.
Internal machinery simplified
PyScripts (Python executed by the service)
Taken over by CEL
Why it was left out
Running operators' Python with exec is arbitrary code in the service; CEL has no statements and no I/O, with cost and time limits.
Why the solution is not affected
Same rating per data point; scripts written in the documented pattern are translated by tools/pyscript2cel.py, others are rewritten.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Done by the Cloud Native platform
Gnocchi and Aetos collectors, Gnocchi fetcher
Taken over by Prometheus
Why it was left out
OpenKeel deploys no Gnocchi: usage comes from Prometheus (kube-prometheus-stack, openstack-exporter).
Why the solution is not affected
Same rated data from the Prometheus metrics; the collectors can be added on demand.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Done by the Cloud Native platform
Elasticsearch, OpenSearch, Loki and storage v1
Taken over by InfluxDB
Why it was left out
The rated history goes to InfluxDB 1.x or 2.x; the other back ends are not deployed.
Why the solution is not affected
Summaries and dataframes as with storage v2; the upstream scope-filter defects of those back ends cannot happen.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Internal machinery simplified
RabbitMQ RPC and tooz locks
Taken over by Kubernetes Leases
Why it was left out
Quotes are computed in the API with the same rating code; scope resets go to the processor through the database; one active processor holds a Lease.
Why the solution is not affected
Same API behaviour, one dependency less, correct on several hosts.
Source: openkeel-cloudkitty/docs/CONFORMANCE.md
Only what was left out by design is listed here; the work not done yet is in the Known gaps of the module's docs/CONFORMANCE.md. Every module