diff --git a/axiom/provider_test.go b/axiom/provider_test.go index d66b478..5f708a9 100644 --- a/axiom/provider_test.go +++ b/axiom/provider_test.go @@ -39,6 +39,7 @@ func TestAccAxiomResources_basic(t *testing.T) { testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_without_description"), resource.TestCheckResourceAttr("axiom_dataset.test", "name", "terraform-provider-dataset"), resource.TestCheckResourceAttr("axiom_dataset.test", "description", "A test dataset"), + resource.TestCheckResourceAttr("axiom_dataset.test", "kind", "axiom:events:v1"), resource.TestCheckResourceAttr("axiom_dataset.test", "use_retention_period", "false"), resource.TestCheckResourceAttr("axiom_dataset.test", "retention_days", "0"), resource.TestCheckResourceAttr("axiom_virtual_field.test", "name", "VF"), @@ -108,6 +109,69 @@ func TestAccAxiomResources_data(t *testing.T) { }) } +func TestAccAxiomDataset_kind(t *testing.T) { + client, err := ax.NewClient() + assert.NoError(t, err) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "axiom": providerserver.NewProtocol6WithError(NewAxiomProvider()), + }, + CheckDestroy: testAccCheckAxiomResourcesDestroyed(client), + Steps: []resource.TestStep{ + { + Config: ` + provider "axiom" { + api_token = "` + os.Getenv("AXIOM_TOKEN") + `" + base_url = "` + os.Getenv("AXIOM_URL") + `" + } + + resource "axiom_dataset" "test_otel_metrics" { + name = "test-otel-metrics-` + uuid.NewString() + `" + kind = "otel:metrics:v1" + description = "Test OTEL metrics dataset" + } + + resource "axiom_dataset" "test_otel_traces" { + name = "test-otel-traces-` + uuid.NewString() + `" + kind = "otel:traces:v1" + description = "Test OTEL traces dataset" + } + + resource "axiom_dataset" "test_otel_logs" { + name = "test-otel-logs-` + uuid.NewString() + `" + kind = "otel:logs:v1" + description = "Test OTEL logs dataset" + } + + resource "axiom_dataset" "test_default_kind" { + name = "test-default-kind-` + uuid.NewString() + `" + description = "Test dataset with default kind" + } + `, + Check: resource.ComposeTestCheckFunc( + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_metrics"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_metrics", "kind", "otel:metrics:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_metrics", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_traces"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_traces", "kind", "otel:traces:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_traces", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_logs"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_logs", "kind", "otel:logs:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_logs", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_default_kind"), + resource.TestCheckResourceAttr("axiom_dataset.test_default_kind", "kind", "axiom:events:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_default_kind", "kind", "kind"), + ), + }, + }, + }) +} + func TestAccAxiomResources_resolvable(t *testing.T) { client, err := ax.NewClient() assert.NoError(t, err) @@ -567,7 +631,7 @@ func TestAccAxiomResources_dataset_map_fields(t *testing.T) { } resource "axiom_dataset" "test" { - name = "` + datasetName + `" + name = "` + datasetName + `" map_fields = ["dupe", "dupe"] } `, @@ -582,7 +646,7 @@ func TestAccAxiomResources_dataset_map_fields(t *testing.T) { } resource "axiom_dataset" "test" { - name = "` + datasetName + `" + name = "` + datasetName + `" map_fields = [] } `, @@ -595,6 +659,69 @@ func TestAccAxiomResources_dataset_map_fields(t *testing.T) { }) } +func TestAccAxiomResources_dataset_map_kind(t *testing.T) { + client, err := ax.NewClient() + assert.NoError(t, err) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "axiom": providerserver.NewProtocol6WithError(NewAxiomProvider()), + }, + CheckDestroy: testAccCheckAxiomResourcesDestroyed(client), + Steps: []resource.TestStep{ + { + Config: ` + provider "axiom" { + api_token = "` + os.Getenv("AXIOM_TOKEN") + `" + base_url = "` + os.Getenv("AXIOM_URL") + `" + } + + resource "axiom_dataset" "test_otel_metrics" { + name = "test-otel-metrics-` + uuid.NewString() + `" + kind = "otel:metrics:v1" + description = "Test OTEL metrics dataset" + } + + resource "axiom_dataset" "test_otel_traces" { + name = "test-otel-traces-` + uuid.NewString() + `" + kind = "otel:traces:v1" + description = "Test OTEL traces dataset" + } + + resource "axiom_dataset" "test_otel_logs" { + name = "test-otel-logs-` + uuid.NewString() + `" + kind = "otel:logs:v1" + description = "Test OTEL logs dataset" + } + + resource "axiom_dataset" "test_default_kind" { + name = "test-default-kind-` + uuid.NewString() + `" + description = "Test dataset with default kind" + } + `, + Check: resource.ComposeTestCheckFunc( + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_metrics"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_metrics", "kind", "otel:metrics:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_metrics", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_traces"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_traces", "kind", "otel:traces:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_traces", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_otel_logs"), + resource.TestCheckResourceAttr("axiom_dataset.test_otel_logs", "kind", "otel:logs:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_otel_logs", "kind", "kind"), + + testAccCheckAxiomResourcesExist(client, "axiom_dataset.test_default_kind"), + resource.TestCheckResourceAttr("axiom_dataset.test_default_kind", "kind", "axiom:events:v1"), + testAccCheckResourcesCreatesCorrectValues(client, "axiom_dataset.test_default_kind", "kind", "kind"), + ), + }, + }, + }) +} + func testAccPreCheck(t *testing.T) { if os.Getenv("AXIOM_TOKEN") == "" { t.Fatalf("AXIOM_TOKEN must be set for acceptance tests") @@ -732,7 +859,7 @@ resource "axiom_dataset" "test" { } resource "axiom_virtual_field" "test" { - depends_on = [axiom_dataset.test] + depends_on = [axiom_dataset.test] name = "VF" description = "my virtual field" expression = "a * b" @@ -790,7 +917,7 @@ resource "axiom_monitor" "test_monitor_without_description" { ] alert_on_no_data = false notify_by_group = false - type = "Threshold" + type = "Threshold" } resource "axiom_monitor" "test_monitor_match_event" { diff --git a/axiom/resource_dataset.go b/axiom/resource_dataset.go index 155969d..aa9a9ed 100644 --- a/axiom/resource_dataset.go +++ b/axiom/resource_dataset.go @@ -182,6 +182,12 @@ func (r *DatasetResource) Create(ctx context.Context, req resource.CreateRequest return } + // Set state immediately after creation to avoid orphaned resources + resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) + if resp.Diagnostics.HasError() { + return + } + if !plan.MapFields.IsUnknown() { mapFields := axiom.MapFields{} diags := plan.MapFields.ElementsAs(ctx, &mapFields, false) @@ -197,9 +203,8 @@ func (r *DatasetResource) Create(ctx context.Context, req resource.CreateRequest } ds.MapFields = resMapFields + resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) } - - resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) } func (r *DatasetResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { @@ -255,6 +260,12 @@ func (r *DatasetResource) Update(ctx context.Context, req resource.UpdateRequest return } + // Set state immediately after update to preserve changes + resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) + if resp.Diagnostics.HasError() { + return + } + if !plan.MapFields.IsUnknown() { mapFields := axiom.MapFields{} diags := plan.MapFields.ElementsAs(ctx, &mapFields, false) @@ -270,9 +281,8 @@ func (r *DatasetResource) Update(ctx context.Context, req resource.UpdateRequest } ds.MapFields = resMapFields + resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) } - - resp.Diagnostics.Append(resp.State.Set(ctx, flattenDataset(ds))...) } func (r *DatasetResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { diff --git a/docs/resources/dataset.md b/docs/resources/dataset.md index 0ff34ce..99bac33 100644 --- a/docs/resources/dataset.md +++ b/docs/resources/dataset.md @@ -22,6 +22,7 @@ description: |- ### Optional - `description` (String) Dataset description +- `kind` (String) Dataset kind. Must be one of: 'axiom:events:v1', 'otel:metrics:v1', 'otel:traces:v1', 'otel:logs:v1'. Defaults to 'axiom:events:v1' - `map_fields` (List of String) Map fields for the dataset - `retention_days` (Number) Retention days for the dataset - `use_retention_period` (Boolean) Use retention for the dataset