Skip to content

feat: ocost-splitter plugin - written split methods for the shared/unattributed pool - #87

Open
rahmankhanjohn wants to merge 1 commit into
opencost:mainfrom
rahmankhanjohn:feat/ocost-splitter
Open

rahmankhanjohn wants to merge 1 commit into
opencost:mainfrom
rahmankhanjohn:feat/ocost-splitter

Conversation

@rahmankhanjohn

Copy link
Copy Markdown

What this adds

A new plugin, ocost-splitter, that addresses the shared/unattributed pool from issue #2890: the cost that no tag splits (control plane, ingress, monitoring, cross-namespace transfer - commonly near 30 percent of a cluster bill).

The plugin reads the allocation data OpenCost already produces (via the OpenCost allocation API, aggregated by namespace), identifies the shared pool from a configurable namespace list, and applies one of four written, auditable split methods:

  • proportional - weighted by each namespace's own totalCost (the scheduler-reserved share)
  • equal - divided evenly across attributed namespaces
  • weighted - by a configured CSV (namespace,weight), typically revenue or headcount shares agreed with finance in writing
  • none - baseline: the pool stays unsplit, emitted as one row

The output is one FOCUS CustomCost row per attributed namespace per window, with the method and the shared sources in labels, and deterministic IDs so re-runs are idempotent.

Why a plugin and not a pipeline change

The shared pool is a policy question, not a data question: which method is defensible is a decision finance signs off on, and it varies per tenant. A plugin keeps the split rule external, written, and versioned - while OpenCost's own allocation data stays untouched. If the maintainers later want the methods in the core allocation pipeline, the logic is small and self-contained.

Structure

Follows the Datadog plugin reference exactly:

  • cmd/main/main.go - OcostSplitterSource implementing CustomCostSource (GetCustomCosts with GetWindows splitting)
  • ocostsplitterplugin/ - config struct (JSON config file), the four split methods, OpenCost allocation API client, FOCUS row builder
  • tests/ - deterministic tests for each method: proportional (100/66.67/33.33 on a 600/200/100 estate), equal, weighted (5/3/2), none baseline, negative-pool rejection, zero-weight rejection, unknown-method rejection, empty-targets rejection

Config example

{
  "opencost_api_address": "http://opencost.opencost:9003",
  "split_method": "proportional",
  "shared_namespaces": ["kube-system", "monitoring", "ingress-nginx"],
  "weights_file": "/config/weights.csv",
  "currency": "USD"
}

Testing

  • 8 deterministic tests, all passing: one per split method plus edge cases (negative pool, zero weight total, unknown method, empty targets)
  • No network in tests: the OpenCost allocation API is stubbed via httptest; the split methods are pure functions
  • Builds with the repo justfile: just build-all-plugins

Closes the tooling half of #2890 (the EKS CUR ingestion as an allocation source is a separate, larger PR I can follow with if the maintainers want it).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant