Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
30e9421
Add Terraform v2 dashboard resource and data source
toppercodes Mar 2, 2026
f0d053b
Align dashboards provider fields to v2 spec and fix lint workflow
toppercodes Mar 2, 2026
5dd48f1
Expand dashboard lifecycle unit tests
toppercodes Mar 2, 2026
450bf1e
Add acceptance tests for dashboard lifecycle
toppercodes Mar 2, 2026
85f7671
Make dashboard metadata read-only and remove message input
toppercodes Mar 2, 2026
032f04e
Harden dashboard UID handling and JSON normalization
toppercodes Mar 2, 2026
f462d65
Default imported dashboard overwrite state to false
toppercodes Mar 2, 2026
6edfaf0
Normalize dashboard state to configured fields
toppercodes Mar 2, 2026
9f1448f
Strip api-injected empty overrides from dashboard state
toppercodes Mar 2, 2026
f479ef5
Use dashboard uid as Terraform resource id
toppercodes Mar 2, 2026
3b0d9d4
Normalize owner casing against configured dashboard JSON
toppercodes Mar 2, 2026
527b9f9
Bump axiom-go dashboards commit and fix lint setup
toppercodes Mar 3, 2026
f84125a
Ignore dashboard metadata fields in resource state
toppercodes Mar 3, 2026
064d1e2
Stop tracking dashboard version in resource state
toppercodes Mar 3, 2026
7fbd666
Update version to 1.4.8 and add new dashboard resource in example con…
toppercodes Mar 3, 2026
e730612
Fix acceptance tests when TF_ACC is not enabled
toppercodes Mar 3, 2026
b3deafb
Revert "Fix acceptance tests when TF_ACC is not enabled"
toppercodes Mar 3, 2026
f0c839c
Stabilize dashboard import acceptance checks
toppercodes Mar 3, 2026
ea3b058
Harden dashboard import assertions
toppercodes Mar 3, 2026
343e27e
Normalize default dashboard owner during import
toppercodes Mar 3, 2026
fe3a90e
Fix dashboard import check UID capture
toppercodes Mar 3, 2026
2450be7
Add dedicated local provider install target
toppercodes Mar 4, 2026
ff2a91e
Refactor provider version handling, update test imports, and enhance …
toppercodes Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NAME=axiom
BINARY=terraform-provider-${NAME}
GIT_TAG:=$(shell git describe --tags --exact-match 2>/dev/null)
VERSION?=$(if $(GIT_TAG),$(patsubst v%,%,$(GIT_TAG)),dev)
LOCAL_TEST_VERSION?=0.0.0-local
LDFLAGS=-X terraform-provider-axiom-provider/axiom.providerVersion=${VERSION}
OS_ARCH=darwin_arm64

Expand Down Expand Up @@ -34,6 +35,11 @@ install: build
mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}
mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}

install-local:
go build -ldflags "-X terraform-provider-axiom-provider/axiom.providerVersion=${LOCAL_TEST_VERSION}" -o ${BINARY}
mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${LOCAL_TEST_VERSION}/${OS_ARCH}
mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${LOCAL_TEST_VERSION}/${OS_ARCH}

test:
go test -count=1 -parallel=4 ./...

Expand Down
137 changes: 137 additions & 0 deletions axiom/data_source_dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package axiom

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/axiomhq/axiom-go/axiom"
)

var _ datasource.DataSource = &DashboardDataSource{}

func NewDashboardDataSource() datasource.DataSource {
return &DashboardDataSource{}
}

type DashboardDataSource struct {
client *axiom.Client
}

type DashboardDataSourceModel struct {
ID types.String `tfsdk:"id"`
UID types.String `tfsdk:"uid"`
Dashboard types.String `tfsdk:"dashboard"`
Version types.Int64 `tfsdk:"version"`
CreatedAt types.String `tfsdk:"created_at"`
UpdatedAt types.String `tfsdk:"updated_at"`
CreatedBy types.String `tfsdk:"created_by"`
UpdatedBy types.String `tfsdk:"updated_by"`
}

