From 128712c4c92b761349a51e5b78a9b3e25927a863 Mon Sep 17 00:00:00 2001 From: duynguyen Date: Thu, 3 Sep 2026 17:26:32 +0700 Subject: [PATCH] add: Infinity datasource plugin for actual-http-api, wired into Grafana MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Installs yesoreyeram-infinity-datasource on the Grafana pod so it can call Actual's own ActualQL run-query endpoint directly (group-by/sum over any field), instead of being limited to the fixed counters actual-budget-exporter publishes. The datasource connection itself (URL + x-api-key) is added by hand in the Grafana UI, not provisioned here — keeps the API key out of git without needing a dedicated K8s Secret for it. --- README.md | 34 +++++++++++++++++++ .../apps/kube-prometheus-stack/values.yaml | 7 ++++ 2 files changed, 41 insertions(+) diff --git a/README.md b/README.md index 4da09e7..4bb1452 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,40 @@ kubectl exec -n jenkins deploy/jenkins -c jenkins -- cat /run/secrets/additional is set inside its own database on first boot, so it cannot be swapped via a `kubectl patch` the way ArgoCD's can. +**Grafana → actual-http-api datasource** (Infinity plugin, queries +`homelab-docker-compose-prod/actual-http-api`'s ActualQL `run-query` endpoint +directly — see `homelab-services` README for why the Prometheus exporter +alone can't answer arbitrary group-by/amount questions). The chart install +just gets the plugin onto the pod; the datasource itself is added by hand in +the Grafana UI (not provisioned/GitOps) so the API key never needs its own +K8s Secret: + +1. Grafana → **Connections → Data sources → Add data source** → search + **Infinity** → select it. +2. URL: `http://192.168.1.41:8003`. +3. **Auth** → enable **Custom HTTP Headers** → add header + `x-api-key` = ``. Grafana stores this encrypted in its own DB (uses + `kube-prometheus-stack-grafana`'s secret key), not in git. +4. **Save & test**. + +Datasource then shows up in Grafana as whatever name you gave it — build a panel +with method `POST`, URL path `/budgets//run-query`, and an +`ActualQLquery` JSON body, e.g. sum of $ per category: + +```json +{ + "ActualQLquery": { + "table": "transactions", + "groupBy": ["category"], + "select": ["category", { "total": { "$sum": "amount" } }] + } +} +``` + +Keep the panel's refresh interval long (≥1m) — each call is a real login +against `actual_server`, same rate-limit risk hit by the exporter earlier. + **Headlamp login token** (ServiceAccount created by `headlamp/rbac.yaml`): ```bash diff --git a/platform/apps/kube-prometheus-stack/values.yaml b/platform/apps/kube-prometheus-stack/values.yaml index 58d0c26..71999cb 100644 --- a/platform/apps/kube-prometheus-stack/values.yaml +++ b/platform/apps/kube-prometheus-stack/values.yaml @@ -3,6 +3,13 @@ grafana: enabled: true storageClassName: nfs-delete size: 5Gi + # Installs the Infinity datasource plugin so Grafana can query a plain + # REST API (actual-http-api) directly — see README for wiring it up. + # The datasource itself (URL + x-api-key) is added by hand in the Grafana + # UI, not provisioned here — avoids a second hand-created Secret just for + # this one credential. + plugins: + - yesoreyeram-infinity-datasource prometheus: prometheusSpec: