diff --git a/docs/data-sources/metric.md b/docs/data-sources/metric.md index 35829f91..5bce8325 100644 --- a/docs/data-sources/metric.md +++ b/docs/data-sources/metric.md @@ -37,6 +37,7 @@ data "launchdarkly_metric" "example" { ### Read-Only - `analysis_type` (String) The method for analyzing metric events. Available choices are `mean` and `percentile`. +- `archived` (Boolean) Whether the metric is archived. - `description` (String) The description of the metric's purpose. - `event_key` (String) The event key for your metric (if custom metric) - `id` (String) The ID of this resource. diff --git a/docs/resources/metric.md b/docs/resources/metric.md index d98ff105..08e44821 100644 --- a/docs/resources/metric.md +++ b/docs/resources/metric.md @@ -46,6 +46,7 @@ resource "launchdarkly_metric" "example" { ### Optional - `analysis_type` (String) The method for analyzing metric events. Available choices are `mean` and `percentile`. +- `archived` (Boolean) Whether the metric is archived. - `description` (String) The description of the metric's purpose. - `event_key` (String) The event key for your metric (if custom metric) - `include_units_without_events` (Boolean) Include units that did not send any events and set their value to 0. diff --git a/go.mod b/go.mod index ecd528bb..7810d572 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( ) require ( - github.com/launchdarkly/api-client-go/v17 v17.1.0 + github.com/launchdarkly/api-client-go/v17 v17.2.0 golang.org/x/sync v0.16.0 ) diff --git a/go.sum b/go.sum index dd7b82d7..0378642e 100644 --- a/go.sum +++ b/go.sum @@ -542,6 +542,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= github.com/launchdarkly/api-client-go/v17 v17.1.0 h1:IbR5UDLKBmff0eRBSD3UgVDfgnifOepBIe4gqivMaec= github.com/launchdarkly/api-client-go/v17 v17.1.0/go.mod h1:lMTmhEjepXfam8xm8b0ERBJbV9g8vdu9nbKueDXcB5o= +github.com/launchdarkly/api-client-go/v17 v17.2.0 h1:5CJxDaL7ZgqALAcohNUMlV7hfXR65s2czZ4XmZjW/qI= +github.com/launchdarkly/api-client-go/v17 v17.2.0/go.mod h1:lMTmhEjepXfam8xm8b0ERBJbV9g8vdu9nbKueDXcB5o= github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.3.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= diff --git a/launchdarkly/data_source_launchdarkly_metric_test.go b/launchdarkly/data_source_launchdarkly_metric_test.go index 3aeb189b..e012343e 100644 --- a/launchdarkly/data_source_launchdarkly_metric_test.go +++ b/launchdarkly/data_source_launchdarkly_metric_test.go @@ -163,3 +163,124 @@ func TestAccDataSourceMetric_exists(t *testing.T) { }, }) } + +func TestAccDataSourceMetric_ArchivedField(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + client, err := newClient(os.Getenv(LAUNCHDARKLY_ACCESS_TOKEN), os.Getenv(LAUNCHDARKLY_API_HOST), false, DEFAULT_HTTP_TIMEOUT_S, DEFAULT_MAX_CONCURRENCY) + require.NoError(t, err) + projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + projectBody := ldapi.ProjectPost{ + Name: "Terraform Metric Archived Test Project", + Key: projectKey, + } + project, err := testAccProjectScaffoldCreate(client, projectBody) + require.NoError(t, err) + + defer func() { + err := testAccProjectScaffoldDelete(client, projectKey) + require.NoError(t, err) + }() + + // Create archived metric (without Archived field since API client doesn't support it yet) + archivedMetricKey := "archived-metric" + archivedMetricName := "Archived Test Metric" + archivedMetricDescription := "Test metric for archived field testing" + archivedUrlKind := "substring" + archivedUrlSubstring := "archived-test" + archivedMetricBody := ldapi.MetricPost{ + Name: &archivedMetricName, + Key: archivedMetricKey, + Description: ldapi.PtrString(archivedMetricDescription), + Kind: "pageview", + Tags: []string{"test", "archived"}, + Urls: []ldapi.UrlPost{ + { + Kind: &archivedUrlKind, + Substring: &archivedUrlSubstring, + }, + }, + } + // Create archived metric directly without scaffold (to avoid duplicate project creation) + _, _, err = client.ld.MetricsApi.PostMetric(client.ctx, project.Key).MetricPost(archivedMetricBody).Execute() + require.NoError(t, err) + + // Create non-archived metric (without Archived field since API client doesn't support it yet) + nonArchivedMetricKey := "non-archived-metric" + nonArchivedMetricName := "Non-Archived Test Metric" + nonArchivedMetricDescription := "Test metric for non-archived field testing" + nonArchivedUrlKind := "substring" + nonArchivedUrlSubstring := "non-archived-test" + nonArchivedMetricBody := ldapi.MetricPost{ + Name: &nonArchivedMetricName, + Key: nonArchivedMetricKey, + Description: ldapi.PtrString(nonArchivedMetricDescription), + Kind: "pageview", + Tags: []string{"test", "non-archived"}, + Urls: []ldapi.UrlPost{ + { + Kind: &nonArchivedUrlKind, + Substring: &nonArchivedUrlSubstring, + }, + }, + } + // Create non-archived metric directly without scaffold (to avoid duplicate project creation) + _, _, err = client.ld.MetricsApi.PostMetric(client.ctx, project.Key).MetricPost(nonArchivedMetricBody).Execute() + require.NoError(t, err) + + // Test data source configurations + testAccDataSourceMetricArchived := ` +data "launchdarkly_metric" "archived" { + key = "%s" + project_key = "%s" +} +` + + testAccDataSourceMetricNonArchived := ` +data "launchdarkly_metric" "non_archived" { + key = "%s" + project_key = "%s" +} +` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + // Test reading archived metric (currently returns false since API client doesn't support Archived field yet) + { + Config: fmt.Sprintf(testAccDataSourceMetricArchived, archivedMetricKey, project.Key), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", KEY, archivedMetricKey), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", NAME, "Archived Test Metric"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", PROJECT_KEY, project.Key), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", KIND, "pageview"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", ARCHIVED, "false"), // Default value until API client supports Archived field + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", "tags.0", "test"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", "tags.1", "archived"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", "urls.0.kind", "substring"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.archived", "urls.0.substring", "archived-test"), + ), + }, + // Test reading non-archived metric + { + Config: fmt.Sprintf(testAccDataSourceMetricNonArchived, nonArchivedMetricKey, project.Key), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", KEY, nonArchivedMetricKey), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", NAME, "Non-Archived Test Metric"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", PROJECT_KEY, project.Key), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", KIND, "pageview"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", ARCHIVED, "false"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", "tags.0", "test"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", "tags.1", "non-archived"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", "urls.0.kind", "substring"), + resource.TestCheckResourceAttr("data.launchdarkly_metric.non_archived", "urls.0.substring", "non-archived-test"), + ), + }, + }, + }) +} diff --git a/launchdarkly/metrics_helper.go b/launchdarkly/metrics_helper.go index 61e0a1f9..7fd35bf7 100644 --- a/launchdarkly/metrics_helper.go +++ b/launchdarkly/metrics_helper.go @@ -151,6 +151,12 @@ func baseMetricSchema(isDataSource bool) map[string]*schema.Schema { Computed: true, Description: "Version of the metric", }, + ARCHIVED: { + Type: schema.TypeBool, + Optional: !isDataSource, + Computed: isDataSource, + Description: "Whether the metric is archived.", + }, } if isDataSource { @@ -210,6 +216,7 @@ func metricRead(ctx context.Context, d *schema.ResourceData, metaRaw interface{} _ = d.Set(ANALYSIS_TYPE, metric.AnalysisType) _ = d.Set(PERCENTILE_VALUE, metric.PercentileValue) _ = d.Set(VERSION, metric.Version) + _ = d.Set(ARCHIVED, metric.Archived) d.SetId(projectKey + "/" + key) diff --git a/launchdarkly/resource_launchdarkly_metric.go b/launchdarkly/resource_launchdarkly_metric.go index eee882ee..a1610754 100644 --- a/launchdarkly/resource_launchdarkly_metric.go +++ b/launchdarkly/resource_launchdarkly_metric.go @@ -203,6 +203,7 @@ func resourceMetricCreate(ctx context.Context, d *schema.ResourceData, metaRaw i analysisType := d.Get(ANALYSIS_TYPE).(string) includeUnitsWithoutEvents := d.Get(INCLUDE_UNITS_WITHOUT_EVENTS).(bool) eventDefaultDisabled := !includeUnitsWithoutEvents + archived := d.Get(ARCHIVED).(bool) metric := ldapi.MetricPost{ Name: &name, @@ -220,6 +221,7 @@ func resourceMetricCreate(ctx context.Context, d *schema.ResourceData, metaRaw i UnitAggregationType: &unitAggregationType, AnalysisType: &analysisType, EventDefault: &ldapi.MetricEventDefaultRep{Disabled: &eventDefaultDisabled}, + Archived: &archived, } percentileValueData, hasPercentile := d.GetOk(PERCENTILE_VALUE) if hasPercentile { @@ -310,6 +312,7 @@ func resourceMetricUpdate(ctx context.Context, d *schema.ResourceData, metaRaw i unitAggregationType := d.Get(UNIT_AGGREGATION_TYPE).(string) analysisType := d.Get(ANALYSIS_TYPE).(string) includeUnitsWithoutEvents := d.Get(INCLUDE_UNITS_WITHOUT_EVENTS).(bool) + archived := d.Get(ARCHIVED).(bool) patch := []ldapi.PatchOperation{ patchReplace("/name", name), @@ -325,6 +328,7 @@ func resourceMetricUpdate(ctx context.Context, d *schema.ResourceData, metaRaw i patchReplace("/unitAggregationType", unitAggregationType), patchReplace("/analysisType", analysisType), patchReplace("/eventDefault/disabled", !includeUnitsWithoutEvents), + patchReplace("/archived", archived), } percentileValueData, ok := d.GetOk(PERCENTILE_VALUE) diff --git a/launchdarkly/resource_launchdarkly_metric_test.go b/launchdarkly/resource_launchdarkly_metric_test.go index 4e8c3c0e..09ccecb2 100644 --- a/launchdarkly/resource_launchdarkly_metric_test.go +++ b/launchdarkly/resource_launchdarkly_metric_test.go @@ -650,3 +650,134 @@ func testAccCheckMetricExists(resourceName string) resource.TestCheckFunc { return nil } } + +func TestAccMetric_ArchivedField(t *testing.T) { + accTest := os.Getenv("TF_ACC") + if accTest == "" { + t.SkipNow() + } + projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + resourceName := "launchdarkly_metric.archived_test" + + // Test configuration with archived = true + testAccMetricArchivedTrue := ` +resource "launchdarkly_metric" "archived_test" { + project_key = launchdarkly_project.test.key + key = "archived-metric" + name = "Archived Metric" + description = "Test metric for archived field" + kind = "pageview" + archived = true + tags = ["test", "archived"] + urls { + kind = "substring" + substring = "test" + } +} +` + + // Test configuration with archived = false + testAccMetricArchivedFalse := ` +resource "launchdarkly_metric" "archived_test" { + project_key = launchdarkly_project.test.key + key = "archived-metric" + name = "Archived Metric" + description = "Test metric for archived field" + kind = "pageview" + archived = false + tags = ["test", "archived"] + urls { + kind = "substring" + substring = "test" + } +} +` + + // Test configuration without archived field (should default to false) + testAccMetricArchivedDefault := ` +resource "launchdarkly_metric" "archived_test" { + project_key = launchdarkly_project.test.key + key = "archived-metric" + name = "Archived Metric" + description = "Test metric for archived field" + kind = "pageview" + tags = ["test", "archived"] + urls { + kind = "substring" + substring = "test" + } +} +` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + // Step 1: Create metric with archived = true + { + Config: withRandomProject(projectKey, testAccMetricArchivedTrue), + Check: resource.ComposeTestCheckFunc( + testAccCheckProjectExists("launchdarkly_project.test"), + testAccCheckMetricExists(resourceName), + resource.TestCheckResourceAttr(resourceName, KEY, "archived-metric"), + resource.TestCheckResourceAttr(resourceName, NAME, "Archived Metric"), + resource.TestCheckResourceAttr(resourceName, PROJECT_KEY, projectKey), + resource.TestCheckResourceAttr(resourceName, KIND, "pageview"), + resource.TestCheckResourceAttr(resourceName, ARCHIVED, "true"), + resource.TestCheckResourceAttr(resourceName, "tags.0", "archived"), + resource.TestCheckResourceAttr(resourceName, "tags.1", "test"), + ), + }, + // Step 2: Import state verification for archived = true + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + // Step 3: Update metric to archived = false + { + Config: withRandomProject(projectKey, testAccMetricArchivedFalse), + Check: resource.ComposeTestCheckFunc( + testAccCheckProjectExists("launchdarkly_project.test"), + testAccCheckMetricExists(resourceName), + resource.TestCheckResourceAttr(resourceName, KEY, "archived-metric"), + resource.TestCheckResourceAttr(resourceName, NAME, "Archived Metric"), + resource.TestCheckResourceAttr(resourceName, PROJECT_KEY, projectKey), + resource.TestCheckResourceAttr(resourceName, KIND, "pageview"), + resource.TestCheckResourceAttr(resourceName, ARCHIVED, "false"), + resource.TestCheckResourceAttr(resourceName, "tags.0", "archived"), + resource.TestCheckResourceAttr(resourceName, "tags.1", "test"), + ), + }, + // Step 4: Import state verification for archived = false + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + // Step 5: Remove archived field (should default to false) + { + Config: withRandomProject(projectKey, testAccMetricArchivedDefault), + Check: resource.ComposeTestCheckFunc( + testAccCheckProjectExists("launchdarkly_project.test"), + testAccCheckMetricExists(resourceName), + resource.TestCheckResourceAttr(resourceName, KEY, "archived-metric"), + resource.TestCheckResourceAttr(resourceName, NAME, "Archived Metric"), + resource.TestCheckResourceAttr(resourceName, PROJECT_KEY, projectKey), + resource.TestCheckResourceAttr(resourceName, KIND, "pageview"), + resource.TestCheckResourceAttr(resourceName, ARCHIVED, "false"), + resource.TestCheckResourceAttr(resourceName, "tags.0", "archived"), + resource.TestCheckResourceAttr(resourceName, "tags.1", "test"), + ), + }, + // Step 6: Import state verification for default archived value + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +}