diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a7126e..4711054b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ -## 2.8.1 (Unreleased) +## 2.8.1 (February 12 2026) ENHANCEMENTS +* Fix datadog and webcheck datafeed params * Update documentation to contain the default values of the fields ## 2.8.0 (January 15 2026) diff --git a/ns1/config.go b/ns1/config.go index f9fd1069..8a654b4d 100644 --- a/ns1/config.go +++ b/ns1/config.go @@ -19,7 +19,7 @@ import ( ) var ( - clientVersion = "2.8.0" + clientVersion = "2.8.1" providerUserAgent = "tf-ns1" + "/" + clientVersion defaultRetryMax = 3 ) diff --git a/ns1/resource_datafeed.go b/ns1/resource_datafeed.go index 0f6d7ab6..d3e5ee4a 100644 --- a/ns1/resource_datafeed.go +++ b/ns1/resource_datafeed.go @@ -48,13 +48,33 @@ func dataFeedToResourceData(d *schema.ResourceData, f *data.Feed) { func resourceDataToDataFeed(d *schema.ResourceData) (feed *data.Feed, e error) { config := d.Get("config").(map[string]interface{}) if config != nil { - test_id := config["test_id"] - if test_id != nil { - test_id_int, err := strconv.Atoi(test_id.(string)) + if testId := config["test_id"]; testId != nil { + intTestId, err := strconv.Atoi(testId.(string)) if err != nil { - return &data.Feed{}, fmt.Errorf("could not convert %v as int %w", test_id, err) + return &data.Feed{}, fmt.Errorf("could not convert test_id = %v as int: %w", testId, err) } - config["test_id"] = test_id_int + config["test_id"] = intTestId + } + if checkId := config["check_id"]; checkId != nil { + intCheckId, err := strconv.Atoi(checkId.(string)) + if err != nil { + return &data.Feed{}, fmt.Errorf("could not convert check_id = %v as int: %w", checkId, err) + } + config["check_id"] = intCheckId + } + if failOnWarning := config["fail_on_warning"]; failOnWarning != nil { + boolFailOnWarning, err := strconv.ParseBool(failOnWarning.(string)) + if err != nil { + return &data.Feed{}, fmt.Errorf("could not convert fail_on_warning = %v as bool: %w", failOnWarning, err) + } + config["fail_on_warning"] = boolFailOnWarning + } + if failOnNoData := config["fail_on_no_data"]; failOnNoData != nil { + boolFailOnNoData, err := strconv.ParseBool(failOnNoData.(string)) + if err != nil { + return &data.Feed{}, fmt.Errorf("could not convert fail_on_no_data = %v as bool: %w", failOnNoData, err) + } + config["fail_on_no_data"] = boolFailOnNoData } } @@ -124,12 +144,23 @@ func DataFeedUpdate(d *schema.ResourceData, meta interface{}) error { func configAdapterOut(f *data.Feed) { config := f.Config if config != nil { - test_id := config["test_id"] - if test_id != nil { - test_id_str := strconv.Itoa(int(test_id.(float64))) - config["test_id"] = test_id_str - f.Config = config + if testId := config["test_id"]; testId != nil { + strTestId := strconv.Itoa(int(testId.(float64))) + config["test_id"] = strTestId + } + if checkId := config["check_id"]; checkId != nil { + strCheckId := strconv.Itoa(int(checkId.(float64))) + config["check_id"] = strCheckId + } + if failOnWarning := config["fail_on_warning"]; failOnWarning != nil { + strFailOnWarning := strconv.FormatBool(failOnWarning.(bool)) + config["fail_on_warning"] = strFailOnWarning + } + if failOnNoData := config["fail_on_no_data"]; failOnNoData != nil { + strFailOnNoData := strconv.FormatBool(failOnNoData.(bool)) + config["fail_on_no_data"] = strFailOnNoData } + f.Config = config } } diff --git a/ns1/resource_datafeed_test.go b/ns1/resource_datafeed_test.go index b39246a0..fb94bf2c 100644 --- a/ns1/resource_datafeed_test.go +++ b/ns1/resource_datafeed_test.go @@ -51,6 +51,44 @@ func TestThousandeyes_Basic(t *testing.T) { }) } +func TestWebcheck_Basic(t *testing.T) { + var dataFeed data.Feed + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDataFeedDestroy, + Steps: []resource.TestStep{ + { + Config: testWebcheckBasic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataFeedExists("ns1_datafeed.uswest_feed", "ns1_datasource.api", &dataFeed, t), + testAccCheckDataFeedName(&dataFeed, "uswest_feed"), + testThousandeyesConfig(&dataFeed, "check_id", 123), + ), + }, + }, + }) +} + +func TestDatadog_Basic(t *testing.T) { + var dataFeed data.Feed + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDataFeedDestroy, + Steps: []resource.TestStep{ + { + Config: testDatadogBasic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDataFeedExists("ns1_datafeed.uswest_feed", "ns1_datasource.api", &dataFeed, t), + testAccCheckDataFeedName(&dataFeed, "uswest_feed"), + testDatadogConfig(&dataFeed, "DataDog Test", true, true), + ), + }, + }, + }) +} + func TestAccDataFeed_updated(t *testing.T) { var dataFeed data.Feed resource.Test(t, resource.TestCase{ @@ -208,6 +246,25 @@ func testThousandeyesConfig(dataFeed *data.Feed, key string, expected float64) r } } +func testDatadogConfig(dataFeed *data.Feed, name string, failOnWarning, failOnNoData bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + + if dataFeed.Config["test_name"] != name { + return fmt.Errorf("dataFeed.Config[name]: got: %#v, want: %s", dataFeed.Config["test_name"], name) + } + + if dataFeed.Config["fail_on_warning"] != failOnWarning { + return fmt.Errorf("dataFeed.Config[fail_on_warning]: got: %#v, want: %t", dataFeed.Config["fail_on_warning"], failOnWarning) + } + + if dataFeed.Config["fail_on_no_data"] != failOnNoData { + return fmt.Errorf("dataFeed.Config[fail_on_no_data]: got: %#v, want: %t", dataFeed.Config["fail_on_no_data"], failOnNoData) + } + + return nil + } +} + // Simulate a manual deletion of a data feed. func testAccManualDeleteDataFeed(dataFeed *data.Feed) func() { return func() { @@ -248,6 +305,36 @@ resource "ns1_datafeed" "uswest_feed" { } }` +const testDatadogBasic = ` +resource "ns1_datasource" "api" { + name = "terraform test" + sourcetype = "datadog" +} + +resource "ns1_datafeed" "uswest_feed" { + name = "uswest_feed" + source_id = "${ns1_datasource.api.id}" + config = { + fail_on_warning = true + fail_on_no_data = true + test_name = "DataDog Test" + } +}` + +const testWebcheckBasic = ` +resource "ns1_datasource" "api" { + name = "terraform test" + sourcetype = "webcheck" +} + +resource "ns1_datafeed" "uswest_feed" { + name = "uswest_feed" + source_id = "${ns1_datasource.api.id}" + config = { + check_id = "123" + } +}` + const testAccDataFeedUpdated = ` resource "ns1_datasource" "api" { name = "terraform test" diff --git a/ns1/resource_monitoringjob.go b/ns1/resource_monitoringjob.go index 03348025..8cdc0d13 100644 --- a/ns1/resource_monitoringjob.go +++ b/ns1/resource_monitoringjob.go @@ -134,19 +134,20 @@ func monitoringJobToResourceData(d *schema.ResourceData, r *monitor.Job) error { d.Set("rapid_recheck", r.RapidRecheck) config := make(map[string]string) for k, v := range r.Config { - if k == "ssl" { + switch k { + case "ssl": if v.(bool) { config[k] = "1" } else { config[k] = "0" } - } else if k == "follow_redirect" || k == "ipv6" || k == "tls_skip_verify" || k == "tls_add_verify" { + case "follow_redirect", "ipv6", "tls_skip_verify", "tls_add_verify": if v.(bool) { config[k] = "true" } else { config[k] = "false" } - } else { + default: switch t := v.(type) { case string: config[k] = t @@ -194,7 +195,6 @@ func resourceDataToMonitoringJob(r *monitor.Job, d *schema.ResourceData) error { } r.Frequency = d.Get("frequency").(int) r.RapidRecheck = d.Get("rapid_recheck").(bool) - var rawRules []interface{} if rawRules := d.Get("rules"); rawRules != nil { r.Rules = make([]*monitor.Rule, len(rawRules.([]interface{}))) for i, v := range rawRules.([]interface{}) { @@ -208,19 +208,6 @@ func resourceDataToMonitoringJob(r *monitor.Job, d *schema.ResourceData) error { } else { r.Rules = make([]*monitor.Rule, 0) } - for i, v := range rawRules { - rule := v.(map[string]interface{}) - r.Rules[i] = &monitor.Rule{ - Comparison: rule["comparison"].(string), - Key: rule["key"].(string), - } - value := rule["value"].(string) - if i, err := strconv.Atoi(value); err == nil { - r.Rules[i].Value = i - } else { - r.Rules[i].Value = value - } - } config := make(map[string]interface{}) if rawConfig := d.Get("config"); rawConfig != nil { for k, v := range rawConfig.(map[string]interface{}) { diff --git a/ns1/resource_monitoringjob_test.go b/ns1/resource_monitoringjob_test.go index e383f39e..e1a68d2b 100644 --- a/ns1/resource_monitoringjob_test.go +++ b/ns1/resource_monitoringjob_test.go @@ -147,27 +147,6 @@ func TestAccMonitoringJob_ManualDelete(t *testing.T) { }) } -func testAccCheckMonitoringJobState(key, value string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources["ns1_monitoringjob.it"] - if !ok { - return fmt.Errorf("not found: %s", "ns1_monitoringjob.it") - } - - if rs.Primary.ID == "" { - return fmt.Errorf("no ID is set") - } - - p := rs.Primary - if p.Attributes[key] != value { - return fmt.Errorf( - "%s != %s (actual: %s)", key, value, p.Attributes[key]) - } - - return nil - } -} - func testAccCheckMonitoringJobExists(n string, monitoringJob *monitor.Job) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n]