Skip to content

Commit 9574864

Browse files
authored
Add usage alerts support (#358)
* Add usage alerts support * Merge * Update examples to show that zone_names is handles * Fix indent * Update comment and examples * Removing maps because we're still using go 1.19
1 parent 3d603d6 commit 9574864

6 files changed

Lines changed: 139 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.7.0 (September 5, 2025)
2+
ENHANCEMENTS
3+
* Adds support for new Alerts
4+
* Deprecating the `notify.billing` permission
5+
16
## 2.6.5 (June 07, 2025)
27
ENHANCEMENTS
38
* Adds support for `manage_redirects` permission field

ns1/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
)
2020

2121
var (
22-
clientVersion = "2.6.5"
22+
clientVersion = "2.7.0"
2323
providerUserAgent = "tf-ns1" + "/" + clientVersion
2424
defaultRetryMax = 3
2525
)

ns1/examples/alert.tf

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
resource "ns1_alert" "example" {
1+
resource "ns1_alert" "example_zone_alert" {
22
#required
3-
name = "Example Alert"
3+
name = "Example Zone Alert"
44
type = "zone"
55
subtype = "transfer_failed"
66

77
#optional
88
notification_lists = []
9-
zone_names = []
9+
zone_names = ["a.b.c.com","myzone"]
1010
record_ids = []
11-
}
11+
}
12+
13+
resource "ns1_alert" "example_usage_alert" {
14+
#required
15+
name = "Example Usage Alert"
16+
type = "account"
17+
subtype = "record_usage"
18+
data {
19+
alert_at_percent = 80
20+
}
21+
}

ns1/resource_alert.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ns1
22

33
import (
4+
"encoding/json"
45
"log"
56

67
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -73,6 +74,18 @@ func alertResource() *schema.Resource {
7374
},
7475
ConflictsWith: []string{"zone_names"},
7576
},
77+
"data": {
78+
Type: schema.TypeSet,
79+
Optional: true,
80+
Elem: &schema.Resource{
81+
Schema: map[string]*schema.Schema{
82+
"alert_at_percent": {
83+
Type: schema.TypeInt,
84+
Optional: true,
85+
},
86+
},
87+
},
88+
},
7689
},
7790
Create: AlertConfigCreate,
7891
Read: AlertConfigRead,
@@ -94,6 +107,14 @@ func alertToResourceData(d *schema.ResourceData, alert *alerting.Alert) error {
94107
d.Set("notification_lists", alert.NotifierListIds)
95108
d.Set("zone_names", alert.ZoneNames)
96109
d.Set("record_ids", alert.RecordIds)
110+
if alert.Data != nil {
111+
params := map[string]any{}
112+
err := json.Unmarshal(alert.Data, &params)
113+
if err != nil {
114+
return err
115+
}
116+
d.Set("data", []any{params})
117+
}
97118
return nil
98119
}
99120

@@ -158,6 +179,25 @@ func resourceDataToAlert(d *schema.ResourceData) (*alerting.Alert, error) {
158179
} else {
159180
alert.RecordIds = []string{}
160181
}
182+
if v, ok := d.GetOk("data"); ok {
183+
params := map[string]any{}
184+
if data, ok := v.(*schema.Set); ok {
185+
for _, p := range data.List() {
186+
if setting, ok := p.(map[string]any); ok {
187+
for k, v := range setting {
188+
params[k] = v
189+
}
190+
}
191+
}
192+
}
193+
jsonData, err := json.Marshal(params)
194+
if err != nil {
195+
return nil, err
196+
}
197+
alert.Data = jsonData
198+
} else {
199+
alert.Data = []byte("{}")
200+
}
161201
return &alert, nil
162202
}
163203

ns1/resource_alert_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"log"
66
"reflect"
7+
"regexp"
78
"sort"
89
"strings"
910
"testing"
@@ -17,6 +18,7 @@ import (
1718
)
1819

1920
// Creating basic DNS alert
21+
// NOTE: You would need the `manage_zones` permission to create this alert type. Otherwise this test will fail!
2022
func TestAccAlert_basic(t *testing.T) {
2123
var (
2224
alert = alerting.Alert{}
@@ -45,6 +47,46 @@ func TestAccAlert_basic(t *testing.T) {
4547
})
4648
}
4749

