Skip to content

Commit

Permalink
fix: alert rule and tests association (#168)
Browse files Browse the repository at this point in the history
* fix: alert rule and tests association

* fix: update go sdk version

* fix: add missing readme generation

* fix: fix typo

Co-authored-by: Jack Browne <[email protected]>

* fix: improve ac tests

---------

Co-authored-by: Jack Browne <[email protected]>
  • Loading branch information
brumarqu-te and jabrowne-te authored May 13, 2024
1 parent d74147c commit 2beea37
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 7 deletions.
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 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
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
}
84 changes: 84 additions & 0 deletions thousandeyes/resource_alert_rule_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
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

0 comments on commit 2beea37

Please sign in to comment.