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

Adding Event Rule Resource #150

Merged
merged 9 commits into from
Aug 23, 2019
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ module github.com/terraform-providers/terraform-provider-pagerduty
require (
github.com/hashicorp/go-hclog v0.7.0 // indirect
github.com/hashicorp/terraform v0.12.0
github.com/heimweh/go-pagerduty v0.0.0-20190625093811-4038e4c7ddb6
github.com/heimweh/go-pagerduty v0.0.0-20190807171021-2a6540956dc5
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ github.com/heimweh/go-pagerduty v0.0.0-20190419203155-2c0c2f005760 h1:9vR2wHQ4ZC
github.com/heimweh/go-pagerduty v0.0.0-20190419203155-2c0c2f005760/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY=
github.com/heimweh/go-pagerduty v0.0.0-20190625093811-4038e4c7ddb6 h1:K1vFV+w33QGeSUqPmjJ4g2S0yJFTYpEYAaiLo+oH8Js=
github.com/heimweh/go-pagerduty v0.0.0-20190625093811-4038e4c7ddb6/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY=
github.com/heimweh/go-pagerduty v0.0.0-20190807171021-2a6540956dc5 h1:UZQ03lpxS/AUrMTlh1yQ/MJEJ+2he5bCItZ4W9Lgs1c=
github.com/heimweh/go-pagerduty v0.0.0-20190807171021-2a6540956dc5/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
Expand Down
30 changes: 30 additions & 0 deletions pagerduty/import_pagerduty_event_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package pagerduty

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)

func TestAccPagerDutyEventRule_import(t *testing.T) {
eventRule := fmt.Sprintf("tf-%s", acctest.RandString(5))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPagerDutyEventRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckPagerDutyEventRuleConfig(eventRule),
},

{
ResourceName: "pagerduty_event_rule.first",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
1 change: 1 addition & 0 deletions pagerduty/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func Provider() terraform.ResourceProvider {
"pagerduty_user": resourcePagerDutyUser(),
"pagerduty_user_contact_method": resourcePagerDutyUserContactMethod(),
"pagerduty_extension": resourcePagerDutyExtension(),
"pagerduty_event_rule": resourcePagerDutyEventRule(),
},

ConfigureFunc: providerConfigure,
Expand Down
145 changes: 145 additions & 0 deletions pagerduty/resource_pagerduty_event_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package pagerduty

import (
"encoding/json"
"log"

"github.com/hashicorp/terraform/helper/schema"
"github.com/heimweh/go-pagerduty/pagerduty"
)

func resourcePagerDutyEventRule() *schema.Resource {
return &schema.Resource{
Create: resourcePagerDutyEventRuleCreate,
Read: resourcePagerDutyEventRuleRead,
Update: resourcePagerDutyEventRuleUpdate,
Delete: resourcePagerDutyEventRuleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"action_json": {
Type: schema.TypeString,
Required: true,
},
"condition_json": {
Type: schema.TypeString,
Required: true,
},
"advanced_condition_json": {
Type: schema.TypeString,
Optional: true,
},
"catch_all": {
Type: schema.TypeBool,
Optional: true,
},
},
}
}

func buildEventRuleStruct(d *schema.ResourceData) *pagerduty.EventRule {
eventRule := &pagerduty.EventRule{
Actions: expandString(d.Get("action_json").(string)),
Condition: expandString(d.Get("condition_json").(string)),
}

if attr, ok := d.GetOk("advanced_condition_json"); ok {
eventRule.AdvancedCondition = expandString(attr.(string))
}

if attr, ok := d.GetOk("catch_all"); ok {
eventRule.CatchAll = attr.(bool)
}

return eventRule
}

func expandString(v string) []interface{} {
var obj []interface{}
err := json.Unmarshal([]byte(v), &obj)

if err != nil {
log.Printf(string(err.Error()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about returning the error here if JSON unmarshal fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, I've adopted the same strategy used in the extension resource. Would that work?

}

return obj
}

func flattenSlice(v []interface{}) string {
b, err := json.Marshal(v)
if err != nil {
log.Printf(string(err.Error()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, do we want to return the error here?

}
return string(b)
}

func resourcePagerDutyEventRuleCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)

eventRule := buildEventRuleStruct(d)

log.Printf("[INFO] Creating PagerDuty event rule: %s", "eventRule")

eventRule, _, err := client.EventRules.Create(eventRule)
if err != nil {
return err
}

d.SetId(eventRule.ID)

return resourcePagerDutyEventRuleRead(d, meta)
}

func resourcePagerDutyEventRuleRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)

log.Printf("[INFO] Reading PagerDuty event rule: %s", d.Id())

resp, _, err := client.EventRules.List()
if err != nil {
return err
}
for _, rule := range resp.EventRules {
Copy link
Collaborator

@heimweh heimweh Aug 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about doing something like (not tested):

var found *pagerduty.EventRule

for _, rule := range resp.EventRules {
  if rule.ID == d.Id() {
    found = rule
    break
  }
}

if found == nil {
  d.SetId("")
}
...
d.Set("catch_all", rule.CatchAll)
...

That way you can set the attributes outside the loop 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense. I've adopted this idea in my next commit.

log.Printf("[DEBUG] Resp rule.ID: %s", rule.ID)
if rule.ID == d.Id() {
d.Set("action_json", flattenSlice(rule.Actions))
d.Set("condition_json", flattenSlice(rule.Condition))
d.Set("advanced_condition_json", flattenSlice(rule.AdvancedCondition))
d.Set("catch_all", rule.CatchAll)
}
}
// check if eventRule not found
if _, ok := d.GetOk("action_json"); !ok {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? This calls d.SetId("") if the response code was a 404.
I added an example above on how to clear it from the state if the event rule is missing from the list of event rules 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appeared to have worked. 🤷‍♂ But, I've changed that logic to match what you were saying in the above comment.

return handleNotFoundError(err, d)
}

return nil
}
func resourcePagerDutyEventRuleUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)

