Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: alert rule and tests association #167

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion docs/resources/alert_rule.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<a id="nestedblock--notifications"></a>
### Nested Schema for `notifications`
Expand Down Expand Up @@ -88,3 +89,12 @@ Required:
- `integration_type` (String) The integration type, as a string.



<a id="nestedblock--tests"></a>
### Nested Schema for `tests`

Optional:

- `test_id` (Number) The list of unique test IDs.


2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
}
34 changes: 34 additions & 0 deletions thousandeyes/acceptance_resources/alert_rule/update_alert_rule.tf
Original file line number Diff line number Diff line change
@@ -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
}
}
18 changes: 16 additions & 2 deletions thousandeyes/resource_alert_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 alerRule, err = client.GetAlertRule(id)
if err != nil {
return nil, err
}
alerRule.TestIds = testIds(*alerRule.Tests)
alerRule.Tests = nil
return alerRule, 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
Expand Down Expand Up @@ -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
}
79 changes: 79 additions & 0 deletions thousandeyes/resource_alert_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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{
resource.TestCheckResourceAttr(alertRuleResourceName, "rounds_violating_required", "3"),
},
checkUpdateFunc: []resource.TestCheckFunc{
resource.TestCheckResourceAttr(alertRuleResourceName, "rounds_violating_required", "4"),
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)
}
2 changes: 1 addition & 1 deletion thousandeyes/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
Loading