Grafana Terraform Provider

repository·main·Indexed 19 days ago

https://github.com/grafana/terraform-provider-grafana

The Grafana Terraform Provider allows users to manage Grafana resources, including dashboards, data sources, and users, using Terraform configuration files. It includes the experimental terraform-provider-grafana-generate CLI tool for importing existing infrastructure and supports multiple architectural layers including the Plugin Framework, SDKv2, and AppPlatform for resource development.

Tokens
175.9K
Snippets
417
Records
683
Agent score
64%

What's inside terraform-provider-grafana

  1. Manage Grafana Alerting contact points with grafana_contact_point

    main

    The grafana_contact_point resource allows you to manage Grafana Alerting contact points via Terraform. Contact points define where Grafana sends alerts (e.g., Email, Discord, Slack, etc.).

    Requirements:

    • Grafana version 9.1.0 or later.

    This resource supports various notification integrations through nested schemas such as email, discord, dingding, googlechat, and jira.

    resource "grafana_contact_point" "my_contact_point" {
      name = "My Contact Point"
    
      email {
        addresses               = ["one@company.org", "two@company.org"]
        message                 = "{{ len .Alerts.Firing }} firing."
        subject                 = "{{ template \"default.title\" .}}"
        single_email            = true
        disable_resolve_message = false
      }
    }
  2. Manage Grafana Alerting notification template groups with grafana_message_template

    main

    The grafana_message_template resource allows you to manage Grafana Alerting notification template groups, which include the actual notification templates used for alerting.

    Note: This resource requires Grafana version 9.1.0 or later.

    resource "grafana_message_template" "my_template" {
      name     = "My Notification Template Group"
      template = "{{define \"custom.message\" }}\n template content\n{{ end }}"
    }
  3. Define Model Structs with tfsdk tags

    main

    In the Plugin Framework, typed structs with tfsdk tags are used instead of *schema.ResourceData.

    Warning: The Plugin Framework does not support struct embedding for tfsdk fields. If you need to share fields across models (common in permission-item resources), you must use explicit converter methods like ToBase() and SetFromBase() to move data between your resource-specific model and a base model.

    type myResourceModel struct {
        ID          types.String `tfsdk:"id"`
        Name        types.String `tfsdk:"name"`
        Description types.String `tfsdk:"description"`
        Tags        types.List   `tfsdk:"tags"`
        Config      types.Object `tfsdk:"config"`
    }
  4. How secure field shapes (map vs struct) work

    main

    The Secure field in your resource can take two forms depending on your requirements and the SecureParser used:

    1. Map Form (Recommended): Uses apicommon.InlineSecureValues. This is the most common approach and works with DefaultSecureParser.
    2. Struct Form: Uses a custom struct where each field is of type apicommon.InlineSecureValue. Use this if the API already exposes secure as a struct or if you require explicit per-field typing and JSON-tag mapping.

    Requirements for DefaultSecureParser

    • The resource object must have an exported Secure field.
    • Each secure.<key> in HCL must be an object containing exactly one of:
      • create: To set or rotate an inline secret value.
      • name: To reference an existing secret by name.
    • If the Terraform key differs from the API key, you must configure SecureValueAttribute.APIName in the schema.
    // Map form (Recommended)
    type MyResource struct {
    	metav1.TypeMeta   `json:",inline"`
    	metav1.ObjectMeta `json:"metadata,omitempty"`
    	Spec              MyResourceSpec              `json:"spec,omitempty"`
    	Secure            apicommon.InlineSecureValues `json:"secure,omitempty"` 
    }
    
    // Struct form
    type MyResourceSecure struct {
    	Token        apicommon.InlineSecureValue `json:"token,omitzero,omitempty"`
    	ClientSecret apicommon.InlineSecureValue `json:"clientSecret,omitzero,omitempty"`
    }
    
    type MyResourceWithStructSecure struct {
    	metav1.TypeMeta   `json:",inline"`
    	metav1.ObjectMeta `json:"metadata,omitempty"`
    	Spec              MyResourceSpec  `json:"spec,omitempty"`
    	Secure            MyResourceSecure `json:"secure,omitempty"` 
    }
  5. Target alerts using matchers in Alert Enrichment

    main

    You can control which alerts trigger an enrichment workflow using three primary methods within the spec block:

    1. Alert Rule UIDs: Provide a list of specific alert_rule_uids. If the list is empty, the enrichment applies to all alert rules.
    2. Label Matchers: Match against alert labels. Each matcher requires a name (key), value, and type. Supported operators are =, !=, =~ (regex match), and !~ (regex non-match).
    3. Annotation Matchers: Match against alert annotations using the same name, value, and type structure as label matchers (supporting =, !=, =~, !~).
    4. Receiver Names: Use the receivers list to match specific receiver names. If empty, it applies to all receivers.
  6. How SecureValueAttributes and SecureParser work together

    main

    The secure block framework relies on a contract between the schema definition and the parser:

    1. SecureValueAttributes: A map defined in ResourceSpecSchema that declares which attributes are sensitive. This causes the Terraform schema to include a secure block and a secure_version attribute.
    2. SecureParser: A function responsible for extracting values from the secure block.

    Constraints:

    • If SecureValueAttributes is provided but SecureParser is missing, the provider returns schema diagnostics.
    • If SecureParser is provided but SecureValueAttributes is missing, the provider returns schema diagnostics.
    • If the user omits the secure block in their configuration, the SecureParser receives a null object and the resource creation should proceed without error (treating it as a no-op).
  7. Define enrichment steps in Alert Enrichment

    main

    The spec.step block defines a sequence of actions performed on a matching alert. Each step must contain exactly one of the following enrichment types:

    • assign: Adds specific annotations to the alert. Use the annotations map to define key-value pairs.
    • data_source: Queries Grafana data sources. Supports logs_query (for log sources like Loki) or raw_query (for advanced requests).
    • external: Calls an external HTTP endpoint via a url for enrichment.
    • explain: Generates an AI explanation and stores it in a specified annotation (defaults to ai_explanation).
    • sift: Analyzes alerts for patterns and insights.
    • assistant_investigations: Uses an AI assistant to investigate alerts and add insights.
    • asserts: Integrates with Grafana Asserts.
    • conditional: Implements if/then/else logic. Contains an if block (with its own matchers and data source conditions), a then block (containing a list of steps), and an optional else block (containing a list of steps).
  8. Manage role assignments with grafana_role_assignment

    main

    The grafana_role_assignment resource manages the complete set of assignments for a specific Grafana RBAC role.

    Important Behavior: This resource manages the entire set of assignments for the role. Any existing assignments for the role that are not explicitly defined in this resource will be removed when applying the configuration.

    Requirement: This resource is only available with Grafana Enterprise 9.2+.

    resource "grafana_role_assignment" "test" {
      role_uid         = grafana_role.test_role.uid
      users            = [grafana_user.test_user.id]
      teams            = [grafana_team.test_team.id]
      service_accounts = [grafana_service_account.test_sa.id]
    }
  9. Configure secure keys with create or name

    main

    Within a secure block, each secret key must be configured as an object using one of two modes:

    1. create: Used for inline secret creation or rotation. You provide the actual secret value here.
    2. name: Used to reference an existing secret by its name in the Grafana API.

    Note that these are modeled as write-only maps; the values are discarded after the provider receives them.

    secure {
      token = {
        create = var.token
      }
      client_secret = {
        name = "my-existing-secret-name"
      }
    }
  10. Compare generic vs. typed app platform resources

    main

    When deciding between a grafana_apps_generic_resource and a typed resource (defined in resource.go), consider how they handle state and drift:

    FeatureGeneric ResourceTyped Resource
    TypingWeak/No strong-typingStrong-typing
    Read/RefreshRefreshes spec from server on every ReadPreserves plan state (does NOT refresh spec)
    Drift DetectionAggressive; detects all server-side changesConservative; follows defined schema
  11. Use conditional logic in Alert Enrichment steps

    main

    The conditional step allows for branching enrichment workflows based on alert properties or data source results.

    • if: The condition to evaluate. It can use annotation_matchers, label_matchers, or a data_source_condition (which uses a request payload).
    • then: A list of step blocks to execute if the condition is met.
    • else: A list of step blocks to execute if the condition is not met.
    • timeout: Maximum execution time for the conditional logic (e.g., 30s, 1m).