diff --git a/CHANGELOG.md b/CHANGELOG.md index dea5a7c81..dc4d8c8c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ NOTES: FEATURES: * **New Data Source:** `pagerduty_service` [GH-141] +* **New Resource:** `pagerduty_event_rule` [GH-150] BUG FIXES: diff --git a/go.mod b/go.mod index ac90b3be5..c64ac54fe 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index 1eeddc762..5c06e862b 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/pagerduty/import_pagerduty_event_rule_test.go b/pagerduty/import_pagerduty_event_rule_test.go new file mode 100644 index 000000000..131d1948a --- /dev/null +++ b/pagerduty/import_pagerduty_event_rule_test.go @@ -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, + }, + }, + }) +} diff --git a/pagerduty/provider.go b/pagerduty/provider.go index e67007d03..0965195a7 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -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, diff --git a/pagerduty/resource_pagerduty_event_rule.go b/pagerduty/resource_pagerduty_event_rule.go new file mode 100644 index 000000000..a699b3209 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_rule.go @@ -0,0 +1,151 @@ +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{} + if err := json.Unmarshal([]byte(v), &obj); err != nil { + log.Printf("[ERROR] Could not unmarshal event rule field %s: %v", v, err) + return nil + } + + return obj +} + +func flattenSlice(v []interface{}) interface{} { + b, err := json.Marshal(v) + if err != nil { + log.Printf("[ERROR] Could not marshal event rule field %s: %v", v, err) + return nil + } + 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 + } + var foundRule *pagerduty.EventRule + + for _, rule := range resp.EventRules { + log.Printf("[DEBUG] Resp rule.ID: %s", rule.ID) + if rule.ID == d.Id() { + foundRule = rule + break + } + } + // check if eventRule not found + if foundRule == nil { + d.SetId("") + return nil + } + // if event rule is found set to ResourceData + d.Set("action_json", flattenSlice(foundRule.Actions)) + d.Set("condition_json", flattenSlice(foundRule.Condition)) + d.Set("advanced_condition_json", flattenSlice(foundRule.AdvancedCondition)) + d.Set("catch_all", foundRule.CatchAll) + + 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 +} diff --git a/pagerduty/resource_pagerduty_event_rule_test.go b/pagerduty/resource_pagerduty_event_rule_test.go new file mode 100644 index 000000000..28f751ead --- /dev/null +++ b/pagerduty/resource_pagerduty_event_rule_test.go @@ -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) +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_rule.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_rule.go index a1d453ea5..88d9974fb 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_rule.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_rule.go @@ -13,14 +13,13 @@ type EventRule struct { CatchAll bool `json:"catch_all,omitempty"` Condition []interface{} `json:"condition,omitempty"` ID string `json:"id,omitempty"` - Options []interface{} `json:"options,omitempty"` } // ListEventRulesResponse represents a list response of event rules. type ListEventRulesResponse struct { ExternalID string `json:"external_id,omitempty"` ObjectVersion string `json:"object_version,omitempty"` - FormatVersion int `json:"format_version,omitempty"` + FormatVersion int `json:"format_version,string,omitempty"` EventRules []*EventRule `json:"rules,omitempty"` } diff --git a/website/docs/r/event_rule.html.markdown b/website/docs/r/event_rule.html.markdown new file mode 100644 index 000000000..2fd74d48b --- /dev/null +++ b/website/docs/r/event_rule.html.markdown @@ -0,0 +1,88 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_rule" +sidebar_current: "docs-pagerduty-resource-event-rule" +description: |- + Creates and manages an event rule in PagerDuty. +--- + +# pagerduty\_event_rule + +An [event rule](https://v2.developer.pagerduty.com/docs/global-event-rules-api) determines what happens to an event that is sent to PagerDuty by monitoring tools and other integrations. + + +## Example Usage + +```hcl +variable "action_list" { + default = [ + [ + "route", + "P5DTL0K" + ], + [ + "severity", + "warning" + ], + [ + "annotate", + "Managed by terraform" + ], + [ + "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" "example" { + action_json = jsonencode(var.action_list) + condition_json = jsonencode(var.condition_list) + advanced_condition_json = jsonencode(var.advanced_condition_list) +} +``` + +## Argument Reference + +The following arguments are supported: + +* `action_json` - (Required) A list of one or more actions for each rule. Each action within the list is itself a list. +* `condition_json` - (Required) Contains a list of conditions. The first field in the list is `and` or `or`, followed by a list of operators and values. +* `advanced_condition_json` - (Required) Contains a list of specific conditions including `active-between`,`scheduled-weekly`, and `frequency-over`. The first element in the list is the label for the condition, followed by a list of values for the specific condition. For more details on these conditions see [Advanced Condition](https://v2.developer.pagerduty.com/docs/global-event-rules-api#section-advanced-condition) in the PagerDuty API documentation. +* `catch_all` - (Optional) A boolean that indicates whether the rule is a catch all for the account. + +## Attributes Reference + +The following attributes are exported: + + * `id` - The ID of the event rule. + +## Import + +Escalation policies can be imported using the `id`, e.g. + +``` +$ terraform import pagerduty_event_rule.main 19acac92-027a-4ea0-b06c-bbf516519601 +``` diff --git a/website/pagerduty.erb b/website/pagerduty.erb index 0851b0387..47c193525 100644 --- a/website/pagerduty.erb +++ b/website/pagerduty.erb @@ -46,6 +46,9 @@