eventRule := buildEventRuleStruct(d)

log.Printf("[INFO] Updating PagerDuty event rule: %s", d.Id())

if _, _, err := client.EventRules.Update(d.Id(), eventRule); err != nil {
return err
}

return nil
}

func resourcePagerDutyEventRuleDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)

log.Printf("[INFO] Deleting PagerDuty event rule: %s", d.Id())

if _, err := client.EventRules.Delete(d.Id()); err != nil {
return err
}

d.SetId("")

return nil
}
195 changes: 195 additions & 0 deletions pagerduty/resource_pagerduty_event_rule_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package pagerduty

import (
"fmt"
"log"
"strings"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/heimweh/go-pagerduty/pagerduty"
)

func init() {
resource.AddTestSweepers("pagerduty_event_rule", &resource.Sweeper{
Name: "pagerduty_event_rule",
F: testSweepEventRule,
Dependencies: []string{
"pagerduty_service",
},
})
}

func testSweepEventRule(region string) error {
config, err := sharedConfigForRegion(region)
if err != nil {
return err
}

client, err := config.Client()
if err != nil {
return err
}

resp, _, err := client.EventRules.List()
if err != nil {
return err
}

for _, rule := range resp.EventRules {
if strings.HasPrefix(rule.ID, "test") || strings.HasPrefix(rule.ID, "tf-") {
log.Printf("Destroying event rule %s", rule.ID)
if _, err := client.EventRules.Delete(rule.ID); err != nil {
return err
}
}
}

return nil
}

func TestAccPagerDutyEventRule_Basic(t *testing.T) {
eventRule := fmt.Sprintf("tf-%s", acctest.RandString(5))
eventRuleUpdated := fmt.Sprintf("tf-%s", acctest.RandString(5))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPagerDutyEventRuleDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckPagerDutyEventRuleConfig(eventRule),
Check: resource.ComposeTestCheckFunc(
testAccCheckPagerDutyEventRuleExists("pagerduty_event_rule.first"),
),
},

{
Config: testAccCheckPagerDutyEventRuleConfigUpdated(eventRuleUpdated),
Check: resource.ComposeTestCheckFunc(
testAccCheckPagerDutyEventRuleExists("pagerduty_event_rule.foo_resource_updated"),
),
},
},
})
}

func testAccCheckPagerDutyEventRuleDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*pagerduty.Client)
for _, r := range s.RootModule().Resources {
if r.Type != "pagerduty_event_rule" {
continue
}
// get list of event_rules and then check that list.
resp, _, err := client.EventRules.List()
if err != nil {
return err
}
for _, er := range resp.EventRules {
if er.ID == r.Primary.ID {
return fmt.Errorf("Event Rule still exists")
}
}
}
return nil
}

func testAccCheckPagerDutyEventRuleExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No Escalation Policy ID is set")
}

client := testAccProvider.Meta().(*pagerduty.Client)
resp, _, err := client.EventRules.List()
if err != nil {
return err
}
var found *pagerduty.EventRule

for _, rule := range resp.EventRules {
if rule.ID == rs.Primary.ID {
found = rule
}
}
if err != nil {
return err
}

if found.ID != rs.Primary.ID {
return fmt.Errorf("Escalation policy not found: %v - %v", rs.Primary.ID, found)
}

return nil
}
}

func testAccCheckPagerDutyEventRuleConfig(eventRule string) string {
return fmt.Sprintf(`
variable "action_list" {
default = [["route","P5DTL0K"],["severity","warning"],["annotate","%s"],["priority","PL451DT"]]
}
variable "condition_list" {
default = ["and",["contains",["path","payload","source"],"website"]]
}
variable "advanced_condition_list" {
default = [
[
"scheduled-weekly",
1565392127032,
3600000,
"America/Los_Angeles",
[
1,
3,
5,
7
]
]
]
}
resource "pagerduty_event_rule" "first" {
action_json = jsonencode(var.action_list)
condition_json = jsonencode(var.condition_list)
advanced_condition_json = jsonencode(var.advanced_condition_list)
}
`, eventRule)
}

func testAccCheckPagerDutyEventRuleConfigUpdated(eventRule string) string {
return fmt.Sprintf(`
variable "action_list" {
default = [["route","P5DTL0K"],["severity","warning"],["annotate","%s"],["priority","PL451DT"]]
}
variable "condition_list" {
default = ["and",["contains",["path","payload","source"],"website"],["contains",["path","headers","from","0","address"],"homer"]]
}
variable "advanced_condition_list" {
default = [
[
"scheduled-weekly",
1565392127032,
3600000,
"America/Los_Angeles",
[
1,
3,
5,
7
]
]
]
}
resource "pagerduty_event_rule" "foo_resource_updated" {
action_json = jsonencode(var.action_list)
condition_json = jsonencode(var.condition_list)
advanced_condition_json = jsonencode(var.advanced_condition_list)
}
`, eventRule)
}
Loading