func (d *DashboardDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*axiom.Client)
if !ok {
resp.Diagnostics.AddError(
"Unexpected datasource Configure Type",
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.client = client
}

func (d *DashboardDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_dashboard"
}

func (d *DashboardDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"uid": schema.StringAttribute{
Required: true,
MarkdownDescription: "Dashboard UID.",
},
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Internal dashboard identifier returned by the API.",
},
"dashboard": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Dashboard document as normalized JSON.",
},
"version": schema.Int64Attribute{
Computed: true,
MarkdownDescription: "Monotonic dashboard version.",
},
"created_at": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Creation timestamp returned by the API.",
},
"updated_at": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Last update timestamp returned by the API.",
},
"created_by": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Creator returned by the API.",
},
"updated_by": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Last updater returned by the API.",
},
},
}
}

func (d *DashboardDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var config DashboardDataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}

if d.client == nil {
resp.Diagnostics.AddError("Client Error", "Client is not set")
return
}

raw, err := d.client.Dashboards.GetRaw(ctx, config.UID.ValueString())
if err != nil {
resp.Diagnostics.AddError("Failed to read dashboard", err.Error())
return
}

dashboard, err := decodeDashboardResource(raw)
if err != nil {
resp.Diagnostics.AddError("Failed to read dashboard", fmt.Sprintf("Unable to decode API response: %s", err))
return
}

dashboardJSON, err := normalizeDashboardRaw(dashboard.Dashboard, types.StringValue(string(dashboard.Dashboard)))
if err != nil {
resp.Diagnostics.AddError("Failed to read dashboard", fmt.Sprintf("Unable to normalize dashboard payload: %s", err))
return
}

state := DashboardDataSourceModel{
UID: types.StringValue(dashboard.UID),
ID: types.StringValue(dashboard.ID),
Dashboard: types.StringValue(dashboardJSON),
Version: types.Int64Value(dashboard.Version),
CreatedAt: types.StringValue(dashboard.CreatedAt),
UpdatedAt: types.StringValue(dashboard.UpdatedAt),
CreatedBy: types.StringValue(dashboard.CreatedBy),
UpdatedBy: types.StringValue(dashboard.UpdatedBy),
}

resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}
2 changes: 2 additions & 0 deletions axiom/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func (p *axiomProvider) Configure(ctx context.Context, req provider.ConfigureReq
// DataSources defines the data sources implemented in the provider.
func (p *axiomProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{
NewDashboardDataSource,
NewDatasetDataSource,
NewMonitorDataSource,
NewNotifierDataSource,
Expand All @@ -137,6 +138,7 @@ func (p *axiomProvider) DataSources(_ context.Context) []func() datasource.DataS
// Resources defines the resources implemented in the provider.
func (p *axiomProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
NewDashboardResource,
NewDatasetResource,
NewMonitorResource,
NewNotifierResource,
Expand Down
16 changes: 16 additions & 0 deletions axiom/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,14 @@ func testAccCheckAxiomResourcesDestroyed(client *ax.Client) func(s *terraform.St
_, err = client.Tokens.Get(context.Background(), resource.Primary.ID)
case "axiom_virtual_field":
_, err = client.VirtualFields.Get(context.Background(), resource.Primary.ID)
case "axiom_dashboard":
uid := resource.Primary.Attributes["uid"]
if uid == "" {
uid = resource.Primary.ID
}
_, err = client.Dashboards.GetRaw(context.Background(), uid)
default:
continue
}
if err == nil {
return fmt.Errorf("resource %s still exists after destroy", id)
Expand Down Expand Up @@ -787,6 +795,14 @@ func testAccCheckAxiomResourcesExist(client *ax.Client, resourceName string) res
_, err = client.Tokens.Get(context.Background(), rs.Primary.ID)
case "axiom_virtual_field":
_, err = client.VirtualFields.Get(context.Background(), rs.Primary.ID)
case "axiom_dashboard":
uid := rs.Primary.Attributes["uid"]
if uid == "" {
uid = rs.Primary.ID
}
_, err = client.Dashboards.GetRaw(context.Background(), uid)
default:
return fmt.Errorf("unsupported resource type in existence check: %s", rs.Type)
}

if err != nil {
Expand Down
Loading
Loading