diff --git a/docs/resources/alert_rule.md b/docs/resources/alert_rule.md
index 3c5fe81..70d964d 100644
--- a/docs/resources/alert_rule.md
+++ b/docs/resources/alert_rule.md
@@ -44,13 +44,14 @@ resource "thousandeyes_alert_rule" "example_alert_rule" {
- `notify_on_clear` (Boolean) Set to 'true' to trigger the notification when the alert clears.
- `rounds_violating_mode` (String) [ANY or EXACT] Defines whether the same agent(s) must meet the EXACT same threshold in consecutive rounds or not. The default value is ANY.
- `severity` (String) [INFO, MINOR, MAJOR or CRITICAL] The severity level of the alert rule. The default value is INFO.
-- `test_ids` (List of Number) The valid test IDs.
+- `tests` (Block List) The list of included tests. (see [below for nested schema](#nestedblock--tests))
### Read-Only
- `alert_rule_id` (Number) The unique ID of the alert rule.
- `id` (String) The ID of this resource.
- `rule_id` (Number) The unique ID of the alert rule.
+- `test_ids` (List of Number) The valid test IDs.
### Nested Schema for `notifications`
@@ -88,3 +89,12 @@ Required:
- `integration_type` (String) The integration type, as a string.
+
+
+### Nested Schema for `tests`
+
+Optional:
+
+- `test_id` (Number) The list of unique test IDs.
+
+
diff --git a/go.mod b/go.mod
index 92d3443..97dfaf7 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
github.com/hashicorp/terraform-plugin-docs v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0
github.com/stretchr/testify v1.8.4
- github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.2
+ github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.3
)
require (
diff --git a/go.sum b/go.sum
index 3d6edd8..0957629 100644
--- a/go.sum
+++ b/go.sum
@@ -169,8 +169,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.2 h1:j84PPcq3EBRtQxJ/zssiBxCajhPQn+unIY5JhDiBWTo=
-github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.2/go.mod h1:XQouPCy3dIp81Xzkp9bqu6vg7fmE4QQpA6REsLVTDdE=
+github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.3 h1:4gCG4SSyhgQsVPuLQl5Jdy4CwdHyyoZkktNTqnfcyJc=
+github.com/thousandeyes/thousandeyes-sdk-go/v2 v2.4.3/go.mod h1:XQouPCy3dIp81Xzkp9bqu6vg7fmE4QQpA6REsLVTDdE=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
diff --git a/thousandeyes/acceptance_resources/alert_rule/create_test_with_alert_rule.tf b/thousandeyes/acceptance_resources/alert_rule/create_test_with_alert_rule.tf
new file mode 100644
index 0000000..d18f3aa
--- /dev/null
+++ b/thousandeyes/acceptance_resources/alert_rule/create_test_with_alert_rule.tf
@@ -0,0 +1,34 @@
+data "thousandeyes_agent" "amsterdam" {
+ agent_name = "Amsterdam, Netherlands"
+}
+
+resource "thousandeyes_alert_rule" "test" {
+ severity = "MAJOR"
+ rule_name = "Agent To Server Alert Rule Test"
+ alert_type = "End-to-End (Server)"
+ expression = "((loss >= 50%) || (probDetail != \"\") || (avgLatency >= 200 ms))"
+ minimum_sources = 2
+ rounds_violating_required = 3
+ rounds_violating_out_of = 4
+}
+
+resource "thousandeyes_agent_to_server" "agent_to_server_test" {
+ test_name = "Agent To Server Test"
+ interval = 300
+ alerts_enabled = true
+ server = "api.stg.thousandeyes.com"
+ protocol = "TCP"
+ port = 443
+ enabled = true
+ bgp_measurements = true
+ use_public_bgp = true
+ mtu_measurements = true
+
+ agents {
+ agent_id = data.thousandeyes_agent.amsterdam.agent_id
+ }
+
+ alert_rules {
+ rule_id = thousandeyes_alert_rule.test.id
+ }
+}
diff --git a/thousandeyes/acceptance_resources/alert_rule/update_alert_rule.tf b/thousandeyes/acceptance_resources/alert_rule/update_alert_rule.tf
new file mode 100644
index 0000000..a95c5c3
--- /dev/null
+++ b/thousandeyes/acceptance_resources/alert_rule/update_alert_rule.tf
@@ -0,0 +1,34 @@
+data "thousandeyes_agent" "amsterdam" {
+ agent_name = "Amsterdam, Netherlands"
+}
+
+resource "thousandeyes_alert_rule" "test" {
+ severity = "MAJOR"
+ rule_name = "Agent To Server Alert Rule Test"
+ alert_type = "End-to-End (Server)"
+ expression = "((loss >= 50%) || (probDetail != \"\") || (avgLatency >= 200 ms))"
+ minimum_sources = 2
+ rounds_violating_required = 4
+ rounds_violating_out_of = 4
+}
+
+resource "thousandeyes_agent_to_server" "agent_to_server_test" {
+ test_name = "Agent To Server Test"
+ interval = 300
+ alerts_enabled = true
+ server = "api.stg.thousandeyes.com"
+ protocol = "TCP"
+ port = 443
+ enabled = true
+ bgp_measurements = true
+ use_public_bgp = true
+ mtu_measurements = true
+
+ agents {
+ agent_id = data.thousandeyes_agent.amsterdam.agent_id
+ }
+
+ alert_rules {
+ rule_id = thousandeyes_alert_rule.test.id
+ }
+}
diff --git a/thousandeyes/resource_alert_rule.go b/thousandeyes/resource_alert_rule.go
index 5b84d7c..2bc1130 100644
--- a/thousandeyes/resource_alert_rule.go
+++ b/thousandeyes/resource_alert_rule.go
@@ -26,14 +26,20 @@ func resourceAlertRule() *schema.Resource {
func resourceAlertRuleRead(d *schema.ResourceData, m interface{}) error {
return GetResource(d, m, func(client *thousandeyes.Client, id int64) (interface{}, error) {
- return client.GetAlertRule(id)
+ var alertRule, err = client.GetAlertRule(id)
+ if err != nil {
+ return nil, err
+ }
+ alertRule.TestIds = testIds(*alertRule.Tests)
+ alertRule.Tests = nil
+ return alertRule, nil
})
}
func resourceAlertRuleUpdate(d *schema.ResourceData, m interface{}) error {
client := m.(*thousandeyes.Client)
- log.Printf("[INFO] Updating ThousandEyes Test %s", d.Id())
+ log.Printf("[INFO] Updating ThousandEyes Alert Rule %s", d.Id())
id, _ := strconv.ParseInt(d.Id(), 10, 64)
// While most ThousandEyes updates only require updated fields and specifically
// disallow some fields on update, Alert Rules actually require the full list of
@@ -74,3 +80,11 @@ func resourceAlertRuleCreate(d *schema.ResourceData, m interface{}) error {
func buildAlertRuleStruct(d *schema.ResourceData) *thousandeyes.AlertRule {
return ResourceBuildStruct(d, &thousandeyes.AlertRule{}).(*thousandeyes.AlertRule)
}
+
+func testIds(tests []thousandeyes.GenericTest) *[]int64 {
+ var testIds []int64
+ for _, test := range tests {
+ testIds = append(testIds, *test.TestID)
+ }
+ return &testIds
+}
diff --git a/thousandeyes/resource_alert_rule_test.go b/thousandeyes/resource_alert_rule_test.go
new file mode 100644
index 0000000..5f8a755
--- /dev/null
+++ b/thousandeyes/resource_alert_rule_test.go
@@ -0,0 +1,84 @@
+package thousandeyes
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccThousandEyesAlertRule(t *testing.T) {
+ var alertRuleResourceName = "thousandeyes_alert_rule.test"
+ testCases := []struct {
+ name string
+ createResourceFile string
+ updateResourceFile string
+ checkDestroyFunction func(*terraform.State) error
+ checkCreateFunc []resource.TestCheckFunc
+ checkUpdateFunc []resource.TestCheckFunc
+ }{
+ {
+ name: "test_association_maintained_after_alert_rule_update",
+ createResourceFile: "acceptance_resources/alert_rule/create_test_with_alert_rule.tf",
+ updateResourceFile: "acceptance_resources/alert_rule/update_alert_rule.tf",
+ checkDestroyFunction: func(state *terraform.State) error {
+ resourceList := []ResourceType{
+ {
+ Name: "Agent To Server Test",
+ ResourceName: "thousandeyes_agent_to_server",
+ GetResource: func(id int64) (interface{}, error) {
+ return testClient.GetAgentServer(id)
+ }},
+ {
+ Name: "Agent To Server Alert Rule Test",
+ ResourceName: "thousandeyes_alert_rule",
+ GetResource: func(id int64) (interface{}, error) {
+ return testClient.GetAlertRule(id)
+ }},
+ }
+ return testAccCheckResourceDestroy(resourceList, state)
+ },
+ checkCreateFunc: []resource.TestCheckFunc{
+ //alert rule is created
+ //with 3 required violating rounds
+ resource.TestCheckResourceAttr(alertRuleResourceName, "rounds_violating_required", "3"),
+ },
+ checkUpdateFunc: []resource.TestCheckFunc{
+ //alert rule is updated
+ //to 4 required violating rounds
+ resource.TestCheckResourceAttr(alertRuleResourceName, "rounds_violating_required", "4"),
+ //and the test association is maintained
+ resource.TestCheckResourceAttr(alertRuleResourceName, "test_ids.#", "1"),
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProviderFactories: providerFactories,
+ CheckDestroy: tc.checkDestroyFunction,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccThousandEyesAlertRuleConfig(tc.createResourceFile),
+ Check: resource.ComposeTestCheckFunc(tc.checkCreateFunc...),
+ },
+ {
+ Config: testAccThousandEyesAlertRuleConfig(tc.updateResourceFile),
+ Check: resource.ComposeTestCheckFunc(tc.checkUpdateFunc...),
+ },
+ },
+ })
+ })
+ }
+}
+
+func testAccThousandEyesAlertRuleConfig(testResource string) string {
+ content, err := os.ReadFile(testResource)
+ if err != nil {
+ panic(err)
+ }
+ return string(content)
+}
diff --git a/thousandeyes/schemas.go b/thousandeyes/schemas.go
index 9a9d599..83c6839 100644
--- a/thousandeyes/schemas.go
+++ b/thousandeyes/schemas.go
@@ -918,7 +918,7 @@ var schemas = map[string]*schema.Schema{
"test_ids": {
Type: schema.TypeList,
Description: "The valid test IDs.",
- Optional: true,
+ Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},