50+
func TestAccAlert_RecordUsage(t *testing.T) {
51+
var (
52+
alert = alerting.Alert{}
53+
alertName = fmt.Sprintf("terraform-test-alert-%s", acctest.RandStringFromCharSet(15, acctest.CharSetAlphaNum))
54+
)
55+
56+
resource.Test(t, resource.TestCase{
57+
PreCheck: func() { testAccPreCheck(t) },
58+
Providers: testAccProviders,
59+
CheckDestroy: testAccCheckAlertDestroy,
60+
Steps: []resource.TestStep{
61+
{Config: testRecordUsageAlert(alertName, 10),
62+
Check: resource.ComposeTestCheckFunc(
63+
testAccCheckAlertExists("ns1_alert.it", &alert),
64+
testAccCheckAlertName(&alert, alertName),
65+
testAccCheckAlertType(&alert, "account"),
66+
testAccCheckAlertSubtype(&alert, "record_usage"),
67+
testAccCheckAlertData(&alert, `{"alert_at_percent":10}`),
68+
)},
69+
{Config: testRecordUsageAlert(alertName, 101),
70+
ExpectError: regexp.MustCompile("Please correct the following field: data.alert_at_percent"),
71+
ExpectNonEmptyPlan: true,
72+
},
73+
{Config: testRecordUsageAlert(alertName, 50),
74+
Check: resource.ComposeTestCheckFunc(
75+
testAccCheckAlertExists("ns1_alert.it", &alert),
76+
testAccCheckAlertName(&alert, alertName),
77+
testAccCheckAlertType(&alert, "account"),
78+
testAccCheckAlertSubtype(&alert, "record_usage"),
79+
testAccCheckAlertData(&alert, `{"alert_at_percent":50}`),
80+
)},
81+
{
82+
ResourceName: "ns1_alert.it",
83+
ImportState: true,
84+
ImportStateVerify: true,
85+
},
86+
},
87+
})
88+
}
89+
4890
func TestAccAlert_links(t *testing.T) {
4991
var (
5092
alert = alerting.Alert{}
@@ -184,6 +226,18 @@ func TestAccAlert_ManualDelete(t *testing.T) {
184226
})
185227
}
186228

229+
func testRecordUsageAlert(alertName string, threshold int) string {
230+
return fmt.Sprintf(`resource "ns1_alert" "it" {
231+
name = "%s"
232+
type = "account"
233+
subtype = "record_usage"
234+
notification_lists = []
235+
data {
236+
alert_at_percent = %d
237+
}
238+
}`, alertName, threshold)
239+
}
240+
187241
func testAccAlertBasic(alertName string) string {
188242
return fmt.Sprintf(`resource "ns1_alert" "it" {
189243
name = "%s"
@@ -306,6 +360,16 @@ func testAccCheckAlertSubtype(alert *alerting.Alert, expected string) resource.T
306360
}
307361
}
308362

363+
func testAccCheckAlertData(alert *alerting.Alert, expected string) resource.TestCheckFunc {
364+
return func(s *terraform.State) error {
365+
data := string(alert.Data)
366+
if data != expected {
367+
return fmt.Errorf("alert.Data: got: %s want: %s", data, expected)
368+
}
369+
return nil
370+
}
371+
}
372+
309373
func testAccCheckAlertZoneNames(alert *alerting.Alert, expected []string) resource.TestCheckFunc {
310374
return func(s *terraform.State) error {
311375
actualSorted := alert.ZoneNames

website/docs/r/alert.html.markdown

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,27 @@ Provides a NS1 Alert resource. This can be used to create, modify, and delete al
1313
## Example Usage
1414

1515
```hcl
16-
resource "ns1_alert" "example" {
16+
resource "ns1_alert" "example_zone_alert" {
1717
#required
18-
name = "Example Alert"
18+
name = "Example Zone Alert"
1919
type = "zone"
2020
subtype = "transfer_failed"
2121
2222
#optional
2323
notification_lists = []
24-
zone_names = []
24+
zone_names = ["a.b.c.com","myzone"]
2525
record_ids = []
2626
}
27+
28+
resource "ns1_alert" "example_usage_alert" {
29+
#required
30+
name = "Example Usage Alert"
31+
type = "account"
32+
subtype = "record_usage"
33+
data {
34+
alert_at_percent = 80
35+
}
36+
}
2737
```
2838

2939
## Argument Reference
@@ -36,6 +46,8 @@ The following arguments are supported:
3646
* `notification_lists` - (Optional) A list of id's for notification lists whose notifiers will be triggered by the alert.
3747
* `zone_names` - (Optional) A list of zones this alert applies to.
3848
* `record_ids` - (Optional) A list of record id's this alert applies to.
49+
* `data` - (Optional) A resource block with additional settings: the name and type of them vary based on the alert type.
50+
* `alert_at_percent` - required by the account/usage alerts, with a value between 1 and 100
3951

4052
## Attributes Reference
4153

0 commit comments

Comments
 (0)