Terraform
Declare Maple dashboards, alert rules, notification destinations, uptime monitors, scrape targets and API keys in Terraform, next to the infrastructure they watch.
The Maple provider for Terraform manages Maple configuration as code: dashboards, alert rules and their destinations, uptime monitors, scrape targets and API keys. It talks to the public v2 API, so anything you can do there with a key you can review in a plan first.
| Provider | mapletechlabs/maple |
| Terraform | 1.0 or later; import blocks need 1.5 |
| Source | packages/terraform-provider-maple |
| Resource reference | Terraform resources |
Quick start
1. Create an API key
In Maple, open Settings → Keys and create an API key. Alert rules, alert destinations, API keys and ingest keys can only be changed with a key created by an org admin. A key with scopes needs the matching :write scope for every resource type it manages, for example dashboards:write and alerts:write.
Export it where you run Terraform:
export MAPLE_API_KEY=maple_ak_...
2. Configure the provider
terraform {
required_providers {
maple = {
source = "mapletechlabs/maple"
version = "~> 0.1"
}
}
}
provider "maple" {}
| Setting | Environment variable | Default |
|---|---|---|
api_key | MAPLE_API_KEY | Required |
api_url | MAPLE_API_URL | https://api.maple.dev |
An organization in the EU region sets api_url = "https://api.eu.maple.dev".
3. Declare an alert
resource "maple_alert_destination" "oncall" {
type = "pagerduty"
name = "Primary on-call"
integration_key = var.pagerduty_integration_key
}
resource "maple_alert_rule" "checkout_errors" {
name = "Checkout error rate"
signal_type = "error_rate"
comparator = "gt"
severity = "critical"
threshold = 0.05
window_minutes = 5
service_names = ["checkout"]
destination_ids = [maple_alert_destination.oncall.id]
}
4. Apply
terraform init
terraform plan
terraform apply
The rule shows up under Alerts in Maple. Change it in the file and apply again: Terraform updates it in place.
Bring existing configuration under Terraform
Every resource can be imported by its ID, which Maple shows in the URL and the API returns as id:
import {
to = maple_dashboard.checkout
id = "dash_2xH8d..."
}
Run terraform plan - to have Terraform write the matching configuration, including the dashboard’s widgets, then move it into your own files. The plan after an import is empty when the configuration matches what is in Maple.
Dashboards, monitors and thresholds are JSON
Dashboard widgets, sections, variables and time_range, an uptime monitor’s config, and an alert rule’s thresholds, query_builder_draft and notification_template are documents in the API’s wire shape. Write them with jsonencode:
resource "maple_uptime_monitor" "api" {
name = "Public API"
config = jsonencode({
type = "http"
url = "https://api.example.com/health"
assertions = [{ type = "status", op = "is", value = "2xx" }]
})
}
A value Maple fills in that you did not write, such as an HTTP monitor’s method = "GET", is not a change. A value you wrote that is different in Maple is, and the next apply puts yours back.
The quickest way to get a dashboard’s widget documents is to build it in Maple and import it.
Secrets and state
Notification credentials (integration_key, webhook_url, bot_token, signing_secret) and a scrape target’s auth_credentials are write-only in the API. Terraform keeps the value you set and sends it on every update, but it cannot see a credential someone changes in Maple.
maple_api_key stores the new key’s secret in state, since Maple only returns it once. The maple_ingest_keys data source reads your ingest keys into state too. Keep state in an encrypted backend.
Rotate API keys
Set rotate on an API key to any value and change it to roll the key. Maple revokes the old key and issues a replacement with the same name and scopes, a new ID and a new secret, so anything that reads maple_api_key.<name>.secret picks up the new one on the same apply:
resource "time_rotating" "quarterly" {
rotation_days = 90
}
resource "maple_api_key" "grafana" {
name = "grafana-readonly"
scopes = ["dashboards:read", "traces:read", "metrics:read"]
rotate = time_rotating.quarterly.id
}
Changing any other attribute of a key, such as its scopes, revokes it and creates a new key.
Wire telemetry with the ingest key
maple_ingest_keys reads your organization’s ingest keys, so a stack can hand the private key to its services without copying it by hand:
data "maple_ingest_keys" "this" {}
resource "kubernetes_secret" "otel" {
metadata { name = "maple-ingest" }
data = { MAPLE_INGEST_KEY = data.maple_ingest_keys.this.private_key }
}
Reading ingest keys needs a key created by an org admin.
Removing things
terraform destroy, or deleting a resource from the configuration, deletes the dashboard, rule, destination, monitor or scrape target in Maple and revokes an API key. Removing an optional attribute from the configuration clears it in Maple, except for the attributes marked default in the resource reference, which keep their last value.