diff --git a/launchdarkly/metrics_helper.go b/launchdarkly/metrics_helper.go index 9b926215..b16711ee 100644 --- a/launchdarkly/metrics_helper.go +++ b/launchdarkly/metrics_helper.go @@ -88,6 +88,8 @@ func baseMetricSchema(isDataSource bool) map[string]*schema.Schema { Optional: true, Description: "The success criteria for your metric (if numeric metric)", ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"HigherThanBaseline", "LowerThanBaseline"}, false)), + Computed: true, + ComputedWhen: []string{KIND}, }, URLS: { Type: schema.TypeList, diff --git a/launchdarkly/resource_launchdarkly_feature_flag.go b/launchdarkly/resource_launchdarkly_feature_flag.go index abad64e0..dc2c9487 100644 --- a/launchdarkly/resource_launchdarkly_feature_flag.go +++ b/launchdarkly/resource_launchdarkly_feature_flag.go @@ -71,6 +71,13 @@ func resourceFeatureFlagCreate(ctx context.Context, d *schema.ResourceData, meta if err != nil { return diag.Errorf("invalid default variations: %v", err) } + variationType := d.Get(VARIATION_TYPE).(string) + if variationType == BOOL_VARIATION && len(variations) == 0 { + // explicitly define default boolean variations. + // this prevents the "Default off variation must be a valid index in the variations list" + // error that we see when we define defaults but no variations + variations = []ldapi.Variation{{Value: true}, {Value: false}} + } flag := ldapi.FeatureFlagBody{ Name: flagName, diff --git a/launchdarkly/resource_launchdarkly_metric.go b/launchdarkly/resource_launchdarkly_metric.go index c765b110..48787a89 100644 --- a/launchdarkly/resource_launchdarkly_metric.go +++ b/launchdarkly/resource_launchdarkly_metric.go @@ -10,6 +10,8 @@ import ( ldapi "github.com/launchdarkly/api-client-go/v14" ) +const CUSTOM_METRIC_DEFAULT_SUCCESS_CRITERIA = "HigherThanBaseline" + // Our required fields for metrics depend on the value of the 'kind' enum. // As of now, TF does not support validating multiple attributes at once, so our only options are // Validating at runtime in Create/Update (and only alerting at apply stage) @@ -53,12 +55,19 @@ func customizeMetricDiff(ctx context.Context, diff *schema.ResourceDiff, v inter return fmt.Errorf("click metrics do not accept 'event_key'") } case "custom": + // enum validation is done in validateFunction against attribute + if successCriteriaInConfig.IsNull() { + err := diff.SetNew(SUCCESS_CRITERIA, CUSTOM_METRIC_DEFAULT_SUCCESS_CRITERIA) + if err != nil { + return err + } + } isNumericInConfig := config.GetAttr(IS_NUMERIC) // numeric custom metrics have extra required fields if isNumericInConfig.True() { - // enum validation is done in validateFunction against attribute if successCriteriaInConfig.IsNull() { return fmt.Errorf("numeric custom metrics require 'success_criteria' to be set") + } if unitInConfig.IsNull() { return fmt.Errorf("numeric custom metrics require 'unit' to be set") @@ -168,6 +177,11 @@ func resourceMetricCreate(ctx context.Context, d *schema.ResourceData, metaRaw i if ok { successCriteria := d.Get(SUCCESS_CRITERIA).(string) metric.SuccessCriteria = &successCriteria + } else { + if kind == "custom" { + successCriteria := CUSTOM_METRIC_DEFAULT_SUCCESS_CRITERIA + metric.SuccessCriteria = &successCriteria + } } _, _, err := client.ld.MetricsApi.PostMetric(client.ctx, projectKey).MetricPost(metric).Execute() @@ -249,6 +263,10 @@ func resourceMetricUpdate(ctx context.Context, d *schema.ResourceData, metaRaw i successCriteria, ok := d.GetOk(SUCCESS_CRITERIA) if ok { patch = append(patch, patchReplace("/successCriteria", successCriteria.(string))) + } else { + if kind == "custom" { + patch = append(patch, patchReplace("/successCriteria", CUSTOM_METRIC_DEFAULT_SUCCESS_CRITERIA)) + } } // Only update the maintainer ID if is specified in the schema diff --git a/launchdarkly/resource_launchdarkly_metric_test.go b/launchdarkly/resource_launchdarkly_metric_test.go index 89d88bb0..47465ba3 100644 --- a/launchdarkly/resource_launchdarkly_metric_test.go +++ b/launchdarkly/resource_launchdarkly_metric_test.go @@ -120,7 +120,7 @@ func scaffoldProjectWithExperimentationSettings(client *Client, betaClient *Clie return err } -func TestAccMetric_Basic(t *testing.T) { +func TestAccMetric_BasicCreateAndUpdate(t *testing.T) { projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) resourceName := "launchdarkly_metric.basic" resource.ParallelTest(t, resource.TestCase{ @@ -149,34 +149,6 @@ func TestAccMetric_Basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, - }, - }) -} - -func TestAccMetric_Update(t *testing.T) { - projectKey := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - resourceName := "launchdarkly_metric.basic" - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { - testAccPreCheck(t) - }, - Providers: testAccProviders, - Steps: []resource.TestStep{ - { - Config: withRandomProject(projectKey, testAccMetricBasic), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectExists("launchdarkly_project.test"), - testAccCheckMetricExists(resourceName), - resource.TestCheckResourceAttr(resourceName, NAME, "Basic Metric"), - resource.TestCheckResourceAttr(resourceName, KEY, "basic-metric"), - resource.TestCheckResourceAttr(resourceName, PROJECT_KEY, projectKey), - resource.TestCheckResourceAttr(resourceName, KIND, "pageview"), - resource.TestCheckResourceAttr(resourceName, "urls.0.kind", "substring"), - resource.TestCheckResourceAttr(resourceName, "urls.0.substring", "foo"), - resource.TestCheckResourceAttr(resourceName, "urls.1.kind", "regex"), - resource.TestCheckResourceAttr(resourceName, "urls.1.pattern", "foo"), - ), - }, { Config: withRandomProject(projectKey, testAccMetricUpdate), Check: resource.ComposeTestCheckFunc(