platform.engineering/grafanaofficialv0.1.6stableresource

installation
$formae plugin install grafana
changelog as of v0.1.7-dev.6 · structured per keep a changelog
unreleased
Added
  • The Grafana target Config takes an auth block that selects an authentication strategy: TokenAuth for a service account token or API key, BasicAuth for a username and password. Every credential field accepts a literal string or a resolvable, so a service account token can now be sourced from a formae-managed secret and resolved live at apply time. Previously only basic auth could be sourced that way, and a token could reach the plugin only through the GRAFANA_AUTH environment variable, which forced a target wanting secret-sourced credentials onto instance-superuser admin basic auth. When auth is set, GRAFANA_AUTH is not consulted and an incomplete block is an error rather than a silent fallback to the environment. Omitting auth keeps the existing GRAFANA_AUTH behaviour unchanged.

  • The target Config declares per-field mutability, so auth and orgId can change on an existing target. Target config fields are immutable unless annotated, which meant any edit to a Grafana target was classified as a replace. Grafana resources are not portable across targets, so the apply was rejected outright with NonPortableResources, listing every folder, dashboard and datasource bound to the target. Adopting the auth block on a live target was therefore impossible without first destroying all of them. url is deliberately still immutable: it is where the resources live, so two URLs are two Grafana databases, and updating in place would leave recorded state for objects that do not exist at the new address.

  • NotificationPolicy.receiver now accepts a resolvable to a contact point's name (myContactPoint.res.name) as well as a literal string, and ContactPoint exposes a res resolvable to support it. Grafana rejects a policy tree naming a receiver that does not exist, so previously a first apply could send the policy before its contact point existed and fail, and a destroy could delete the contact point before the policy was reset, leaving the tree inconsistent. Using the resolvable makes the dependency explicit, so formae creates the contact point first and resets the policy first on teardown. Receivers named inside routes are part of an opaque JSON string and still carry no dependency edge.

  • The target Config takes an optional proxyUrl, scoped to that target alone: no other target is affected. It accepts socks5://, socks5h:// or http://; socks5 and socks5h are aliases in Go and behave identically, always handing the destination hostname to the proxy rather than resolving it locally. Setting it makes the target ignore the ambient HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables entirely. Leaving it unset changes nothing: the target still dials through Go's default transport, which continues to honour those variables exactly as before. There is no https:// proxy yet, since a TLS connection to the proxy itself generally needs a private CA or a client certificate this field cannot express, and no support for proxy credentials yet either. A proxyUrl that is malformed, names an unsupported scheme, carries credentials, or is otherwise unusable is rejected as an error when the client is constructed, rather than silently falling back to unproxied dialing.

Changed
  • The target Config fields username and password are replaced by the auth block: write auth = new grafana.BasicAuth { username = …; password = … }. The fields existed only in the 0.1.7-dev.0 prerelease, so no released version is affected.
Fixed
  • An alert rule, notification policy or mute timing whose content is unchanged now reconciles as a true 0-change instead of reporting an update on every apply. AlertRule.data, AlertRule.labels, AlertRule.annotations, NotificationPolicy.routes, NotificationPolicy.groupBy and MuteTiming.timeIntervals each carry a serialized JSON document in a plain String, and none declared a format, so formae compared them byte-for-byte: the authored Pkl source text against the plugin's marshalled output. Those two agree on content but not on key order, so every rule drifted forever and an empty change set stopped being a meaningful signal. All six are now declared as serialized JSON, so both sides are canonicalized before the update diff — the same declaration a dashboard's configJson already carries.

    Two consequences worth knowing. Canonicalization equates two spellings of the same document, not two different documents: members Grafana populates when you omit them (queryType and relativeTimeRange inside data), members stripped on read (a null-valued member of a timeIntervals interval) and an authored "{}" against an absent field are differences in content and still diff — declare those values explicitly. And because these fields are now parsed during the diff, a malformed JSON value can surface as a planning-time failure where it was previously discarded silently and the resource was written without that member.

  • Updating a contact point no longer records its secret settings in cleartext. Grafana stores the secret fields of a contact point encrypted (a Slack url, a PagerDuty integrationKey, a webhook password) and returns them as [REDACTED] on every read path. Update echoed back the settings it had just sent instead of the server's view, so the plaintext secret was written into recorded state on every update, and stayed permanently diverged from what a read reported. Update now reports the state read back from Grafana, which is what create already did.

v0.1.6stableinstalled default
Fixed
  • A Grafana target whose endpoint is unreachable (the backing service is gone — for example a torn-down Compose stack or a decommissioned host) is now reported as unreachable instead of an opaque internal failure. Transport failures on a read — connection refused, DNS failure, dial/read timeout — now map to NetworkFailure/ServiceTimeout rather than the InternalFailure default, so the agent can tell "unreachable" apart from "deleted" and eventually reap a permanently-gone target.
v0.1.5stable
Changed
  • Requires formae 0.87.0 or later.
Fixed
  • Dashboards no longer show formatting-only drift: a dashboard loaded from a pretty-printed JSON file (for example read("dashboard.json")) is stored by Grafana in its own compacted, key-reordered form. Previously every sync reported the dashboard as changed and every apply generated a no-op update, pure whitespace and key-ordering noise, even when nothing about the dashboard had actually changed. The dashboard JSON is now compared by content, so an unchanged dashboard stays quiet, and reformatting your source file (reindenting or reordering keys) on its own no longer triggers an update.
v0.1.4stable
Added
  • Contact point settings as resolvables (settingsMap): GRAFANA::Alerting::ContactPoint gains a settingsMap field whose values accept formae resolvables, so a setting can flow in from another resource (even one managed by a different plugin) in a single apply. This is what lets a PagerDuty integration key wire straight into a Grafana contact point:

    settingsMap = new Mapping {
        ["integrationKey"] = pdIntegration.res.integrationKey
    }

    Provide exactly one of settings (the JSON-string form) or settingsMap.

Changed
  • Provider-immutable fields marked createOnly: fields the Grafana API will not change in place (for example a contact point's name) are now annotated createOnly, so formae replaces the resource instead of attempting an invalid in-place update.
  • Requires formae 0.86.0 or later.
v0.1.3stable
Changed
  • Resource type prefix renamed to GRAFANA::: the namespace prefix is now uppercase to match the formae convention (namespace = "GRAFANA"). All ten resource types are affected (folder, dashboard, alert_rule, contact_point, datasource, message_template, mute_timing, notification_policy, service_account, team). The schema generates these names automatically, so PKL forma files that import the Grafana schema don't need any change. Forma files that reference the resource types by string (e.g. in queries) should switch from Grafana::… to GRAFANA::….
v0.1.2stable
Added
  • Resolvable target URL: The Grafana target URL now accepts resolvable references, so you can wire it directly to another resource's output. For example, connect Grafana to a compose stack endpoint without workarounds:

    config = new grafana.Config {
        url = lgtmStack.res.endpoints.at("lgtm:3000")
    }

    The Endpoints/EndpointKey pattern still works but is deprecated and will be removed in a future release.

v0.1.1
Fixed
  • DataSource resources with default jsonData values no longer cause drift on every sync. Grafana-populated defaults are now recognised as provider defaults.
  • Deleting a NotificationPolicy outside of formae (e.g. via the Grafana UI) is now correctly detected during sync. Previously the resource remained in inventory after an out-of-band delete.
  • Dashboards and AlertRules that reference a folder via folderUid can now use a resolvable reference (folder.res.uid), ensuring the folder is created before the resources that depend on it.
v0.1.0
Added
  • Initial release of the Grafana plugin as a standalone package built on the formae Plugin SDK.
type
resource
category
observability
license
FSL-1.1-ALv2
originator
platform.engineering
namespace
GRAFANA
latest
v0.1.6 · stable
platforms
repo
github.com/platform-engineering-labs/formae-plugin-grafana
versions (14)
select a version to jump to its notes
v0.1.7-dev.6dev
2026-08-23
v0.1.7-dev.5dev
2026-08-15
v0.1.7-dev.4dev
2026-08-11
v0.1.7-dev.3dev
2026-08-09
v0.1.7-dev.2dev
2026-08-07
v0.1.7-dev.1dev
2026-08-07
v0.1.7-dev.0dev
2026-08-07
v0.1.6stable
2026-07-24
v0.1.5stable
2026-06-30
v0.1.5-dev.1dev
2026-06-30
v0.1.5-dev.0dev
2026-06-27
v0.1.4stable
2026-06-26
v0.1.3stable
2026-05-13
v0.1.2stable
2026-05-12