From e3ba4e718b1e96d11701a49bb072be7560b10c12 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 4 May 2022 16:22:54 -0400 Subject: [PATCH 01/51] ORCA-3459 - event orchestration resource --- go.mod | 2 +- go.sum | 2 + pagerduty/provider.go | 1 + .../resource_pagerduty_event_orchestration.go | 168 +++++++++++++++ ...urce_pagerduty_event_orchestration_test.go | 87 ++++++++ .../go-pagerduty/pagerduty/orchestration.go | 70 +++++++ .../go-pagerduty/pagerduty/pagerduty.go | 2 + .../go-pagerduty/pagerduty/references.go | 3 + vendor/modules.txt | 2 +- ...event_orchestration_resource.html.markdown | 193 ++++++++++++++++++ 10 files changed, 528 insertions(+), 2 deletions(-) create mode 100644 pagerduty/resource_pagerduty_event_orchestration.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_test.go create mode 100644 vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go create mode 100644 website/docs/r/event_orchestration_resource.html.markdown diff --git a/go.mod b/go.mod index b3380923d..dddc8d81a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( cloud.google.com/go v0.71.0 // indirect github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1 - github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f + github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd // indirect google.golang.org/api v0.35.0 // indirect google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb // indirect diff --git a/go.sum b/go.sum index 9c893f216..cf2737f7e 100644 --- a/go.sum +++ b/go.sum @@ -286,6 +286,8 @@ github.com/heimweh/go-pagerduty v0.0.0-20220208023456-83fe435832fb h1:p3faOVCU8L github.com/heimweh/go-pagerduty v0.0.0-20220208023456-83fe435832fb/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f h1:NLk7iDq85F2lz0q1gY32vZR506aYiNcgvV+Us1rX1q4= github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= +github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 h1:ETKxW+KSjOPaRzZU9f+QrjCkrL7hQqtMPKDv8DnLDO4= +github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 4af8626dc..bdc34448f 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -87,6 +87,7 @@ func Provider() *schema.Provider { "pagerduty_slack_connection": resourcePagerDutySlackConnection(), "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), + "pagerduty_orchestration": resourcePagerDutyOrchestration(), }, } diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go new file mode 100644 index 000000000..4b0f063c6 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -0,0 +1,168 @@ +package pagerduty + +import ( + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" +) + +func resourcePagerDutyOrchestration() *schema.Resource { + return &schema.Resource{ + Create: resourcePagerDutyOrchestrationCreate, + Read: resourcePagerDutyOrchestrationRead, + Update: resourcePagerDutyOrchestrationUpdate, + Delete: resourcePagerDutyOrchestrationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "team": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + }, + } +} + +func buildOrchestrationStruct(d *schema.ResourceData) *pagerduty.Orchestration { + orchestration := &pagerduty.Orchestration{ + Name: d.Get("name").(string), + } + + if attr, ok := d.GetOk("description"); ok { + orchestration.Description = attr.(string) + } + + if attr, ok := d.GetOk("team"); ok { + orchestration.Team = expandOrchestrationTeam(attr) + } + + return orchestration +} + +// TODO why is "team" a list? +func expandOrchestrationTeam(v interface{}) *pagerduty.OrchestrationObject { + var team *pagerduty.OrchestrationObject + t := v.([]interface{})[0].(map[string]interface{}) + team = &pagerduty.OrchestrationObject{ + ID: t["id"].(string), + } + + return team +} + +func resourcePagerDutyOrchestrationCreate(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + orchestration := buildOrchestrationStruct(d) + + log.Printf("[INFO] Creating PagerDuty orchestration: %s", orchestration.Name) + + retryErr := resource.Retry(10*time.Second, func() *resource.RetryError { + if orchestration, _, err := client.Orchestrations.Create(orchestration); err != nil { + if isErrCode(err, 400) || isErrCode(err, 429) { + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } else if orchestration != nil { + d.SetId(orchestration.ID) + } + return nil + }) + + if retryErr != nil { + return retryErr + } + + setOrchestrationProps(d, orchestration) + + return nil +} + +func resourcePagerDutyOrchestrationRead(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + return resource.Retry(2*time.Minute, func() *resource.RetryError { + orch, _, err := client.Orchestrations.Get(d.Id()) + if err != nil { + errResp := handleNotFoundError(err, d) + if errResp != nil { + time.Sleep(2 * time.Second) + return resource.RetryableError(errResp) + } + + return nil + } + + setOrchestrationProps(d, orch) + + return nil + }) +} + +func resourcePagerDutyOrchestrationUpdate(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + orchestration := buildOrchestrationStruct(d) + + log.Printf("[INFO] Updating PagerDuty orchestration: %s", d.Id()) + + if _, _, err := client.Orchestrations.Update(d.Id(), orchestration); err != nil { + return err + } + + return nil +} + +func resourcePagerDutyOrchestrationDelete(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + log.Printf("[INFO] Deleting PagerDuty orchestration: %s", d.Id()) + if _, err := client.Orchestrations.Delete(d.Id()); err != nil { + return err + } + + d.SetId("") + + return nil +} + +func setOrchestrationProps(d *schema.ResourceData, o *pagerduty.Orchestration) error { + d.Set("name", o.Name) + d.Set("description", o.Description) + // TODO: set team, number of routes, integrations if exist + return nil +} \ No newline at end of file diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go new file mode 100644 index 000000000..c2079adae --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -0,0 +1,87 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func init() { + resource.AddTestSweepers("pagerduty_orchestration", &resource.Sweeper{ + Name: "pagerduty_orchestration", + F: testSweepOrchestration, + }) +} + +func testSweepOrchestration(region string) error { + // TODO: delete all orchestrations created by the tests + return nil +} + +func TestAccPagerDutyOrchestration_Basic(t *testing.T) { + orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyOrchestrationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyOrchestrationConfigNameOnly(orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyOrchestrationExists("pagerduty_orchestration.nameonly"), + resource.TestCheckResourceAttr( + "pagerduty_orchestration.nameonly", "name", orchestration), + ), + }, + }, + }) +} + +func testAccCheckPagerDutyOrchestrationDestroy(s *terraform.State) error { + client, _ := testAccProvider.Meta().(*Config).Client() + for _, r := range s.RootModule().Resources { + if r.Type != "pagerduty_orchestration" { + continue + } + if _, _, err := client.Orchestrations.Get(r.Primary.ID); err == nil { + return fmt.Errorf("Orchestration still exists") + } + } + return nil +} + +func testAccCheckPagerDutyOrchestrationExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + orch, ok := s.RootModule().Resources[rn] + if !ok { + return fmt.Errorf("Not found: %s", rn) + } + if orch.Primary.ID == "" { + return fmt.Errorf("No Orchestration ID is set") + } + + client, _ := testAccProvider.Meta().(*Config).Client() + found, _, err := client.Orchestrations.Get(orch.Primary.ID) + if err != nil { + return err + } + if found.ID != orch.Primary.ID { + return fmt.Errorf("Orchrestration not found: %v - %v", orch.Primary.ID, found) + } + + return nil + } +} + +func testAccCheckPagerDutyOrchestrationConfigNameOnly(n string) string { + return fmt.Sprintf(` + +resource "pagerduty_orchestration" "nameonly" { + name = "%s" +} +`, n) +} \ No newline at end of file diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go new file mode 100644 index 000000000..0a81bfe9e --- /dev/null +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go @@ -0,0 +1,70 @@ +package pagerduty + +import ( + "fmt" +) + +type OrchestrationService service + +type Orchestration struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Team *OrchestrationObject `json:"team,omitempty"` + // TODO: add Integrations, Routes, Updater, Creator + expand tests to verify these props +} + +type OrchestrationObject struct { + Type string `json:"type,omitempty"` + ID string `json:"id,omitempty"` +} + +type OrchestrationPayload struct { + Orchestration *Orchestration `json:"orchestration,omitempty"` +} + +var orchestrationBaseUrl = "/event_orchestrations" + +func (s *OrchestrationService) Create(orchestration *Orchestration) (*Orchestration, *Response, error) { + v := new(OrchestrationPayload) + p := &OrchestrationPayload{Orchestration: orchestration} + + resp, err := s.client.newRequestDo("POST", orchestrationBaseUrl, nil, p, v) + + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *OrchestrationService) Get(ID string) (*Orchestration, *Response, error) { + u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) + v := new(OrchestrationPayload) + p := &OrchestrationPayload{} + + resp, err := s.client.newRequestDo("GET", u, nil, p, v) + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *OrchestrationService) Update(ID string, orchestration *Orchestration) (*Orchestration, *Response, error) { + u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) + v := new(OrchestrationPayload) + p := &OrchestrationPayload{Orchestration: orchestration} + + resp, err := s.client.newRequestDo("PUT", u, nil, p, v) + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *OrchestrationService) Delete(ID string) (*Response, error) { + u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) + return s.client.newRequestDo("DELETE", u, nil, nil, nil) +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go index e3dbbaf8f..75a133a2a 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go @@ -41,6 +41,7 @@ type Client struct { Extensions *ExtensionService MaintenanceWindows *MaintenanceWindowService Rulesets *RulesetService + Orchestrations *OrchestrationService Schedules *ScheduleService Services *ServicesService Teams *TeamService @@ -99,6 +100,7 @@ func NewClient(config *Config) (*Client, error) { c.EscalationPolicies = &EscalationPolicyService{c} c.MaintenanceWindows = &MaintenanceWindowService{c} c.Rulesets = &RulesetService{c} + c.Orchestrations = &OrchestrationService{c} c.Schedules = &ScheduleService{c} c.Services = &ServicesService{c} c.Teams = &TeamService{c} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go index 8716eb0f2..6a41314f9 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go @@ -49,5 +49,8 @@ type ExtensionSchemaReference resourceReference // RulesetReference represents a reference to a ruleset schema type RulesetReference resourceReference +// OrchestrationReference represents a reference to an orchestration schema +type OrchestrationReference resourceReference + // SubscriberReference represents a reference to a subscriber schema type SubscriberReference resourceReference diff --git a/vendor/modules.txt b/vendor/modules.txt index 8f52ef197..c0bcd8506 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -124,7 +124,7 @@ github.com/hashicorp/terraform-registry-address github.com/hashicorp/terraform-svchost # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f +# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 ## explicit github.com/heimweh/go-pagerduty/pagerduty # github.com/klauspost/compress v1.11.2 diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown new file mode 100644 index 000000000..25e106f4c --- /dev/null +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -0,0 +1,193 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: event_orchestration_separate_resources_per_type" +sidebar_current: "docs-pagerduty-resource-event-orchestration-router" +description: |- + Creates and manages an orchestration path (router|unrouted|service) associated with a Global Event Orchestration in PagerDuty. +--- + +# Separate resources for each "type" of Orchestration path & no rule resource + +In this example, we have separate resources for each "type" of Orchestration: + +* `pagerduty_event_orchestration_router` +* `pagerduty_event_orchestration_unrouted` +* `pagerduty_event_orchestration_service` + +Rules are defined as attributes of the orchestration path resource + + +## Example of configuring a Global Event Orchestration + +```hcl +resource "pagerduty_team" "engineering" { + name = "Engineering" +} + +resource "pagerduty_event_orchestration" "my_monitor" { + name = "My Monitoring Orchestration" + description = "Send events to a pair of services" + team { + id = pagerduty_team.foo.id + } +} +``` + +## Example of configuring Router rules for an Orchestration + +```hcl +resource "pagerduty_event_orchestration_router" "my_monitor" { + event_orchestration = pagerduty_event_orchestration.my_monitor + # Note: the router currently only supports a single set of rules. + # If we change routers to support multiple sets in the future we'd need to introde a `sets` argument. + rules = [ + { + name = "Events relating to our relational database" + conditions = [ + { expression = "event.summary matches part 'database'" }, + { expression = "event.source matches regex 'db[0-9]+-server'" } + ] + route_to = pagerduty_service.database.id + }, + { + name = "Events relating to our www app server" + conditions = [ + { expression = "event.summary matches part 'www'" } + ] + route_to = pagerduty_service.www.id + } + ] + catch_all = { + route_to = "unrouted" + } +} +``` + +**Argument Reference:** supports same rule and catch-all arguments as the [Router Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0Mzk-update-the-router-for-a-global-event-orchestration) of the Public API + +## Example of configuring a Unrouted Rules for an Orchestration + +```hcl +resource "pagerduty_event_orchestration_unrouted" "my_monitor" { + event_orchestration = pagerduty_event_orchestration.my_monitor + sets = [ + { + id = "start" + rules = [ + { + name = "Update the summary of un-matched Critical alerts so they're easier to spot" + conditions = [ + { expression = "event.severity matches 'critical'" } + ] + actions { + extractions = [ + { + target = "event.summary" + template = "[Critical Unrouted] {{event.summary}}" + } + ] + } + }, + { + name = "Reduce the severity of all other unrouted events" + conditions = [] + actions = { + severity = "info" + } + } + ] + } + ] + # In this example the user has defined their own "all other unrouted events" rule with no conditions + # so they aren't defining global catch_all behavior for the pagerduty_event_orchestration_unrouted resource + # but using the catch_all would be a totally legit alternative. +} +``` + +**Argument Reference:** supports same rule, set, and catch-all arguments as the [Unrouted Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0NDE-update-the-unrouted-orchestration-for-a-global-event-orchestration) of the Public API + +## Example of configuring a Service Orchestration + +```hcl +resource "pagerduty_event_orchestration_service" "www" { + service = route_to = pagerduty_service.www.id + sets = [ + { + id: "start" + rules = [ + { + name = "Always apply some consistent event transformations to all events" + conditions = [] + actions { + variables { + name = "hostname" + path = "event.component" + value = "hostname: (.*)" + type = "regex" + } + extractions = [ + { + # Demonstrating a template-style extraction + template = "{{variables.hostname}}" + target = "event.custom_details.hostname" + }, + { + # Demonstrating a regex-style extractions + source = "event.source" + regex = "www (.*) service" + target = "event.source" + } + ] + route_to = "step-two" + } + } + ] + }, + { + id: "step-two" + rules = [ + { + name = "All critical alerts should be treated as P1 incidents" + conditions = [ + { expression = "event.severity matches 'critical'" } + ] + actions { + annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" + priority = "P0IN2KQ" + suppress = false + } + }, + { + name = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" + conditions = [ + { expression = "event.custom_details.hostname matches part 'canary'" } + ] + actions { + automation_actions = [ + { + name = "Canary Slack Notification" + url = "https://our-slack-listerner.test/canary-notification" + auto_send = true + parameters = [] + } + ] + } + }, + { + name = "Never bother the on-call for info-level events outside of work hours" + conditions = [ + { expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" } + ] + actions { + suppress = true + } + } + ] + } + ] + catch_all = { + suppress = true + } +} +``` +**Argument Reference:** supports same rule, set, and catch-all arguments as the [Service Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0NDM-update-the-service-orchestration-for-a-service) of the Public API \ No newline at end of file From 2ca22ded134cc0d99207dc942f01c29ceb460972 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 4 May 2022 16:26:35 -0400 Subject: [PATCH 02/51] reformat --- pagerduty/provider.go | 2 +- pagerduty/resource_pagerduty_event_orchestration.go | 6 +++--- pagerduty/resource_pagerduty_event_orchestration_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pagerduty/provider.go b/pagerduty/provider.go index bdc34448f..8a1531a83 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -87,7 +87,7 @@ func Provider() *schema.Provider { "pagerduty_slack_connection": resourcePagerDutySlackConnection(), "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), - "pagerduty_orchestration": resourcePagerDutyOrchestration(), + "pagerduty_orchestration": resourcePagerDutyOrchestration(), }, } diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 4b0f063c6..8889acecf 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -12,7 +12,7 @@ import ( func resourcePagerDutyOrchestration() *schema.Resource { return &schema.Resource{ Create: resourcePagerDutyOrchestrationCreate, - Read: resourcePagerDutyOrchestrationRead, + Read: resourcePagerDutyOrchestrationRead, Update: resourcePagerDutyOrchestrationUpdate, Delete: resourcePagerDutyOrchestrationDelete, Importer: &schema.ResourceImporter{ @@ -120,7 +120,7 @@ func resourcePagerDutyOrchestrationRead(d *schema.ResourceData, meta interface{} return nil } - + setOrchestrationProps(d, orch) return nil @@ -165,4 +165,4 @@ func setOrchestrationProps(d *schema.ResourceData, o *pagerduty.Orchestration) e d.Set("description", o.Description) // TODO: set team, number of routes, integrations if exist return nil -} \ No newline at end of file +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index c2079adae..cbc93ecf3 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -84,4 +84,4 @@ resource "pagerduty_orchestration" "nameonly" { name = "%s" } `, n) -} \ No newline at end of file +} From 59695ae3bfd0935ecb7d500679516775b9038712 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 4 May 2022 16:35:08 -0400 Subject: [PATCH 03/51] [REVERT LATER] Temporarily pointing to the local copy of go-pagerduty --- go.mod | 2 + .../pagerduty/event_orchestration.go | 123 ++++++++++++++++++ .../go-pagerduty/pagerduty/orchestration.go | 70 ---------- .../go-pagerduty/pagerduty/pagerduty.go | 4 +- .../go-pagerduty/pagerduty/references.go | 4 +- .../heimweh/go-pagerduty/pagerduty/ruleset.go | 14 +- .../pagerduty/webhook_subscription.go | 2 +- vendor/modules.txt | 2 +- 8 files changed, 138 insertions(+), 83 deletions(-) create mode 100644 vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go delete mode 100644 vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go diff --git a/go.mod b/go.mod index dddc8d81a..2f0a52f4a 100644 --- a/go.mod +++ b/go.mod @@ -11,3 +11,5 @@ require ( google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb // indirect google.golang.org/grpc v1.33.2 // indirect ) + +replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty \ No newline at end of file diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go new file mode 100644 index 000000000..25ee15614 --- /dev/null +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go @@ -0,0 +1,123 @@ +package pagerduty + +import ( + "fmt" +) + +type EventOrchestrationService service + +type EventOrchestration struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description"` + Team *EventOrchestrationObject `json:"team"` + Routes int `json:"routes,omitempty"` + Integrations []*EventOrchestrationIntegration `json:"integrations,omitempty"` + // TODO: figure out if we need Updater, Creator / updated_by, created_by, updated_at, created_at, version +} + +type EventOrchestrationObject struct { + Type string `json:"type,omitempty"` + ID string `json:"id,omitempty"` +} + +type EventOrchestrationIntegrationParameters struct { + RoutingKey string `json:"routing_key,omitempty"` + Type string `json:"type,omitempty"` +} + +type EventOrchestrationIntegration struct { + ID string `json:"id,omitempty"` + Parameters *EventOrchestrationIntegrationParameters `json:"parameters,omitempty"` +} + +type EventOrchestrationPayload struct { + Orchestration *EventOrchestration `json:"orchestration,omitempty"` +} + +type ListEventOrchestrationsResponse struct { + Total int `json:"total,omitempty"` + Offset int `json:"offset,omitempty"` + More bool `json:"more,omitempty"` + Limit int `json:"limit,omitempty"` + Orchestrations []*EventOrchestration `json:"orchestrations,omitempty"` +} + +var eventOrchestrationBaseUrl = "/event_orchestrations" + +func (s *EventOrchestrationService) List() (*ListEventOrchestrationsResponse, *Response, error) { + v := new(ListEventOrchestrationsResponse) + + orchestrations := make([]*EventOrchestration, 0) + + // Create a handler closure capable of parsing data from the event orchestrations endpoint + // and appending resultant orchestrations to the return slice. + responseHandler := func(response *Response) (ListResp, *Response, error) { + var result ListEventOrchestrationsResponse + + if err := s.client.DecodeJSON(response, &result); err != nil { + return ListResp{}, response, err + } + + orchestrations = append(orchestrations, result.Orchestrations...) + + // Return stats on the current page. Caller can use this information to + // adjust for requesting additional pages. + return ListResp{ + More: result.More, + Offset: result.Offset, + Limit: result.Limit, + }, response, nil + } + err := s.client.newRequestPagedGetDo(eventOrchestrationBaseUrl, responseHandler) + if err != nil { + return nil, nil, err + } + v.Orchestrations = orchestrations + + return v, nil, nil +} + +func (s *EventOrchestrationService) Create(orchestration *EventOrchestration) (*EventOrchestration, *Response, error) { + v := new(EventOrchestrationPayload) + p := &EventOrchestrationPayload{Orchestration: orchestration} + + resp, err := s.client.newRequestDo("POST", eventOrchestrationBaseUrl, nil, p, v) + + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *EventOrchestrationService) Get(ID string) (*EventOrchestration, *Response, error) { + u := fmt.Sprintf("%s/%s", eventOrchestrationBaseUrl, ID) + v := new(EventOrchestrationPayload) + p := &EventOrchestrationPayload{} + + resp, err := s.client.newRequestDo("GET", u, nil, p, v) + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *EventOrchestrationService) Update(ID string, orchestration *EventOrchestration) (*EventOrchestration, *Response, error) { + u := fmt.Sprintf("%s/%s", eventOrchestrationBaseUrl, ID) + v := new(EventOrchestrationPayload) + p := &EventOrchestrationPayload{Orchestration: orchestration} + + resp, err := s.client.newRequestDo("PUT", u, nil, p, v) + if err != nil { + return nil, nil, err + } + + return v.Orchestration, resp, nil +} + +func (s *EventOrchestrationService) Delete(ID string) (*Response, error) { + u := fmt.Sprintf("%s/%s", eventOrchestrationBaseUrl, ID) + return s.client.newRequestDo("DELETE", u, nil, nil, nil) +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go deleted file mode 100644 index 0a81bfe9e..000000000 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/orchestration.go +++ /dev/null @@ -1,70 +0,0 @@ -package pagerduty - -import ( - "fmt" -) - -type OrchestrationService service - -type Orchestration struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - Team *OrchestrationObject `json:"team,omitempty"` - // TODO: add Integrations, Routes, Updater, Creator + expand tests to verify these props -} - -type OrchestrationObject struct { - Type string `json:"type,omitempty"` - ID string `json:"id,omitempty"` -} - -type OrchestrationPayload struct { - Orchestration *Orchestration `json:"orchestration,omitempty"` -} - -var orchestrationBaseUrl = "/event_orchestrations" - -func (s *OrchestrationService) Create(orchestration *Orchestration) (*Orchestration, *Response, error) { - v := new(OrchestrationPayload) - p := &OrchestrationPayload{Orchestration: orchestration} - - resp, err := s.client.newRequestDo("POST", orchestrationBaseUrl, nil, p, v) - - if err != nil { - return nil, nil, err - } - - return v.Orchestration, resp, nil -} - -func (s *OrchestrationService) Get(ID string) (*Orchestration, *Response, error) { - u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) - v := new(OrchestrationPayload) - p := &OrchestrationPayload{} - - resp, err := s.client.newRequestDo("GET", u, nil, p, v) - if err != nil { - return nil, nil, err - } - - return v.Orchestration, resp, nil -} - -func (s *OrchestrationService) Update(ID string, orchestration *Orchestration) (*Orchestration, *Response, error) { - u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) - v := new(OrchestrationPayload) - p := &OrchestrationPayload{Orchestration: orchestration} - - resp, err := s.client.newRequestDo("PUT", u, nil, p, v) - if err != nil { - return nil, nil, err - } - - return v.Orchestration, resp, nil -} - -func (s *OrchestrationService) Delete(ID string) (*Response, error) { - u := fmt.Sprintf("%s/%s", orchestrationBaseUrl, ID) - return s.client.newRequestDo("DELETE", u, nil, nil, nil) -} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go index 75a133a2a..0feb0db13 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go @@ -41,7 +41,7 @@ type Client struct { Extensions *ExtensionService MaintenanceWindows *MaintenanceWindowService Rulesets *RulesetService - Orchestrations *OrchestrationService + EventOrchestrations *EventOrchestrationService Schedules *ScheduleService Services *ServicesService Teams *TeamService @@ -100,7 +100,7 @@ func NewClient(config *Config) (*Client, error) { c.EscalationPolicies = &EscalationPolicyService{c} c.MaintenanceWindows = &MaintenanceWindowService{c} c.Rulesets = &RulesetService{c} - c.Orchestrations = &OrchestrationService{c} + c.EventOrchestrations = &EventOrchestrationService{c} c.Schedules = &ScheduleService{c} c.Services = &ServicesService{c} c.Teams = &TeamService{c} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go index 6a41314f9..69f22a44b 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go @@ -49,8 +49,8 @@ type ExtensionSchemaReference resourceReference // RulesetReference represents a reference to a ruleset schema type RulesetReference resourceReference -// OrchestrationReference represents a reference to an orchestration schema -type OrchestrationReference resourceReference +// EventOrchestrationReference represents a reference to an event orchestration schema +type EventOrchestrationReference resourceReference // SubscriberReference represents a reference to a subscriber schema type SubscriberReference resourceReference diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go index f2091da5b..9cd6a421d 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go @@ -120,14 +120,14 @@ type ListRulesetRulesResponse struct { // RuleActions represents a rule action type RuleActions struct { - Suppress *RuleActionSuppress `json:"suppress"` - Annotate *RuleActionParameter `json:"annotate"` - Severity *RuleActionParameter `json:"severity"` - Priority *RuleActionParameter `json:"priority"` - Route *RuleActionParameter `json:"route"` - EventAction *RuleActionParameter `json:"event_action"` + Suppress *RuleActionSuppress `json:"suppress,omitempty"` + Annotate *RuleActionParameter `json:"annotate,omitempty"` + Severity *RuleActionParameter `json:"severity,omitempty"` + Priority *RuleActionParameter `json:"priority,omitempty"` + Route *RuleActionParameter `json:"route,omitempty"` + EventAction *RuleActionParameter `json:"event_action,omitempty"` Extractions []*RuleActionExtraction `json:"extractions,omitempty"` - Suspend *RuleActionIntParameter `json:"suspend"` + Suspend *RuleActionIntParameter `json:"suspend,omitempty"` } // RuleActionParameter represents a string parameter object on a rule action diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go index 19f06ddbd..8390be7db 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go @@ -21,7 +21,7 @@ type DeliveryMethod struct { TemporarilyDisabled bool `json:"temporarily_disabled,omitempty"` Type string `json:"type,omitempty"` URL string `json:"url,omitempty"` - CustomHeaders []*CustomHeaders `json:"custom_headers"` + CustomHeaders []*CustomHeaders `json:"custom_headers,omitempty"` } type CustomHeaders struct { diff --git a/vendor/modules.txt b/vendor/modules.txt index c0bcd8506..0838b566b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -124,7 +124,7 @@ github.com/hashicorp/terraform-registry-address github.com/hashicorp/terraform-svchost # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 +# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty ## explicit github.com/heimweh/go-pagerduty/pagerduty # github.com/klauspost/compress v1.11.2 From 77b07ad010772d08919da04bd676196263dd7433 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 4 May 2022 17:13:44 -0400 Subject: [PATCH 04/51] rename Orchestration references to EventOrchestration --- pagerduty/provider.go | 2 +- .../resource_pagerduty_event_orchestration.go | 52 +++++++++---------- ...urce_pagerduty_event_orchestration_test.go | 34 ++++++------ 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 8a1531a83..cabf0a391 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -87,7 +87,7 @@ func Provider() *schema.Provider { "pagerduty_slack_connection": resourcePagerDutySlackConnection(), "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), - "pagerduty_orchestration": resourcePagerDutyOrchestration(), + "pagerduty_event_orchestration": resourcePagerDutyEventOrchestration(), }, } diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 8889acecf..721e524b1 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -9,12 +9,12 @@ import ( "github.com/heimweh/go-pagerduty/pagerduty" ) -func resourcePagerDutyOrchestration() *schema.Resource { +func resourcePagerDutyEventOrchestration() *schema.Resource { return &schema.Resource{ - Create: resourcePagerDutyOrchestrationCreate, - Read: resourcePagerDutyOrchestrationRead, - Update: resourcePagerDutyOrchestrationUpdate, - Delete: resourcePagerDutyOrchestrationDelete, + Create: resourcePagerDutyEventOrchestrationCreate, + Read: resourcePagerDutyEventOrchestrationRead, + Update: resourcePagerDutyEventOrchestrationUpdate, + Delete: resourcePagerDutyEventOrchestrationDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -44,8 +44,8 @@ func resourcePagerDutyOrchestration() *schema.Resource { } } -func buildOrchestrationStruct(d *schema.ResourceData) *pagerduty.Orchestration { - orchestration := &pagerduty.Orchestration{ +func buildEventOrchestrationStruct(d *schema.ResourceData) *pagerduty.EventOrchestration { + orchestration := &pagerduty.EventOrchestration{ Name: d.Get("name").(string), } @@ -61,28 +61,28 @@ func buildOrchestrationStruct(d *schema.ResourceData) *pagerduty.Orchestration { } // TODO why is "team" a list? -func expandOrchestrationTeam(v interface{}) *pagerduty.OrchestrationObject { - var team *pagerduty.OrchestrationObject +func expandOrchestrationTeam(v interface{}) *pagerduty.EventOrchestrationObject { + var team *pagerduty.EventOrchestrationObject t := v.([]interface{})[0].(map[string]interface{}) - team = &pagerduty.OrchestrationObject{ + team = &pagerduty.EventOrchestrationObject{ ID: t["id"].(string), } return team } -func resourcePagerDutyOrchestrationCreate(d *schema.ResourceData, meta interface{}) error { +func resourcePagerDutyEventOrchestrationCreate(d *schema.ResourceData, meta interface{}) error { client, err := meta.(*Config).Client() if err != nil { return err } - orchestration := buildOrchestrationStruct(d) + orchestration := buildEventOrchestrationStruct(d) - log.Printf("[INFO] Creating PagerDuty orchestration: %s", orchestration.Name) + log.Printf("[INFO] Creating PagerDuty Event Orchestration: %s", orchestration.Name) retryErr := resource.Retry(10*time.Second, func() *resource.RetryError { - if orchestration, _, err := client.Orchestrations.Create(orchestration); err != nil { + if orchestration, _, err := client.EventOrchestrations.Create(orchestration); err != nil { if isErrCode(err, 400) || isErrCode(err, 429) { return resource.RetryableError(err) } @@ -98,19 +98,19 @@ func resourcePagerDutyOrchestrationCreate(d *schema.ResourceData, meta interface return retryErr } - setOrchestrationProps(d, orchestration) + setEventOrchestrationProps(d, orchestration) return nil } -func resourcePagerDutyOrchestrationRead(d *schema.ResourceData, meta interface{}) error { +func resourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta interface{}) error { client, err := meta.(*Config).Client() if err != nil { return err } return resource.Retry(2*time.Minute, func() *resource.RetryError { - orch, _, err := client.Orchestrations.Get(d.Id()) + orch, _, err := client.EventOrchestrations.Get(d.Id()) if err != nil { errResp := handleNotFoundError(err, d) if errResp != nil { @@ -121,37 +121,37 @@ func resourcePagerDutyOrchestrationRead(d *schema.ResourceData, meta interface{} return nil } - setOrchestrationProps(d, orch) + setEventOrchestrationProps(d, orch) return nil }) } -func resourcePagerDutyOrchestrationUpdate(d *schema.ResourceData, meta interface{}) error { +func resourcePagerDutyEventOrchestrationUpdate(d *schema.ResourceData, meta interface{}) error { client, err := meta.(*Config).Client() if err != nil { return err } - orchestration := buildOrchestrationStruct(d) + orchestration := buildEventOrchestrationStruct(d) - log.Printf("[INFO] Updating PagerDuty orchestration: %s", d.Id()) + log.Printf("[INFO] Updating PagerDuty Event Orchestration: %s", d.Id()) - if _, _, err := client.Orchestrations.Update(d.Id(), orchestration); err != nil { + if _, _, err := client.EventOrchestrations.Update(d.Id(), orchestration); err != nil { return err } return nil } -func resourcePagerDutyOrchestrationDelete(d *schema.ResourceData, meta interface{}) error { +func resourcePagerDutyEventOrchestrationDelete(d *schema.ResourceData, meta interface{}) error { client, err := meta.(*Config).Client() if err != nil { return err } - log.Printf("[INFO] Deleting PagerDuty orchestration: %s", d.Id()) - if _, err := client.Orchestrations.Delete(d.Id()); err != nil { + log.Printf("[INFO] Deleting PagerDuty Event Orchestration: %s", d.Id()) + if _, err := client.EventOrchestrations.Delete(d.Id()); err != nil { return err } @@ -160,7 +160,7 @@ func resourcePagerDutyOrchestrationDelete(d *schema.ResourceData, meta interface return nil } -func setOrchestrationProps(d *schema.ResourceData, o *pagerduty.Orchestration) error { +func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrchestration) error { d.Set("name", o.Name) d.Set("description", o.Description) // TODO: set team, number of routes, integrations if exist diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index cbc93ecf3..deba5727c 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -10,67 +10,67 @@ import ( ) func init() { - resource.AddTestSweepers("pagerduty_orchestration", &resource.Sweeper{ - Name: "pagerduty_orchestration", - F: testSweepOrchestration, + resource.AddTestSweepers("pagerduty_event_orchestration", &resource.Sweeper{ + Name: "pagerduty_event_orchestration", + F: testSweepEventOrchestration, }) } -func testSweepOrchestration(region string) error { +func testSweepEventOrchestration(region string) error { // TODO: delete all orchestrations created by the tests return nil } -func TestAccPagerDutyOrchestration_Basic(t *testing.T) { +func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckPagerDutyOrchestrationDestroy, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, Steps: []resource.TestStep{ { Config: testAccCheckPagerDutyOrchestrationConfigNameOnly(orchestration), Check: resource.ComposeTestCheckFunc( - testAccCheckPagerDutyOrchestrationExists("pagerduty_orchestration.nameonly"), + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), resource.TestCheckResourceAttr( - "pagerduty_orchestration.nameonly", "name", orchestration), + "pagerduty_event_orchestration.nameonly", "name", orchestration), ), }, }, }) } -func testAccCheckPagerDutyOrchestrationDestroy(s *terraform.State) error { +func testAccCheckPagerDutyEventOrchestrationDestroy(s *terraform.State) error { client, _ := testAccProvider.Meta().(*Config).Client() for _, r := range s.RootModule().Resources { - if r.Type != "pagerduty_orchestration" { + if r.Type != "pagerduty_event_orchestration" { continue } - if _, _, err := client.Orchestrations.Get(r.Primary.ID); err == nil { - return fmt.Errorf("Orchestration still exists") + if _, _, err := client.EventOrchestrations.Get(r.Primary.ID); err == nil { + return fmt.Errorf("Event Orchestration still exists") } } return nil } -func testAccCheckPagerDutyOrchestrationExists(rn string) resource.TestCheckFunc { +func testAccCheckPagerDutyEventOrchestrationExists(rn string) resource.TestCheckFunc { return func(s *terraform.State) error { orch, ok := s.RootModule().Resources[rn] if !ok { return fmt.Errorf("Not found: %s", rn) } if orch.Primary.ID == "" { - return fmt.Errorf("No Orchestration ID is set") + return fmt.Errorf("No Event Orchestration ID is set") } client, _ := testAccProvider.Meta().(*Config).Client() - found, _, err := client.Orchestrations.Get(orch.Primary.ID) + found, _, err := client.EventOrchestrations.Get(orch.Primary.ID) if err != nil { return err } if found.ID != orch.Primary.ID { - return fmt.Errorf("Orchrestration not found: %v - %v", orch.Primary.ID, found) + return fmt.Errorf("Event Orchrestration not found: %v - %v", orch.Primary.ID, found) } return nil @@ -80,7 +80,7 @@ func testAccCheckPagerDutyOrchestrationExists(rn string) resource.TestCheckFunc func testAccCheckPagerDutyOrchestrationConfigNameOnly(n string) string { return fmt.Sprintf(` -resource "pagerduty_orchestration" "nameonly" { +resource "pagerduty_event_orchestration" "nameonly" { name = "%s" } `, n) From 9dc2976f9052da327fa5742350fa20deb2cfb4b5 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Thu, 5 May 2022 13:21:42 -0400 Subject: [PATCH 05/51] add more properties, mapping logic; add tests --- .../resource_pagerduty_event_orchestration.go | 74 ++++++++++++++++++- ...urce_pagerduty_event_orchestration_test.go | 67 +++++++++++++++-- 2 files changed, 134 insertions(+), 7 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 721e524b1..53c54f3e5 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -40,6 +40,39 @@ func resourcePagerDutyEventOrchestration() *schema.Resource { }, }, }, + "routes": { + Type: schema.TypeInt, + Computed: true, + }, + "integrations": { + Type: schema.TypeList, + Computed: true, + Optional: true, // Tests keep failing if "Optional: true" is not provided + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "parameters": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "routing_key": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, }, } } @@ -160,9 +193,48 @@ func resourcePagerDutyEventOrchestrationDelete(d *schema.ResourceData, meta inte return nil } +func flattenEventOrchestrationTeam(v *pagerduty.EventOrchestrationObject) []interface{} { + team := map[string]interface{}{ + "id": v.ID, + } + + return []interface{}{team} +} + +func flattenEventOrchestrationIntegrations(eoi []*pagerduty.EventOrchestrationIntegration) []interface{} { + var result []interface{} + + for _, i := range eoi { + integration := map[string]interface{}{ + "id": i.ID, + "parameters": flattenEventOrchestrationIntegrationParameters(i.Parameters), + } + result = append(result, integration) + } + return result +} + +func flattenEventOrchestrationIntegrationParameters(p *pagerduty.EventOrchestrationIntegrationParameters) []interface{} { + result := map[string]interface{}{ + "routing_key": p.RoutingKey, + "type": p.Type, + } + + return []interface{}{result} +} + func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrchestration) error { d.Set("name", o.Name) d.Set("description", o.Description) - // TODO: set team, number of routes, integrations if exist + d.Set("routes", o.Routes) + + if o.Team != nil { + d.Set("team", flattenEventOrchestrationTeam(o.Team)) + } + + if len(o.Integrations) > 0 { + d.Set("integrations", flattenEventOrchestrationIntegrations(o.Integrations)) + } + return nil } diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index deba5727c..829bf353e 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -2,6 +2,8 @@ package pagerduty import ( "fmt" + "log" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" @@ -17,24 +19,61 @@ func init() { } func testSweepEventOrchestration(region string) error { - // TODO: delete all orchestrations created by the tests + config, err := sharedConfigForRegion(region) + if err != nil { + return err + } + + client, err := config.Client() + if err != nil { + return err + } + + resp, _, err := client.EventOrchestrations.List() + if err != nil { + return err + } + + for _, orchestration := range resp.Orchestrations { + if strings.HasPrefix(orchestration.Name, "tf-name-") { + log.Printf("Destroying Event Orchestration %s (%s)", orchestration.Name, orchestration.ID) + if _, err := client.EventOrchestrations.Delete(orchestration.ID); err != nil { + return err + } + } + } + return nil } func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { - orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) + teamName := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, Steps: []resource.TestStep{ + // { + // Config: testAccCheckPagerDutyEventOrchestrationConfigNameOnly(name), + // Check: resource.ComposeTestCheckFunc( + // testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), + // resource.TestCheckResourceAttr( + // "pagerduty_event_orchestration.nameonly", "name", name), + // ), + // }, { - Config: testAccCheckPagerDutyOrchestrationConfigNameOnly(orchestration), + Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, teamName), Check: resource.ComposeTestCheckFunc( - testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "name", name, + ), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration.nameonly", "name", orchestration), + "pagerduty_event_orchestration.foo", "description", description, + ), ), }, }, @@ -77,7 +116,23 @@ func testAccCheckPagerDutyEventOrchestrationExists(rn string) resource.TestCheck } } -func testAccCheckPagerDutyOrchestrationConfigNameOnly(n string) string { +func testAccCheckPagerDutyEventOrchestrationConfig(name, description, team string) string { + return fmt.Sprintf(` + +resource "pagerduty_team" "foo" { + name = "%s" +} +resource "pagerduty_event_orchestration" "foo" { + name = "%s" + description = "%s" + team { + id = pagerduty_team.foo.id + } +} +`, team, name, description) +} + +func testAccCheckPagerDutyEventOrchestrationConfigNameOnly(n string) string { return fmt.Sprintf(` resource "pagerduty_event_orchestration" "nameonly" { From c5aa9378bc5d115e5ce8f8c60cf904c592c93d0f Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 5 May 2022 16:24:37 -0400 Subject: [PATCH 06/51] more tests to event_orchestration_resource --- ...urce_pagerduty_event_orchestration_test.go | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index 829bf353e..cfc24442f 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -50,20 +50,23 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) teamName := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) + nameUpdated := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + descriptionUpdated := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) + teamNameUpdated := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, Steps: []resource.TestStep{ - // { - // Config: testAccCheckPagerDutyEventOrchestrationConfigNameOnly(name), - // Check: resource.ComposeTestCheckFunc( - // testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), - // resource.TestCheckResourceAttr( - // "pagerduty_event_orchestration.nameonly", "name", name), - // ), - // }, + { + Config: testAccCheckPagerDutyEventOrchestrationConfigNameOnly(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.nameonly", "name", name), + ), + }, { Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, teamName), Check: resource.ComposeTestCheckFunc( @@ -76,6 +79,18 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { ), ), }, + { + Config: testAccCheckPagerDutyEventOrchestrationConfigUpdated(nameUpdated, descriptionUpdated, teamNameUpdated), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "name", nameUpdated, + ), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "description", descriptionUpdated, + ), + ), + }, }, }) } @@ -140,3 +155,19 @@ resource "pagerduty_event_orchestration" "nameonly" { } `, n) } + +func testAccCheckPagerDutyEventOrchestrationConfigUpdated(name, description, team string) string { + return fmt.Sprintf(` + +resource "pagerduty_team" "foo" { + name = "%s" +} +resource "pagerduty_event_orchestration" "foo" { + name = "%s" + description = "%s" + team { + id = pagerduty_team.foo.id + } +} +`, team, name, description) +} From 60cfa6cdf05a841f68b5e69cb65979087586cd67 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 5 May 2022 16:24:50 -0400 Subject: [PATCH 07/51] add datasource event orchestration --- ...ta_source_pagerduty_event_orchestration.go | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 pagerduty/data_source_pagerduty_event_orchestration.go diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go new file mode 100644 index 000000000..81ea0c02f --- /dev/null +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -0,0 +1,106 @@ +package pagerduty + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" +) + +func dataSourcePagerDutyEventOrchestration() *schema.Resource { + return &schema.Resource{ + Read: dataSourcePagerDutyEventOrchestrationRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "routes": { + Type: schema.TypeInt, + Computed: true, + }, + "integrations": { + Type: schema.TypeList, + Computed: true, + Optional: true, // Tests keep failing if "Optional: true" is not provided + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "parameters": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "routing_key": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + log.Printf("[INFO] Reading PagerDuty Event Orchestration") + + searchName := d.Get("name").(string) + + return resource.Retry(5*time.Minute, func() *resource.RetryError { + resp, _, err := client.EventOrchestrations.List() + if err != nil { + if isErrCode(err, 429) { + // Delaying retry by 30s as recommended by PagerDuty + // https://developer.pagerduty.com/docs/rest-api-v2/rate-limiting/#what-are-possible-workarounds-to-the-events-api-rate-limit + time.Sleep(30 * time.Second) + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } + + var found *pagerduty.EventOrchestration + + for _, orchestration := range resp.Orchestrations { + if orchestration.Name == searchName { + found = orchestration + break + } + } + + if found == nil { + return resource.NonRetryableError( + fmt.Errorf("Unable to locate any Event Orchestration with the name: %s", searchName), + ) + } + + d.SetId(found.ID) + setEventOrchestrationProps(d, found) + + return nil + }) +} From febcb67bc4270104148707a1dc2110a07d89912d Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 5 May 2022 16:25:08 -0400 Subject: [PATCH 08/51] [REVERT LATER]-local testing --- go.mod | 2 +- .../go-pagerduty/pagerduty/event_orchestration.go | 10 +++++----- .../heimweh/go-pagerduty/pagerduty/ruleset.go | 14 +++++++------- .../go-pagerduty/pagerduty/webhook_subscription.go | 2 +- vendor/modules.txt | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 2f0a52f4a..84786596f 100644 --- a/go.mod +++ b/go.mod @@ -12,4 +12,4 @@ require ( google.golang.org/grpc v1.33.2 // indirect ) -replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty \ No newline at end of file +replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/pdhanakoti/Documents/projects/go/src/github.com/alenapan/go-pagerduty diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go index 25ee15614..4448d431e 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go @@ -10,7 +10,7 @@ type EventOrchestration struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description"` - Team *EventOrchestrationObject `json:"team"` + Team *EventOrchestrationObject `json:"team,omitempty"` Routes int `json:"routes,omitempty"` Integrations []*EventOrchestrationIntegration `json:"integrations,omitempty"` // TODO: figure out if we need Updater, Creator / updated_by, created_by, updated_at, created_at, version @@ -36,10 +36,10 @@ type EventOrchestrationPayload struct { } type ListEventOrchestrationsResponse struct { - Total int `json:"total,omitempty"` - Offset int `json:"offset,omitempty"` - More bool `json:"more,omitempty"` - Limit int `json:"limit,omitempty"` + Total int `json:"total,omitempty"` + Offset int `json:"offset,omitempty"` + More bool `json:"more,omitempty"` + Limit int `json:"limit,omitempty"` Orchestrations []*EventOrchestration `json:"orchestrations,omitempty"` } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go index 9cd6a421d..f2091da5b 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go @@ -120,14 +120,14 @@ type ListRulesetRulesResponse struct { // RuleActions represents a rule action type RuleActions struct { - Suppress *RuleActionSuppress `json:"suppress,omitempty"` - Annotate *RuleActionParameter `json:"annotate,omitempty"` - Severity *RuleActionParameter `json:"severity,omitempty"` - Priority *RuleActionParameter `json:"priority,omitempty"` - Route *RuleActionParameter `json:"route,omitempty"` - EventAction *RuleActionParameter `json:"event_action,omitempty"` + Suppress *RuleActionSuppress `json:"suppress"` + Annotate *RuleActionParameter `json:"annotate"` + Severity *RuleActionParameter `json:"severity"` + Priority *RuleActionParameter `json:"priority"` + Route *RuleActionParameter `json:"route"` + EventAction *RuleActionParameter `json:"event_action"` Extractions []*RuleActionExtraction `json:"extractions,omitempty"` - Suspend *RuleActionIntParameter `json:"suspend,omitempty"` + Suspend *RuleActionIntParameter `json:"suspend"` } // RuleActionParameter represents a string parameter object on a rule action diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go index 8390be7db..19f06ddbd 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/webhook_subscription.go @@ -21,7 +21,7 @@ type DeliveryMethod struct { TemporarilyDisabled bool `json:"temporarily_disabled,omitempty"` Type string `json:"type,omitempty"` URL string `json:"url,omitempty"` - CustomHeaders []*CustomHeaders `json:"custom_headers,omitempty"` + CustomHeaders []*CustomHeaders `json:"custom_headers"` } type CustomHeaders struct { diff --git a/vendor/modules.txt b/vendor/modules.txt index 0838b566b..cf2bdd29e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -124,7 +124,7 @@ github.com/hashicorp/terraform-registry-address github.com/hashicorp/terraform-svchost # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty +# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/pdhanakoti/Documents/projects/go/src/github.com/alenapan/go-pagerduty ## explicit github.com/heimweh/go-pagerduty/pagerduty # github.com/klauspost/compress v1.11.2 From 4f8a589608ea8fd04e23e9444eb0adaa9e492918 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Thu, 5 May 2022 19:20:25 -0400 Subject: [PATCH 09/51] fix create logic (set integrations), remove description and routes from orchestration data source --- go.mod | 2 +- ...ta_source_pagerduty_event_orchestration.go | 8 --- ...urce_pagerduty_event_orchestration_test.go | 68 +++++++++++++++++++ pagerduty/provider.go | 1 + .../resource_pagerduty_event_orchestration.go | 17 ++--- .../pagerduty/event_orchestration.go | 5 ++ vendor/modules.txt | 2 +- 7 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 pagerduty/data_source_pagerduty_event_orchestration_test.go diff --git a/go.mod b/go.mod index 84786596f..76857bf54 100644 --- a/go.mod +++ b/go.mod @@ -12,4 +12,4 @@ require ( google.golang.org/grpc v1.33.2 // indirect ) -replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/pdhanakoti/Documents/projects/go/src/github.com/alenapan/go-pagerduty +replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index 81ea0c02f..1443a717e 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -19,14 +19,6 @@ func dataSourcePagerDutyEventOrchestration() *schema.Resource { Type: schema.TypeString, Required: true, }, - "description": { - Type: schema.TypeString, - Optional: true, - }, - "routes": { - Type: schema.TypeInt, - Computed: true, - }, "integrations": { Type: schema.TypeList, Computed: true, diff --git a/pagerduty/data_source_pagerduty_event_orchestration_test.go b/pagerduty/data_source_pagerduty_event_orchestration_test.go new file mode 100644 index 000000000..aeb2ef55a --- /dev/null +++ b/pagerduty/data_source_pagerduty_event_orchestration_test.go @@ -0,0 +1,68 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccDataSourcePagerDutyEventOrchestration_Basic(t *testing.T) { + name := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourcePagerDutyEventOrchestrationConfig(name), + Check: resource.ComposeTestCheckFunc( + testAccDataSourcePagerDutyEventOrchestration("pagerduty_event_orchestration.test", "data.pagerduty_event_orchestration.by_name"), + ), + }, + }, + }) +} + +func testAccDataSourcePagerDutyEventOrchestration(src, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + srcR := s.RootModule().Resources[src] + srcA := srcR.Primary.Attributes + + r := s.RootModule().Resources[n] + a := r.Primary.Attributes + + if a["id"] == "" { + return fmt.Errorf("Expected to get an Event Orchestration ID from PagerDuty") + } + + testAtts := []string{"id", "name"} + + // TODO: figure out what's the best way to populate integrations. + // We store routing keys in Elasticsearch but we don't return them in the API. + // We can make a list + get call to retrieve integrations for the "found" orchestration + + for _, att := range testAtts { + if a[att] != srcA[att] { + return fmt.Errorf("Expected the Event Orchestration %s to be: %s, but got: %s", att, srcA[att], a[att]) + } + } + + return nil + } +} + +func testAccDataSourcePagerDutyEventOrchestrationConfig(name string) string { + return fmt.Sprintf(` +resource "pagerduty_event_orchestration" "test" { + name = "%s" +} + +data "pagerduty_event_orchestration" "by_name" { + name = pagerduty_event_orchestration.test.name +} +`, name) +} \ No newline at end of file diff --git a/pagerduty/provider.go b/pagerduty/provider.go index cabf0a391..0c0456bec 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -59,6 +59,7 @@ func Provider() *schema.Provider { "pagerduty_priority": dataSourcePagerDutyPriority(), "pagerduty_ruleset": dataSourcePagerDutyRuleset(), "pagerduty_tag": dataSourcePagerDutyTag(), + "pagerduty_event_orchestration": dataSourcePagerDutyEventOrchestration(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 53c54f3e5..99389e3ee 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -93,7 +93,6 @@ func buildEventOrchestrationStruct(d *schema.ResourceData) *pagerduty.EventOrche return orchestration } -// TODO why is "team" a list? func expandOrchestrationTeam(v interface{}) *pagerduty.EventOrchestrationObject { var team *pagerduty.EventOrchestrationObject t := v.([]interface{})[0].(map[string]interface{}) @@ -110,19 +109,21 @@ func resourcePagerDutyEventOrchestrationCreate(d *schema.ResourceData, meta inte return err } - orchestration := buildEventOrchestrationStruct(d) + payload := buildEventOrchestrationStruct(d) + var orchestration *pagerduty.EventOrchestration - log.Printf("[INFO] Creating PagerDuty Event Orchestration: %s", orchestration.Name) + log.Printf("[INFO] Creating PagerDuty Event Orchestration: %s", payload.Name) retryErr := resource.Retry(10*time.Second, func() *resource.RetryError { - if orchestration, _, err := client.EventOrchestrations.Create(orchestration); err != nil { + if orch, _, err := client.EventOrchestrations.Create(payload); err != nil { if isErrCode(err, 400) || isErrCode(err, 429) { return resource.RetryableError(err) } return resource.NonRetryableError(err) - } else if orchestration != nil { - d.SetId(orchestration.ID) + } else if orch != nil { + d.SetId(orch.ID) + orchestration = orch } return nil }) @@ -232,9 +233,9 @@ func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrches d.Set("team", flattenEventOrchestrationTeam(o.Team)) } - if len(o.Integrations) > 0 { + if len(o.Integrations) > 0 { d.Set("integrations", flattenEventOrchestrationIntegrations(o.Integrations)) } - + return nil } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go index 4448d431e..90c7eb6d2 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go @@ -47,6 +47,7 @@ var eventOrchestrationBaseUrl = "/event_orchestrations" func (s *EventOrchestrationService) List() (*ListEventOrchestrationsResponse, *Response, error) { v := new(ListEventOrchestrationsResponse) + v.Total = 0 orchestrations := make([]*EventOrchestration, 0) @@ -59,6 +60,10 @@ func (s *EventOrchestrationService) List() (*ListEventOrchestrationsResponse, *R return ListResp{}, response, err } + v.Total += result.Total + v.Offset = result.Offset + v.More = result.More + v.Limit = result.Limit orchestrations = append(orchestrations, result.Orchestrations...) // Return stats on the current page. Caller can use this information to diff --git a/vendor/modules.txt b/vendor/modules.txt index cf2bdd29e..0838b566b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -124,7 +124,7 @@ github.com/hashicorp/terraform-registry-address github.com/hashicorp/terraform-svchost # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/pdhanakoti/Documents/projects/go/src/github.com/alenapan/go-pagerduty +# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty ## explicit github.com/heimweh/go-pagerduty/pagerduty # github.com/klauspost/compress v1.11.2 From f86990f0e0fbc7271e919226b2c133f4942d61ef Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 6 May 2022 09:48:20 -0400 Subject: [PATCH 10/51] fix data source, add data source tests --- ...ta_source_pagerduty_event_orchestration.go | 19 +++++++++++++++++-- ...urce_pagerduty_event_orchestration_test.go | 6 +----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index 1443a717e..a3e0bae01 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -90,8 +90,23 @@ func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta inte ) } - d.SetId(found.ID) - setEventOrchestrationProps(d, found) + // Get the found orchestration by ID so we can set the integrations property + // since the list ndpoint does not return it + orch, _, err := client.EventOrchestrations.Get(found.ID) + if err != nil { + if isErrCode(err, 429) { + return resource.RetryableError(err) + } + + return resource.NonRetryableError(err) + } + + d.SetId(orch.ID) + d.Set("name", orch.Name) + + if len(orch.Integrations) > 0 { + d.Set("integrations", flattenEventOrchestrationIntegrations(orch.Integrations)) + } return nil }) diff --git a/pagerduty/data_source_pagerduty_event_orchestration_test.go b/pagerduty/data_source_pagerduty_event_orchestration_test.go index aeb2ef55a..14d7ebb08 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration_test.go +++ b/pagerduty/data_source_pagerduty_event_orchestration_test.go @@ -39,11 +39,7 @@ func testAccDataSourcePagerDutyEventOrchestration(src, n string) resource.TestCh return fmt.Errorf("Expected to get an Event Orchestration ID from PagerDuty") } - testAtts := []string{"id", "name"} - - // TODO: figure out what's the best way to populate integrations. - // We store routing keys in Elasticsearch but we don't return them in the API. - // We can make a list + get call to retrieve integrations for the "found" orchestration + testAtts := []string{"id", "name", "intergations"} for _, att := range testAtts { if a[att] != srcA[att] { From 6ce2d6720f72f5525e6ee56b0edd11e319cd4b9e Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 6 May 2022 09:50:28 -0400 Subject: [PATCH 11/51] reformat --- .../data_source_pagerduty_event_orchestration.go | 6 +++--- ...data_source_pagerduty_event_orchestration_test.go | 2 +- pagerduty/resource_pagerduty_event_orchestration.go | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index a3e0bae01..b36c05709 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -12,7 +12,7 @@ import ( func dataSourcePagerDutyEventOrchestration() *schema.Resource { return &schema.Resource{ - Read: dataSourcePagerDutyEventOrchestrationRead, + Read: dataSourcePagerDutyEventOrchestrationRead, Schema: map[string]*schema.Schema{ "name": { @@ -20,7 +20,7 @@ func dataSourcePagerDutyEventOrchestration() *schema.Resource { Required: true, }, "integrations": { - Type: schema.TypeList, + Type: schema.TypeList, Computed: true, Optional: true, // Tests keep failing if "Optional: true" is not provided Elem: &schema.Resource{ @@ -103,7 +103,7 @@ func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta inte d.SetId(orch.ID) d.Set("name", orch.Name) - + if len(orch.Integrations) > 0 { d.Set("integrations", flattenEventOrchestrationIntegrations(orch.Integrations)) } diff --git a/pagerduty/data_source_pagerduty_event_orchestration_test.go b/pagerduty/data_source_pagerduty_event_orchestration_test.go index 14d7ebb08..0850b94ee 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration_test.go +++ b/pagerduty/data_source_pagerduty_event_orchestration_test.go @@ -61,4 +61,4 @@ data "pagerduty_event_orchestration" "by_name" { name = pagerduty_event_orchestration.test.name } `, name) -} \ No newline at end of file +} diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 99389e3ee..1ccccde03 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -41,11 +41,11 @@ func resourcePagerDutyEventOrchestration() *schema.Resource { }, }, "routes": { - Type: schema.TypeInt, + Type: schema.TypeInt, Computed: true, }, "integrations": { - Type: schema.TypeList, + Type: schema.TypeList, Computed: true, Optional: true, // Tests keep failing if "Optional: true" is not provided Elem: &schema.Resource{ @@ -207,7 +207,7 @@ func flattenEventOrchestrationIntegrations(eoi []*pagerduty.EventOrchestrationIn for _, i := range eoi { integration := map[string]interface{}{ - "id": i.ID, + "id": i.ID, "parameters": flattenEventOrchestrationIntegrationParameters(i.Parameters), } result = append(result, integration) @@ -218,7 +218,7 @@ func flattenEventOrchestrationIntegrations(eoi []*pagerduty.EventOrchestrationIn func flattenEventOrchestrationIntegrationParameters(p *pagerduty.EventOrchestrationIntegrationParameters) []interface{} { result := map[string]interface{}{ "routing_key": p.RoutingKey, - "type": p.Type, + "type": p.Type, } return []interface{}{result} @@ -228,12 +228,12 @@ func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrches d.Set("name", o.Name) d.Set("description", o.Description) d.Set("routes", o.Routes) - + if o.Team != nil { d.Set("team", flattenEventOrchestrationTeam(o.Team)) } - if len(o.Integrations) > 0 { + if len(o.Integrations) > 0 { d.Set("integrations", flattenEventOrchestrationIntegrations(o.Integrations)) } From b253c9660b957bd0243c940526dfafdc2b012f1d Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 6 May 2022 14:30:16 -0400 Subject: [PATCH 12/51] Add import tests --- ...port_pagerduty_event_orchestration_test.go | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 pagerduty/import_pagerduty_event_orchestration_test.go diff --git a/pagerduty/import_pagerduty_event_orchestration_test.go b/pagerduty/import_pagerduty_event_orchestration_test.go new file mode 100644 index 000000000..f3741eaa8 --- /dev/null +++ b/pagerduty/import_pagerduty_event_orchestration_test.go @@ -0,0 +1,52 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccPagerDutyEventOrchestration_import(t *testing.T) { + name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) + teamName := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, teamName), + }, + { + ResourceName: "pagerduty_event_orchestration.foo", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccPagerDutyEventOrchestrationNameOnly_import(t *testing.T) { + name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationConfigNameOnly(name), + }, + + { + ResourceName: "pagerduty_event_orchestration.nameonly", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} From cf4c9d8f7bc0ced80597b675c2a6b8c961d65f99 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 6 May 2022 14:50:13 -0400 Subject: [PATCH 13/51] update to latest alenapan/go-pagerduty --- go.mod | 1 + .../pagerduty/event_orchestration_path.go | 146 ++++++++++++++++++ .../go-pagerduty/pagerduty/pagerduty.go | 2 + 3 files changed, 149 insertions(+) create mode 100644 vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go diff --git a/go.mod b/go.mod index 76857bf54..ac8e1700a 100644 --- a/go.mod +++ b/go.mod @@ -12,4 +12,5 @@ require ( google.golang.org/grpc v1.33.2 // indirect ) +// providing a relative path as "../../alenapan/go-pagerduty" doesn't work for some reason, leaving the path as is for now replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go new file mode 100644 index 000000000..e99c9e0bb --- /dev/null +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go @@ -0,0 +1,146 @@ +package pagerduty + +import ( + "fmt" +) + +// TODO: Check omitempty for all structs +type EventOrchestrationPathService service + +type EventOrchestrationPath struct { + Type string `json:"type,omitempty"` + Self string `json:"self,omitempty"` + Parent *EventOrchestrationPathReference `json:"parent,omitempty"` + Sets []*EventOrchestrationPathSet `json:"sets,omitempty"` + CatchAll *EventOrchestrationPathCatchAll `json:"catch_all,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + CreatedBy *EventOrchestrationPathReference `json:"created_by,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + UpdatedBy *EventOrchestrationPathReference `json:"updated_by,omitempty"` + Version string `json:"version,omitempty"` +} + +// A reference to a related object (e.g. an EventOrchestration, User, Team, etc) +type EventOrchestrationPathReference struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Self string `json:"self,omitempty"` +} + +type EventOrchestrationPathSet struct { + ID string `json:"id,omitempty"` + Rules []*EventOrchestrationPathRule `json:"rules,omitempty"` +} + +type EventOrchestrationPathRule struct { + ID string `json:"id,omitempty"` + Label string `json:"label,omitempty"` + Conditions []*EventOrchestrationPathRuleCondition `json:"conditions,omitempty"` + Actions *EventOrchestrationPathRuleActions `json:"actions,omitempty"` + Disabled bool `json:"disabled,omitempty"` +} + +type EventOrchestrationPathRuleCondition struct { + // A PCL string: https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview + Expression string `json:"expression,omitempty"` +} + +// See the full list of supported actions for path types: +// Router: https://developer.pagerduty.com/api-reference/f0fae270c70b3-get-the-router-for-a-global-event-orchestration +// Service: https://developer.pagerduty.com/api-reference/179537b835e2d-get-the-service-orchestration-for-a-service +// Unrouted: https://developer.pagerduty.com/api-reference/70aa1139e1013-get-the-unrouted-orchestration-for-a-global-event-orchestration +type EventOrchestrationPathRuleActions struct { + RouteTo string `json:"route_to,omitempty"` + Suppress bool `json:"suppress,omitempty"` + Suspend int `json:"suspend,omitempty"` + Priority string `json:"priority,omitempty"` + Annotate string `json:"annotate,omitempty"` + PagerdutyAutomationActions []*EventOrchestrationPathPagerdutyAutomationAction `json:"pagerduty_automation_actions,omitempty"` + AutomationActions []*EventOrchestrationPathAutomationAction `json:"automation_actions,omitempty"` + Severity string `json:"severity,omitempty"` + EventAction string `json:"event_action,omitempty"` + Variables []*EventOrchestrationPathActionVariables `json:"variables,omitempty"` + Extractions []*EventOrchestrationPathActionExtractions `json:"extractions,omitempty"` +} + +type EventOrchestrationPathPagerdutyAutomationAction struct { + ActionId string `json:"action_id,omitempty"` +} + +type EventOrchestrationPathAutomationAction struct { + Name string `json:"name,omitempty"` + Url string `json:"url,omitempty"` + AutoSend bool `json:"auto_send,omitempty"` + Headers []*EventOrchestrationPathAutomationActionObject `json:"headers,omitempty"` + Parameters []*EventOrchestrationPathAutomationActionObject `json:"parameters,omitempty"` +} + +type EventOrchestrationPathAutomationActionObject struct { + Key string `json:"key,omitempty"` + Value string `json:"value,omitempty"` +} + +type EventOrchestrationPathActionVariables struct { + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` + Type string `json:"type,omitempty"` + Value string `json:"value,omitempty"` +} + +type EventOrchestrationPathActionExtractions struct { + Target string `json:"target,omitempty"` + Template string `json:"template,omitempty"` +} + +type EventOrchestrationPathCatchAll struct { + Actions *EventOrchestrationPathRuleActions `json:"actions,omitempty"` +} + +type EventOrchestrationPathPayload struct { + OrchestrationPath *EventOrchestrationPath `json:"orchestration_path,omitempty"` +} + +const PathTypeRouter string = "router" +const PathTypeService string = "service" +const PathTypeUnrouted string = "unrouted" + +func orchestrationPathUrlBuilder(id string, pathType string) string { + switch { + case pathType == PathTypeService: + return fmt.Sprintf("%s/services/%s", eventOrchestrationBaseUrl, id) + case pathType == PathTypeUnrouted: + return fmt.Sprintf("%s/%s/unrouted", eventOrchestrationBaseUrl, id) + case pathType == PathTypeRouter: + return fmt.Sprintf("%s/%s/router", eventOrchestrationBaseUrl, id) + default: + return "" + } +} + +// Get for EventOrchestrationPath +func (s *EventOrchestrationPathService) Get(id string, pathType string) (*EventOrchestrationPath, *Response, error) { + u := orchestrationPathUrlBuilder(id, pathType) + v := new(EventOrchestrationPathPayload) + + resp, err := s.client.newRequestDo("GET", u, nil, nil, &v) + + if err != nil { + return nil, nil, err + } + + return v.OrchestrationPath, resp, nil +} + +// Update for EventOrchestrationPath +func (s *EventOrchestrationPathService) Update(id string, pathType string, orchestration_path *EventOrchestrationPath) (*EventOrchestrationPath, *Response, error) { + u := orchestrationPathUrlBuilder(id, pathType) + v := new(EventOrchestrationPathPayload) + p := EventOrchestrationPathPayload{OrchestrationPath: orchestration_path} + + resp, err := s.client.newRequestDo("PUT", u, nil, p, &v) + if err != nil { + return nil, nil, err + } + + return v.OrchestrationPath, resp, nil +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go index 0feb0db13..f25b916d7 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go @@ -42,6 +42,7 @@ type Client struct { MaintenanceWindows *MaintenanceWindowService Rulesets *RulesetService EventOrchestrations *EventOrchestrationService + EventOrchestrationPaths *EventOrchestrationPathService Schedules *ScheduleService Services *ServicesService Teams *TeamService @@ -101,6 +102,7 @@ func NewClient(config *Config) (*Client, error) { c.MaintenanceWindows = &MaintenanceWindowService{c} c.Rulesets = &RulesetService{c} c.EventOrchestrations = &EventOrchestrationService{c} + c.EventOrchestrationPaths = &EventOrchestrationPathService{c} c.Schedules = &ScheduleService{c} c.Services = &ServicesService{c} c.Teams = &TeamService{c} From 37c010778752943573ebfd80f004af4f7a0fa0de Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 6 May 2022 15:40:19 -0400 Subject: [PATCH 14/51] add team checks to the tests --- ...port_pagerduty_event_orchestration_test.go | 5 +- ...urce_pagerduty_event_orchestration_test.go | 50 +++++++++++++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/pagerduty/import_pagerduty_event_orchestration_test.go b/pagerduty/import_pagerduty_event_orchestration_test.go index f3741eaa8..3cd60b35f 100644 --- a/pagerduty/import_pagerduty_event_orchestration_test.go +++ b/pagerduty/import_pagerduty_event_orchestration_test.go @@ -11,7 +11,8 @@ import ( func TestAccPagerDutyEventOrchestration_import(t *testing.T) { name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) - teamName := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) + team1 := fmt.Sprintf("tf-team1-%s", acctest.RandString(5)) + team2 := fmt.Sprintf("tf-team2-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -19,7 +20,7 @@ func TestAccPagerDutyEventOrchestration_import(t *testing.T) { CheckDestroy: testAccCheckPagerDutyEventOrchestrationDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, teamName), + Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, team1, team2), }, { ResourceName: "pagerduty_event_orchestration.foo", diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index cfc24442f..a807b7fce 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -49,10 +49,10 @@ func testSweepEventOrchestration(region string) error { func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) - teamName := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) nameUpdated := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) descriptionUpdated := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) - teamNameUpdated := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) + team1 := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) + team2 := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -68,7 +68,7 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, teamName), + Config: testAccCheckPagerDutyEventOrchestrationConfig(name, description, team1, team2), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), resource.TestCheckResourceAttr( @@ -77,10 +77,11 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { resource.TestCheckResourceAttr( "pagerduty_event_orchestration.foo", "description", description, ), + testAccCheckPagerDutyEventOrchestrationTeamMatch("pagerduty_event_orchestration.foo", "pagerduty_team.foo"), ), }, { - Config: testAccCheckPagerDutyEventOrchestrationConfigUpdated(nameUpdated, descriptionUpdated, teamNameUpdated), + Config: testAccCheckPagerDutyEventOrchestrationConfigUpdated(nameUpdated, descriptionUpdated, team1, team2), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), resource.TestCheckResourceAttr( @@ -89,6 +90,7 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { resource.TestCheckResourceAttr( "pagerduty_event_orchestration.foo", "description", descriptionUpdated, ), + testAccCheckPagerDutyEventOrchestrationTeamMatch("pagerduty_event_orchestration.foo", "pagerduty_team.bar"), ), }, }, @@ -131,12 +133,39 @@ func testAccCheckPagerDutyEventOrchestrationExists(rn string) resource.TestCheck } } -func testAccCheckPagerDutyEventOrchestrationConfig(name, description, team string) string { +func testAccCheckPagerDutyEventOrchestrationTeamMatch(orchName, teamName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + o, orchOk := s.RootModule().Resources[orchName] + + if !orchOk { + return fmt.Errorf("Not found: %s", orchName) + } + + t, tOk := s.RootModule().Resources[teamName] + if !tOk { + return fmt.Errorf("Not found: %s", teamName) + } + + var otId = o.Primary.Attributes["team.0.id"] + var tId = t.Primary.Attributes["id"] + + if otId != tId { + return fmt.Errorf("Event Orchestration team ID (%v) not matching provided team ID: %v", otId, tId) + } + + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationConfig(name, description, team1, team2 string) string { return fmt.Sprintf(` resource "pagerduty_team" "foo" { name = "%s" } +resource "pagerduty_team" "bar" { + name = "%s" +} resource "pagerduty_event_orchestration" "foo" { name = "%s" description = "%s" @@ -144,7 +173,7 @@ resource "pagerduty_event_orchestration" "foo" { id = pagerduty_team.foo.id } } -`, team, name, description) +`, team1, team2, name, description) } func testAccCheckPagerDutyEventOrchestrationConfigNameOnly(n string) string { @@ -156,18 +185,21 @@ resource "pagerduty_event_orchestration" "nameonly" { `, n) } -func testAccCheckPagerDutyEventOrchestrationConfigUpdated(name, description, team string) string { +func testAccCheckPagerDutyEventOrchestrationConfigUpdated(name, description, team1, team2 string) string { return fmt.Sprintf(` resource "pagerduty_team" "foo" { name = "%s" } +resource "pagerduty_team" "bar" { + name = "%s" +} resource "pagerduty_event_orchestration" "foo" { name = "%s" description = "%s" team { - id = pagerduty_team.foo.id + id = pagerduty_team.bar.id } } -`, team, name, description) +`, team1, team2, name, description) } From e25a2f3ff9af8d1e2c5e61227a938a7e2c559435 Mon Sep 17 00:00:00 2001 From: alenapan <47909261+alenapan@users.noreply.github.com> Date: Tue, 10 May 2022 17:06:57 -0400 Subject: [PATCH 15/51] [ORCA-3475] Allow deleting event orchestration team from an orchestration (#494) * support unsetting orch team * add retry logic to the event orchestration update method --- ...port_pagerduty_event_orchestration_test.go | 2 +- .../resource_pagerduty_event_orchestration.go | 22 ++++++- ...urce_pagerduty_event_orchestration_test.go | 59 +++++++++++++++---- .../pagerduty/event_orchestration.go | 6 +- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/pagerduty/import_pagerduty_event_orchestration_test.go b/pagerduty/import_pagerduty_event_orchestration_test.go index 3cd60b35f..d6b7c8d14 100644 --- a/pagerduty/import_pagerduty_event_orchestration_test.go +++ b/pagerduty/import_pagerduty_event_orchestration_test.go @@ -44,7 +44,7 @@ func TestAccPagerDutyEventOrchestrationNameOnly_import(t *testing.T) { }, { - ResourceName: "pagerduty_event_orchestration.nameonly", + ResourceName: "pagerduty_event_orchestration.foo", ImportState: true, ImportStateVerify: true, }, diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 1ccccde03..75f0de9ba 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -88,6 +88,11 @@ func buildEventOrchestrationStruct(d *schema.ResourceData) *pagerduty.EventOrche if attr, ok := d.GetOk("team"); ok { orchestration.Team = expandOrchestrationTeam(attr) + } else { + var tId *string + orchestration.Team = &pagerduty.EventOrchestrationObject{ + ID: tId, + } } return orchestration @@ -97,7 +102,7 @@ func expandOrchestrationTeam(v interface{}) *pagerduty.EventOrchestrationObject var team *pagerduty.EventOrchestrationObject t := v.([]interface{})[0].(map[string]interface{}) team = &pagerduty.EventOrchestrationObject{ - ID: t["id"].(string), + ID: stringTypeToStringPtr(t["id"].(string)), } return team @@ -171,8 +176,19 @@ func resourcePagerDutyEventOrchestrationUpdate(d *schema.ResourceData, meta inte log.Printf("[INFO] Updating PagerDuty Event Orchestration: %s", d.Id()) - if _, _, err := client.EventOrchestrations.Update(d.Id(), orchestration); err != nil { - return err + retryErr := resource.Retry(10*time.Second, func() *resource.RetryError { + if _, _, err := client.EventOrchestrations.Update(d.Id(), orchestration); err != nil { + if isErrCode(err, 400) || isErrCode(err, 429) { + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + + return nil + }) + + if retryErr != nil { + return retryErr } return nil diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index a807b7fce..afbdf0979 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -62,9 +62,16 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { { Config: testAccCheckPagerDutyEventOrchestrationConfigNameOnly(name), Check: resource.ComposeTestCheckFunc( - testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.nameonly"), + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "name", name, + ), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration.nameonly", "name", name), + "pagerduty_event_orchestration.foo", "description", "", + ), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "team.#", "0", + ), ), }, { @@ -93,6 +100,21 @@ func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { testAccCheckPagerDutyEventOrchestrationTeamMatch("pagerduty_event_orchestration.foo", "pagerduty_team.bar"), ), }, + { + Config: testAccCheckPagerDutyEventOrchestrationConfigDescriptionTeamDeleted(nameUpdated, team1, team2), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationExists("pagerduty_event_orchestration.foo"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "name", nameUpdated, + ), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "description", "", + ), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration.foo", "team.#", "0", + ), + ), + }, }, }) } @@ -157,6 +179,15 @@ func testAccCheckPagerDutyEventOrchestrationTeamMatch(orchName, teamName string) } } +func testAccCheckPagerDutyEventOrchestrationConfigNameOnly(n string) string { + return fmt.Sprintf(` + +resource "pagerduty_event_orchestration" "foo" { + name = "%s" +} +`, n) +} + func testAccCheckPagerDutyEventOrchestrationConfig(name, description, team1, team2 string) string { return fmt.Sprintf(` @@ -176,15 +207,6 @@ resource "pagerduty_event_orchestration" "foo" { `, team1, team2, name, description) } -func testAccCheckPagerDutyEventOrchestrationConfigNameOnly(n string) string { - return fmt.Sprintf(` - -resource "pagerduty_event_orchestration" "nameonly" { - name = "%s" -} -`, n) -} - func testAccCheckPagerDutyEventOrchestrationConfigUpdated(name, description, team1, team2 string) string { return fmt.Sprintf(` @@ -203,3 +225,18 @@ resource "pagerduty_event_orchestration" "foo" { } `, team1, team2, name, description) } + +func testAccCheckPagerDutyEventOrchestrationConfigDescriptionTeamDeleted(name, team1, team2 string) string { + return fmt.Sprintf(` + +resource "pagerduty_team" "foo" { + name = "%s" +} +resource "pagerduty_team" "bar" { + name = "%s" +} +resource "pagerduty_event_orchestration" "foo" { + name = "%s" +} +`, team1, team2, name) +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go index 90c7eb6d2..38c1ad0fa 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go @@ -10,15 +10,15 @@ type EventOrchestration struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description"` - Team *EventOrchestrationObject `json:"team,omitempty"` + Team *EventOrchestrationObject `json:"team"` Routes int `json:"routes,omitempty"` Integrations []*EventOrchestrationIntegration `json:"integrations,omitempty"` // TODO: figure out if we need Updater, Creator / updated_by, created_by, updated_at, created_at, version } type EventOrchestrationObject struct { - Type string `json:"type,omitempty"` - ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + ID *string `json:"id"` } type EventOrchestrationIntegrationParameters struct { From 735f4015d126f74e7f8aaa402e548dd160383d42 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 12 May 2022 16:34:52 -0400 Subject: [PATCH 16/51] [ORCA-3463] Orchestration Path Router Resource (#493) * router path * Add support for parent * refactor * update handler and actions support * support conditions * move conditions to util * move parent to util * test for multiple rules and conditions * actions and catchall * refactor tests * validateFunc * refactor * undo local vendor module path change * rules schema change and test * PR comments addressed --- pagerduty/event_orchestration_path_util.go | 27 ++ pagerduty/provider.go | 1 + ...gerduty_event_orchestration_path_router.go | 391 +++++++++++++++ ...ty_event_orchestration_path_router_test.go | 459 ++++++++++++++++++ 4 files changed, 878 insertions(+) create mode 100644 pagerduty/event_orchestration_path_util.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_router.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_router_test.go diff --git a/pagerduty/event_orchestration_path_util.go b/pagerduty/event_orchestration_path_util.go new file mode 100644 index 000000000..54746b226 --- /dev/null +++ b/pagerduty/event_orchestration_path_util.go @@ -0,0 +1,27 @@ +package pagerduty + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var PagerDutyEventOrchestrationPathParent = map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "self": { + Type: schema.TypeString, + Computed: true, + }, +} + +var PagerDutyEventOrchestrationPathConditions = map[string]*schema.Schema{ + "expression": { + Type: schema.TypeString, + Required: true, + }, +} diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 0c0456bec..9ce2a67df 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -89,6 +89,7 @@ func Provider() *schema.Provider { "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), "pagerduty_event_orchestration": resourcePagerDutyEventOrchestration(), + "pagerduty_event_orchestration_router": resourcePagerDutyEventOrchestrationPathRouter(), }, } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go new file mode 100644 index 000000000..05ba206ac --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -0,0 +1,391 @@ +package pagerduty + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" + "log" + "time" +) + +func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { + return &schema.Resource{ + Read: resourcePagerDutyEventOrchestrationPathRouterRead, + Create: resourcePagerDutyEventOrchestrationPathRouterCreate, + Update: resourcePagerDutyEventOrchestrationPathRouterUpdate, + Delete: resourcePagerDutyEventOrchestrationPathRouterDelete, + Importer: &schema.ResourceImporter{ + State: resourcePagerDutyEventOrchestrationPathRouterImport, + }, + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + }, + "parent": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathParent, + }, + }, + "sets": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, // Router can only have 'start' set + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "rules": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "label": { + Type: schema.TypeString, + Optional: true, + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathConditions, + }, + }, + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, //there can only be one action for router + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_to": { + Type: schema.TypeString, + Required: true, + ValidateFunc: func(v interface{}, key string) (warns []string, errs []error) { + value := v.(string) + if value == "unrouted" { + errs = append(errs, fmt.Errorf("route_to within a set's rule has to be a Service ID. Got: %q", v)) + } + return + }, + }, + }, + }, + }, + "disabled": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "catch_all": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_to": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourcePagerDutyEventOrchestrationPathRouterRead(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + return resource.Retry(2*time.Minute, func() *resource.RetryError { + log.Printf("[INFO] Reading PagerDuty Event Orchestration Path of type %s for orchestration: %s", "router", d.Id()) + + if routerPath, _, err := client.EventOrchestrationPaths.Get(d.Id(), "router"); err != nil { + time.Sleep(2 * time.Second) + return resource.RetryableError(err) + } else if routerPath != nil { + + if routerPath.Sets != nil { + d.Set("sets", flattenSets(routerPath.Sets)) + } + + if routerPath.CatchAll != nil { + d.Set("catch_all", flattenCatchAll(routerPath.CatchAll)) + } + } + return nil + }) + +} + +// EventOrchestrationPath cannot be created, use update to add / edit / remove rules and sets +func resourcePagerDutyEventOrchestrationPathRouterCreate(d *schema.ResourceData, meta interface{}) error { + return resourcePagerDutyEventOrchestrationPathRouterUpdate(d, meta) +} + +func resourcePagerDutyEventOrchestrationPathRouterDelete(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} + +func resourcePagerDutyEventOrchestrationPathRouterUpdate(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + updatePath := buildRouterPathStructForUpdate(d) + + log.Printf("[INFO] Updating PagerDuty Event Orchestration Path of type %s for orchestration: %s", "router", updatePath.Parent.ID) + + return performRouterPathUpdate(d, updatePath, client) +} + +func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.EventOrchestrationPath, client *pagerduty.Client) error { + retryErr := resource.Retry(30*time.Second, func() *resource.RetryError { + updatedPath, _, err := client.EventOrchestrationPaths.Update(routerPath.Parent.ID, "router", routerPath) + if err != nil { + return resource.RetryableError(err) + } + if updatedPath == nil { + return resource.NonRetryableError(fmt.Errorf("No Event Orchestration Router found.")) + } + // set props + d.SetId(routerPath.Parent.ID) + if routerPath.Sets != nil { + d.Set("sets", flattenSets(routerPath.Sets)) + } + if updatedPath.CatchAll != nil { + d.Set("catch_all", flattenCatchAll(updatedPath.CatchAll)) + } + return nil + }) + if retryErr != nil { + time.Sleep(2 * time.Second) + return retryErr + } + return nil +} + +func buildRouterPathParent(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { + orchPath := &pagerduty.EventOrchestrationPath{} + + if attr, ok := d.GetOk("parent"); ok { + orchPath.Parent = expandOrchestrationPathParent(attr) + } + + return orchPath +} + +func buildRouterPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { + + orchPath := buildRouterPathParent(d) + + if attr, ok := d.GetOk("parent"); ok { + orchPath.Parent = expandOrchestrationPathParent(attr) + } + + if attr, ok := d.GetOk("sets"); ok { + orchPath.Sets = expandSets(attr) + } + + if attr, ok := d.GetOk("catch_all"); ok { + orchPath.CatchAll = expandCatchAll(attr) + } + + return orchPath +} + +func expandOrchestrationPathParent(v interface{}) *pagerduty.EventOrchestrationPathReference { + var parent *pagerduty.EventOrchestrationPathReference + p := v.([]interface{})[0].(map[string]interface{}) + parent = &pagerduty.EventOrchestrationPathReference{ + ID: p["id"].(string), + } + + return parent +} + +func expandSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { + var sets []*pagerduty.EventOrchestrationPathSet + + for _, set := range v.([]interface{}) { + s := set.(map[string]interface{}) + + orchPathSet := &pagerduty.EventOrchestrationPathSet{ + ID: s["id"].(string), + Rules: expandRules(s["rules"].(interface{})), + } + + sets = append(sets, orchPathSet) + } + + return sets +} + +func expandRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { + items := v.([]interface{}) + rules := []*pagerduty.EventOrchestrationPathRule{} + + for _, rule := range items { + r := rule.(map[string]interface{}) + + ruleInSet := &pagerduty.EventOrchestrationPathRule{ + ID: r["id"].(string), + Label: r["label"].(string), + Disabled: r["disabled"].(bool), + Conditions: expandRouterConditions(r["conditions"].(interface{})), + Actions: expandRouterActions(r["actions"].([]interface{})), + } + + rules = append(rules, ruleInSet) + } + return rules +} + +func expandRouterConditions(v interface{}) []*pagerduty.EventOrchestrationPathRuleCondition { + items := v.([]interface{}) + conditions := []*pagerduty.EventOrchestrationPathRuleCondition{} + + for _, cond := range items { + c := cond.(map[string]interface{}) + + cx := &pagerduty.EventOrchestrationPathRuleCondition{ + Expression: c["expression"].(string), + } + + conditions = append(conditions, cx) + } + + return conditions +} + +func expandRouterActions(v interface{}) *pagerduty.EventOrchestrationPathRuleActions { + var actions = new(pagerduty.EventOrchestrationPathRuleActions) + for _, ai := range v.([]interface{}) { + am := ai.(map[string]interface{}) + actions.RouteTo = am["route_to"].(string) + } + + return actions +} + +func expandCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { + var catchAll = new(pagerduty.EventOrchestrationPathCatchAll) + + for _, ca := range v.([]interface{}) { + am := ca.(map[string]interface{}) + catchAll.Actions = expandRouterActions(am["actions"].(interface{})) + } + + return catchAll +} + +func flattenSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interface{} { + var flattenedSets []interface{} + for _, set := range orchPathSets { + flattenedSet := map[string]interface{}{ + "id": set.ID, + "rules": flattenRules(set.Rules), + } + flattenedSets = append(flattenedSets, flattenedSet) + } + return flattenedSets +} + +func flattenRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { + var flattenedRules []interface{} + + if rules != nil { + for _, rule := range rules { + flattenedRule := map[string]interface{}{ + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "conditions": flattenRouterConditions(rule.Conditions), + "actions": flattenRouterActions(rule.Actions), + } + flattenedRules = append(flattenedRules, flattenedRule) + } + } + + return flattenedRules +} + +func flattenRouterConditions(conditions []*pagerduty.EventOrchestrationPathRuleCondition) []interface{} { + var flattendConditions []interface{} + + for _, condition := range conditions { + flattendCondition := map[string]interface{}{ + "expression": condition.Expression, + } + flattendConditions = append(flattendConditions, flattendCondition) + } + + return flattendConditions +} + +func flattenRouterActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { + var actionsMap []map[string]interface{} + + am := make(map[string]interface{}) + am["route_to"] = actions.RouteTo + actionsMap = append(actionsMap, am) + return actionsMap +} + +func flattenCatchAll(catchAll *pagerduty.EventOrchestrationPathCatchAll) []map[string]interface{} { + var caMap []map[string]interface{} + + c := make(map[string]interface{}) + + c["actions"] = flattenRouterActions(catchAll.Actions) + caMap = append(caMap, c) + + return caMap +} + +func resourcePagerDutyEventOrchestrationPathRouterImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client, err := meta.(*Config).Client() + if err != nil { + return []*schema.ResourceData{}, err + } + // given an orchestration ID import the router orchestration path + orchestrationID := d.Id() + pathType := "router" + _, _, err = client.EventOrchestrationPaths.Get(orchestrationID, pathType) + + if err != nil { + return []*schema.ResourceData{}, err + } + + d.SetId(orchestrationID) + + return []*schema.ResourceData{d}, nil +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go new file mode 100644 index 000000000..51e33c070 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -0,0 +1,459 @@ +package pagerduty + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "testing" +) + +func init() { + resource.AddTestSweepers("pagerduty_event_orchestration_router", &resource.Sweeper{ + Name: "router", + Dependencies: []string{ + "pagerduty_schedule", + "pagerduty_team", + "pagerduty_user", + "pagerduty_escalation_policy", + "pagerduty_service", + "pagerduty_event_orchestration", + }, + }) +} + +func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { + team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + escalation_policy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationRouterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "type", "router"), + testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( + "pagerduty_event_orchestration_router.router", "unrouted", true), //test for catch_all route_to prop, by default it should be unrouted + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "0"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfig(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "type", "router"), + testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( + "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", false), // test for rule action route_to + testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( + "pagerduty_event_orchestration_router.router", "unrouted", true), //test for catch_all route_to prop, by default it should be unrouted + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'database'"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'database'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.1.conditions.0.expression", "event.severity matches part 'critical'"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "1"), + testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( + "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", true), //test for catch_all routing to service if provided + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "1"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.#", "0"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "0"), + testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( + "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", true), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(team, escalation_policy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationRouterNotExists("pagerduty_event_orchestration_router.router"), + ), + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationRouterDestroy(s *terraform.State) error { + client, _ := testAccProvider.Meta().(*Config).Client() + for _, r := range s.RootModule().Resources { + if r.Type != "pagerduty_event_orchestration_path_router" { + continue + } + + orch, _ := s.RootModule().Resources["pagerduty_event_orchestration.orch"] + + if _, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "router"); err == nil { + return fmt.Errorf("Event Orchestration Path still exists") + } + } + return nil +} + +func testAccCheckPagerDutyEventOrchestrationRouterExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[rn] + if !ok { + return fmt.Errorf("Not found: %s", rn) + } + if rs.Primary.ID == "" { + return fmt.Errorf("No Event Orchestration Path Type is set") + } + + orch, _ := s.RootModule().Resources["pagerduty_event_orchestration.orch"] + client, _ := testAccProvider.Meta().(*Config).Client() + found, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "router") + + if err != nil { + return fmt.Errorf("Orchestration Path type not found: %v for orchestration %v", "router", orch.Primary.ID) + } + if found.Type != "router" { + return fmt.Errorf("Event Orchrestration path not found: %v - %v", "router", found) + } + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationRouterNotExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[rn] + if ok { + return fmt.Errorf("Event Orchestration Router Path is not deleted: %s", rn) + } + + return nil + } +} + +func createBaseConfig(t, ep, s, o string) string { + return fmt.Sprintf(` + resource "pagerduty_team" "foo" { + name = "%s" + } + + resource "pagerduty_user" "foo" { + name = "tf-user" + email = "user@pagerduty.com" + color = "green" + role = "user" + job_title = "foo" + description = "foo" + } + + resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } + } + + resource "pagerduty_service" "bar" { + name = "%s" + escalation_policy = pagerduty_escalation_policy.foo.id + + incident_urgency_rule { + type = "constant" + urgency = "high" + } + } + + resource "pagerduty_event_orchestration" "orch" { + name = "%s" + team { + id = pagerduty_team.foo.id + } + } + `, t, ep, s, o) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfig(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + ` +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.summary matches part 'database'" + } + } + } +} +`) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(t, ep, s, o string) string { + return fmt.Sprintf( + "%s%s", createBaseConfig(t, ep, s, o), + ` +resource "pagerduty_service" "bar2" { + name = "tf-barService2" + escalation_policy = pagerduty_escalation_policy.foo.id + + incident_urgency_rule { + type = "constant" + urgency = "high" + } +} + +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.summary matches part 'database'" + } + conditions { + expression = "event.severity matches part 'critical'" + } + } + + rules { + disabled = false + label = "rule2 label" + actions { + route_to = pagerduty_service.bar2.id + } + conditions { + expression = "event.severity matches part 'critical'" + } + } + } +} +`) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + ` +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = pagerduty_service.bar.id + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + } + } +} +`) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + ` +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = pagerduty_service.bar.id + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.severity matches part 'critical'" + } + } + } +} +`) +} + +func testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), + ` +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.orch.id + } + catch_all { + actions { + route_to = pagerduty_service.bar.id + } + } + sets { + id = "start" + } +} +`) +} +func testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(t, ep, s, o string) string { + return fmt.Sprintf(createBaseConfig(t, ep, s, o)) +} +func testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(router, service string, catchAll bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + r, rOk := s.RootModule().Resources[router] + if !rOk { + return fmt.Errorf("Not found: %s", router) + } + + var rRouteToId = "" + if catchAll == true { + rRouteToId = r.Primary.Attributes["catch_all.0.actions.0.route_to"] + } else { + rRouteToId = r.Primary.Attributes["sets.0.rules.0.actions.0.route_to"] + } + + var sId = "" + if service == "unrouted" { + sId = "unrouted" + } else { + svc, sOk := s.RootModule().Resources[service] + if !sOk { + return fmt.Errorf("Not found: %s", service) + } + sId = svc.Primary.Attributes["id"] + } + + if rRouteToId != sId { + return fmt.Errorf("Event Orchestration Router Route to Service ID (%v) not matching provided service ID: %v", rRouteToId, sId) + } + + return nil + } +} From bdf67f212b422474415a629871bc438292f9433e Mon Sep 17 00:00:00 2001 From: Alex Zakabluk Date: Fri, 13 May 2022 14:53:23 -0400 Subject: [PATCH 17/51] Event orchestration unrouted resource (#495) * Init commit for unrouted * Added tests for unrouted * Added catch_all to unrouted schema * Tweaked catch_all * Merge event-orchestrations * Add testacc for unrouted * Added full config test for unrouted * Add test for number of extractions and variables * Cleaned router and added new test checks to unrouted * Change escalation_policy from snake case to camel case --- pagerduty/provider.go | 56 +- ...gerduty_event_orchestration_path_router.go | 27 +- ...ty_event_orchestration_path_router_test.go | 23 +- ...rduty_event_orchestration_path_unrouted.go | 617 ++++++++++++++++++ ..._event_orchestration_path_unrouted_test.go | 477 ++++++++++++++ 5 files changed, 1147 insertions(+), 53 deletions(-) create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 9ce2a67df..432cd6662 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -63,34 +63,34 @@ func Provider() *schema.Provider { }, ResourcesMap: map[string]*schema.Resource{ - "pagerduty_addon": resourcePagerDutyAddon(), - "pagerduty_escalation_policy": resourcePagerDutyEscalationPolicy(), - "pagerduty_maintenance_window": resourcePagerDutyMaintenanceWindow(), - "pagerduty_schedule": resourcePagerDutySchedule(), - "pagerduty_service": resourcePagerDutyService(), - "pagerduty_service_integration": resourcePagerDutyServiceIntegration(), - "pagerduty_team": resourcePagerDutyTeam(), - "pagerduty_team_membership": resourcePagerDutyTeamMembership(), - "pagerduty_user": resourcePagerDutyUser(), - "pagerduty_user_contact_method": resourcePagerDutyUserContactMethod(), - "pagerduty_user_notification_rule": resourcePagerDutyUserNotificationRule(), - "pagerduty_extension": resourcePagerDutyExtension(), - "pagerduty_extension_servicenow": resourcePagerDutyExtensionServiceNow(), - "pagerduty_event_rule": resourcePagerDutyEventRule(), - "pagerduty_ruleset": resourcePagerDutyRuleset(), - "pagerduty_ruleset_rule": resourcePagerDutyRulesetRule(), - "pagerduty_business_service": resourcePagerDutyBusinessService(), - "pagerduty_service_dependency": resourcePagerDutyServiceDependency(), - "pagerduty_response_play": resourcePagerDutyResponsePlay(), - "pagerduty_tag": resourcePagerDutyTag(), - "pagerduty_tag_assignment": resourcePagerDutyTagAssignment(), - "pagerduty_service_event_rule": resourcePagerDutyServiceEventRule(), - "pagerduty_slack_connection": resourcePagerDutySlackConnection(), - "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), - "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), - "pagerduty_event_orchestration": resourcePagerDutyEventOrchestration(), - "pagerduty_event_orchestration_router": resourcePagerDutyEventOrchestrationPathRouter(), - }, + "pagerduty_addon": resourcePagerDutyAddon(), + "pagerduty_escalation_policy": resourcePagerDutyEscalationPolicy(), + "pagerduty_maintenance_window": resourcePagerDutyMaintenanceWindow(), + "pagerduty_schedule": resourcePagerDutySchedule(), + "pagerduty_service": resourcePagerDutyService(), + "pagerduty_service_integration": resourcePagerDutyServiceIntegration(), + "pagerduty_team": resourcePagerDutyTeam(), + "pagerduty_team_membership": resourcePagerDutyTeamMembership(), + "pagerduty_user": resourcePagerDutyUser(), + "pagerduty_user_contact_method": resourcePagerDutyUserContactMethod(), + "pagerduty_user_notification_rule": resourcePagerDutyUserNotificationRule(), + "pagerduty_extension": resourcePagerDutyExtension(), + "pagerduty_extension_servicenow": resourcePagerDutyExtensionServiceNow(), + "pagerduty_event_rule": resourcePagerDutyEventRule(), + "pagerduty_ruleset": resourcePagerDutyRuleset(), + "pagerduty_ruleset_rule": resourcePagerDutyRulesetRule(), + "pagerduty_business_service": resourcePagerDutyBusinessService(), + "pagerduty_service_dependency": resourcePagerDutyServiceDependency(), + "pagerduty_response_play": resourcePagerDutyResponsePlay(), + "pagerduty_tag": resourcePagerDutyTag(), + "pagerduty_tag_assignment": resourcePagerDutyTagAssignment(), + "pagerduty_service_event_rule": resourcePagerDutyServiceEventRule(), + "pagerduty_slack_connection": resourcePagerDutySlackConnection(), + "pagerduty_business_service_subscriber": resourcePagerDutyBusinessServiceSubscriber(), + "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), + "pagerduty_event_orchestration": resourcePagerDutyEventOrchestration(), + "pagerduty_event_orchestration_router": resourcePagerDutyEventOrchestrationPathRouter(), + "pagerduty_event_orchestration_unrouted": resourcePagerDutyEventOrchestrationPathUnrouted()}, } p.ConfigureFunc = func(d *schema.ResourceData) (interface{}, error) { diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index 05ba206ac..db1c7235a 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -2,11 +2,12 @@ package pagerduty import ( "fmt" + "log" + "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/heimweh/go-pagerduty/pagerduty" - "log" - "time" ) func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { @@ -240,7 +241,7 @@ func expandSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { orchPathSet := &pagerduty.EventOrchestrationPathSet{ ID: s["id"].(string), - Rules: expandRules(s["rules"].(interface{})), + Rules: expandRules(s["rules"]), } sets = append(sets, orchPathSet) @@ -301,7 +302,7 @@ func expandCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { for _, ca := range v.([]interface{}) { am := ca.(map[string]interface{}) - catchAll.Actions = expandRouterActions(am["actions"].(interface{})) + catchAll.Actions = expandRouterActions(am["actions"]) } return catchAll @@ -322,17 +323,15 @@ func flattenSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interfac func flattenRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { var flattenedRules []interface{} - if rules != nil { - for _, rule := range rules { - flattenedRule := map[string]interface{}{ - "id": rule.ID, - "label": rule.Label, - "disabled": rule.Disabled, - "conditions": flattenRouterConditions(rule.Conditions), - "actions": flattenRouterActions(rule.Actions), - } - flattenedRules = append(flattenedRules, flattenedRule) + for _, rule := range rules { + flattenedRule := map[string]interface{}{ + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "conditions": flattenRouterConditions(rule.Conditions), + "actions": flattenRouterActions(rule.Actions), } + flattenedRules = append(flattenedRules, flattenedRule) } return flattenedRules diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index 51e33c070..8d0d05cc5 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -2,10 +2,11 @@ package pagerduty import ( "fmt" + "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "testing" ) func init() { @@ -24,7 +25,7 @@ func init() { func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) - escalation_policy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) service := fmt.Sprintf("tf-%s", acctest.RandString(5)) orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) @@ -34,7 +35,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { CheckDestroy: testAccCheckPagerDutyEventOrchestrationRouterDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -46,7 +47,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfig(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfig(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -58,7 +59,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -66,7 +67,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -78,7 +79,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -88,7 +89,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -98,7 +99,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( @@ -108,7 +109,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { ), }, { - Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(team, escalation_policy, service, orchestration), + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterNotExists("pagerduty_event_orchestration_router.router"), ), @@ -423,7 +424,7 @@ resource "pagerduty_event_orchestration_router" "router" { `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(t, ep, s, o string) string { - return fmt.Sprintf(createBaseConfig(t, ep, s, o)) + return createBaseConfig(t, ep, s, o) } func testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(router, service string, catchAll bool) resource.TestCheckFunc { return func(s *terraform.State) error { diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go new file mode 100644 index 000000000..9518a1c4d --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -0,0 +1,617 @@ +package pagerduty + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" +) + +func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { + return &schema.Resource{ + Read: resourcePagerDutyEventOrchestrationPathUnroutedRead, + Create: resourcePagerDutyEventOrchestrationPathUnroutedCreate, + Update: resourcePagerDutyEventOrchestrationPathUnroutedUpdate, + Delete: resourcePagerDutyEventOrchestrationPathUnroutedDelete, + Importer: &schema.ResourceImporter{ + State: resourcePagerDutyEventOrchestrationPathUnroutedImport, + }, + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + }, + "parent": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathParent, + }, + }, + "sets": { + Type: schema.TypeList, + Required: true, + MinItems: 1, // An Unrouted Orchestration must contain at least a "start" set + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "rules": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "label": { + Type: schema.TypeString, + Optional: true, + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathConditions, + }, + }, + "actions": { + Type: schema.TypeList, + Required: true, // even if there are no actions, API returns actions as an empty list + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_to": { + Type: schema.TypeString, + Optional: true, // If there is only start set we don't need route_to + }, + "severity": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "info", + "error", + "warning", + "critical", + }), + }, + "event_action": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "trigger", + "resolve", + }), + }, + "variables": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "path": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }}}, + "extractions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeString, + Required: true, + }, + "template": { + Type: schema.TypeString, + Required: true, + }, + }}, + }, + }, + }, + }, + "disabled": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "catch_all": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "suppress": { + Type: schema.TypeBool, + Computed: true, + }, + "severity": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "info", + "error", + "warning", + "critical", + }), + }, + "event_action": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "trigger", + "resolve", + }), + }, + "variables": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "path": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }}}, + "extractions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "target": { + Type: schema.TypeString, + Required: true, + }, + "template": { + Type: schema.TypeString, + Required: true, + }, + }}, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourcePagerDutyEventOrchestrationPathUnroutedRead(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + return resource.Retry(2*time.Minute, func() *resource.RetryError { + + log.Printf("[INFO] Reading PagerDuty Event Orchestration Path of type: %s for orchestration: %s", "unrouted", d.Id()) + + if unroutedPath, _, err := client.EventOrchestrationPaths.Get(d.Id(), "unrouted"); err != nil { + time.Sleep(2 * time.Second) + return resource.RetryableError(err) + } else if unroutedPath != nil { + + if unroutedPath.Sets != nil { + d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) + } + + if unroutedPath.CatchAll != nil { + d.Set("catch_all", flattenUnroutedCatchAll(unroutedPath.CatchAll)) + } + } + return nil + }) + +} + +// EventOrchestrationPath cannot be created, use update to add / edit / remove rules and sets +func resourcePagerDutyEventOrchestrationPathUnroutedCreate(d *schema.ResourceData, meta interface{}) error { + return resourcePagerDutyEventOrchestrationPathUnroutedUpdate(d, meta) +} + +// EventOrchestrationPath cannot be deleted, use update to add / edit / remove rules and sets +func resourcePagerDutyEventOrchestrationPathUnroutedDelete(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} + +func resourcePagerDutyEventOrchestrationPathUnroutedUpdate(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + updatePath := buildUnroutedPathStructForUpdate(d) + + log.Printf("[INFO] Updating PagerDuty EventOrchestrationPath of type: %s for orchestration: %s", "unrouted", updatePath.Parent.ID) + + return performUnroutedPathUpdate(d, updatePath, client) +} + +func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.EventOrchestrationPath, client *pagerduty.Client) error { + retryErr := resource.Retry(30*time.Second, func() *resource.RetryError { + updatedPath, _, err := client.EventOrchestrationPaths.Update(unroutedPath.Parent.ID, "unrouted", unroutedPath) + if err != nil { + return resource.RetryableError(err) + } + if updatedPath == nil { + return resource.NonRetryableError(fmt.Errorf("no event orchestration unrouted found")) + } + // set props + d.SetId(unroutedPath.Parent.ID) + if unroutedPath.Sets != nil { + d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) + } + if updatedPath.CatchAll != nil { + d.Set("catch_all", flattenUnroutedCatchAll(updatedPath.CatchAll)) + } + return nil + }) + if retryErr != nil { + time.Sleep(2 * time.Second) + return retryErr + } + return nil +} + +func buildUnroutedPathParent(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { + orchPath := &pagerduty.EventOrchestrationPath{} + + if attr, ok := d.GetOk("parent"); ok { + orchPath.Parent = expandOrchestrationPathUnroutedParent(attr) + } + + return orchPath +} + +func buildUnroutedPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { + + orchPath := buildUnroutedPathParent(d) + + if attr, ok := d.GetOk("parent"); ok { + orchPath.Parent = expandOrchestrationPathUnroutedParent(attr) + } + + if attr, ok := d.GetOk("sets"); ok { + orchPath.Sets = expandUnroutedSets(attr.([]interface{})) + } + + if attr, ok := d.GetOk("catch_all"); ok { + orchPath.CatchAll = expandUnroutedCatchAll(attr.([]interface{})) + } + + return orchPath +} + +func expandOrchestrationPathUnroutedParent(v interface{}) *pagerduty.EventOrchestrationPathReference { + var parent *pagerduty.EventOrchestrationPathReference + p := v.([]interface{})[0].(map[string]interface{}) + parent = &pagerduty.EventOrchestrationPathReference{ + ID: p["id"].(string), + } + + return parent +} + +func expandUnroutedSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { + var sets []*pagerduty.EventOrchestrationPathSet + + for _, set := range v.([]interface{}) { + s := set.(map[string]interface{}) + + orchPathSet := &pagerduty.EventOrchestrationPathSet{ + ID: s["id"].(string), + Rules: expandUnroutedRules(s["rules"]), + } + + sets = append(sets, orchPathSet) + } + + return sets +} + +func expandUnroutedRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { + items := v.([]interface{}) + rules := []*pagerduty.EventOrchestrationPathRule{} + + for _, rule := range items { + r := rule.(map[string]interface{}) + + ruleInSet := &pagerduty.EventOrchestrationPathRule{ + ID: r["id"].(string), + Label: r["label"].(string), + Disabled: r["disabled"].(bool), + Conditions: expandUnroutedConditions(r["conditions"]), + Actions: expandUnroutedActions(r["actions"].([]interface{})), + } + + rules = append(rules, ruleInSet) + } + return rules +} + +func expandUnroutedActions(v interface{}) *pagerduty.EventOrchestrationPathRuleActions { + var actions = &pagerduty.EventOrchestrationPathRuleActions{ + Variables: []*pagerduty.EventOrchestrationPathActionVariables{}, + Extractions: []*pagerduty.EventOrchestrationPathActionExtractions{}, + } + + for _, ai := range v.([]interface{}) { + if ai != nil { + am := ai.(map[string]interface{}) + actions.RouteTo = am["route_to"].(string) + actions.Severity = am["severity"].(string) + actions.EventAction = am["event_action"].(string) + actions.Variables = expandUnroutedActionsVariables(am["variables"]) + actions.Extractions = expandUnroutedActionsExtractions(am["extractions"]) + } + } + + return actions +} + +func expandUnroutedConditions(v interface{}) []*pagerduty.EventOrchestrationPathRuleCondition { + items := v.([]interface{}) + conditions := []*pagerduty.EventOrchestrationPathRuleCondition{} + + for _, cond := range items { + c := cond.(map[string]interface{}) + + cx := &pagerduty.EventOrchestrationPathRuleCondition{ + Expression: c["expression"].(string), + } + + conditions = append(conditions, cx) + } + + return conditions +} + +func expandUnroutedActionsExtractions(v interface{}) []*pagerduty.EventOrchestrationPathActionExtractions { + unroutedExtractions := []*pagerduty.EventOrchestrationPathActionExtractions{} + + for _, eai := range v.([]interface{}) { + ea := eai.(map[string]interface{}) + ext := &pagerduty.EventOrchestrationPathActionExtractions{ + Target: ea["target"].(string), + Template: ea["template"].(string), + } + unroutedExtractions = append(unroutedExtractions, ext) + } + return unroutedExtractions +} + +func expandUnroutedActionsVariables(v interface{}) []*pagerduty.EventOrchestrationPathActionVariables { + unroutedVariables := []*pagerduty.EventOrchestrationPathActionVariables{} + + for _, er := range v.([]interface{}) { + rer := er.(map[string]interface{}) + + unroutedVar := &pagerduty.EventOrchestrationPathActionVariables{ + Name: rer["name"].(string), + Path: rer["path"].(string), + Type: rer["type"].(string), + Value: rer["value"].(string), + } + + unroutedVariables = append(unroutedVariables, unroutedVar) + } + + return unroutedVariables +} + +func expandUnroutedCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { + var catchAll = new(pagerduty.EventOrchestrationPathCatchAll) + + for _, ca := range v.([]interface{}) { + if ca != nil { + am := ca.(map[string]interface{}) + catchAll.Actions = expandUnroutedCatchAllActions(am["actions"]) + } + } + + return catchAll +} + +func expandUnroutedCatchAllActions(v interface{}) *pagerduty.EventOrchestrationPathRuleActions { + var actions = new(pagerduty.EventOrchestrationPathRuleActions) + for _, ai := range v.([]interface{}) { + if ai != nil { + am := ai.(map[string]interface{}) + actions.Severity = am["severity"].(string) + actions.EventAction = am["event_action"].(string) + actions.Variables = expandUnroutedActionsVariables(am["variables"]) + actions.Extractions = expandUnroutedActionsExtractions(am["extractions"]) + } + } + + return actions +} + +func flattenUnroutedSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interface{} { + var flattenedSets []interface{} + + for _, set := range orchPathSets { + flattenedSet := map[string]interface{}{ + "id": set.ID, + "rules": flattenUnroutedRules(set.Rules), + } + flattenedSets = append(flattenedSets, flattenedSet) + } + return flattenedSets +} + +func flattenUnroutedRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { + var flattenedRules []interface{} + + for _, rule := range rules { + flattenedRule := map[string]interface{}{ + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "conditions": flattenUnroutedConditions(rule.Conditions), + "actions": flattenUnroutedActions(rule.Actions), + } + flattenedRules = append(flattenedRules, flattenedRule) + } + + return flattenedRules +} + +func flattenUnroutedConditions(conditions []*pagerduty.EventOrchestrationPathRuleCondition) []interface{} { + var flattendConditions []interface{} + + for _, condition := range conditions { + flattendCondition := map[string]interface{}{ + "expression": condition.Expression, + } + flattendConditions = append(flattendConditions, flattendCondition) + } + + return flattendConditions +} + +func flattenUnroutedActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { + var actionsMap []map[string]interface{} + + flattenedAction := map[string]interface{}{ + "route_to": actions.RouteTo, + "severity": actions.Severity, + "event_action": actions.EventAction, + } + + if actions.Variables != nil { + flattenedAction["variables"] = flattenUnroutedActionsVariables(actions.Variables) + } + if actions.Variables != nil { + flattenedAction["extractions"] = flattenUnroutedActionsExtractions(actions.Extractions) + } + + actionsMap = append(actionsMap, flattenedAction) + + return actionsMap +} + +func flattenUnroutedActionsVariables(v []*pagerduty.EventOrchestrationPathActionVariables) []interface{} { + var flatVariablesList []interface{} + + for _, s := range v { + flatVariable := map[string]interface{}{ + "name": s.Name, + "path": s.Path, + "type": s.Type, + "value": s.Value, + } + flatVariablesList = append(flatVariablesList, flatVariable) + } + return flatVariablesList +} + +func flattenUnroutedActionsExtractions(e []*pagerduty.EventOrchestrationPathActionExtractions) []interface{} { + var flatExtractionsList []interface{} + + for _, s := range e { + flatExtraction := map[string]interface{}{ + "target": s.Target, + "template": s.Template, + } + flatExtractionsList = append(flatExtractionsList, flatExtraction) + } + return flatExtractionsList +} + +func flattenUnroutedCatchAll(catchAll *pagerduty.EventOrchestrationPathCatchAll) []map[string]interface{} { + var caMap []map[string]interface{} + + c := make(map[string]interface{}) + + c["actions"] = flattenUnroutedCatchAllActions(catchAll.Actions) + caMap = append(caMap, c) + + return caMap +} + +func flattenUnroutedCatchAllActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { + var actionsMap []map[string]interface{} + + flattenedAction := map[string]interface{}{ + "severity": actions.Severity, + "event_action": actions.EventAction, + "suppress": actions.Suppress, // By default suppress is set to "true" by API for unrouted + } + + if actions.Variables != nil { + flattenedAction["variables"] = flattenUnroutedActionsVariables(actions.Variables) + } + if actions.Variables != nil { + flattenedAction["extractions"] = flattenUnroutedActionsExtractions(actions.Extractions) + } + + actionsMap = append(actionsMap, flattenedAction) + + return actionsMap +} + +func resourcePagerDutyEventOrchestrationPathUnroutedImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client, err := meta.(*Config).Client() + if err != nil { + return []*schema.ResourceData{}, err + } + // given an orchestration ID import the unrouted orchestration path + orchestrationID := d.Id() + pathType := "unrouted" + _, _, err = client.EventOrchestrationPaths.Get(orchestrationID, pathType) + + if err != nil { + return []*schema.ResourceData{}, err + } + + d.SetId(orchestrationID) + + return []*schema.ResourceData{d}, nil +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go new file mode 100644 index 000000000..813bbf534 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -0,0 +1,477 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func init() { + resource.AddTestSweepers("pagerduty_event_orchestration_unrouted", &resource.Sweeper{ + Name: "unrouted", + Dependencies: []string{ + "pagerduty_schedule", + "pagerduty_team", + "pagerduty_user", + "pagerduty_escalation_policy", + "pagerduty_service", + "pagerduty_event_orchestration", + }, + }) +} + +func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { + team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationPathUnroutedDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "type", "unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'rds'"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'rds'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.1.expression", "event.severity matches part 'warning'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.1.conditions.0.expression", "event.severity matches part 'info'"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.#", "2"), + //Set #1 + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.id", "start"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.route_to", "child-1"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.severity matches part 'info'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.1.expression", "event.severity matches part 'warning'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.severity", "info"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.event_action", "trigger"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.name", "server_name_cpu"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.path", "event.summary"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.type", "regex"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.value", "High CPU on (.*) server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.name", "server_name_memory"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.path", "event.custom_details"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.type", "regex"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.value", "High memory usage on (.*) server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.0.target", "event.summary"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.0.template", "High memory usage on variables.hostname server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.1.target", "event.custom_details"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.1.template", "High memory usage on variables.hostname server"), + //Set #2 + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.id", "child-1"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.0.conditions.0.expression", "event.severity matches part 'warning'"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.0.actions.0.event_action", "resolve"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.1.conditions.0.expression", "event.severity matches part 'critical'"), + // Catch All + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.severity", "critical"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.event_action", "trigger"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.name", "server_name_cpu"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.path", "event.summary"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.type", "regex"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.value", "High CPU on (.*) server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.name", "server_name_memory"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.path", "event.custom_details"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.type", "regex"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.value", "High memory usage on (.*) server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.#", "2"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.0.target", "event.summary"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.0.template", "High memory usage on variables.hostname server"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.1.target", "event.custom_details"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.1.template", "High memory usage on variables.hostname server"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "type", "unrouted"), + resource.TestCheckResourceAttr( + "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigDelete(team, escalationPolicy, service, orchestration), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationPathUnroutedNotExists("pagerduty_event_orchestration_unrouted.unrouted"), + ), + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedDestroy(s *terraform.State) error { + client, _ := testAccProvider.Meta().(*Config).Client() + for _, r := range s.RootModule().Resources { + if r.Type != "pagerduty_event_orchestration_path_unrouted" { + continue + } + + orch := s.RootModule().Resources["pagerduty_event_orchestration.orch"] + + if _, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "unrouted"); err == nil { + return fmt.Errorf("Event Orchestration Path still exists") + } + } + return nil +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[rn] + if !ok { + return fmt.Errorf("Not found: %s", rn) + } + if rs.Primary.ID == "" { + return fmt.Errorf("No Event Orchestration Path Type is set") + } + + orch := s.RootModule().Resources["pagerduty_event_orchestration.orch"] + client, _ := testAccProvider.Meta().(*Config).Client() + found, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "unrouted") + + if err != nil { + return fmt.Errorf("Orchestration Path type not found: %v for orchestration %v", "unrouted", orch.Primary.ID) + } + if found.Type != "unrouted" { + return fmt.Errorf("Event Orchrestration path not found: %v - %v", "unrouted", found) + } + + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedNotExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[rn] + if ok { + return fmt.Errorf("Event Orchestration Unrouted Path is not deleted: %s", rn) + } + + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigDelete(t, ep, s, o string) string { + return createUnroutedBaseConfig(t, ep, s, o) +} + +func createUnroutedBaseConfig(t, ep, s, o string) string { + return fmt.Sprintf(` + resource "pagerduty_team" "foo" { + name = "%s" + } + resource "pagerduty_user" "foo" { + name = "tf-user" + email = "user@pagerduty.com" + color = "green" + role = "user" + job_title = "foo" + description = "foo" + } + resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } + } + resource "pagerduty_service" "bar" { + name = "%s" + escalation_policy = pagerduty_escalation_policy.foo.id + incident_urgency_rule { + type = "constant" + urgency = "high" + } + } + resource "pagerduty_event_orchestration" "orch" { + name = "%s" + team { + id = pagerduty_team.foo.id + } + } + `, t, ep, s, o) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + parent { + id = pagerduty_event_orchestration.orch.id + } + sets { + id = "start" + } + catch_all { + actions { } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + parent { + id = pagerduty_event_orchestration.orch.id + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { } + conditions { + expression = "event.summary matches part 'rds'" + } + } + } + catch_all { + actions { } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + parent { + id = pagerduty_event_orchestration.orch.id + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { } + conditions { + expression = "event.summary matches part 'rds'" + } + conditions { + expression = "event.severity matches part 'warning'" + } + } + + rules { + disabled = false + label = "rule2 label" + actions { } + conditions { + expression = "event.severity matches part 'info'" + } + } + } + catch_all { + actions { } + } + } +`) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, o string) string { + return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), + `resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + parent { + id = pagerduty_event_orchestration.orch.id + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + conditions { + expression = "event.severity matches part 'info'" + } + conditions { + expression = "event.severity matches part 'warning'" + } + actions { + route_to = "child-1" + severity = "info" + event_action = "trigger" + variables { + name = "server_name_cpu" + path = "event.summary" + type = "regex" + value = "High CPU on (.*) server" + } + variables { + name = "server_name_memory" + path = "event.custom_details" + type = "regex" + value = "High memory usage on (.*) server" + } + extractions { + target = "event.summary" + template = "High memory usage on variables.hostname server" + } + extractions { + target = "event.custom_details" + template = "High memory usage on variables.hostname server" + } + } + } + } + sets { + id = "child-1" + rules { + disabled = false + label = "rule2 label1" + conditions { + expression = "event.severity matches part 'warning'" + } + actions { + severity = "warning" + event_action = "resolve" + variables { + name = "server_name_cpu" + path = "event.summary" + type = "regex" + value = "High CPU on (.*) server" + } + extractions { + target = "event.summary" + template = "High CPU on event.custom_details.hostname server" + } + } + } + rules { + disabled = false + label = "rule2 label2" + conditions { + expression = "event.severity matches part 'critical'" + } + actions { + severity = "warning" + event_action = "trigger" + variables { + name = "server_name_cpu" + path = "event.summary" + type = "regex" + value = "High CPU on (.*) server" + } + extractions { + target = "event.summary" + template = "High CPU on event.custom_details.hostname server" + } + } + } + } + catch_all { + actions { + severity = "critical" + event_action = "trigger" + variables { + name = "server_name_cpu" + path = "event.summary" + type = "regex" + value = "High CPU on (.*) server" + } + variables { + name = "server_name_memory" + path = "event.custom_details" + type = "regex" + value = "High memory usage on (.*) server" + } + extractions { + target = "event.summary" + template = "High memory usage on variables.hostname server" + } + extractions { + target = "event.custom_details" + template = "High memory usage on variables.hostname server" + } + } + } + } + `) +} From 3162fdcace5754c885b83598da6f2a4119d248e4 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 19 May 2022 10:45:42 -0400 Subject: [PATCH 18/51] make type computed and set it on read/update --- .../resource_pagerduty_event_orchestration_path_router.go | 5 ++++- ...ource_pagerduty_event_orchestration_path_router_test.go | 7 ------- ...resource_pagerduty_event_orchestration_path_unrouted.go | 4 +++- ...rce_pagerduty_event_orchestration_path_unrouted_test.go | 4 ---- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index db1c7235a..4cd3d52d3 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -22,7 +22,7 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { Schema: map[string]*schema.Schema{ "type": { Type: schema.TypeString, - Required: true, + Computed: true, }, "parent": { Type: schema.TypeList, @@ -131,6 +131,7 @@ func resourcePagerDutyEventOrchestrationPathRouterRead(d *schema.ResourceData, m time.Sleep(2 * time.Second) return resource.RetryableError(err) } else if routerPath != nil { + d.Set("type", routerPath.Type) if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) @@ -179,6 +180,8 @@ func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.Event } // set props d.SetId(routerPath.Parent.ID) + d.Set("type", updatedPath.Type) + if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index 8d0d05cc5..452c30a03 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -220,7 +220,6 @@ func createBaseConfig(t, ep, s, o string) string { func testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -239,7 +238,6 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(t, ep, s, o stri func testAccCheckPagerDutyEventOrchestrationRouterConfig(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -266,7 +264,6 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(t, ep, s, return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), ` resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -307,7 +304,6 @@ resource "pagerduty_service" "bar2" { } resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -351,7 +347,6 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(t, ep, s, o return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), ` resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -378,7 +373,6 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(t, return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), ` resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } @@ -408,7 +402,6 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(t, e return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), ` resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { id = pagerduty_event_orchestration.orch.id } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 9518a1c4d..6c84d94da 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -22,7 +22,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Schema: map[string]*schema.Schema{ "type": { Type: schema.TypeString, - Required: true, + Computed: true, }, "parent": { Type: schema.TypeList, @@ -235,6 +235,7 @@ func resourcePagerDutyEventOrchestrationPathUnroutedRead(d *schema.ResourceData, time.Sleep(2 * time.Second) return resource.RetryableError(err) } else if unroutedPath != nil { + d.Set("type", unroutedPath.Type) if unroutedPath.Sets != nil { d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) @@ -284,6 +285,7 @@ func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.E } // set props d.SetId(unroutedPath.Parent.ID) + d.Set("type", updatedPath.Type) if unroutedPath.Sets != nil { d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index 813bbf534..64d5f57ea 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -280,7 +280,6 @@ func createUnroutedBaseConfig(t, ep, s, o string) string { func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" parent { id = pagerduty_event_orchestration.orch.id } @@ -297,7 +296,6 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" parent { id = pagerduty_event_orchestration.orch.id } @@ -322,7 +320,6 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" parent { id = pagerduty_event_orchestration.orch.id } @@ -359,7 +356,6 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules( func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" parent { id = pagerduty_event_orchestration.orch.id } From 0459e901297c9306f23dd6de8d3ef8b6539330b1 Mon Sep 17 00:00:00 2001 From: Alex Zakabluk Date: Thu, 19 May 2022 10:58:43 -0400 Subject: [PATCH 19/51] Orca 3486 refactor (#500) * Clean sweeper function for router/unrouted * Clean sweeper function --- ...erduty_event_orchestration_path_router_test.go | 13 +++---------- ...duty_event_orchestration_path_unrouted_test.go | 15 ++++----------- ...resource_pagerduty_event_orchestration_test.go | 9 ++++++++- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index 452c30a03..9ecaa1acd 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -11,15 +11,8 @@ import ( func init() { resource.AddTestSweepers("pagerduty_event_orchestration_router", &resource.Sweeper{ - Name: "router", - Dependencies: []string{ - "pagerduty_schedule", - "pagerduty_team", - "pagerduty_user", - "pagerduty_escalation_policy", - "pagerduty_service", - "pagerduty_event_orchestration", - }, + Name: "pagerduty_event_orchestration_router", + F: testSweepEventOrchestration, }) } @@ -27,7 +20,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) service := fmt.Sprintf("tf-%s", acctest.RandString(5)) - orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index 64d5f57ea..ced0a0e05 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -11,23 +11,16 @@ import ( func init() { resource.AddTestSweepers("pagerduty_event_orchestration_unrouted", &resource.Sweeper{ - Name: "unrouted", - Dependencies: []string{ - "pagerduty_schedule", - "pagerduty_team", - "pagerduty_user", - "pagerduty_escalation_policy", - "pagerduty_service", - "pagerduty_event_orchestration", - }, + Name: "pagerduty_event_orchestration_unrouted", + F: testSweepEventOrchestration, }) } func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { - team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + team := fmt.Sprintf("tf-team-%s", acctest.RandString(5)) escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) service := fmt.Sprintf("tf-%s", acctest.RandString(5)) - orchestration := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5)) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index afbdf0979..75288583b 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -15,6 +15,13 @@ func init() { resource.AddTestSweepers("pagerduty_event_orchestration", &resource.Sweeper{ Name: "pagerduty_event_orchestration", F: testSweepEventOrchestration, + Dependencies: []string{ + "pagerduty_schedule", + "pagerduty_team", + "pagerduty_user", + "pagerduty_escalation_policy", + "pagerduty_service", + }, }) } @@ -35,7 +42,7 @@ func testSweepEventOrchestration(region string) error { } for _, orchestration := range resp.Orchestrations { - if strings.HasPrefix(orchestration.Name, "tf-name-") { + if strings.HasPrefix(orchestration.Name, "tf-orchestration-") { log.Printf("Destroying Event Orchestration %s (%s)", orchestration.Name, orchestration.ID) if _, err := client.EventOrchestrations.Delete(orchestration.ID); err != nil { return err From ab94a67221ec4e34fb3198c4a90c17233780b478 Mon Sep 17 00:00:00 2001 From: alenapan <47909261+alenapan@users.noreply.github.com> Date: Fri, 20 May 2022 10:56:51 -0400 Subject: [PATCH 20/51] [ORCA-3465] - Event Orchestration Service path resource (#499) * ORCA-3465 - Event Orchestration Service Path resource * add resource file * fix read/update, add test * more tests * more service path tests, add conditions * more tests * more tests * add more service path props * fix orch path PUT payload, add tests * fix Suspend * ToDos * add catch_all support, fix tests * add support for regex extractions, add mor tests, add service path import test * update client * PR feedback --- pagerduty/event_orchestration_path_util.go | 105 +++ ...y_event_orchestration_path_service_test.go | 36 + pagerduty/provider.go | 4 +- ...erduty_event_orchestration_path_service.go | 620 ++++++++++++++ ...y_event_orchestration_path_service_test.go | 786 ++++++++++++++++++ ...rduty_event_orchestration_path_unrouted.go | 99 +-- pagerduty/util.go | 7 + .../pagerduty/event_orchestration_path.go | 33 +- 8 files changed, 1601 insertions(+), 89 deletions(-) create mode 100644 pagerduty/import_pagerduty_event_orchestration_path_service_test.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_service.go create mode 100644 pagerduty/resource_pagerduty_event_orchestration_path_service_test.go diff --git a/pagerduty/event_orchestration_path_util.go b/pagerduty/event_orchestration_path_util.go index 54746b226..7891cefda 100644 --- a/pagerduty/event_orchestration_path_util.go +++ b/pagerduty/event_orchestration_path_util.go @@ -1,7 +1,10 @@ package pagerduty import ( + "context" + "fmt" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" ) var PagerDutyEventOrchestrationPathParent = map[string]*schema.Schema{ @@ -25,3 +28,105 @@ var PagerDutyEventOrchestrationPathConditions = map[string]*schema.Schema{ Required: true, }, } + +func checkExtractions(context context.Context, diff *schema.ResourceDiff, i interface{}) error { + sn := diff.Get("sets.#").(int) + + for si := 0; si < sn; si++ { + rn := diff.Get(fmt.Sprintf("sets.%d.rules.#", si)).(int) + for ri := 0; ri < rn; ri++ { + res := checkExtractionAttributes(diff, fmt.Sprintf("sets.%d.rules.%d.actions.0.extractions", si, ri)) + if res != nil { + return res + } + } + } + return checkExtractionAttributes(diff, "catch_all.0.actions.0.extractions") +} + +func checkExtractionAttributes(diff *schema.ResourceDiff, loc string) error { + num := diff.Get(fmt.Sprintf("%s.#", loc)).(int) + for i := 0; i < num; i++ { + prefix := fmt.Sprintf("%s.%d", loc, i) + r := diff.Get(fmt.Sprintf("%s.regex", prefix)).(string) + t := diff.Get(fmt.Sprintf("%s.template", prefix)).(string) + + if r == "" && t == "" { + return fmt.Errorf("Invalid configuration in %s: regex and template cannot both be null", prefix) + } + if r != "" && t != "" { + return fmt.Errorf("Invalid configuration in %s: regex and template cannot both have values", prefix) + } + + s := diff.Get(fmt.Sprintf("%s.source", prefix)).(string) + if r != "" && s == "" { + return fmt.Errorf("Invalid configuration in %s: source can't be blank", prefix) + } + } + return nil +} + +func expandEventOrchestrationPathVariables(v interface{}) []*pagerduty.EventOrchestrationPathActionVariables { + res := []*pagerduty.EventOrchestrationPathActionVariables{} + + for _, er := range v.([]interface{}) { + rer := er.(map[string]interface{}) + + av := &pagerduty.EventOrchestrationPathActionVariables{ + Name: rer["name"].(string), + Path: rer["path"].(string), + Type: rer["type"].(string), + Value: rer["value"].(string), + } + + res = append(res, av) + } + + return res +} + +func flattenEventOrchestrationPathVariables(v []*pagerduty.EventOrchestrationPathActionVariables) []interface{} { + var res []interface{} + + for _, s := range v { + fv := map[string]interface{}{ + "name": s.Name, + "path": s.Path, + "type": s.Type, + "value": s.Value, + } + res = append(res, fv) + } + return res +} + +func expandEventOrchestrationPathExtractions(v interface{}) []*pagerduty.EventOrchestrationPathActionExtractions { + res := []*pagerduty.EventOrchestrationPathActionExtractions{} + + for _, eai := range v.([]interface{}) { + ea := eai.(map[string]interface{}) + ext := &pagerduty.EventOrchestrationPathActionExtractions{ + Target: ea["target"].(string), + Regex: ea["regex"].(string), + Template: ea["template"].(string), + Source: ea["source"].(string), + } + res = append(res, ext) + } + return res +} + +func flattenEventOrchestrationPathExtractions(e []*pagerduty.EventOrchestrationPathActionExtractions) []interface{} { + var res []interface{} + + for _, s := range e { + e := map[string]interface{}{ + "target": s.Target, + "regex": s.Regex, + "template": s.Template, + "source": s.Source, + } + res = append(res, e) + } + return res +} diff --git a/pagerduty/import_pagerduty_event_orchestration_path_service_test.go b/pagerduty/import_pagerduty_event_orchestration_path_service_test.go new file mode 100644 index 000000000..afa007a85 --- /dev/null +++ b/pagerduty/import_pagerduty_event_orchestration_path_service_test.go @@ -0,0 +1,36 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccPagerDutyEventOrchestrationPathService_import(t *testing.T) { + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationServicePathDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(escalationPolicy, service), + }, + { + ResourceName: "pagerduty_event_orchestration_service.serviceA", + ImportStateIdFunc: testAccCheckPagerDutyEventOrchestrationPathServiceID, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceID(s *terraform.State) (string, error) { + return s.RootModule().Resources["pagerduty_service.bar"].Primary.ID, nil +} diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 432cd6662..92e478397 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -90,7 +90,9 @@ func Provider() *schema.Provider { "pagerduty_webhook_subscription": resourcePagerDutyWebhookSubscription(), "pagerduty_event_orchestration": resourcePagerDutyEventOrchestration(), "pagerduty_event_orchestration_router": resourcePagerDutyEventOrchestrationPathRouter(), - "pagerduty_event_orchestration_unrouted": resourcePagerDutyEventOrchestrationPathUnrouted()}, + "pagerduty_event_orchestration_unrouted": resourcePagerDutyEventOrchestrationPathUnrouted(), + "pagerduty_event_orchestration_service": resourcePagerDutyEventOrchestrationPathService(), + }, } p.ConfigureFunc = func(d *schema.ResourceData) (interface{}, error) { diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service.go b/pagerduty/resource_pagerduty_event_orchestration_path_service.go new file mode 100644 index 000000000..7b813cd51 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service.go @@ -0,0 +1,620 @@ +package pagerduty + +import ( + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" +) + +var eventOrchestrationAutomationActionObject = map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, +} + +var eventOrchestrationPathServiceCatchAllActions = map[string]*schema.Schema{ + "suppress": { + Type: schema.TypeBool, + Optional: true, + }, + "suspend": { + Type: schema.TypeInt, + Optional: true, + }, + "priority": { + Type: schema.TypeString, + Optional: true, + }, + "annotate": { + Type: schema.TypeString, + Optional: true, + }, + "pagerduty_automation_actions": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_id": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "automation_actions": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "url": { + Type: schema.TypeString, + Required: true, + }, + "auto_send": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "headers": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: eventOrchestrationAutomationActionObject, + }, + }, + "parameters": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: eventOrchestrationAutomationActionObject, + }, + }, + }, + }, + }, + "severity": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "info", + "error", + "warning", + "critical", + }), + }, + "event_action": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateValueFunc([]string{ + "trigger", + "resolve", + }), + }, + "variables": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "path": { + Type: schema.TypeString, + Required: true, + }, + "type": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + }}, + }, + "extractions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "regex": { + Type: schema.TypeString, + Optional: true, + }, + "source": { + Type: schema.TypeString, + Optional: true, + }, + "target": { + Type: schema.TypeString, + Required: true, + }, + "template": { + Type: schema.TypeString, + Optional: true, + }, + }}, + }, +} + +var eventOrchestrationPathServiceRuleActions = buildEventOrchestrationPathServiceRuleActions() + +func buildEventOrchestrationPathServiceRuleActions() map[string]*schema.Schema { + a := eventOrchestrationPathServiceCatchAllActions + a["route_to"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + } + + return a +} + +func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { + return &schema.Resource{ + Read: resourcePagerDutyEventOrchestrationPathServiceRead, + Create: resourcePagerDutyEventOrchestrationPathServiceCreate, + Update: resourcePagerDutyEventOrchestrationPathServiceUpdate, + Delete: resourcePagerDutyEventOrchestrationPathServiceDelete, + Importer: &schema.ResourceImporter{ + State: resourcePagerDutyEventOrchestrationPathServiceImport, + }, + CustomizeDiff: checkExtractions, + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Computed: true, + }, + "parent": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathParent, + }, + }, + "sets": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "rules": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "label": { + Type: schema.TypeString, + Optional: true, + }, + "conditions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: PagerDutyEventOrchestrationPathConditions, + }, + }, + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: eventOrchestrationPathServiceRuleActions, + }, + }, + "disabled": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "catch_all": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: eventOrchestrationPathServiceRuleActions, + }, + }, + }, + }, + }, + }, + } +} + +func resourcePagerDutyEventOrchestrationPathServiceRead(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + return resource.Retry(2*time.Minute, func() *resource.RetryError { + id := d.Id() + t := "service" + log.Printf("[INFO] Reading PagerDuty Event Orchestration Path of type %s for orchestration: %s", t, id) + + if path, _, err := client.EventOrchestrationPaths.Get(d.Id(), t); err != nil { + time.Sleep(2 * time.Second) + return resource.RetryableError(err) + } else if path != nil { + setEventOrchestrationPathServiceProps(d, path) + } + return nil + }) + +} + +func resourcePagerDutyEventOrchestrationPathServiceCreate(d *schema.ResourceData, meta interface{}) error { + return resourcePagerDutyEventOrchestrationPathServiceUpdate(d, meta) +} + +func resourcePagerDutyEventOrchestrationPathServiceUpdate(d *schema.ResourceData, meta interface{}) error { + client, err := meta.(*Config).Client() + if err != nil { + return err + } + + payload := buildServicePathStruct(d) + var servicePath *pagerduty.EventOrchestrationPath + + log.Printf("[INFO] Creating PagerDuty Event Orchestration Service Path: %s", payload.Parent.ID) + + retryErr := resource.Retry(30*time.Second, func() *resource.RetryError { + if path, _, err := client.EventOrchestrationPaths.Update(payload.Parent.ID, "service", payload); err != nil { + return resource.RetryableError(err) + } else if path != nil { + d.SetId(path.Parent.ID) + servicePath = path + } + return nil + }) + + if retryErr != nil { + return retryErr + } + + setEventOrchestrationPathServiceProps(d, servicePath) + + return nil +} + +func resourcePagerDutyEventOrchestrationPathServiceDelete(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} + +func resourcePagerDutyEventOrchestrationPathServiceImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client, err := meta.(*Config).Client() + if err != nil { + return []*schema.ResourceData{}, err + } + + id := d.Id() + + p, _, pErr := client.EventOrchestrationPaths.Get(id, "service") + if pErr != nil { + return []*schema.ResourceData{}, pErr + } + + d.SetId(id) + d.Set("parent", flattenServicePathParent(p.Parent)) + + return []*schema.ResourceData{d}, nil +} + +func buildServicePathStruct(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { + return &pagerduty.EventOrchestrationPath{ + Parent: &pagerduty.EventOrchestrationPathReference{ + ID: d.Get("parent.0.id").(string), + }, + Sets: expandServicePathSets(d.Get("sets")), + CatchAll: expandServicePathCatchAll(d.Get("catch_all")), + } +} + +// TODO: see if we can reuse expand functions for all orch path sets. +// Maybe pass in the rule actions and catch-all rule actions expanding function? +func expandServicePathSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { + var sets []*pagerduty.EventOrchestrationPathSet + + for _, set := range v.([]interface{}) { + s := set.(map[string]interface{}) + + orchPathSet := &pagerduty.EventOrchestrationPathSet{ + ID: s["id"].(string), + Rules: expandServicePathRules(s["rules"].(interface{})), + } + + sets = append(sets, orchPathSet) + } + + return sets +} + +func expandServicePathRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { + items := v.([]interface{}) + rules := []*pagerduty.EventOrchestrationPathRule{} + + for _, rule := range items { + r := rule.(map[string]interface{}) + + ruleInSet := &pagerduty.EventOrchestrationPathRule{ + ID: r["id"].(string), + Label: r["label"].(string), + Disabled: r["disabled"].(bool), + // TODO: move conditions logic to util + Conditions: expandRouterConditions(r["conditions"].(interface{})), + Actions: expandServicePathActions(r["actions"].([]interface{})), + } + + rules = append(rules, ruleInSet) + } + return rules +} + +func expandServicePathCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { + var catchAll = new(pagerduty.EventOrchestrationPathCatchAll) + + for _, ca := range v.([]interface{}) { + if ca != nil { + am := ca.(map[string]interface{}) + catchAll.Actions = expandServicePathActions(am["actions"]) + } + } + + return catchAll +} + +func expandServicePathActions(v interface{}) *pagerduty.EventOrchestrationPathRuleActions { + var actions = &pagerduty.EventOrchestrationPathRuleActions{ + AutomationActions: []*pagerduty.EventOrchestrationPathAutomationAction{}, + PagerdutyAutomationActions: []*pagerduty.EventOrchestrationPathPagerdutyAutomationAction{}, + Variables: []*pagerduty.EventOrchestrationPathActionVariables{}, + Extractions: []*pagerduty.EventOrchestrationPathActionExtractions{}, + } + + for _, i := range v.([]interface{}) { + if i == nil { + continue + } + a := i.(map[string]interface{}) + + actions.RouteTo = a["route_to"].(string) + actions.Suppress = a["suppress"].(bool) + actions.Suspend = intTypeToIntPtr(a["suspend"].(int)) + actions.Priority = a["priority"].(string) + actions.Annotate = a["annotate"].(string) + actions.Severity = a["severity"].(string) + actions.EventAction = a["event_action"].(string) + actions.PagerdutyAutomationActions = expandServicePathPagerDutyAutomationActions(a["pagerduty_automation_actions"]) + actions.AutomationActions = expandServicePathAutomationActions(a["automation_actions"]) + actions.Variables = expandEventOrchestrationPathVariables(a["variables"]) + actions.Extractions = expandEventOrchestrationPathExtractions(a["extractions"]) + } + + return actions +} + +func expandServicePathPagerDutyAutomationActions(v interface{}) []*pagerduty.EventOrchestrationPathPagerdutyAutomationAction { + result := []*pagerduty.EventOrchestrationPathPagerdutyAutomationAction{} + + for _, i := range v.([]interface{}) { + a := i.(map[string]interface{}) + pdaa := &pagerduty.EventOrchestrationPathPagerdutyAutomationAction{ + ActionId: a["action_id"].(string), + } + + result = append(result, pdaa) + } + + return result +} + +func expandServicePathAutomationActions(v interface{}) []*pagerduty.EventOrchestrationPathAutomationAction { + result := []*pagerduty.EventOrchestrationPathAutomationAction{} + + for _, i := range v.([]interface{}) { + a := i.(map[string]interface{}) + aa := &pagerduty.EventOrchestrationPathAutomationAction{ + Name: a["name"].(string), + Url: a["url"].(string), + AutoSend: a["auto_send"].(bool), + Headers: expandEventOrchestrationAutomationActionObjects(a["headers"]), + Parameters: expandEventOrchestrationAutomationActionObjects(a["parameters"]), + } + + result = append(result, aa) + } + + return result +} + +func expandEventOrchestrationAutomationActionObjects(v interface{}) []*pagerduty.EventOrchestrationPathAutomationActionObject { + result := []*pagerduty.EventOrchestrationPathAutomationActionObject{} + + for _, i := range v.([]interface{}) { + o := i.(map[string]interface{}) + obj := &pagerduty.EventOrchestrationPathAutomationActionObject{ + Key: o["key"].(string), + Value: o["value"].(string), + } + + result = append(result, obj) + } + + return result +} + +func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty.EventOrchestrationPath) error { + d.SetId(p.Parent.ID) + d.Set("type", p.Type) + d.Set("parent", flattenServicePathParent(p.Parent)) + // TODO: see if we can reuse expand functions for all orch path sets. + // Maybe pass in the rule actions and catch-all rule actions expanding function? + d.Set("sets", flattenServicePathSets(p.Sets)) + d.Set("catch_all", flattenServicePathCatchAll(p.CatchAll)) + return nil +} + +func flattenServicePathParent(p *pagerduty.EventOrchestrationPathReference) []interface{} { + var parent = map[string]interface{}{ + "id": p.ID, + "type": p.Type, + "self": p.Self, + } + + return []interface{}{parent} +} + +func flattenServicePathSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interface{} { + var flattenedSets []interface{} + + for _, set := range orchPathSets { + flattenedSet := map[string]interface{}{ + "id": set.ID, + "rules": flattenServicePathRules(set.Rules), + } + flattenedSets = append(flattenedSets, flattenedSet) + } + return flattenedSets +} + +func flattenServicePathCatchAll(catchAll *pagerduty.EventOrchestrationPathCatchAll) []map[string]interface{} { + var caMap []map[string]interface{} + + c := make(map[string]interface{}) + + c["actions"] = flattenServicePathActions(catchAll.Actions) + caMap = append(caMap, c) + + return caMap +} + +func flattenServicePathRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { + var flattenedRules []interface{} + + for _, rule := range rules { + flattenedRule := map[string]interface{}{ + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + // TODO: move conditions logic to util + "conditions": flattenRouterConditions(rule.Conditions), + "actions": flattenServicePathActions(rule.Actions), + } + flattenedRules = append(flattenedRules, flattenedRule) + } + + return flattenedRules +} + +func flattenServicePathActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { + var actionsMap []map[string]interface{} + + flattenedAction := map[string]interface{}{ + "route_to": actions.RouteTo, + "severity": actions.Severity, + "event_action": actions.EventAction, + "suppress": actions.Suppress, + "suspend": actions.Suspend, + "priority": actions.Priority, + "annotate": actions.Annotate, + } + + if actions.Variables != nil { + flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) + } + if actions.Extractions != nil { + flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) + } + if actions.PagerdutyAutomationActions != nil { + flattenedAction["pagerduty_automation_actions"] = flattenServicePathPagerDutyAutomationActions(actions.PagerdutyAutomationActions) + } + if actions.AutomationActions != nil { + flattenedAction["automation_actions"] = flattenServicePathAutomationActions(actions.AutomationActions) + } + + actionsMap = append(actionsMap, flattenedAction) + + return actionsMap +} + +func flattenServicePathPagerDutyAutomationActions(v []*pagerduty.EventOrchestrationPathPagerdutyAutomationAction) []interface{} { + var result []interface{} + + for _, i := range v { + pdaa := map[string]string{ + "action_id": i.ActionId, + } + + result = append(result, pdaa) + } + + return result +} + +func flattenServicePathAutomationActions(v []*pagerduty.EventOrchestrationPathAutomationAction) []interface{} { + var result []interface{} + + for _, i := range v { + pdaa := map[string]interface{}{ + "name": i.Name, + "url": i.Url, + "auto_send": i.AutoSend, + "headers": flattenServicePathAutomationActionObjects(i.Headers), + "parameters": flattenServicePathAutomationActionObjects(i.Parameters), + } + + result = append(result, pdaa) + } + + return result +} + +func flattenServicePathAutomationActionObjects(v []*pagerduty.EventOrchestrationPathAutomationActionObject) []interface{} { + var result []interface{} + + for _, i := range v { + pdaa := map[string]interface{}{ + "key": i.Key, + "value": i.Value, + } + + result = append(result, pdaa) + } + + return result +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go new file mode 100644 index 000000000..498c5f268 --- /dev/null +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go @@ -0,0 +1,786 @@ +package pagerduty + +import ( + "fmt" + "regexp" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func init() { + resource.AddTestSweepers("pagerduty_event_orchestration_service", &resource.Sweeper{ + Name: "pagerduty_event_orchestration_service", + F: testSweepEventOrchestration, + }) +} + +func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resourceName := "pagerduty_event_orchestration_service.serviceA" + serviceResourceName := "pagerduty_service.bar" + + // Checks that run on every step except the last one. These checks that verify the existance of the resource + // and computed/default attributes. We're not checking individual resource attributes because + // according to the official docs (https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#TestCheckResourceAttr) + // "State value checking is only recommended for testing Computed attributes and attribute defaults." + baseChecks := []resource.TestCheckFunc{ + testAccCheckPagerDutyEventOrchestrationPathServiceExists(resourceName), + testAccCheckPagerDutyEventOrchestrationPathServiceParent(resourceName, serviceResourceName), + resource.TestCheckResourceAttr(resourceName, "type", "service"), + } + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationServicePathDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc(baseChecks...), + }, + // Adding/updating/deleting automation_actions properties + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + )..., + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUpdateConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + resource.TestCheckResourceAttr( + resourceName, "sets.0.rules.0.actions.0.automation_actions.0.auto_send", "false", + ), + )..., + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsDeleteConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc(baseChecks...), + }, + // Providing invalid extractions attributes for set rules + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, invalidExtractionRegexTemplateNilConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both be null"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, invalidExtractionRegexTemplateValConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, invalidExtractionRegexNilSourceConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: source can't be blank"), + }, + // Providing invalid extractions attributes for the catch_all rule + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, "", invalidExtractionRegexTemplateNilConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both be null"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, "", invalidExtractionRegexTemplateValConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both have values"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( + escalationPolicy, service, "", invalidExtractionRegexNilSourceConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: source can't be blank"), + }, + // Adding/updating/deleting all actions + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + []resource.TestCheckFunc{ + resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + }..., + )..., + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + []resource.TestCheckFunc{ + resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + }..., + )..., + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsDeleteConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + []resource.TestCheckFunc{ + resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + }..., + )..., + ), + }, + // Deleting sets and the service path resource + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceOneSetNoActionsConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + append( + baseChecks, + resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + )..., + ), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathServiceResourceDeleteConfig(escalationPolicy, service), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyEventOrchestrationServicePathNotExists(resourceName), + ), + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationServicePathDestroy(s *terraform.State) error { + client, _ := testAccProvider.Meta().(*Config).Client() + for _, r := range s.RootModule().Resources { + if r.Type != "pagerduty_event_orchestration_path_service" { + continue + } + + srv := s.RootModule().Resources["pagerduty_service.bar"] + + if _, _, err := client.EventOrchestrationPaths.Get(srv.Primary.ID, "service"); err == nil { + return fmt.Errorf("Event Orchestration Service Path still exists") + } + } + return nil +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + orch, ok := s.RootModule().Resources[rn] + if !ok { + return fmt.Errorf("Not found: %s", rn) + } + if orch.Primary.ID == "" { + return fmt.Errorf("No Event Orchestration Service ID is set") + } + + client, _ := testAccProvider.Meta().(*Config).Client() + found, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "service") + if err != nil { + return err + } + if found.Parent.ID != orch.Primary.ID { + return fmt.Errorf("Event Orchrestration Service not found: %v - %v", orch.Primary.ID, found) + } + + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationServicePathNotExists(rn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[rn] + if ok { + return fmt.Errorf("Event Orchestration Service Path is not deleted from the state: %s", rn) + } + + return nil + } +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceParent(rn, sn string) resource.TestCheckFunc { + return func(s *terraform.State) error { + p, _ := s.RootModule().Resources[rn] + srv, ok := s.RootModule().Resources[sn] + + if !ok { + return fmt.Errorf("Service not found: %s", sn) + } + + var pId = p.Primary.Attributes["parent.0.id"] + var sId = srv.Primary.Attributes["id"] + if pId != sId { + return fmt.Errorf("Event Orchestration Service path parent ID (%v) not matching provided service ID: %v", pId, sId) + } + + var t = p.Primary.Attributes["parent.0.type"] + if t != "service_reference" { + return fmt.Errorf("Event Orchestration Service path parent type (%v) not matching expected type: 'service_reference'", t) + } + + var self = p.Primary.Attributes["parent.0.self"] + if !strings.HasSuffix(self, sId) { + return fmt.Errorf("Event Orchestration Service path parent self URL (%v) not containing expected service ID", self) + } + + return nil + } +} + +func createBaseServicePathConfig(ep, s string) string { + return fmt.Sprintf(` + resource "pagerduty_user" "foo" { + name = "tf-user" + email = "user@pagerduty.com" + color = "green" + role = "user" + job_title = "foo" + description = "foo" + } + + resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "bar" + num_loops = 2 + + rule { + escalation_delay_in_minutes = 10 + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } + } + + resource "pagerduty_service" "bar" { + name = "%s" + escalation_policy = pagerduty_escalation_policy.foo.id + + incident_urgency_rule { + type = "constant" + urgency = "high" + } + } + `, ep, s) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + } + + catch_all { + actions { } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1" + actions { + automation_actions { + name = "test" + url = "https://test.com" + auto_send = true + + headers { + key = "foo" + value = "bar" + } + headers { + key = "baz" + value = "buz" + } + + parameters { + key = "source" + value = "orch" + } + parameters { + key = "region" + value = "us" + } + } + } + } + } + + catch_all { + actions { + automation_actions { + name = "catch-all test" + url = "https://catch-all-test.com" + auto_send = true + + headers { + key = "foo1" + value = "bar1" + } + headers { + key = "baz1" + value = "buz1" + } + + parameters { + key = "source1" + value = "orch1" + } + parameters { + key = "region1" + value = "us1" + } + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUpdateConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1" + actions { + automation_actions { + name = "test1" + url = "https://test1.com" + + headers { + key = "foo1" + value = "bar1" + } + parameters { + key = "source_region" + value = "eu" + } + } + } + } + } + + catch_all { + actions { + automation_actions { + name = "catch-all test upd" + url = "https://catch-all-test-upd.com" + + headers { + key = "baz2" + value = "buz2" + } + + parameters { + key = "source2" + value = "orch2" + } + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsDeleteConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1" + actions { + automation_actions { + name = "test" + url = "https://test.com" + } + } + } + } + + catch_all { + actions { + automation_actions { + name = "catch-all test upd" + url = "https://catch-all-test-upd.com" + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig(ep, s, re, cae string) string { + return fmt.Sprintf( + "%s%s", + createBaseServicePathConfig(ep, s), + fmt.Sprintf(`resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + sets { + id = "start" + rules { + actions { + %s + } + } + } + catch_all { + actions { + %s + } + } + } + `, re, cae), + ) +} + +func invalidExtractionRegexTemplateNilConfig() string { + return ` + extractions { + target = "event.summary" + }` +} + +func invalidExtractionRegexTemplateValConfig() string { + return ` + extractions { + regex = ".*" + template = "hi" + target = "event.summary" + }` +} + +func invalidExtractionRegexNilSourceConfig() string { + return ` + extractions { + regex = ".*" + target = "event.summary" + }` +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1" + conditions { + expression = "event.summary matches part 'timeout'" + } + conditions { + expression = "event.custom_details.timeout_err exists" + } + actions { + route_to = "set-1" + priority = "P0IN2KQ" + annotate = "Routed through an event orchestration" + pagerduty_automation_actions { + action_id = "01CSB5SMOKCKVRI5GN0LJG7SMB" + } + severity = "critical" + event_action = "trigger" + variables { + name = "hostname" + path = "event.source" + type = "regex" + value = "Source host: (.*)" + } + variables { + name = "cpu_val" + path = "event.custom_details.cpu" + type = "regex" + value = "(.*)" + } + extractions { + target = "event.summary" + template = "High CPU usage on {{variables.hostname}}" + } + extractions { + regex = ".*" + source = "event.group" + target = "event.custom_details.message" + } + } + } + } + sets { + id = "set-1" + rules { + label = "set-1 rule 1" + actions { + suspend = 300 + } + } + rules { + label = "set-1 rule 2" + conditions { + expression = "event.source matches part 'stg-'" + } + actions { + suppress = true + } + } + } + + catch_all { + actions { + suspend = 120 + priority = "P0IN2KW" + annotate = "Routed through an event orchestration - catch-all rule" + pagerduty_automation_actions { + action_id = "01CSB5SMOKCKVRI5GN0LJG7SMC" + } + severity = "warning" + event_action = "trigger" + variables { + name = "user_id" + path = "event.custom_details.user_id" + type = "regex" + value = "Source host: (.*)" + } + variables { + name = "updated_at" + path = "event.custom_details.updated_at" + type = "regex" + value = "(.*)" + } + extractions { + target = "event.custom_details.message" + template = "Last modified by {{variables.user_id}} on {{variables.updated_at}}" + } + extractions { + regex = ".*" + source = "event.custom_details.region" + target = "event.group" + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1 updated" + conditions { + expression = "event.custom_details.timeout_err matches part 'timeout'" + } + actions { + route_to = "set-2" + priority = "P0IN2KR" + annotate = "Routed through a service orchestration!" + pagerduty_automation_actions { + action_id = "01CSB5SMOKCKVRI5GN0LJG7SMBUPDATED" + } + severity = "warning" + event_action = "resolve" + variables { + name = "cpu_val_upd" + path = "event.custom_details.cpu_upd" + type = "regex" + value = "CPU:(.*)" + } + extractions { + regex = ".*" + source = "event.custom_details.region_upd" + target = "event.source" + } + extractions { + target = "event.custom_details.message_upd" + template = "[UPD] High CPU usage on {{variables.hostname}}: {{variables.cpu_val}}" + } + } + } + } + sets { + id = "set-2" + rules { + label = "set-2 rule 1" + actions { + suspend = 15 + } + } + rules { + label = "set-2 rule 2" + conditions { + expression = "event.source matches part 'test-'" + } + actions { + annotate = "Matched set-2 rule 2" + variables { + name = "host_name" + path = "event.custom_details.memory" + type = "regex" + value = "High memory usage on (.*) server" + } + extractions { + target = "event.summary" + template = "High memory usage on {{variables.hostname}} server: {{event.custom_details.max_memory}}" + } + extractions { + regex = ".*" + source = "event.custom_details.region" + target = "event.group" + } + extractions { + regex = ".*" + source = "event.custom_details.hostname" + target = "event.source" + } + } + } + } + + catch_all { + actions { + suspend = 360 + suppress = true + priority = "P0IN2KX" + annotate = "[UPD] Routed through an event orchestration - catch-all rule" + pagerduty_automation_actions { + action_id = "01CSB5SMOKCKVRI5GN0LJG7SMD" + } + severity = "info" + event_action = "resolve" + variables { + name = "updated_at_upd" + path = "event.custom_details.updated_at" + type = "regex" + value = "UPD (.*)" + } + extractions { + regex = ".*" + source = "event.custom_details.region_upd" + target = "event.class" + } + } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsDeleteConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1 updated" + actions { + route_to = "set-2" + } + } + } + sets { + id = "set-2" + rules { + label = "set-2 rule 1" + actions { } + } + rules { + label = "set-2 rule 2" + actions { } + } + } + + catch_all { + actions { } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceOneSetNoActionsConfig(ep, s string) string { + return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), + `resource "pagerduty_event_orchestration_service" "serviceA" { + parent { + id = pagerduty_service.bar.id + } + + sets { + id = "start" + rules { + label = "rule 1 updated" + actions {} + } + } + + catch_all { + actions { } + } + } + `) +} + +func testAccCheckPagerDutyEventOrchestrationPathServiceResourceDeleteConfig(ep, s string) string { + return createBaseServicePathConfig(ep, s) +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 6c84d94da..8de2ae3f3 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -117,13 +117,21 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "regex": { + Type: schema.TypeString, + Optional: true, + }, + "source": { + Type: schema.TypeString, + Optional: true, + }, "target": { Type: schema.TypeString, Required: true, }, "template": { Type: schema.TypeString, - Required: true, + Optional: true, }, }}, }, @@ -201,13 +209,21 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "regex": { + Type: schema.TypeString, + Optional: true, + }, + "source": { + Type: schema.TypeString, + Optional: true, + }, "target": { Type: schema.TypeString, Required: true, }, "template": { Type: schema.TypeString, - Required: true, + Optional: true, }, }}, }, @@ -389,8 +405,8 @@ func expandUnroutedActions(v interface{}) *pagerduty.EventOrchestrationPathRuleA actions.RouteTo = am["route_to"].(string) actions.Severity = am["severity"].(string) actions.EventAction = am["event_action"].(string) - actions.Variables = expandUnroutedActionsVariables(am["variables"]) - actions.Extractions = expandUnroutedActionsExtractions(am["extractions"]) + actions.Variables = expandEventOrchestrationPathVariables(am["variables"]) + actions.Extractions = expandEventOrchestrationPathExtractions(am["extractions"]) } } @@ -414,39 +430,6 @@ func expandUnroutedConditions(v interface{}) []*pagerduty.EventOrchestrationPath return conditions } -func expandUnroutedActionsExtractions(v interface{}) []*pagerduty.EventOrchestrationPathActionExtractions { - unroutedExtractions := []*pagerduty.EventOrchestrationPathActionExtractions{} - - for _, eai := range v.([]interface{}) { - ea := eai.(map[string]interface{}) - ext := &pagerduty.EventOrchestrationPathActionExtractions{ - Target: ea["target"].(string), - Template: ea["template"].(string), - } - unroutedExtractions = append(unroutedExtractions, ext) - } - return unroutedExtractions -} - -func expandUnroutedActionsVariables(v interface{}) []*pagerduty.EventOrchestrationPathActionVariables { - unroutedVariables := []*pagerduty.EventOrchestrationPathActionVariables{} - - for _, er := range v.([]interface{}) { - rer := er.(map[string]interface{}) - - unroutedVar := &pagerduty.EventOrchestrationPathActionVariables{ - Name: rer["name"].(string), - Path: rer["path"].(string), - Type: rer["type"].(string), - Value: rer["value"].(string), - } - - unroutedVariables = append(unroutedVariables, unroutedVar) - } - - return unroutedVariables -} - func expandUnroutedCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { var catchAll = new(pagerduty.EventOrchestrationPathCatchAll) @@ -467,8 +450,8 @@ func expandUnroutedCatchAllActions(v interface{}) *pagerduty.EventOrchestrationP am := ai.(map[string]interface{}) actions.Severity = am["severity"].(string) actions.EventAction = am["event_action"].(string) - actions.Variables = expandUnroutedActionsVariables(am["variables"]) - actions.Extractions = expandUnroutedActionsExtractions(am["extractions"]) + actions.Variables = expandEventOrchestrationPathVariables(am["variables"]) + actions.Extractions = expandEventOrchestrationPathExtractions(am["extractions"]) } } @@ -528,10 +511,10 @@ func flattenUnroutedActions(actions *pagerduty.EventOrchestrationPathRuleActions } if actions.Variables != nil { - flattenedAction["variables"] = flattenUnroutedActionsVariables(actions.Variables) + flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) } - if actions.Variables != nil { - flattenedAction["extractions"] = flattenUnroutedActionsExtractions(actions.Extractions) + if actions.Extractions != nil { + flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) } actionsMap = append(actionsMap, flattenedAction) @@ -539,34 +522,6 @@ func flattenUnroutedActions(actions *pagerduty.EventOrchestrationPathRuleActions return actionsMap } -func flattenUnroutedActionsVariables(v []*pagerduty.EventOrchestrationPathActionVariables) []interface{} { - var flatVariablesList []interface{} - - for _, s := range v { - flatVariable := map[string]interface{}{ - "name": s.Name, - "path": s.Path, - "type": s.Type, - "value": s.Value, - } - flatVariablesList = append(flatVariablesList, flatVariable) - } - return flatVariablesList -} - -func flattenUnroutedActionsExtractions(e []*pagerduty.EventOrchestrationPathActionExtractions) []interface{} { - var flatExtractionsList []interface{} - - for _, s := range e { - flatExtraction := map[string]interface{}{ - "target": s.Target, - "template": s.Template, - } - flatExtractionsList = append(flatExtractionsList, flatExtraction) - } - return flatExtractionsList -} - func flattenUnroutedCatchAll(catchAll *pagerduty.EventOrchestrationPathCatchAll) []map[string]interface{} { var caMap []map[string]interface{} @@ -588,10 +543,10 @@ func flattenUnroutedCatchAllActions(actions *pagerduty.EventOrchestrationPathRul } if actions.Variables != nil { - flattenedAction["variables"] = flattenUnroutedActionsVariables(actions.Variables) + flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) } if actions.Variables != nil { - flattenedAction["extractions"] = flattenUnroutedActionsExtractions(actions.Extractions) + flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) } actionsMap = append(actionsMap, flattenedAction) diff --git a/pagerduty/util.go b/pagerduty/util.go index ea256a931..7689b8c45 100644 --- a/pagerduty/util.go +++ b/pagerduty/util.go @@ -145,3 +145,10 @@ func stringPtrToStringType(v *string) string { } return *v } + +func intTypeToIntPtr(v int) *int { + if v == 0 { + return nil + } + return &v +} diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go index e99c9e0bb..ddc7e0091 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go @@ -4,7 +4,6 @@ import ( "fmt" ) -// TODO: Check omitempty for all structs type EventOrchestrationPathService service type EventOrchestrationPath struct { @@ -29,13 +28,13 @@ type EventOrchestrationPathReference struct { type EventOrchestrationPathSet struct { ID string `json:"id,omitempty"` - Rules []*EventOrchestrationPathRule `json:"rules,omitempty"` + Rules []*EventOrchestrationPathRule `json:"rules"` } type EventOrchestrationPathRule struct { ID string `json:"id,omitempty"` Label string `json:"label,omitempty"` - Conditions []*EventOrchestrationPathRuleCondition `json:"conditions,omitempty"` + Conditions []*EventOrchestrationPathRuleCondition `json:"conditions"` Actions *EventOrchestrationPathRuleActions `json:"actions,omitempty"` Disabled bool `json:"disabled,omitempty"` } @@ -50,17 +49,17 @@ type EventOrchestrationPathRuleCondition struct { // Service: https://developer.pagerduty.com/api-reference/179537b835e2d-get-the-service-orchestration-for-a-service // Unrouted: https://developer.pagerduty.com/api-reference/70aa1139e1013-get-the-unrouted-orchestration-for-a-global-event-orchestration type EventOrchestrationPathRuleActions struct { - RouteTo string `json:"route_to,omitempty"` - Suppress bool `json:"suppress,omitempty"` - Suspend int `json:"suspend,omitempty"` - Priority string `json:"priority,omitempty"` - Annotate string `json:"annotate,omitempty"` - PagerdutyAutomationActions []*EventOrchestrationPathPagerdutyAutomationAction `json:"pagerduty_automation_actions,omitempty"` - AutomationActions []*EventOrchestrationPathAutomationAction `json:"automation_actions,omitempty"` - Severity string `json:"severity,omitempty"` - EventAction string `json:"event_action,omitempty"` - Variables []*EventOrchestrationPathActionVariables `json:"variables,omitempty"` - Extractions []*EventOrchestrationPathActionExtractions `json:"extractions,omitempty"` + RouteTo string `json:"route_to"` + Suppress bool `json:"suppress"` + Suspend *int `json:"suspend"` + Priority string `json:"priority"` + Annotate string `json:"annotate"` + PagerdutyAutomationActions []*EventOrchestrationPathPagerdutyAutomationAction `json:"pagerduty_automation_actions"` + AutomationActions []*EventOrchestrationPathAutomationAction `json:"automation_actions"` + Severity string `json:"severity"` + EventAction string `json:"event_action"` + Variables []*EventOrchestrationPathActionVariables `json:"variables"` + Extractions []*EventOrchestrationPathActionExtractions `json:"extractions"` } type EventOrchestrationPathPagerdutyAutomationAction struct { @@ -71,8 +70,8 @@ type EventOrchestrationPathAutomationAction struct { Name string `json:"name,omitempty"` Url string `json:"url,omitempty"` AutoSend bool `json:"auto_send,omitempty"` - Headers []*EventOrchestrationPathAutomationActionObject `json:"headers,omitempty"` - Parameters []*EventOrchestrationPathAutomationActionObject `json:"parameters,omitempty"` + Headers []*EventOrchestrationPathAutomationActionObject `json:"headers"` + Parameters []*EventOrchestrationPathAutomationActionObject `json:"parameters"` } type EventOrchestrationPathAutomationActionObject struct { @@ -89,7 +88,9 @@ type EventOrchestrationPathActionVariables struct { type EventOrchestrationPathActionExtractions struct { Target string `json:"target,omitempty"` + Regex string `json:"regex,omitempty"` Template string `json:"template,omitempty"` + Source string `json:"source,omitempty"` } type EventOrchestrationPathCatchAll struct { From 1c89062280f8854d840c3456ef63b77874fef1fc Mon Sep 17 00:00:00 2001 From: Alex Zakabluk Date: Fri, 20 May 2022 15:33:07 -0400 Subject: [PATCH 21/51] Flatten teams block (#506) * Flatten teams block * Fixed naming for the test orchestration --- .../resource_pagerduty_event_orchestration.go | 27 ++++--------------- ...urce_pagerduty_event_orchestration_test.go | 12 +++------ 2 files changed, 9 insertions(+), 30 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 75f0de9ba..154b0bbb0 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -28,17 +28,8 @@ func resourcePagerDutyEventOrchestration() *schema.Resource { Optional: true, }, "team": { - Type: schema.TypeList, + Type: schema.TypeString, Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Required: true, - }, - }, - }, }, "routes": { Type: schema.TypeInt, @@ -87,7 +78,9 @@ func buildEventOrchestrationStruct(d *schema.ResourceData) *pagerduty.EventOrche } if attr, ok := d.GetOk("team"); ok { - orchestration.Team = expandOrchestrationTeam(attr) + orchestration.Team = &pagerduty.EventOrchestrationObject{ + ID: stringTypeToStringPtr(attr.(string)), + } } else { var tId *string orchestration.Team = &pagerduty.EventOrchestrationObject{ @@ -98,16 +91,6 @@ func buildEventOrchestrationStruct(d *schema.ResourceData) *pagerduty.EventOrche return orchestration } -func expandOrchestrationTeam(v interface{}) *pagerduty.EventOrchestrationObject { - var team *pagerduty.EventOrchestrationObject - t := v.([]interface{})[0].(map[string]interface{}) - team = &pagerduty.EventOrchestrationObject{ - ID: stringTypeToStringPtr(t["id"].(string)), - } - - return team -} - func resourcePagerDutyEventOrchestrationCreate(d *schema.ResourceData, meta interface{}) error { client, err := meta.(*Config).Client() if err != nil { @@ -246,7 +229,7 @@ func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrches d.Set("routes", o.Routes) if o.Team != nil { - d.Set("team", flattenEventOrchestrationTeam(o.Team)) + d.Set("team", o.Team.ID) } if len(o.Integrations) > 0 { diff --git a/pagerduty/resource_pagerduty_event_orchestration_test.go b/pagerduty/resource_pagerduty_event_orchestration_test.go index 75288583b..6e39fa640 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_test.go @@ -54,7 +54,7 @@ func testSweepEventOrchestration(region string) error { } func TestAccPagerDutyEventOrchestration_Basic(t *testing.T) { - name := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + name := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5)) description := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) nameUpdated := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) descriptionUpdated := fmt.Sprintf("tf-description-%s", acctest.RandString(5)) @@ -175,7 +175,7 @@ func testAccCheckPagerDutyEventOrchestrationTeamMatch(orchName, teamName string) return fmt.Errorf("Not found: %s", teamName) } - var otId = o.Primary.Attributes["team.0.id"] + var otId = o.Primary.Attributes["team"] var tId = t.Primary.Attributes["id"] if otId != tId { @@ -207,9 +207,7 @@ resource "pagerduty_team" "bar" { resource "pagerduty_event_orchestration" "foo" { name = "%s" description = "%s" - team { - id = pagerduty_team.foo.id - } + team = pagerduty_team.foo.id } `, team1, team2, name, description) } @@ -226,9 +224,7 @@ resource "pagerduty_team" "bar" { resource "pagerduty_event_orchestration" "foo" { name = "%s" description = "%s" - team { - id = pagerduty_team.bar.id - } + team = pagerduty_team.bar.id } `, team1, team2, name, description) } From 8f4d19bc22c796b60c38a18d964fd4103f8b93d2 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 11:43:03 -0400 Subject: [PATCH 22/51] ORCA-3486 - remove team attribute from service path --- .../resource_pagerduty_event_orchestration_path_service.go | 5 ----- ...source_pagerduty_event_orchestration_path_service_test.go | 1 - 2 files changed, 6 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service.go b/pagerduty/resource_pagerduty_event_orchestration_path_service.go index 7b813cd51..6748c7518 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service.go @@ -175,10 +175,6 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { }, CustomizeDiff: checkExtractions, Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, - Computed: true, - }, "parent": { Type: schema.TypeList, Required: true, @@ -480,7 +476,6 @@ func expandEventOrchestrationAutomationActionObjects(v interface{}) []*pagerduty func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty.EventOrchestrationPath) error { d.SetId(p.Parent.ID) - d.Set("type", p.Type) d.Set("parent", flattenServicePathParent(p.Parent)) // TODO: see if we can reuse expand functions for all orch path sets. // Maybe pass in the rule actions and catch-all rule actions expanding function? diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go index 498c5f268..39efa3cf1 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go @@ -32,7 +32,6 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { baseChecks := []resource.TestCheckFunc{ testAccCheckPagerDutyEventOrchestrationPathServiceExists(resourceName), testAccCheckPagerDutyEventOrchestrationPathServiceParent(resourceName, serviceResourceName), - resource.TestCheckResourceAttr(resourceName, "type", "service"), } resource.Test(t, resource.TestCase{ From f1397abd61814d716eb47267f7c7fcc972ba5e43 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 12:23:40 -0400 Subject: [PATCH 23/51] flatten/rename parent to 'service' for service path --- ...erduty_event_orchestration_path_service.go | 26 ++------- ...y_event_orchestration_path_service_test.go | 56 +++++-------------- 2 files changed, 20 insertions(+), 62 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service.go b/pagerduty/resource_pagerduty_event_orchestration_path_service.go index 6748c7518..902f34cbc 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service.go @@ -175,13 +175,9 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { }, CustomizeDiff: checkExtractions, Schema: map[string]*schema.Schema{ - "parent": { - Type: schema.TypeList, + "service": { + Type: schema.TypeString, Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathParent, - }, }, "sets": { Type: schema.TypeList, @@ -320,13 +316,13 @@ func resourcePagerDutyEventOrchestrationPathServiceImport(d *schema.ResourceData id := d.Id() - p, _, pErr := client.EventOrchestrationPaths.Get(id, "service") + _, _, pErr := client.EventOrchestrationPaths.Get(id, "service") if pErr != nil { return []*schema.ResourceData{}, pErr } d.SetId(id) - d.Set("parent", flattenServicePathParent(p.Parent)) + d.Set("service", id) return []*schema.ResourceData{d}, nil } @@ -334,7 +330,7 @@ func resourcePagerDutyEventOrchestrationPathServiceImport(d *schema.ResourceData func buildServicePathStruct(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { return &pagerduty.EventOrchestrationPath{ Parent: &pagerduty.EventOrchestrationPathReference{ - ID: d.Get("parent.0.id").(string), + ID: d.Get("service").(string), }, Sets: expandServicePathSets(d.Get("sets")), CatchAll: expandServicePathCatchAll(d.Get("catch_all")), @@ -476,7 +472,7 @@ func expandEventOrchestrationAutomationActionObjects(v interface{}) []*pagerduty func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty.EventOrchestrationPath) error { d.SetId(p.Parent.ID) - d.Set("parent", flattenServicePathParent(p.Parent)) + d.Set("service", p.Parent.ID) // TODO: see if we can reuse expand functions for all orch path sets. // Maybe pass in the rule actions and catch-all rule actions expanding function? d.Set("sets", flattenServicePathSets(p.Sets)) @@ -484,16 +480,6 @@ func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty. return nil } -func flattenServicePathParent(p *pagerduty.EventOrchestrationPathReference) []interface{} { - var parent = map[string]interface{}{ - "id": p.ID, - "type": p.Type, - "self": p.Self, - } - - return []interface{}{parent} -} - func flattenServicePathSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interface{} { var flattenedSets []interface{} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go index 39efa3cf1..fb7bcb7a3 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go @@ -3,7 +3,6 @@ package pagerduty import ( "fmt" "regexp" - "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" @@ -31,7 +30,7 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { // "State value checking is only recommended for testing Computed attributes and attribute defaults." baseChecks := []resource.TestCheckFunc{ testAccCheckPagerDutyEventOrchestrationPathServiceExists(resourceName), - testAccCheckPagerDutyEventOrchestrationPathServiceParent(resourceName, serviceResourceName), + testAccCheckPagerDutyEventOrchestrationPathServiceServiceID(resourceName, serviceResourceName), } resource.Test(t, resource.TestCase{ @@ -222,7 +221,7 @@ func testAccCheckPagerDutyEventOrchestrationServicePathNotExists(rn string) reso } } -func testAccCheckPagerDutyEventOrchestrationPathServiceParent(rn, sn string) resource.TestCheckFunc { +func testAccCheckPagerDutyEventOrchestrationPathServiceServiceID(rn, sn string) resource.TestCheckFunc { return func(s *terraform.State) error { p, _ := s.RootModule().Resources[rn] srv, ok := s.RootModule().Resources[sn] @@ -231,20 +230,10 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceParent(rn, sn string) res return fmt.Errorf("Service not found: %s", sn) } - var pId = p.Primary.Attributes["parent.0.id"] + var pId = p.Primary.Attributes["service"] var sId = srv.Primary.Attributes["id"] if pId != sId { - return fmt.Errorf("Event Orchestration Service path parent ID (%v) not matching provided service ID: %v", pId, sId) - } - - var t = p.Primary.Attributes["parent.0.type"] - if t != "service_reference" { - return fmt.Errorf("Event Orchestration Service path parent type (%v) not matching expected type: 'service_reference'", t) - } - - var self = p.Primary.Attributes["parent.0.self"] - if !strings.HasSuffix(self, sId) { - return fmt.Errorf("Event Orchestration Service path parent self URL (%v) not containing expected service ID", self) + return fmt.Errorf("Event Orchestration Service path service ID (%v) not matching provided service ID: %v", pId, sId) } return nil @@ -291,9 +280,7 @@ func createBaseServicePathConfig(ep, s string) string { func testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -309,9 +296,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(ep, s strin func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -379,9 +364,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(e func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUpdateConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -430,9 +413,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUp func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsDeleteConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -464,9 +445,8 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( "%s%s", createBaseServicePathConfig(ep, s), fmt.Sprintf(`resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id + sets { id = "start" rules { @@ -512,9 +492,7 @@ func invalidExtractionRegexNilSourceConfig() string { func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -618,9 +596,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s st func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -726,9 +702,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(ep func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsDeleteConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" @@ -761,9 +735,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsDeleteConfig(ep func testAccCheckPagerDutyEventOrchestrationPathServiceOneSetNoActionsConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { - parent { - id = pagerduty_service.bar.id - } + service = pagerduty_service.bar.id sets { id = "start" From 91b1c62dbe72c709cfc3a43e9f3dbc9fa7d6bbe5 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 13:37:21 -0400 Subject: [PATCH 24/51] remove type attribute from unrouted --- ...e_pagerduty_event_orchestration_path_unrouted.go | 8 -------- ...erduty_event_orchestration_path_unrouted_test.go | 13 +++---------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 8de2ae3f3..f3de2ef31 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -20,10 +20,6 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { State: resourcePagerDutyEventOrchestrationPathUnroutedImport, }, Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, - Computed: true, - }, "parent": { Type: schema.TypeList, Required: true, @@ -251,8 +247,6 @@ func resourcePagerDutyEventOrchestrationPathUnroutedRead(d *schema.ResourceData, time.Sleep(2 * time.Second) return resource.RetryableError(err) } else if unroutedPath != nil { - d.Set("type", unroutedPath.Type) - if unroutedPath.Sets != nil { d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) } @@ -299,9 +293,7 @@ func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.E if updatedPath == nil { return resource.NonRetryableError(fmt.Errorf("no event orchestration unrouted found")) } - // set props d.SetId(unroutedPath.Parent.ID) - d.Set("type", updatedPath.Type) if unroutedPath.Sets != nil { d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index ced0a0e05..c7065d624 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -31,8 +31,6 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "type", "unrouted"), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), ), @@ -156,8 +154,6 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "type", "unrouted"), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), ), @@ -195,18 +191,15 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedExists(rn string) resour return fmt.Errorf("Not found: %s", rn) } if rs.Primary.ID == "" { - return fmt.Errorf("No Event Orchestration Path Type is set") + return fmt.Errorf("No Event Orchestration Unrouted Path is set") } orch := s.RootModule().Resources["pagerduty_event_orchestration.orch"] client, _ := testAccProvider.Meta().(*Config).Client() - found, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "unrouted") + _, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "unrouted") if err != nil { - return fmt.Errorf("Orchestration Path type not found: %v for orchestration %v", "unrouted", orch.Primary.ID) - } - if found.Type != "unrouted" { - return fmt.Errorf("Event Orchrestration path not found: %v - %v", "unrouted", found) + return fmt.Errorf("Event Orchestration Unrouted Path not found: %v for orchestration %v", "unrouted", orch.Primary.ID) } return nil From 468d254823cf7ccbd34df91dcf6641bc5431737f Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 13:49:24 -0400 Subject: [PATCH 25/51] remove type attribute from router --- ...urce_pagerduty_event_orchestration_path_router.go | 8 -------- ...pagerduty_event_orchestration_path_router_test.go | 12 +++--------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index 4cd3d52d3..8db81f236 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -20,10 +20,6 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { State: resourcePagerDutyEventOrchestrationPathRouterImport, }, Schema: map[string]*schema.Schema{ - "type": { - Type: schema.TypeString, - Computed: true, - }, "parent": { Type: schema.TypeList, Required: true, @@ -131,8 +127,6 @@ func resourcePagerDutyEventOrchestrationPathRouterRead(d *schema.ResourceData, m time.Sleep(2 * time.Second) return resource.RetryableError(err) } else if routerPath != nil { - d.Set("type", routerPath.Type) - if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) } @@ -178,9 +172,7 @@ func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.Event if updatedPath == nil { return resource.NonRetryableError(fmt.Errorf("No Event Orchestration Router found.")) } - // set props d.SetId(routerPath.Parent.ID) - d.Set("type", updatedPath.Type) if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index 9ecaa1acd..8cc79aefc 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -31,8 +31,6 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Config: testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "type", "router"), testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( "pagerduty_event_orchestration_router.router", "unrouted", true), //test for catch_all route_to prop, by default it should be unrouted resource.TestCheckResourceAttr( @@ -43,8 +41,6 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Config: testAccCheckPagerDutyEventOrchestrationRouterConfig(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "type", "router"), testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", false), // test for rule action route_to testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( @@ -134,19 +130,17 @@ func testAccCheckPagerDutyEventOrchestrationRouterExists(rn string) resource.Tes return fmt.Errorf("Not found: %s", rn) } if rs.Primary.ID == "" { - return fmt.Errorf("No Event Orchestration Path Type is set") + return fmt.Errorf("No Event Orchestration Router is set") } orch, _ := s.RootModule().Resources["pagerduty_event_orchestration.orch"] client, _ := testAccProvider.Meta().(*Config).Client() - found, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "router") + _, _, err := client.EventOrchestrationPaths.Get(orch.Primary.ID, "router") if err != nil { return fmt.Errorf("Orchestration Path type not found: %v for orchestration %v", "router", orch.Primary.ID) } - if found.Type != "router" { - return fmt.Errorf("Event Orchrestration path not found: %v - %v", "router", found) - } + return nil } } From 8db156a3f3c58ce19387e02ed34c7e4b05eea2a4 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 14:50:28 -0400 Subject: [PATCH 26/51] flatten/rename parent to 'event_orchestration' for router --- ...gerduty_event_orchestration_path_router.go | 39 +-- ...ty_event_orchestration_path_router_test.go | 280 +++++++++--------- 2 files changed, 144 insertions(+), 175 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index 8db81f236..5123c0b28 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -20,13 +20,9 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { State: resourcePagerDutyEventOrchestrationPathRouterImport, }, Schema: map[string]*schema.Schema{ - "parent": { - Type: schema.TypeList, + "event_orchestration": { + Type: schema.TypeString, Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathParent, - }, }, "sets": { Type: schema.TypeList, @@ -127,6 +123,8 @@ func resourcePagerDutyEventOrchestrationPathRouterRead(d *schema.ResourceData, m time.Sleep(2 * time.Second) return resource.RetryableError(err) } else if routerPath != nil { + d.Set("event_orchestration", routerPath.Parent.ID) + if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) } @@ -173,6 +171,7 @@ func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.Event return resource.NonRetryableError(fmt.Errorf("No Event Orchestration Router found.")) } d.SetId(routerPath.Parent.ID) + d.Set("event_orchestration", routerPath.Parent.ID) if routerPath.Sets != nil { d.Set("sets", flattenSets(routerPath.Sets)) @@ -189,22 +188,12 @@ func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.Event return nil } -func buildRouterPathParent(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { - orchPath := &pagerduty.EventOrchestrationPath{} - - if attr, ok := d.GetOk("parent"); ok { - orchPath.Parent = expandOrchestrationPathParent(attr) - } - - return orchPath -} - func buildRouterPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { - orchPath := buildRouterPathParent(d) - - if attr, ok := d.GetOk("parent"); ok { - orchPath.Parent = expandOrchestrationPathParent(attr) + orchPath := &pagerduty.EventOrchestrationPath{ + Parent: &pagerduty.EventOrchestrationPathReference{ + ID: d.Get("event_orchestration").(string), + }, } if attr, ok := d.GetOk("sets"); ok { @@ -218,16 +207,6 @@ func buildRouterPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrch return orchPath } -func expandOrchestrationPathParent(v interface{}) *pagerduty.EventOrchestrationPathReference { - var parent *pagerduty.EventOrchestrationPathReference - p := v.([]interface{})[0].(map[string]interface{}) - parent = &pagerduty.EventOrchestrationPathReference{ - ID: p["id"].(string), - } - - return parent -} - func expandSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { var sets []*pagerduty.EventOrchestrationPathSet diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index 8cc79aefc..b7324fc8e 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -207,205 +207,195 @@ func createBaseConfig(t, ep, s, o string) string { func testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = "unrouted" + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" } } - sets { - id = "start" - } - } `) } func testAccCheckPagerDutyEventOrchestrationRouterConfig(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = "unrouted" - } - } - sets { - id = "start" - rules { - disabled = false - label = "rule1 label" + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { actions { - route_to = pagerduty_service.bar.id + route_to = "unrouted" + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } } } } - } `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), - ` -resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = "unrouted" - } - } - sets { - id = "start" - rules { - disabled = false - label = "rule1 label" - actions { - route_to = pagerduty_service.bar.id + `resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = "unrouted" + } } - conditions { - expression = "event.summary matches part 'database'" + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.summary matches part 'database'" + } + } } } - } -} -`) + `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(t, ep, s, o string) string { return fmt.Sprintf( "%s%s", createBaseConfig(t, ep, s, o), - ` -resource "pagerduty_service" "bar2" { - name = "tf-barService2" - escalation_policy = pagerduty_escalation_policy.foo.id - - incident_urgency_rule { - type = "constant" - urgency = "high" - } -} + `resource "pagerduty_service" "bar2" { + name = "tf-barService2" + escalation_policy = pagerduty_escalation_policy.foo.id -resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = "unrouted" - } - } - sets { - id = "start" - rules { - disabled = false - label = "rule1 label" - actions { - route_to = pagerduty_service.bar.id - } - conditions { - expression = "event.summary matches part 'database'" - } - conditions { - expression = "event.severity matches part 'critical'" + incident_urgency_rule { + type = "constant" + urgency = "high" } } - rules { - disabled = false - label = "rule2 label" - actions { - route_to = pagerduty_service.bar2.id + resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = "unrouted" + } } - conditions { - expression = "event.severity matches part 'critical'" + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.summary matches part 'database'" + } + conditions { + expression = "event.severity matches part 'critical'" + } + } + + rules { + disabled = false + label = "rule2 label" + actions { + route_to = pagerduty_service.bar2.id + } + conditions { + expression = "event.severity matches part 'critical'" + } + } } } - } -} -`) + `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), - ` -resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = pagerduty_service.bar.id - } - } - sets { - id = "start" - rules { - disabled = false - label = "rule1 label" - actions { - route_to = pagerduty_service.bar.id + `resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = pagerduty_service.bar.id + } + } + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + } } } - } -} -`) + `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), - ` -resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = pagerduty_service.bar.id - } - } - sets { - id = "start" - rules { - disabled = false - label = "rule1 label" - actions { - route_to = pagerduty_service.bar.id + `resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = pagerduty_service.bar.id + } } - conditions { - expression = "event.severity matches part 'critical'" + sets { + id = "start" + rules { + disabled = false + label = "rule1 label" + actions { + route_to = pagerduty_service.bar.id + } + conditions { + expression = "event.severity matches part 'critical'" + } + } } } - } -} -`) + `) } func testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), - ` -resource "pagerduty_event_orchestration_router" "router" { - parent { - id = pagerduty_event_orchestration.orch.id - } - catch_all { - actions { - route_to = pagerduty_service.bar.id + `resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.orch.id + + catch_all { + actions { + route_to = pagerduty_service.bar.id + } + } + sets { + id = "start" + } } - } - sets { - id = "start" - } -} -`) + `) } + func testAccCheckPagerDutyEventOrchestrationRouterConfigDelete(t, ep, s, o string) string { return createBaseConfig(t, ep, s, o) } + func testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(router, service string, catchAll bool) resource.TestCheckFunc { return func(s *terraform.State) error { r, rOk := s.RootModule().Resources[router] From 2d4ac6b0474453f1fe4abc2e107c36c22a34a47d Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 14:58:38 -0400 Subject: [PATCH 27/51] set event_orchestration attr on router import --- pagerduty/resource_pagerduty_event_orchestration_path_router.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index 5123c0b28..ebbd6b5e5 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -359,6 +359,7 @@ func resourcePagerDutyEventOrchestrationPathRouterImport(d *schema.ResourceData, } d.SetId(orchestrationID) + d.Set("event_orchestration", orchestrationID) return []*schema.ResourceData{d}, nil } From 4f8f3aa18e9c868cdd288f1f7f28f04a05a9c807 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 20 May 2022 15:15:51 -0400 Subject: [PATCH 28/51] flatten/rename parent to 'event_orchestration' for unrouted --- ...rduty_event_orchestration_path_unrouted.go | 38 ++++--------------- ..._event_orchestration_path_unrouted_test.go | 20 ++++------ 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index f3de2ef31..103510eab 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -20,13 +20,9 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { State: resourcePagerDutyEventOrchestrationPathUnroutedImport, }, Schema: map[string]*schema.Schema{ - "parent": { - Type: schema.TypeList, + "event_orchestration": { + Type: schema.TypeString, Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathParent, - }, }, "sets": { Type: schema.TypeList, @@ -294,6 +290,7 @@ func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.E return resource.NonRetryableError(fmt.Errorf("no event orchestration unrouted found")) } d.SetId(unroutedPath.Parent.ID) + d.Set("event_orchestration", unroutedPath.Parent.ID) if unroutedPath.Sets != nil { d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) } @@ -309,22 +306,12 @@ func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.E return nil } -func buildUnroutedPathParent(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { - orchPath := &pagerduty.EventOrchestrationPath{} - - if attr, ok := d.GetOk("parent"); ok { - orchPath.Parent = expandOrchestrationPathUnroutedParent(attr) - } - - return orchPath -} - func buildUnroutedPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrchestrationPath { - orchPath := buildUnroutedPathParent(d) - - if attr, ok := d.GetOk("parent"); ok { - orchPath.Parent = expandOrchestrationPathUnroutedParent(attr) + orchPath := &pagerduty.EventOrchestrationPath{ + Parent: &pagerduty.EventOrchestrationPathReference{ + ID: d.Get("event_orchestration").(string), + }, } if attr, ok := d.GetOk("sets"); ok { @@ -338,16 +325,6 @@ func buildUnroutedPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOr return orchPath } -func expandOrchestrationPathUnroutedParent(v interface{}) *pagerduty.EventOrchestrationPathReference { - var parent *pagerduty.EventOrchestrationPathReference - p := v.([]interface{})[0].(map[string]interface{}) - parent = &pagerduty.EventOrchestrationPathReference{ - ID: p["id"].(string), - } - - return parent -} - func expandUnroutedSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { var sets []*pagerduty.EventOrchestrationPathSet @@ -561,6 +538,7 @@ func resourcePagerDutyEventOrchestrationPathUnroutedImport(d *schema.ResourceDat } d.SetId(orchestrationID) + d.Set("event_orchestration", orchestrationID) return []*schema.ResourceData{d}, nil } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index c7065d624..deedb301e 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -266,9 +266,8 @@ func createUnroutedBaseConfig(t, ep, s, o string) string { func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - parent { - id = pagerduty_event_orchestration.orch.id - } + event_orchestration = pagerduty_event_orchestration.orch.id + sets { id = "start" } @@ -282,9 +281,8 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - parent { - id = pagerduty_event_orchestration.orch.id - } + event_orchestration = pagerduty_event_orchestration.orch.id + sets { id = "start" rules { @@ -306,9 +304,8 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - parent { - id = pagerduty_event_orchestration.orch.id - } + event_orchestration = pagerduty_event_orchestration.orch.id + sets { id = "start" rules { @@ -342,9 +339,8 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules( func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, o string) string { return fmt.Sprintf("%s%s", createUnroutedBaseConfig(t, ep, s, o), `resource "pagerduty_event_orchestration_unrouted" "unrouted" { - parent { - id = pagerduty_event_orchestration.orch.id - } + event_orchestration = pagerduty_event_orchestration.orch.id + sets { id = "start" rules { From 5c91e514944aaeb78d14c655f564fea1b8f258dd Mon Sep 17 00:00:00 2001 From: azakabluk Date: Fri, 20 May 2022 15:48:19 -0400 Subject: [PATCH 29/51] Clean teams block --- ...resource_pagerduty_event_orchestration_path_router_test.go | 4 +--- ...source_pagerduty_event_orchestration_path_unrouted_test.go | 4 +--- website/docs/r/event_orchestration_resource.html.markdown | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index b7324fc8e..d38480e18 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -197,9 +197,7 @@ func createBaseConfig(t, ep, s, o string) string { resource "pagerduty_event_orchestration" "orch" { name = "%s" - team { - id = pagerduty_team.foo.id - } + team = pagerduty_team.foo.id } `, t, ep, s, o) } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index deedb301e..e646793c1 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -256,9 +256,7 @@ func createUnroutedBaseConfig(t, ep, s, o string) string { } resource "pagerduty_event_orchestration" "orch" { name = "%s" - team { - id = pagerduty_team.foo.id - } + team = pagerduty_team.foo.id } `, t, ep, s, o) } diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown index 25e106f4c..2340701c4 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -27,9 +27,7 @@ resource "pagerduty_team" "engineering" { resource "pagerduty_event_orchestration" "my_monitor" { name = "My Monitoring Orchestration" description = "Send events to a pair of services" - team { - id = pagerduty_team.foo.id - } + team = pagerduty_team.foo.id } ``` From 62f424c3daff1ab515419df9c1b9344cf80caa38 Mon Sep 17 00:00:00 2001 From: azakabluk Date: Fri, 20 May 2022 16:03:36 -0400 Subject: [PATCH 30/51] revert changes on web file --- website/docs/r/event_orchestration_resource.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown index 2340701c4..25e106f4c 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -27,7 +27,9 @@ resource "pagerduty_team" "engineering" { resource "pagerduty_event_orchestration" "my_monitor" { name = "My Monitoring Orchestration" description = "Send events to a pair of services" - team = pagerduty_team.foo.id + team { + id = pagerduty_team.foo.id + } } ``` From 8170b513c744505a0f3865120c8a2c88b7116897 Mon Sep 17 00:00:00 2001 From: alenapan <47909261+alenapan@users.noreply.github.com> Date: Fri, 20 May 2022 18:21:58 -0400 Subject: [PATCH 31/51] [ORCA-3486] - Reuse shared Event Orchestration Path logic, add import tests (#509) * ORCA-3486 - add import tests for router/unrouted * ORCA-3486 - add import tests for router, unrouted * reuse severity/event_action validation functions in unrouted/service * reuse variables and extractions schema in router/unrouted * reuse shared conditions schema and mapping functions in router/unrouted/service --- pagerduty/event_orchestration_path_util.go | 82 +++++++++- ...ty_event_orchestration_path_router_test.go | 38 +++++ ...y_event_orchestration_path_service_test.go | 2 +- ..._event_orchestration_path_unrouted_test.go | 38 +++++ ...gerduty_event_orchestration_path_router.go | 38 +---- ...erduty_event_orchestration_path_service.go | 104 ++++--------- ...rduty_event_orchestration_path_unrouted.go | 140 +++--------------- 7 files changed, 205 insertions(+), 237 deletions(-) create mode 100644 pagerduty/import_pagerduty_event_orchestration_path_router_test.go create mode 100644 pagerduty/import_pagerduty_event_orchestration_path_unrouted_test.go diff --git a/pagerduty/event_orchestration_path_util.go b/pagerduty/event_orchestration_path_util.go index 7891cefda..9aa5dbc24 100644 --- a/pagerduty/event_orchestration_path_util.go +++ b/pagerduty/event_orchestration_path_util.go @@ -7,26 +7,65 @@ import ( "github.com/heimweh/go-pagerduty/pagerduty" ) -var PagerDutyEventOrchestrationPathParent = map[string]*schema.Schema{ - "id": { +var eventOrchestrationPathConditionsSchema = map[string]*schema.Schema{ + "expression": { + Type: schema.TypeString, + Required: true, + }, +} + +var eventOrchestrationPathVariablesSchema = map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "path": { Type: schema.TypeString, Required: true, }, "type": { Type: schema.TypeString, - Computed: true, + Required: true, }, - "self": { + "value": { Type: schema.TypeString, - Computed: true, + Required: true, }, } -var PagerDutyEventOrchestrationPathConditions = map[string]*schema.Schema{ - "expression": { +var eventOrchestrationPathExtractionsSchema = map[string]*schema.Schema{ + "regex": { + Type: schema.TypeString, + Optional: true, + }, + "source": { + Type: schema.TypeString, + Optional: true, + }, + "target": { Type: schema.TypeString, Required: true, }, + "template": { + Type: schema.TypeString, + Optional: true, + }, +} + +func validateEventOrchestrationPathSeverity() schema.SchemaValidateFunc { + return validateValueFunc([]string{ + "info", + "error", + "warning", + "critical", + }) +} + +func validateEventOrchestrationPathEventAction() schema.SchemaValidateFunc { + return validateValueFunc([]string{ + "trigger", + "resolve", + }) } func checkExtractions(context context.Context, diff *schema.ResourceDiff, i interface{}) error { @@ -66,6 +105,35 @@ func checkExtractionAttributes(diff *schema.ResourceDiff, loc string) error { return nil } +func expandEventOrchestrationPathConditions(v interface{}) []*pagerduty.EventOrchestrationPathRuleCondition { + conditions := []*pagerduty.EventOrchestrationPathRuleCondition{} + + for _, cond := range v.([]interface{}) { + c := cond.(map[string]interface{}) + + cx := &pagerduty.EventOrchestrationPathRuleCondition{ + Expression: c["expression"].(string), + } + + conditions = append(conditions, cx) + } + + return conditions +} + +func flattenEventOrchestrationPathConditions(conditions []*pagerduty.EventOrchestrationPathRuleCondition) []interface{} { + var flattendConditions []interface{} + + for _, condition := range conditions { + flattendCondition := map[string]interface{}{ + "expression": condition.Expression, + } + flattendConditions = append(flattendConditions, flattendCondition) + } + + return flattendConditions +} + func expandEventOrchestrationPathVariables(v interface{}) []*pagerduty.EventOrchestrationPathActionVariables { res := []*pagerduty.EventOrchestrationPathActionVariables{} diff --git a/pagerduty/import_pagerduty_event_orchestration_path_router_test.go b/pagerduty/import_pagerduty_event_orchestration_path_router_test.go new file mode 100644 index 000000000..976e80057 --- /dev/null +++ b/pagerduty/import_pagerduty_event_orchestration_path_router_test.go @@ -0,0 +1,38 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccPagerDutyEventOrchestrationPathRouter_import(t *testing.T) { + team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationRouterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(team, escalationPolicy, service, orchestration), + }, + { + ResourceName: "pagerduty_event_orchestration_router.router", + ImportStateIdFunc: testAccCheckPagerDutyEventOrchestrationPathRouterID, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationPathRouterID(s *terraform.State) (string, error) { + return s.RootModule().Resources["pagerduty_event_orchestration.orch"].Primary.ID, nil +} diff --git a/pagerduty/import_pagerduty_event_orchestration_path_service_test.go b/pagerduty/import_pagerduty_event_orchestration_path_service_test.go index afa007a85..579d2c957 100644 --- a/pagerduty/import_pagerduty_event_orchestration_path_service_test.go +++ b/pagerduty/import_pagerduty_event_orchestration_path_service_test.go @@ -19,7 +19,7 @@ func TestAccPagerDutyEventOrchestrationPathService_import(t *testing.T) { CheckDestroy: testAccCheckPagerDutyEventOrchestrationServicePathDestroy, Steps: []resource.TestStep{ { - Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(escalationPolicy, service), + Config: testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(escalationPolicy, service), }, { ResourceName: "pagerduty_event_orchestration_service.serviceA", diff --git a/pagerduty/import_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/import_pagerduty_event_orchestration_path_unrouted_test.go new file mode 100644 index 000000000..9ab539ba4 --- /dev/null +++ b/pagerduty/import_pagerduty_event_orchestration_path_unrouted_test.go @@ -0,0 +1,38 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccPagerDutyEventOrchestrationPathUnrouted_import(t *testing.T) { + team := fmt.Sprintf("tf-name-%s", acctest.RandString(5)) + escalationPolicy := fmt.Sprintf("tf-%s", acctest.RandString(5)) + service := fmt.Sprintf("tf-%s", acctest.RandString(5)) + orchestration := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPagerDutyEventOrchestrationPathUnroutedDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(team, escalationPolicy, service, orchestration), + }, + { + ResourceName: "pagerduty_event_orchestration_unrouted.unrouted", + ImportStateIdFunc: testAccCheckPagerDutyEventOrchestrationPathUnroutedID, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedID(s *terraform.State) (string, error) { + return s.RootModule().Resources["pagerduty_event_orchestration.orch"].Primary.ID, nil +} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index ebbd6b5e5..b8a763b2b 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -51,7 +51,7 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathConditions, + Schema: eventOrchestrationPathConditionsSchema, }, }, "actions": { @@ -235,8 +235,8 @@ func expandRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { ID: r["id"].(string), Label: r["label"].(string), Disabled: r["disabled"].(bool), - Conditions: expandRouterConditions(r["conditions"].(interface{})), - Actions: expandRouterActions(r["actions"].([]interface{})), + Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Actions: expandRouterActions(r["actions"]), } rules = append(rules, ruleInSet) @@ -244,23 +244,6 @@ func expandRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { return rules } -func expandRouterConditions(v interface{}) []*pagerduty.EventOrchestrationPathRuleCondition { - items := v.([]interface{}) - conditions := []*pagerduty.EventOrchestrationPathRuleCondition{} - - for _, cond := range items { - c := cond.(map[string]interface{}) - - cx := &pagerduty.EventOrchestrationPathRuleCondition{ - Expression: c["expression"].(string), - } - - conditions = append(conditions, cx) - } - - return conditions -} - func expandRouterActions(v interface{}) *pagerduty.EventOrchestrationPathRuleActions { var actions = new(pagerduty.EventOrchestrationPathRuleActions) for _, ai := range v.([]interface{}) { @@ -302,7 +285,7 @@ func flattenRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { "id": rule.ID, "label": rule.Label, "disabled": rule.Disabled, - "conditions": flattenRouterConditions(rule.Conditions), + "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), "actions": flattenRouterActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) @@ -311,19 +294,6 @@ func flattenRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { return flattenedRules } -func flattenRouterConditions(conditions []*pagerduty.EventOrchestrationPathRuleCondition) []interface{} { - var flattendConditions []interface{} - - for _, condition := range conditions { - flattendCondition := map[string]interface{}{ - "expression": condition.Expression, - } - flattendConditions = append(flattendConditions, flattendCondition) - } - - return flattendConditions -} - func flattenRouterActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { var actionsMap []map[string]interface{} diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service.go b/pagerduty/resource_pagerduty_event_orchestration_path_service.go index 902f34cbc..fb7dcd199 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service.go @@ -9,7 +9,7 @@ import ( "github.com/heimweh/go-pagerduty/pagerduty" ) -var eventOrchestrationAutomationActionObject = map[string]*schema.Schema{ +var eventOrchestrationAutomationActionObjectSchema = map[string]*schema.Schema{ "key": { Type: schema.TypeString, Required: true, @@ -20,7 +20,7 @@ var eventOrchestrationAutomationActionObject = map[string]*schema.Schema{ }, } -var eventOrchestrationPathServiceCatchAllActions = map[string]*schema.Schema{ +var eventOrchestrationPathServiceCatchAllActionsSchema = map[string]*schema.Schema{ "suppress": { Type: schema.TypeBool, Optional: true, @@ -73,89 +73,49 @@ var eventOrchestrationPathServiceCatchAllActions = map[string]*schema.Schema{ Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: eventOrchestrationAutomationActionObject, + Schema: eventOrchestrationAutomationActionObjectSchema, }, }, "parameters": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: eventOrchestrationAutomationActionObject, + Schema: eventOrchestrationAutomationActionObjectSchema, }, }, }, }, }, "severity": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateValueFunc([]string{ - "info", - "error", - "warning", - "critical", - }), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateEventOrchestrationPathSeverity(), }, "event_action": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateValueFunc([]string{ - "trigger", - "resolve", - }), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateEventOrchestrationPathEventAction(), }, "variables": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "path": { - Type: schema.TypeString, - Required: true, - }, - "type": { - Type: schema.TypeString, - Required: true, - }, - "value": { - Type: schema.TypeString, - Required: true, - }, - }}, + Schema: eventOrchestrationPathVariablesSchema, + }, }, "extractions": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "regex": { - Type: schema.TypeString, - Optional: true, - }, - "source": { - Type: schema.TypeString, - Optional: true, - }, - "target": { - Type: schema.TypeString, - Required: true, - }, - "template": { - Type: schema.TypeString, - Optional: true, - }, - }}, + Schema: eventOrchestrationPathExtractionsSchema, + }, }, } -var eventOrchestrationPathServiceRuleActions = buildEventOrchestrationPathServiceRuleActions() +var eventOrchestrationPathServiceRuleActionsSchema = buildEventOrchestrationPathServiceRuleActionsSchema() -func buildEventOrchestrationPathServiceRuleActions() map[string]*schema.Schema { - a := eventOrchestrationPathServiceCatchAllActions +func buildEventOrchestrationPathServiceRuleActionsSchema() map[string]*schema.Schema { + a := eventOrchestrationPathServiceCatchAllActionsSchema a["route_to"] = &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -205,7 +165,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathConditions, + Schema: eventOrchestrationPathConditionsSchema, }, }, "actions": { @@ -213,7 +173,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Required: true, MaxItems: 1, Elem: &schema.Resource{ - Schema: eventOrchestrationPathServiceRuleActions, + Schema: eventOrchestrationPathServiceRuleActionsSchema, }, }, "disabled": { @@ -237,7 +197,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Required: true, MaxItems: 1, Elem: &schema.Resource{ - Schema: eventOrchestrationPathServiceRuleActions, + Schema: eventOrchestrationPathServiceRuleActionsSchema, }, }, }, @@ -337,8 +297,6 @@ func buildServicePathStruct(d *schema.ResourceData) *pagerduty.EventOrchestratio } } -// TODO: see if we can reuse expand functions for all orch path sets. -// Maybe pass in the rule actions and catch-all rule actions expanding function? func expandServicePathSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { var sets []*pagerduty.EventOrchestrationPathSet @@ -364,12 +322,11 @@ func expandServicePathRules(v interface{}) []*pagerduty.EventOrchestrationPathRu r := rule.(map[string]interface{}) ruleInSet := &pagerduty.EventOrchestrationPathRule{ - ID: r["id"].(string), - Label: r["label"].(string), - Disabled: r["disabled"].(bool), - // TODO: move conditions logic to util - Conditions: expandRouterConditions(r["conditions"].(interface{})), - Actions: expandServicePathActions(r["actions"].([]interface{})), + ID: r["id"].(string), + Label: r["label"].(string), + Disabled: r["disabled"].(bool), + Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Actions: expandServicePathActions(r["actions"]), } rules = append(rules, ruleInSet) @@ -473,8 +430,6 @@ func expandEventOrchestrationAutomationActionObjects(v interface{}) []*pagerduty func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty.EventOrchestrationPath) error { d.SetId(p.Parent.ID) d.Set("service", p.Parent.ID) - // TODO: see if we can reuse expand functions for all orch path sets. - // Maybe pass in the rule actions and catch-all rule actions expanding function? d.Set("sets", flattenServicePathSets(p.Sets)) d.Set("catch_all", flattenServicePathCatchAll(p.CatchAll)) return nil @@ -509,11 +464,10 @@ func flattenServicePathRules(rules []*pagerduty.EventOrchestrationPathRule) []in for _, rule := range rules { flattenedRule := map[string]interface{}{ - "id": rule.ID, - "label": rule.Label, - "disabled": rule.Disabled, - // TODO: move conditions logic to util - "conditions": flattenRouterConditions(rule.Conditions), + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), "actions": flattenServicePathActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 103510eab..8d3543041 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -51,7 +51,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: PagerDutyEventOrchestrationPathConditions, + Schema: eventOrchestrationPathConditionsSchema, }, }, "actions": { @@ -65,67 +65,28 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Optional: true, // If there is only start set we don't need route_to }, "severity": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateValueFunc([]string{ - "info", - "error", - "warning", - "critical", - }), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateEventOrchestrationPathSeverity(), }, "event_action": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateValueFunc([]string{ - "trigger", - "resolve", - }), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateEventOrchestrationPathEventAction(), }, "variables": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "path": { - Type: schema.TypeString, - Required: true, - }, - "type": { - Type: schema.TypeString, - Required: true, - }, - "value": { - Type: schema.TypeString, - Required: true, - }, - }}}, + Schema: eventOrchestrationPathVariablesSchema, + }, + }, "extractions": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "regex": { - Type: schema.TypeString, - Optional: true, - }, - "source": { - Type: schema.TypeString, - Optional: true, - }, - "target": { - Type: schema.TypeString, - Required: true, - }, - "template": { - Type: schema.TypeString, - Optional: true, - }, - }}, + Schema: eventOrchestrationPathExtractionsSchema, + }, }, }, }, @@ -178,46 +139,15 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "path": { - Type: schema.TypeString, - Required: true, - }, - "type": { - Type: schema.TypeString, - Required: true, - }, - "value": { - Type: schema.TypeString, - Required: true, - }, - }}}, + Schema: eventOrchestrationPathVariablesSchema, + }, + }, "extractions": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "regex": { - Type: schema.TypeString, - Optional: true, - }, - "source": { - Type: schema.TypeString, - Optional: true, - }, - "target": { - Type: schema.TypeString, - Required: true, - }, - "template": { - Type: schema.TypeString, - Optional: true, - }, - }}, + Schema: eventOrchestrationPathExtractionsSchema, + }, }, }, }, @@ -353,8 +283,8 @@ func expandUnroutedRules(v interface{}) []*pagerduty.EventOrchestrationPathRule ID: r["id"].(string), Label: r["label"].(string), Disabled: r["disabled"].(bool), - Conditions: expandUnroutedConditions(r["conditions"]), - Actions: expandUnroutedActions(r["actions"].([]interface{})), + Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Actions: expandUnroutedActions(r["actions"]), } rules = append(rules, ruleInSet) @@ -382,23 +312,6 @@ func expandUnroutedActions(v interface{}) *pagerduty.EventOrchestrationPathRuleA return actions } -func expandUnroutedConditions(v interface{}) []*pagerduty.EventOrchestrationPathRuleCondition { - items := v.([]interface{}) - conditions := []*pagerduty.EventOrchestrationPathRuleCondition{} - - for _, cond := range items { - c := cond.(map[string]interface{}) - - cx := &pagerduty.EventOrchestrationPathRuleCondition{ - Expression: c["expression"].(string), - } - - conditions = append(conditions, cx) - } - - return conditions -} - func expandUnroutedCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll { var catchAll = new(pagerduty.EventOrchestrationPathCatchAll) @@ -448,7 +361,7 @@ func flattenUnroutedRules(rules []*pagerduty.EventOrchestrationPathRule) []inter "id": rule.ID, "label": rule.Label, "disabled": rule.Disabled, - "conditions": flattenUnroutedConditions(rule.Conditions), + "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), "actions": flattenUnroutedActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) @@ -457,19 +370,6 @@ func flattenUnroutedRules(rules []*pagerduty.EventOrchestrationPathRule) []inter return flattenedRules } -func flattenUnroutedConditions(conditions []*pagerduty.EventOrchestrationPathRuleCondition) []interface{} { - var flattendConditions []interface{} - - for _, condition := range conditions { - flattendCondition := map[string]interface{}{ - "expression": condition.Expression, - } - flattendConditions = append(flattendConditions, flattendCondition) - } - - return flattendConditions -} - func flattenUnroutedActions(actions *pagerduty.EventOrchestrationPathRuleActions) []map[string]interface{} { var actionsMap []map[string]interface{} From 0f2bd6ef651c67898fa4f343414376399290f4f4 Mon Sep 17 00:00:00 2001 From: Alex Zakabluk Date: Tue, 24 May 2022 09:28:25 -0400 Subject: [PATCH 32/51] [ORCA-3486] Extend unrouted tests, add CustomizeDiff, clean shared functions (#510) * Extend unrouted tests, add CustomizeDiff, clean shared functions * Move shared functions for unrouted and service paths to utils file --- pagerduty/event_orchestration_path_util.go | 25 +++ ...y_event_orchestration_path_service_test.go | 24 --- ...rduty_event_orchestration_path_unrouted.go | 1 + ..._event_orchestration_path_unrouted_test.go | 204 +++++++++++++----- 4 files changed, 176 insertions(+), 78 deletions(-) diff --git a/pagerduty/event_orchestration_path_util.go b/pagerduty/event_orchestration_path_util.go index 9aa5dbc24..728dabebd 100644 --- a/pagerduty/event_orchestration_path_util.go +++ b/pagerduty/event_orchestration_path_util.go @@ -3,6 +3,7 @@ package pagerduty import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/heimweh/go-pagerduty/pagerduty" ) @@ -52,6 +53,30 @@ var eventOrchestrationPathExtractionsSchema = map[string]*schema.Schema{ }, } +func invalidExtractionRegexTemplateNilConfig() string { + return ` + extractions { + target = "event.summary" + }` +} + +func invalidExtractionRegexTemplateValConfig() string { + return ` + extractions { + regex = ".*" + template = "hi" + target = "event.summary" + }` +} + +func invalidExtractionRegexNilSourceConfig() string { + return ` + extractions { + regex = ".*" + target = "event.summary" + }` +} + func validateEventOrchestrationPathSeverity() schema.SchemaValidateFunc { return validateValueFunc([]string{ "info", diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go index fb7bcb7a3..74ae61d80 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go @@ -465,30 +465,6 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( ) } -func invalidExtractionRegexTemplateNilConfig() string { - return ` - extractions { - target = "event.summary" - }` -} - -func invalidExtractionRegexTemplateValConfig() string { - return ` - extractions { - regex = ".*" - template = "hi" - target = "event.summary" - }` -} - -func invalidExtractionRegexNilSourceConfig() string { - return ` - extractions { - regex = ".*" - target = "event.summary" - }` -} - func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s string) string { return fmt.Sprintf("%s%s", createBaseServicePathConfig(ep, s), `resource "pagerduty_event_orchestration_service" "serviceA" { diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 8d3543041..70e54d3e5 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -19,6 +19,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Importer: &schema.ResourceImporter{ State: resourcePagerDutyEventOrchestrationPathUnroutedImport, }, + CustomizeDiff: checkExtractions, Schema: map[string]*schema.Schema{ "event_orchestration": { Type: schema.TypeString, diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index e646793c1..b790a32c4 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -2,6 +2,7 @@ package pagerduty import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" @@ -80,32 +81,45 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.event_action", "trigger"), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.#", "2"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.name", "server_name_cpu"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.path", "event.summary"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.type", "regex"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.0.value", "High CPU on (.*) server"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.name", "server_name_memory"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.path", "event.custom_details"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.type", "regex"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.1.value", "High memory usage on (.*) server"), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "sets.0.rules.0.actions.0.variables.*", + map[string]string{ + "name": "server_name_cpu", + "path": "event.summary", + "type": "regex", + "value": "High CPU on (.*) server", + }, + ), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "sets.0.rules.0.actions.0.variables.*", + map[string]string{ + "name": "server_name_memory", + "path": "event.custom_details", + "type": "regex", + "value": "High memory usage on (.*) server", + }, + ), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.#", "2"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.0.target", "event.summary"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.0.template", "High memory usage on variables.hostname server"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.1.target", "event.custom_details"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.1.template", "High memory usage on variables.hostname server"), + + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "sets.0.rules.0.actions.0.extractions.*", + map[string]string{ + "target": "event.summary", + "template": "High memory usage on {{variables.hostname}} server", + }, + ), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "sets.0.rules.0.actions.0.extractions.*", + map[string]string{ + "target": "event.custom_details", + "template": "High memory usage on {{variables.hostname}} server", + }, + ), //Set #2 resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.id", "child-1"), @@ -122,34 +136,91 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.event_action", "trigger"), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.#", "2"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.name", "server_name_cpu"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.path", "event.summary"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.type", "regex"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.0.value", "High CPU on (.*) server"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.name", "server_name_memory"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.path", "event.custom_details"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.type", "regex"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.1.value", "High memory usage on (.*) server"), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "catch_all.0.actions.0.variables.*", + map[string]string{ + "name": "server_name_cpu", + "path": "event.summary", + "type": "regex", + "value": "High CPU on (.*) server", + }, + ), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "catch_all.0.actions.0.variables.*", + map[string]string{ + "name": "server_name_memory", + "path": "event.custom_details", + "type": "regex", + "value": "High memory usage on (.*) server", + }, + ), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.#", "2"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.0.target", "event.summary"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.0.template", "High memory usage on variables.hostname server"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.1.target", "event.custom_details"), - resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.1.template", "High memory usage on variables.hostname server"), + + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "catch_all.0.actions.0.extractions.*", + map[string]string{ + "target": "event.summary", + "template": "High memory usage on {{variables.hostname}} server", + }, + ), + resource.TestCheckTypeSetElemNestedAttrs( + "pagerduty_event_orchestration_unrouted.unrouted", + "catch_all.0.actions.0.extractions.*", + map[string]string{ + "target": "event.custom_details", + "template": "High memory usage on {{variables.hostname}} server", + }, + ), ), }, + // Providing invalid extractions attributes for set rules + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, invalidExtractionRegexTemplateValConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, invalidExtractionRegexTemplateValConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, invalidExtractionRegexNilSourceConfig(), "", + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: source can't be blank"), + }, + // Providing invalid extractions attributes for the catch_all rule + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, "", invalidExtractionRegexTemplateNilConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both be null"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, "", invalidExtractionRegexTemplateValConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both have values"), + }, + { + Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( + team, escalationPolicy, service, orchestration, "", invalidExtractionRegexNilSourceConfig(), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: source can't be blank"), + }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( @@ -368,11 +439,11 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, } extractions { target = "event.summary" - template = "High memory usage on variables.hostname server" + template = "High memory usage on {{variables.hostname}} server" } extractions { target = "event.custom_details" - template = "High memory usage on variables.hostname server" + template = "High memory usage on {{variables.hostname}} server" } } } @@ -396,7 +467,7 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, } extractions { target = "event.summary" - template = "High CPU on event.custom_details.hostname server" + template = "High CPU on {{event.custom_details.hostname}} server" } } } @@ -417,7 +488,7 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, } extractions { target = "event.summary" - template = "High CPU on event.custom_details.hostname server" + template = "High CPU on {{event.custom_details.hostname}} server" } } } @@ -440,14 +511,39 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, } extractions { target = "event.summary" - template = "High memory usage on variables.hostname server" + template = "High memory usage on {{variables.hostname}} server" } extractions { target = "event.custom_details" - template = "High memory usage on variables.hostname server" + template = "High memory usage on {{variables.hostname}} server" } } } } `) } + +func testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig(t, ep, s, o, re, cae string) string { + return fmt.Sprintf( + "%s%s", + createUnroutedBaseConfig(t, ep, s, o), + fmt.Sprintf(`resource "pagerduty_event_orchestration_unrouted" "unrouted" { + event_orchestration = pagerduty_event_orchestration.orch.id + + sets { + id = "start" + rules { + actions { + %s + } + } + } + catch_all { + actions { + %s + } + } + } + `, re, cae), + ) +} From 0a4781dbe504af15b444b6413326fe58e6a1892d Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Wed, 18 May 2022 09:00:10 -0400 Subject: [PATCH 33/51] orchestration and path resource documentation --- ..._orchestration_path_resource.html.markdown | 215 +++++++++++++++++ ..._orchestration_resource.html copy.markdown | 225 ++++++++++++++++++ 2 files changed, 440 insertions(+) create mode 100644 website/docs/r/event_orchestration_path_resource.html.markdown create mode 100644 website/docs/r/event_orchestration_resource.html copy.markdown diff --git a/website/docs/r/event_orchestration_path_resource.html.markdown b/website/docs/r/event_orchestration_path_resource.html.markdown new file mode 100644 index 000000000..0d122a18a --- /dev/null +++ b/website/docs/r/event_orchestration_path_resource.html.markdown @@ -0,0 +1,215 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration_path" +sidebar_current: "docs-pagerduty-resource-event-orchestration-path" +description: |- + Creates and manages an orchestration path (router|unrouted|service) associated with a Global Event Orchestration in PagerDuty. +--- + +# pagerduty_event_orchestration_router + +An Orchestration Router allows users to create a set of Event Rules. The Router evaluates events sent to this Orchestration against each of its rules, one at a time, and routes the event to a specific Service based on the first rule that matches. If an event doesn't match any rules, it'll be sent to service specified in the catch_all or to the "Unrouted" Orchestration if no service is specified. Rules are defined as attributes of the orchestration path resource. + +## Example of configuring Router rules for an Orchestration + +```hcl + # In this example the user has defined the router with two rules, each routing to a different service + # The first rule matches only if either of the two conditions are matched + # The second rule matches always + # The catch_all routes to unrouted path. + # but using the catch_all to route to another service is allowed. +resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + id = pagerduty_event_orchestration.my_monitor.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + rules { + label = "Events relating to our relational database" + conditions { + expression = "event.summary matches part 'database'" + } + conditions { + expression = "event.source matches regex 'db[0-9]+-server'" + } + actions { + route_to = pageduty_service.database.id + } + } + rules { + actions { + route_to = pagerduty_service.www.id + } + disabled = false + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `type` - (Required) Type of the orchestration path. For router path, it is `router`. +* `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. +* `sets` - (Required) The Router contains a single set of rules (the "start" set) +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + + +### Parent (`parent`) supports the following: +* `id` - (Required) ID of the Event Orchestration to which the Router path belongs to + +### Sets (`sets`) supports the following: +* `id` - (Required) ID of the start set. Router path supports only one set and it's id has to be `start` +* `rules` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. + * `route_to' - (Required) With a value of 'unrouted', all events are sent to the Unrouted Orchestration. + +## Attributes Reference + +The following attributes are exported: +* `parent` + * `type' - Type of the parent (Event Orchestration) reference for this Event Orchestration Path. + * `self` - The URL at which the parent object (Event Orchestration) is accessible. +* `self` - The URL at which the Router Event Orchestration path is accessible. +* `rules` + * `id` - The ID of the rule within the `start` set. + +## Import + +Router Orchestration path can be imported using the `id` of the event orchestration, e.g. + +``` +$ terraform import pagerduty_event_orchestration_router 1b49abe7-26db-4439-a715-c6d883acfb3e +``` + +# pagerduty_event_orchestration_unrouted + +An Unrouted Orchestration allows users to create a set of Event Rules that will be evaluated against all events that don't match any rules in the Orchestration's Router. + +The Unrouted Orchestration evaluates events sent to it against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Unrouted Orchestration for further processing. + +## Example of configuring a Unrouted Rules for an Orchestration + +```hcl + # In this example the user has defined the unrouted orchestration path with two rules, each routing to a different service + # As there is a single set, route_to is not defined for the rules. + # If there are more than one set, the rules in start set must define route_to with id of the next set + # The first rule matches only if the condition is matched + # The second rule matches always + # The catch_all without actions as in this example will set suppressed action to true. + # but using the catch_all to set severity, event_action, variables and extractions is allowed. +resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + sets { + id = "start" + rules { + label = "Update the summary of un-matched Critical alerts so they're easier to spot" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + severity = "info" + extractions { + target = "event.summary" + template = "[Critical Unrouted] {{event.summary}}" + } + } + } + rules { + disabled = false + label = "Reduce the severity of all other unrouted events" + actions { + severity = "info" + } + } + } + catch_all { + actions { } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `type` - (Required) Type of the orchestration path. For unrouted path, it is `unrouted`. +* `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. +* `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + + +### Parent (`parent`) supports the following: +* `id` - (Required) ID of the Event Orchestration to which the Unrouted path belongs to. + +### Sets (`sets`) supports the following: +* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. +* `rules` - (Optional) The unrouted path evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. +* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` +* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` +* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. + * `name` - (Required) The name of the variable + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event`s `fieldname` data. + * `type` - (Required) Only `regex` is supported + * `value` - The Regex expression to match against.Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. +* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. + * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction`s `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. + * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. + * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. + * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF] (https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. + +## Attributes Reference + +The following attributes are exported: +* `parent` + * `type' - Type of the parent (Event Orchestration) reference for this Event .Orchestration Path + * `self` - The URL at which the parent object (Event Orchestration) is accessible. +* `self` - The URL at which the Unrouted Event Orchestration path is accessible. +* `rules` + * `id` - The ID of the rule within the `start` set. +* `catch_all` + * `actions` + * `suppress` - The suppress action for catch_all rule. This is always True. + +## Import + +Unrouted Orchestration path can be imported using the `id` of the event orchestration, e.g. + +``` +$ terraform import pagerduty_event_orchestration_unrouted 1b49abe7-26db-4439-a715-c6d883acfb3e +``` diff --git a/website/docs/r/event_orchestration_resource.html copy.markdown b/website/docs/r/event_orchestration_resource.html copy.markdown new file mode 100644 index 000000000..d7de1f2dc --- /dev/null +++ b/website/docs/r/event_orchestration_resource.html copy.markdown @@ -0,0 +1,225 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration" +sidebar_current: "docs-pagerduty-resource-event-orchestration" +description: |- + Creates and manages a Global Event Orchestration / Service Orchestration in PagerDuty. +--- + + + +# pagerduty_event_orchestration + +[Event Orchestrations](https://support.pagerduty.com/docs/event-orchestration) allows users to route events to an endpoint and create nested rules, which define sets of actions to take based on event content. + +## Example of configuring a Global Event Orchestration + +```hcl +resource "pagerduty_team" "engineering" { + name = "Engineering" +} + +resource "pagerduty_event_orchestration" "my_monitor" { + name = "My Monitoring Orchestration" + description = "Send events to a pair of services" + team { + id = pagerduty_team.foo.id + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the Event Orchestration. +* `description` - (Optional) A human-friendly description of the Event Orchestration. +* `team` - (Optional) Reference to the team that owns the Event Orchestration. If none is specified, only admins have access. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Event Orchestration. +* `integrations` - Routing keys routed to this Event Orchestration. + +## Import + +EventOrchestrations can be imported using the `id`, e.g. + +``` +$ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bbf516519601 +``` + +# pagerduty_event_orchestration_service + +When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. + +## Example of configuring a Service Orchestration + +```hcl + # In this example the user has defined the service orchestration with nested rulesets. + # The start set rule routes to the second set +resource "pagerduty_event_orchestration_service" "www" { + sets { + id = "start" + rules { + label = "Always apply some consistent event transformations to all events" + actions { + variables { + name = "hostname" + path = "event.component" + value = "hostname: (.*)" + type = "regex" + } + extractions { + # Demonstrating a template-style extraction + template = "{{variables.hostname}}" + target = "event.custom_details.hostname" + } + extractions { + # Demonstrating a regex-style extractions + source = "event.source" + regex = "www (.*) service" + target = "event.source" + } + route_to = "step-two" + } + } + } + sets { + id = "step-two" + rules { + label = "All critical alerts should be treated as P1 incident" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" + priority = "P0IN2KQ" + suppress = false + } + } + rules { + label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" + conditions { + expression = "event.custom_details.hostname matches part 'canary'" + } + # create webhook action with parameters and headers + actions { + automation_actions { + name = "Canary Slack Notification" + url = "https://our-slack-listerner.test/canary-notification" + auto_send = true + parameters { + key = "channel" + value = "#my-team-channel" + } + parameters { + key = "message" + value = "something is wrong with the canary deployment" + } + headers { + key = "X-Notification-Source" + value = "PagerDuty Incident Webhook" + } + } + } + } + rules { + label = "Never bother the on-call for info-level events outside of work hours" + conditions { + expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" + } + actions { + suppress = true + } + } + } + # catch_all always sets suppressed action to true. Other actions like annotate, severity, priority, variables and extractions, webhooks can be set as well + catch_all { + actions { } + } +} +``` +## Argument Reference + +The following arguments are supported: + +* `type` - (Required) Type of the orchestration. For service orchestrations, it is `service`. +* `parent` - (Required) Parent (Service) to which this orchestration belongs to. +* `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + + +### Parent (`parent`) supports the following: +* `id` - (Required) ID of the Service to which this service orchestration belongs to. + +### Sets (`sets`) supports the following: +* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. +* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. +* `suppress` - (Optional) Set whether the resulting alert is suppressed. Suppressed alerts will not trigger an incident. +* `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a resolve event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. +* `priority` - (Optional) The ID of the priority you want to set on resulting incident. You can find the list of priority IDs for your account by calling the priorities endpoint. +* `annotate` - (Optional) Add this text as a note on the resulting incident. +* `pagerduty_automation_actions` - (Optional) Configure an [Automation Action](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. + * `action_id` - (Required) Id of the PagerDutyAutomationAction to be triggered. +* `automation_actions` - (Optional) Create a [Webhoook](https://support.pagerduty.com/docs/event-orchestration#webhooks) associated with the resulting incident. + * `name` - (Required) Name of this Webhook. + * `url` - (Required) The API endpoint where PagerDuty's servers will send the webhook request. + * `auto_send` - (Optional) When true, PagerDuty's servers will automatically send this webhook request as soon as the resulting incident is created. When false, your incident responder will be able to manually trigger the Webhook via the PagerDuty website and mobile app. + * `headers` - (Optional) Specify custom key/value pairs that'll be sent with the webhook request as request headers. + * `key` - (Required) Name to identify the header + * `value` - (Required) Value of this header + * `parameters` - (Optional) Specify custom key/value pairs that'll be included in the webhook request's JSON payload. + * `key` - (Required) Name to identify the parameter + * `value` - (Required) Value of this parameter +* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` +* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` +* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. + * `name` - (Required) The name of the variable + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event`s `fieldname` data. + * `type` - (Required) Only `regex` is supported + * `value` - The Regex expression to match against.Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. +* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. + * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction`s `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. + * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. + * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. + * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF] (https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. + + +## Attributes Reference + +The following attributes are exported: +* `parent` + * `type' - Type of the parent (Event Orchestration) reference for this Event Orchestration Path + * `self` - The URL at which the parent object (Event Orchestration) is accessible +* `self` - The URL at which the Service Orchestration path is accessible +* `rules` + * `id` - The ID of the rule within the `start` set. +* `catch_all` + * `actions` + * `suppress` - The suppress action for catch_all rule. This is always True. + +## Import + +Service Orchestrations can be imported using the `id` of the service, e.g. + +``` +$ terraform import pagerduty_event_orchestration_service PFEODA7 +``` From b48c9a64355255b4d2ddb36ec7a204e0eb957b10 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Wed, 18 May 2022 09:22:44 -0400 Subject: [PATCH 34/51] datasource documentation --- .../docs/d/eventorchestration.html.markdown | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 website/docs/d/eventorchestration.html.markdown diff --git a/website/docs/d/eventorchestration.html.markdown b/website/docs/d/eventorchestration.html.markdown new file mode 100644 index 000000000..b329bb2dd --- /dev/null +++ b/website/docs/d/eventorchestration.html.markdown @@ -0,0 +1,38 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration" +sidebar_current: "docs-pagerduty-datasource-event-orchestration" +description: |- + Get information about a Global Event Orchestration that you have created. +--- + +# pagerduty\_event_orchestration + +Use this data source to get information about a specific global [Event Orchestration][1] + +## Example Usage + +```hcl +data "pagerduty_event_orchestration" "example" { + name = "My Global Event Orchestration" +} + +resource "pagerduty_event_orchestration" "foo" { + name = data.pagerduty_event_orchestration.example.name +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Global Event orchestration to find in the PagerDuty API. + +## Attributes Reference + +* `id` - The ID of the found Event Orchestration. +* `name` - The name of the found Event Orchestration. +* `integrations` - Routing keys routed to this Event Orchestration. + + +[1]: https://developer.pagerduty.com/api-reference/7ba0fe7bdb26a-list-event-orchestrations From a69211938da91cac0139503656c4a8d094f6c2ae Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Wed, 18 May 2022 09:58:32 -0400 Subject: [PATCH 35/51] refactor --- .../docs/d/eventorchestration.html.markdown | 2 +- ..._orchestration_path_resource.html.markdown | 121 +++--- ..._orchestration_resource.html copy.markdown | 225 ----------- ...event_orchestration_resource.html.markdown | 377 +++++++++++------- 4 files changed, 290 insertions(+), 435 deletions(-) delete mode 100644 website/docs/r/event_orchestration_resource.html copy.markdown diff --git a/website/docs/d/eventorchestration.html.markdown b/website/docs/d/eventorchestration.html.markdown index b329bb2dd..537766c4f 100644 --- a/website/docs/d/eventorchestration.html.markdown +++ b/website/docs/d/eventorchestration.html.markdown @@ -8,7 +8,7 @@ description: |- # pagerduty\_event_orchestration -Use this data source to get information about a specific global [Event Orchestration][1] +Use this data source to get information about a specific Global [Event Orchestration][1] ## Example Usage diff --git a/website/docs/r/event_orchestration_path_resource.html.markdown b/website/docs/r/event_orchestration_path_resource.html.markdown index 0d122a18a..36dbc4894 100644 --- a/website/docs/r/event_orchestration_path_resource.html.markdown +++ b/website/docs/r/event_orchestration_path_resource.html.markdown @@ -3,7 +3,7 @@ layout: "pagerduty" page_title: "PagerDuty: pagerduty_event_orchestration_path" sidebar_current: "docs-pagerduty-resource-event-orchestration-path" description: |- - Creates and manages an orchestration path (router|unrouted|service) associated with a Global Event Orchestration in PagerDuty. + Creates and manages an orchestration path (router|unrouted) associated with a Global Event Orchestration in PagerDuty. --- # pagerduty_event_orchestration_router @@ -14,41 +14,43 @@ An Orchestration Router allows users to create a set of Event Rules. The Router ```hcl # In this example the user has defined the router with two rules, each routing to a different service + # This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource. # The first rule matches only if either of the two conditions are matched # The second rule matches always - # The catch_all routes to unrouted path. + # The catch_all routes to unrouted path # but using the catch_all to route to another service is allowed. -resource "pagerduty_event_orchestration_router" "router" { - type = "router" - parent { - id = pagerduty_event_orchestration.my_monitor.id - } - catch_all { - actions { - route_to = "unrouted" - } - } - sets { - rules { - label = "Events relating to our relational database" - conditions { - expression = "event.summary matches part 'database'" - } - conditions { - expression = "event.source matches regex 'db[0-9]+-server'" - } + resource "pagerduty_event_orchestration_router" "router" { + type = "router" + parent { + # id of the Global Event Orchestrartion + id = pagerduty_event_orchestration.my_monitor.id + } + catch_all { actions { - route_to = pageduty_service.database.id + route_to = "unrouted" } } - rules { - actions { - route_to = pagerduty_service.www.id + sets { + rules { + label = "Events relating to our relational database" + conditions { + expression = "event.summary matches part 'database'" + } + conditions { + expression = "event.source matches regex 'db[0-9]+-server'" + } + actions { + route_to = pageduty_service.database.id + } + } + rules { + actions { + route_to = pagerduty_service.www.id + } + disabled = false } - disabled = false } } -} ``` ## Argument Reference @@ -82,7 +84,7 @@ The following arguments are supported: ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. - * `route_to' - (Required) With a value of 'unrouted', all events are sent to the Unrouted Orchestration. + * `route_to' - (Required) With a value of `unrouted`, all events are sent to the Unrouted Orchestration. ## Attributes Reference @@ -112,41 +114,46 @@ The Unrouted Orchestration evaluates events sent to it against each of its rules ```hcl # In this example the user has defined the unrouted orchestration path with two rules, each routing to a different service + # This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource. # As there is a single set, route_to is not defined for the rules. # If there are more than one set, the rules in start set must define route_to with id of the next set # The first rule matches only if the condition is matched # The second rule matches always # The catch_all without actions as in this example will set suppressed action to true. # but using the catch_all to set severity, event_action, variables and extractions is allowed. -resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" - sets { - id = "start" - rules { - label = "Update the summary of un-matched Critical alerts so they're easier to spot" - conditions { - expression = "event.severity matches 'critical'" + resource "pagerduty_event_orchestration_unrouted" "unrouted" { + type = "unrouted" + parent { + # id of the Global Event Orchestrartion + id = pagerduty_event_orchestration.my_monitor.id + } + sets { + id = "start" + rules { + label = "Update the summary of un-matched Critical alerts so they're easier to spot" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + severity = "info" + extractions { + target = "event.summary" + template = "[Critical Unrouted] {{event.summary}}" + } + } } - actions { - severity = "info" - extractions { - target = "event.summary" - template = "[Critical Unrouted] {{event.summary}}" + rules { + disabled = false + label = "Reduce the severity of all other unrouted events" + actions { + severity = "info" } } } - rules { - disabled = false - label = "Reduce the severity of all other unrouted events" - actions { - severity = "info" - } + catch_all { + actions { } } } - catch_all { - actions { } - } -} ``` ## Argument Reference @@ -176,19 +183,19 @@ The following arguments are supported: * `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. +* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the [Services API endpoint](https://developer.pagerduty.com/api-reference/e960cca205c0f-list-services). * `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` * `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` * `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. * `name` - (Required) The name of the variable - * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event`s `fieldname` data. + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. * `type` - (Required) Only `regex` is supported - * `value` - The Regex expression to match against.Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. + * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. * `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. - * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction`s `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. + * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. - * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF] (https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. @@ -197,7 +204,7 @@ The following arguments are supported: The following attributes are exported: * `parent` - * `type' - Type of the parent (Event Orchestration) reference for this Event .Orchestration Path + * `type` - Type of the parent (Event Orchestration) reference for this Event .Orchestration Path * `self` - The URL at which the parent object (Event Orchestration) is accessible. * `self` - The URL at which the Unrouted Event Orchestration path is accessible. * `rules` diff --git a/website/docs/r/event_orchestration_resource.html copy.markdown b/website/docs/r/event_orchestration_resource.html copy.markdown deleted file mode 100644 index d7de1f2dc..000000000 --- a/website/docs/r/event_orchestration_resource.html copy.markdown +++ /dev/null @@ -1,225 +0,0 @@ ---- -layout: "pagerduty" -page_title: "PagerDuty: pagerduty_event_orchestration" -sidebar_current: "docs-pagerduty-resource-event-orchestration" -description: |- - Creates and manages a Global Event Orchestration / Service Orchestration in PagerDuty. ---- - - - -# pagerduty_event_orchestration - -[Event Orchestrations](https://support.pagerduty.com/docs/event-orchestration) allows users to route events to an endpoint and create nested rules, which define sets of actions to take based on event content. - -## Example of configuring a Global Event Orchestration - -```hcl -resource "pagerduty_team" "engineering" { - name = "Engineering" -} - -resource "pagerduty_event_orchestration" "my_monitor" { - name = "My Monitoring Orchestration" - description = "Send events to a pair of services" - team { - id = pagerduty_team.foo.id - } -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) Name of the Event Orchestration. -* `description` - (Optional) A human-friendly description of the Event Orchestration. -* `team` - (Optional) Reference to the team that owns the Event Orchestration. If none is specified, only admins have access. - -## Attributes Reference - -The following attributes are exported: - -* `id` - The ID of the Event Orchestration. -* `integrations` - Routing keys routed to this Event Orchestration. - -## Import - -EventOrchestrations can be imported using the `id`, e.g. - -``` -$ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bbf516519601 -``` - -# pagerduty_event_orchestration_service - -When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. - -## Example of configuring a Service Orchestration - -```hcl - # In this example the user has defined the service orchestration with nested rulesets. - # The start set rule routes to the second set -resource "pagerduty_event_orchestration_service" "www" { - sets { - id = "start" - rules { - label = "Always apply some consistent event transformations to all events" - actions { - variables { - name = "hostname" - path = "event.component" - value = "hostname: (.*)" - type = "regex" - } - extractions { - # Demonstrating a template-style extraction - template = "{{variables.hostname}}" - target = "event.custom_details.hostname" - } - extractions { - # Demonstrating a regex-style extractions - source = "event.source" - regex = "www (.*) service" - target = "event.source" - } - route_to = "step-two" - } - } - } - sets { - id = "step-two" - rules { - label = "All critical alerts should be treated as P1 incident" - conditions { - expression = "event.severity matches 'critical'" - } - actions { - annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" - priority = "P0IN2KQ" - suppress = false - } - } - rules { - label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" - conditions { - expression = "event.custom_details.hostname matches part 'canary'" - } - # create webhook action with parameters and headers - actions { - automation_actions { - name = "Canary Slack Notification" - url = "https://our-slack-listerner.test/canary-notification" - auto_send = true - parameters { - key = "channel" - value = "#my-team-channel" - } - parameters { - key = "message" - value = "something is wrong with the canary deployment" - } - headers { - key = "X-Notification-Source" - value = "PagerDuty Incident Webhook" - } - } - } - } - rules { - label = "Never bother the on-call for info-level events outside of work hours" - conditions { - expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" - } - actions { - suppress = true - } - } - } - # catch_all always sets suppressed action to true. Other actions like annotate, severity, priority, variables and extractions, webhooks can be set as well - catch_all { - actions { } - } -} -``` -## Argument Reference - -The following arguments are supported: - -* `type` - (Required) Type of the orchestration. For service orchestrations, it is `service`. -* `parent` - (Required) Parent (Service) to which this orchestration belongs to. -* `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. -* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. - - -### Parent (`parent`) supports the following: -* `id` - (Required) ID of the Service to which this service orchestration belongs to. - -### Sets (`sets`) supports the following: -* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. - -### Rules (`rules`) supports the following: -* `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. -* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. -* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. - -### Conditions (`conditions`) supports the following: -* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. - -### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. -* `suppress` - (Optional) Set whether the resulting alert is suppressed. Suppressed alerts will not trigger an incident. -* `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a resolve event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. -* `priority` - (Optional) The ID of the priority you want to set on resulting incident. You can find the list of priority IDs for your account by calling the priorities endpoint. -* `annotate` - (Optional) Add this text as a note on the resulting incident. -* `pagerduty_automation_actions` - (Optional) Configure an [Automation Action](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. - * `action_id` - (Required) Id of the PagerDutyAutomationAction to be triggered. -* `automation_actions` - (Optional) Create a [Webhoook](https://support.pagerduty.com/docs/event-orchestration#webhooks) associated with the resulting incident. - * `name` - (Required) Name of this Webhook. - * `url` - (Required) The API endpoint where PagerDuty's servers will send the webhook request. - * `auto_send` - (Optional) When true, PagerDuty's servers will automatically send this webhook request as soon as the resulting incident is created. When false, your incident responder will be able to manually trigger the Webhook via the PagerDuty website and mobile app. - * `headers` - (Optional) Specify custom key/value pairs that'll be sent with the webhook request as request headers. - * `key` - (Required) Name to identify the header - * `value` - (Required) Value of this header - * `parameters` - (Optional) Specify custom key/value pairs that'll be included in the webhook request's JSON payload. - * `key` - (Required) Name to identify the parameter - * `value` - (Required) Value of this parameter -* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` -* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` -* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. - * `name` - (Required) The name of the variable - * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event`s `fieldname` data. - * `type` - (Required) Only `regex` is supported - * `value` - The Regex expression to match against.Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. -* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. - * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction`s `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. - * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. - * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. - * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF] (https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. - -### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. - - -## Attributes Reference - -The following attributes are exported: -* `parent` - * `type' - Type of the parent (Event Orchestration) reference for this Event Orchestration Path - * `self` - The URL at which the parent object (Event Orchestration) is accessible -* `self` - The URL at which the Service Orchestration path is accessible -* `rules` - * `id` - The ID of the rule within the `start` set. -* `catch_all` - * `actions` - * `suppress` - The suppress action for catch_all rule. This is always True. - -## Import - -Service Orchestrations can be imported using the `id` of the service, e.g. - -``` -$ terraform import pagerduty_event_orchestration_service PFEODA7 -``` diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown index 25e106f4c..89ff5c963 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -1,21 +1,16 @@ --- layout: "pagerduty" -page_title: "PagerDuty: event_orchestration_separate_resources_per_type" -sidebar_current: "docs-pagerduty-resource-event-orchestration-router" +page_title: "PagerDuty: pagerduty_event_orchestration" +sidebar_current: "docs-pagerduty-resource-event-orchestration" description: |- - Creates and manages an orchestration path (router|unrouted|service) associated with a Global Event Orchestration in PagerDuty. + Creates and manages a Global Event Orchestration / Service Orchestration in PagerDuty. --- -# Separate resources for each "type" of Orchestration path & no rule resource -In this example, we have separate resources for each "type" of Orchestration: -* `pagerduty_event_orchestration_router` -* `pagerduty_event_orchestration_unrouted` -* `pagerduty_event_orchestration_service` - -Rules are defined as attributes of the orchestration path resource +# pagerduty_event_orchestration +[Event Orchestrations](https://support.pagerduty.com/docs/event-orchestration) allows users to route events to an endpoint and create nested rules, which define sets of actions to take based on event content. ## Example of configuring a Global Event Orchestration @@ -28,166 +23,244 @@ resource "pagerduty_event_orchestration" "my_monitor" { name = "My Monitoring Orchestration" description = "Send events to a pair of services" team { - id = pagerduty_team.foo.id + id = pagerduty_team.engineering.id } } ``` -## Example of configuring Router rules for an Orchestration +## Argument Reference -```hcl -resource "pagerduty_event_orchestration_router" "my_monitor" { - event_orchestration = pagerduty_event_orchestration.my_monitor - # Note: the router currently only supports a single set of rules. - # If we change routers to support multiple sets in the future we'd need to introde a `sets` argument. - rules = [ - { - name = "Events relating to our relational database" - conditions = [ - { expression = "event.summary matches part 'database'" }, - { expression = "event.source matches regex 'db[0-9]+-server'" } - ] - route_to = pagerduty_service.database.id - }, - { - name = "Events relating to our www app server" - conditions = [ - { expression = "event.summary matches part 'www'" } - ] - route_to = pagerduty_service.www.id - } - ] - catch_all = { - route_to = "unrouted" - } -} -``` +The following arguments are supported: -**Argument Reference:** supports same rule and catch-all arguments as the [Router Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0Mzk-update-the-router-for-a-global-event-orchestration) of the Public API +* `name` - (Required) Name of the Event Orchestration. +* `description` - (Optional) A human-friendly description of the Event Orchestration. +* `team` - (Optional) Reference to the team that owns the Event Orchestration. If none is specified, only admins have access. -## Example of configuring a Unrouted Rules for an Orchestration +## Attributes Reference -```hcl -resource "pagerduty_event_orchestration_unrouted" "my_monitor" { - event_orchestration = pagerduty_event_orchestration.my_monitor - sets = [ - { - id = "start" - rules = [ - { - name = "Update the summary of un-matched Critical alerts so they're easier to spot" - conditions = [ - { expression = "event.severity matches 'critical'" } - ] - actions { - extractions = [ - { - target = "event.summary" - template = "[Critical Unrouted] {{event.summary}}" - } - ] - } - }, - { - name = "Reduce the severity of all other unrouted events" - conditions = [] - actions = { - severity = "info" - } - } - ] - } - ] - # In this example the user has defined their own "all other unrouted events" rule with no conditions - # so they aren't defining global catch_all behavior for the pagerduty_event_orchestration_unrouted resource - # but using the catch_all would be a totally legit alternative. -} +The following attributes are exported: + +* `id` - The ID of the Event Orchestration. +* `integrations` - Routing keys routed to this Event Orchestration. + +## Import + +EventOrchestrations can be imported using the `id`, e.g. + +``` +$ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bbf516519601 ``` -**Argument Reference:** supports same rule, set, and catch-all arguments as the [Unrouted Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0NDE-update-the-unrouted-orchestration-for-a-global-event-orchestration) of the Public API +# pagerduty_event_orchestration_service + +When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. ## Example of configuring a Service Orchestration ```hcl + # user, escalation policy are required for a service. + # a service orchestration is required to point to an existing service. + # This example shows creating the prerequisite resources for a Service Orchestration (team, user, escalationpolicy and service) + resource "pagerduty_team" "engineering" { + name = "Engineering" +} + + resource "pagerduty_user" "example" { + name = "Earline Greenholt" + email = "125.greenholt.earline@graham.name" + teams = [pagerduty_team.engineering.id] +} + +resource "pagerduty_escalation_policy" "foo" { + name = "Engineering Escalation Policy" + num_loops = 2 + + rule { + escalation_delay_in_minutes = 10 + + target { + type = "user" + id = pagerduty_user.example.id + } + } +} + +resource "pagerduty_service" "example" { + name = "My Web App" + auto_resolve_timeout = 14400 + acknowledgement_timeout = 600 + escalation_policy = pagerduty_escalation_policy.example.id + alert_creation = "create_alerts_and_incidents" +} + +# In this example the user has defined the service orchestration with nested rulesets. +# The start set rule in this example routes to the second set resource "pagerduty_event_orchestration_service" "www" { - service = route_to = pagerduty_service.www.id - sets = [ - { - id: "start" - rules = [ - { - name = "Always apply some consistent event transformations to all events" - conditions = [] - actions { - variables { - name = "hostname" - path = "event.component" - value = "hostname: (.*)" - type = "regex" - } - extractions = [ - { - # Demonstrating a template-style extraction - template = "{{variables.hostname}}" - target = "event.custom_details.hostname" - }, - { - # Demonstrating a regex-style extractions - source = "event.source" - regex = "www (.*) service" - target = "event.source" - } - ] - route_to = "step-two" - } + type = "service" + parent { + # id of the Service + id = pagerduty_service.example.id + } + sets { + id = "start" + rules { + label = "Always apply some consistent event transformations to all events" + actions { + variables { + name = "hostname" + path = "event.component" + value = "hostname: (.*)" + type = "regex" + } + extractions { + # Demonstrating a template-style extraction + template = "{{variables.hostname}}" + target = "event.custom_details.hostname" } - ] - }, - { - id: "step-two" - rules = [ - { - name = "All critical alerts should be treated as P1 incidents" - conditions = [ - { expression = "event.severity matches 'critical'" } - ] - actions { - annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" - priority = "P0IN2KQ" - suppress = false - } - }, - { - name = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" - conditions = [ - { expression = "event.custom_details.hostname matches part 'canary'" } - ] - actions { - automation_actions = [ - { - name = "Canary Slack Notification" - url = "https://our-slack-listerner.test/canary-notification" - auto_send = true - parameters = [] - } - ] - } - }, - { - name = "Never bother the on-call for info-level events outside of work hours" - conditions = [ - { expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" } - ] - actions { - suppress = true - } + extractions { + # Demonstrating a regex-style extractions + source = "event.source" + regex = "www (.*) service" + target = "event.source" } - ] + # Id of the next set + route_to = "step-two" + } } - ] - catch_all = { - suppress = true + } + sets { + id = "step-two" + rules { + label = "All critical alerts should be treated as P1 incident" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" + priority = "P0IN2KQ" + suppress = false + } + } + rules { + label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" + conditions { + expression = "event.custom_details.hostname matches part 'canary'" + } + # create webhook action with parameters and headers + actions { + automation_actions { + name = "Canary Slack Notification" + url = "https://our-slack-listerner.test/canary-notification" + auto_send = true + parameters { + key = "channel" + value = "#my-team-channel" + } + parameters { + key = "message" + value = "something is wrong with the canary deployment" + } + headers { + key = "X-Notification-Source" + value = "PagerDuty Incident Webhook" + } + } + } + } + rules { + label = "Never bother the on-call for info-level events outside of work hours" + conditions { + expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" + } + actions { + suppress = true + } + } + } + # catch_all always sets suppressed action to true. Other actions like annotate, severity, priority, variables and extractions, webhooks can be set as well + catch_all { + actions { } } } ``` -**Argument Reference:** supports same rule, set, and catch-all arguments as the [Service Orchestration endpoint](https://developer.pagerduty.com/api-reference/b3A6MzU3MDU0NDM-update-the-service-orchestration-for-a-service) of the Public API \ No newline at end of file +## Argument Reference + +The following arguments are supported: + +* `type` - (Required) Type of the orchestration. For service orchestrations, it is `service`. +* `parent` - (Required) Parent (Service) to which this orchestration belongs to. +* `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + + +### Parent (`parent`) supports the following: +* `id` - (Required) ID of the Service to which this service orchestration belongs to. + +### Sets (`sets`) supports the following: +* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. +* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the [Services API endpoint](https://developer.pagerduty.com/api-reference/e960cca205c0f-list-services). +* `suppress` - (Optional) Set whether the resulting alert is suppressed. Suppressed alerts will not trigger an incident. +* `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a `resolve` event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. +* `priority` - (Optional) The ID of the priority you want to set on resulting incident. You can find the list of priority IDs for your account by calling the priorities endpoint. +* `annotate` - (Optional) Add this text as a note on the resulting incident. +* `pagerduty_automation_actions` - (Optional) Configure a [Process Automation](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. + * `action_id` - (Required) Id of the Process Automation action to be triggered. +* `automation_actions` - (Optional) Create a [Webhook](https://support.pagerduty.com/docs/event-orchestration#webhooks) associated with the resulting incident. + * `name` - (Required) Name of this Webhook. + * `url` - (Required) The API endpoint where PagerDuty's servers will send the webhook request. + * `auto_send` - (Optional) When true, PagerDuty's servers will automatically send this webhook request as soon as the resulting incident is created. When false, your incident responder will be able to manually trigger the Webhook via the PagerDuty website and mobile app. + * `headers` - (Optional) Specify custom key/value pairs that'll be sent with the webhook request as request headers. + * `key` - (Required) Name to identify the header + * `value` - (Required) Value of this header + * `parameters` - (Optional) Specify custom key/value pairs that'll be included in the webhook request's JSON payload. + * `key` - (Required) Name to identify the parameter + * `value` - (Required) Value of this parameter +* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` +* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` +* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. + * `name` - (Required) The name of the variable + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. + * `type` - (Required) Only `regex` is supported + * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. +* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. + * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. + * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. + * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. + * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. + + +## Attributes Reference + +The following attributes are exported: +* `parent` + * `type` - Type of the parent (Event Orchestration) reference for this Event Orchestration Path + * `self` - The URL at which the parent object (Event Orchestration) is accessible +* `self` - The URL at which the Service Orchestration path is accessible +* `rules` + * `id` - The ID of the rule within the `start` set. +* `catch_all` + * `actions` + * `suppress` - The suppress action for catch_all rule. This is always True. + +## Import + +Service Orchestrations can be imported using the `id` of the service, e.g. + +``` +$ terraform import pagerduty_event_orchestration_service PFEODA7 +``` From fb82f8bd9a6dbb6ba6a0c294ee404a2278ec783e Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Wed, 18 May 2022 10:17:20 -0400 Subject: [PATCH 36/51] update comment --- website/docs/r/event_orchestration_resource.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown index 89ff5c963..feb534063 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -53,7 +53,7 @@ $ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bb # pagerduty_event_orchestration_service -When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. +When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. As a prerequisite, please ensure the service is set to evaluate orchestrations using the [Service Orchestration Active status endpoint](https://developer.pagerduty.com/api-reference/855659be83d9e-update-the-service-orchestration-active-status-for-a-service) ## Example of configuring a Service Orchestration From 282404b4ac38b720c331f37c4094e8e976e59405 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Thu, 19 May 2022 11:02:34 -0400 Subject: [PATCH 37/51] update type field documentation --- .../docs/r/event_orchestration_path_resource.html.markdown | 6 ++---- website/docs/r/event_orchestration_resource.html.markdown | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/website/docs/r/event_orchestration_path_resource.html.markdown b/website/docs/r/event_orchestration_path_resource.html.markdown index 36dbc4894..622a63957 100644 --- a/website/docs/r/event_orchestration_path_resource.html.markdown +++ b/website/docs/r/event_orchestration_path_resource.html.markdown @@ -20,7 +20,6 @@ An Orchestration Router allows users to create a set of Event Rules. The Router # The catch_all routes to unrouted path # but using the catch_all to route to another service is allowed. resource "pagerduty_event_orchestration_router" "router" { - type = "router" parent { # id of the Global Event Orchestrartion id = pagerduty_event_orchestration.my_monitor.id @@ -57,7 +56,6 @@ An Orchestration Router allows users to create a set of Event Rules. The Router The following arguments are supported: -* `type` - (Required) Type of the orchestration path. For router path, it is `router`. * `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. * `sets` - (Required) The Router contains a single set of rules (the "start" set) * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. @@ -89,6 +87,7 @@ The following arguments are supported: ## Attributes Reference The following attributes are exported: +* `type` - Type of the orchestration path. For router path, it is `router`. * `parent` * `type' - Type of the parent (Event Orchestration) reference for this Event Orchestration Path. * `self` - The URL at which the parent object (Event Orchestration) is accessible. @@ -122,7 +121,6 @@ The Unrouted Orchestration evaluates events sent to it against each of its rules # The catch_all without actions as in this example will set suppressed action to true. # but using the catch_all to set severity, event_action, variables and extractions is allowed. resource "pagerduty_event_orchestration_unrouted" "unrouted" { - type = "unrouted" parent { # id of the Global Event Orchestrartion id = pagerduty_event_orchestration.my_monitor.id @@ -160,7 +158,6 @@ The Unrouted Orchestration evaluates events sent to it against each of its rules The following arguments are supported: -* `type` - (Required) Type of the orchestration path. For unrouted path, it is `unrouted`. * `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. * `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. @@ -203,6 +200,7 @@ The following arguments are supported: ## Attributes Reference The following attributes are exported: +* `type` - Type of the orchestration path. For unrouted path, it is `unrouted`. * `parent` * `type` - Type of the parent (Event Orchestration) reference for this Event .Orchestration Path * `self` - The URL at which the parent object (Event Orchestration) is accessible. diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_resource.html.markdown index feb534063..729e90979 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_resource.html.markdown @@ -96,7 +96,6 @@ resource "pagerduty_service" "example" { # In this example the user has defined the service orchestration with nested rulesets. # The start set rule in this example routes to the second set resource "pagerduty_event_orchestration_service" "www" { - type = "service" parent { # id of the Service id = pagerduty_service.example.id @@ -187,7 +186,6 @@ resource "pagerduty_event_orchestration_service" "www" { The following arguments are supported: -* `type` - (Required) Type of the orchestration. For service orchestrations, it is `service`. * `parent` - (Required) Parent (Service) to which this orchestration belongs to. * `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. @@ -247,6 +245,7 @@ The following arguments are supported: ## Attributes Reference The following attributes are exported: +* `type` - Type of the orchestration. For service orchestrations, it is `service`. * `parent` * `type` - Type of the parent (Event Orchestration) reference for this Event Orchestration Path * `self` - The URL at which the parent object (Event Orchestration) is accessible From e69c11f8ca5b889e99e3a3d4b6c351195794f285 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Fri, 20 May 2022 10:57:51 -0400 Subject: [PATCH 38/51] update documentation --- ...down => event_orchestration.html.markdown} | 6 +- .../docs/r/event_orchestration.html.markdown | 52 +++++ ..._orchestration_path_resource.html.markdown | 220 ------------------ .../event_orchestration_router.html.markdown | 91 ++++++++ ...event_orchestration_service.html.markdown} | 211 ++++++----------- ...event_orchestration_unrouted.html.markdown | 107 +++++++++ 6 files changed, 329 insertions(+), 358 deletions(-) rename website/docs/d/{eventorchestration.html.markdown => event_orchestration.html.markdown} (79%) create mode 100644 website/docs/r/event_orchestration.html.markdown delete mode 100644 website/docs/r/event_orchestration_path_resource.html.markdown create mode 100644 website/docs/r/event_orchestration_router.html.markdown rename website/docs/r/{event_orchestration_resource.html.markdown => event_orchestration_service.html.markdown} (56%) create mode 100644 website/docs/r/event_orchestration_unrouted.html.markdown diff --git a/website/docs/d/eventorchestration.html.markdown b/website/docs/d/event_orchestration.html.markdown similarity index 79% rename from website/docs/d/eventorchestration.html.markdown rename to website/docs/d/event_orchestration.html.markdown index 537766c4f..2e5e53e8d 100644 --- a/website/docs/d/eventorchestration.html.markdown +++ b/website/docs/d/event_orchestration.html.markdown @@ -32,7 +32,11 @@ The following arguments are supported: * `id` - The ID of the found Event Orchestration. * `name` - The name of the found Event Orchestration. -* `integrations` - Routing keys routed to this Event Orchestration. +* `integrations` - List of integrations for the Event Orchestration. + * `id` - ID of the integration + * `parameters` + * `routing_key` - Routing key that routes to this Orchestration. + * `type` - Type of the routing key. `global` is the default type. [1]: https://developer.pagerduty.com/api-reference/7ba0fe7bdb26a-list-event-orchestrations diff --git a/website/docs/r/event_orchestration.html.markdown b/website/docs/r/event_orchestration.html.markdown new file mode 100644 index 000000000..f25acf083 --- /dev/null +++ b/website/docs/r/event_orchestration.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration" +sidebar_current: "docs-pagerduty-resource-event-orchestration" +description: |- + Creates and manages a Global Event Orchestration in PagerDuty. +--- + +# pagerduty_event_orchestration + +[Global Event Orchestrations](https://support.pagerduty.com/docs/event-orchestration#global-orchestrations) allow you define a set of Event Rules, so that when you ingest events using the Orchestration's Routing Key your events will be routed to the correct Service, based on the event's content. + +## Example of configuring a Global Event Orchestration + +```hcl +resource "pagerduty_team" "engineering" { + name = "Engineering" +} + +resource "pagerduty_event_orchestration" "my_monitor" { + name = "My Monitoring Orchestration" + description = "Send events to a pair of services" + team = pagerduty_team.engineering.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the Event Orchestration. +* `description` - (Optional) A human-friendly description of the Event Orchestration. +* `team` - (Optional) ID of the team that owns the Event Orchestration. If none is specified, only admins have access. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Event Orchestration. +* `integrations` - List of integrations for the Event Orchestration. + * `id` - ID of the integration + * `parameters` + * `routing_key` - Routing key that routes to this Orchestration. + * `type` - Type of the routing key. `global` is the default type. + +## Import + +EventOrchestrations can be imported using the `id`, e.g. + +``` +$ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bbf516519601 +``` diff --git a/website/docs/r/event_orchestration_path_resource.html.markdown b/website/docs/r/event_orchestration_path_resource.html.markdown deleted file mode 100644 index 622a63957..000000000 --- a/website/docs/r/event_orchestration_path_resource.html.markdown +++ /dev/null @@ -1,220 +0,0 @@ ---- -layout: "pagerduty" -page_title: "PagerDuty: pagerduty_event_orchestration_path" -sidebar_current: "docs-pagerduty-resource-event-orchestration-path" -description: |- - Creates and manages an orchestration path (router|unrouted) associated with a Global Event Orchestration in PagerDuty. ---- - -# pagerduty_event_orchestration_router - -An Orchestration Router allows users to create a set of Event Rules. The Router evaluates events sent to this Orchestration against each of its rules, one at a time, and routes the event to a specific Service based on the first rule that matches. If an event doesn't match any rules, it'll be sent to service specified in the catch_all or to the "Unrouted" Orchestration if no service is specified. Rules are defined as attributes of the orchestration path resource. - -## Example of configuring Router rules for an Orchestration - -```hcl - # In this example the user has defined the router with two rules, each routing to a different service - # This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource. - # The first rule matches only if either of the two conditions are matched - # The second rule matches always - # The catch_all routes to unrouted path - # but using the catch_all to route to another service is allowed. - resource "pagerduty_event_orchestration_router" "router" { - parent { - # id of the Global Event Orchestrartion - id = pagerduty_event_orchestration.my_monitor.id - } - catch_all { - actions { - route_to = "unrouted" - } - } - sets { - rules { - label = "Events relating to our relational database" - conditions { - expression = "event.summary matches part 'database'" - } - conditions { - expression = "event.source matches regex 'db[0-9]+-server'" - } - actions { - route_to = pageduty_service.database.id - } - } - rules { - actions { - route_to = pagerduty_service.www.id - } - disabled = false - } - } - } -``` - -## Argument Reference - -The following arguments are supported: - -* `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. -* `sets` - (Required) The Router contains a single set of rules (the "start" set) -* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. - - -### Parent (`parent`) supports the following: -* `id` - (Required) ID of the Event Orchestration to which the Router path belongs to - -### Sets (`sets`) supports the following: -* `id` - (Required) ID of the start set. Router path supports only one set and it's id has to be `start` -* `rules` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. - -### Rules (`rules`) supports the following: -* `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. -* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. -* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. - -### Conditions (`conditions`) supports the following: -* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. - -### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the services endpoint. - -### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. - * `route_to' - (Required) With a value of `unrouted`, all events are sent to the Unrouted Orchestration. - -## Attributes Reference - -The following attributes are exported: -* `type` - Type of the orchestration path. For router path, it is `router`. -* `parent` - * `type' - Type of the parent (Event Orchestration) reference for this Event Orchestration Path. - * `self` - The URL at which the parent object (Event Orchestration) is accessible. -* `self` - The URL at which the Router Event Orchestration path is accessible. -* `rules` - * `id` - The ID of the rule within the `start` set. - -## Import - -Router Orchestration path can be imported using the `id` of the event orchestration, e.g. - -``` -$ terraform import pagerduty_event_orchestration_router 1b49abe7-26db-4439-a715-c6d883acfb3e -``` - -# pagerduty_event_orchestration_unrouted - -An Unrouted Orchestration allows users to create a set of Event Rules that will be evaluated against all events that don't match any rules in the Orchestration's Router. - -The Unrouted Orchestration evaluates events sent to it against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Unrouted Orchestration for further processing. - -## Example of configuring a Unrouted Rules for an Orchestration - -```hcl - # In this example the user has defined the unrouted orchestration path with two rules, each routing to a different service - # This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource. - # As there is a single set, route_to is not defined for the rules. - # If there are more than one set, the rules in start set must define route_to with id of the next set - # The first rule matches only if the condition is matched - # The second rule matches always - # The catch_all without actions as in this example will set suppressed action to true. - # but using the catch_all to set severity, event_action, variables and extractions is allowed. - resource "pagerduty_event_orchestration_unrouted" "unrouted" { - parent { - # id of the Global Event Orchestrartion - id = pagerduty_event_orchestration.my_monitor.id - } - sets { - id = "start" - rules { - label = "Update the summary of un-matched Critical alerts so they're easier to spot" - conditions { - expression = "event.severity matches 'critical'" - } - actions { - severity = "info" - extractions { - target = "event.summary" - template = "[Critical Unrouted] {{event.summary}}" - } - } - } - rules { - disabled = false - label = "Reduce the severity of all other unrouted events" - actions { - severity = "info" - } - } - } - catch_all { - actions { } - } - } -``` - -## Argument Reference - -The following arguments are supported: - -* `parent` - (Required) Parent (Event Orchestration) to which this orchestration path belongs to. -* `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. -* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. - - -### Parent (`parent`) supports the following: -* `id` - (Required) ID of the Event Orchestration to which the Unrouted path belongs to. - -### Sets (`sets`) supports the following: -* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The unrouted path evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. - -### Rules (`rules`) supports the following: -* `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. -* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. -* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. - -### Conditions (`conditions`) supports the following: -* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. - -### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the [Services API endpoint](https://developer.pagerduty.com/api-reference/e960cca205c0f-list-services). -* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` -* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` -* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. - * `name` - (Required) The name of the variable - * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. - * `type` - (Required) Only `regex` is supported - * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. -* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. - * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. - * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. - * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. - * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. - -### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. - -## Attributes Reference - -The following attributes are exported: -* `type` - Type of the orchestration path. For unrouted path, it is `unrouted`. -* `parent` - * `type` - Type of the parent (Event Orchestration) reference for this Event .Orchestration Path - * `self` - The URL at which the parent object (Event Orchestration) is accessible. -* `self` - The URL at which the Unrouted Event Orchestration path is accessible. -* `rules` - * `id` - The ID of the rule within the `start` set. -* `catch_all` - * `actions` - * `suppress` - The suppress action for catch_all rule. This is always True. - -## Import - -Unrouted Orchestration path can be imported using the `id` of the event orchestration, e.g. - -``` -$ terraform import pagerduty_event_orchestration_unrouted 1b49abe7-26db-4439-a715-c6d883acfb3e -``` diff --git a/website/docs/r/event_orchestration_router.html.markdown b/website/docs/r/event_orchestration_router.html.markdown new file mode 100644 index 000000000..e1dbcd074 --- /dev/null +++ b/website/docs/r/event_orchestration_router.html.markdown @@ -0,0 +1,91 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration_router" +sidebar_current: "docs-pagerduty-resource-event-orchestration-router" +description: |- + Creates and manages a Router for Global Event Orchestration in PagerDuty. +--- + +# pagerduty_event_orchestration_router + +An Orchestration Router allows users to create a set of Event Rules. The Router evaluates events sent to this Orchestration against each of its rules, one at a time, and routes the event to a specific Service based on the first rule that matches. If an event doesn't match any rules, it'll be sent to service specified in the catch_all or to the "Unrouted" Orchestration if no service is specified. + +## Example of configuring Router rules for an Orchestration + + In this example the user has defined the Router with two rules, each routing to a different service. + This example assumes services used in the `route_to` configuration already exists. So it does not show creation of service resource. + +```hcl +resource "pagerduty_event_orchestration_router" "router" { + event_orchestration = pagerduty_event_orchestration.my_monitor.id + sets { + rules { + label = "Events relating to our relational database" + conditions { + expression = "event.summary matches part 'database'" + } + conditions { + expression = "event.source matches regex 'db[0-9]+-server'" + } + actions { + route_to = pageduty_service.database.id + } + } + rules { + conditions { + expression = "event.summary matches part 'www'" + } + actions { + route_to = pagerduty_service.www.id + } + } + } + catch_all { + actions { + route_to = "unrouted" + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `event_orchestration` - (Required) ID of the Event Orchestration to which the Router belongs to. +* `sets` - (Required) The Router contains a single set of rules (the "start" set) +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + +### Sets (`sets`) supports the following: +* `id` - (Required) ID of the start set. Router supports only one set and it's id has to be `start` +* `rules` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. + * `route_to` - (Required) Defines where an alert will be sent if doesn't match any rules. Can either be the ID of a Service _or_ the string `"unrouted"` to send events to the Unrouted Orchestration. +## Attributes Reference + +The following attributes are exported: +* `self` - The URL at which the Router Orchestration is accessible. +* `rules` + * `id` - The ID of the rule within the `start` set. + +## Import + +Router can be imported using the `id` of the Event Orchestration, e.g. + +``` +$ terraform import pagerduty_event_orchestration_router 1b49abe7-26db-4439-a715-c6d883acfb3e +``` diff --git a/website/docs/r/event_orchestration_resource.html.markdown b/website/docs/r/event_orchestration_service.html.markdown similarity index 56% rename from website/docs/r/event_orchestration_resource.html.markdown rename to website/docs/r/event_orchestration_service.html.markdown index 729e90979..ba4d570ca 100644 --- a/website/docs/r/event_orchestration_resource.html.markdown +++ b/website/docs/r/event_orchestration_service.html.markdown @@ -1,82 +1,37 @@ --- layout: "pagerduty" -page_title: "PagerDuty: pagerduty_event_orchestration" -sidebar_current: "docs-pagerduty-resource-event-orchestration" +page_title: "PagerDuty: pagerduty_event_orchestration_service" +sidebar_current: "docs-pagerduty-resource-event-orchestration-service" description: |- - Creates and manages a Global Event Orchestration / Service Orchestration in PagerDuty. + Creates and manages a Service Orchestration for a Service. --- - - -# pagerduty_event_orchestration - -[Event Orchestrations](https://support.pagerduty.com/docs/event-orchestration) allows users to route events to an endpoint and create nested rules, which define sets of actions to take based on event content. - -## Example of configuring a Global Event Orchestration - -```hcl -resource "pagerduty_team" "engineering" { - name = "Engineering" -} - -resource "pagerduty_event_orchestration" "my_monitor" { - name = "My Monitoring Orchestration" - description = "Send events to a pair of services" - team { - id = pagerduty_team.engineering.id - } -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) Name of the Event Orchestration. -* `description` - (Optional) A human-friendly description of the Event Orchestration. -* `team` - (Optional) Reference to the team that owns the Event Orchestration. If none is specified, only admins have access. - -## Attributes Reference - -The following attributes are exported: - -* `id` - The ID of the Event Orchestration. -* `integrations` - Routing keys routed to this Event Orchestration. - -## Import - -EventOrchestrations can be imported using the `id`, e.g. - -``` -$ terraform import pagerduty_event_orchestration.main 19acac92-027a-4ea0-b06c-bbf516519601 -``` - # pagerduty_event_orchestration_service -When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. As a prerequisite, please ensure the service is set to evaluate orchestrations using the [Service Orchestration Active status endpoint](https://developer.pagerduty.com/api-reference/855659be83d9e-update-the-service-orchestration-active-status-for-a-service) +When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the `"start"` set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. As a prerequisite, please ensure the service is set to evaluate orchestrations using the [Service Orchestration Active Status endpoint](https://developer.pagerduty.com/api-reference/855659be83d9e-update-the-service-orchestration-active-status-for-a-service) ## Example of configuring a Service Orchestration + This example shows creating `team`, `user`, `escalation policy` and `service` resources followed by the `service orchestration` resource. In this example the user has defined the service orchestration with nested rulesets. + The `start` set rule in this example routes to another set. + `catch_all` with empty `actions` block suppresses the alerts that do not match any rules. Other `actions` like `annotate`, `severity`, `priority`, `variables`, `extractions`, `webhooks`, `process automation` can be set in `catch_all` block. ```hcl - # user, escalation policy are required for a service. - # a service orchestration is required to point to an existing service. - # This example shows creating the prerequisite resources for a Service Orchestration (team, user, escalationpolicy and service) - resource "pagerduty_team" "engineering" { - name = "Engineering" +resource "pagerduty_team" "engineering" { +name = "Engineering" } - resource "pagerduty_user" "example" { - name = "Earline Greenholt" - email = "125.greenholt.earline@graham.name" - teams = [pagerduty_team.engineering.id] +resource "pagerduty_user" "example" { +name = "Earline Greenholt" +email = "125.greenholt.earline@graham.name" +teams = [pagerduty_team.engineering.id] } resource "pagerduty_escalation_policy" "foo" { - name = "Engineering Escalation Policy" - num_loops = 2 +name = "Engineering Escalation Policy" +num_loops = 2 rule { - escalation_delay_in_minutes = 10 + escalation_delay_in_minutes = 10 target { type = "user" @@ -86,20 +41,15 @@ resource "pagerduty_escalation_policy" "foo" { } resource "pagerduty_service" "example" { - name = "My Web App" - auto_resolve_timeout = 14400 - acknowledgement_timeout = 600 - escalation_policy = pagerduty_escalation_policy.example.id - alert_creation = "create_alerts_and_incidents" +name = "My Web App" +auto_resolve_timeout = 14400 +acknowledgement_timeout = 600 +escalation_policy = pagerduty_escalation_policy.example.id +alert_creation = "create_alerts_and_incidents" } -# In this example the user has defined the service orchestration with nested rulesets. -# The start set rule in this example routes to the second set resource "pagerduty_event_orchestration_service" "www" { - parent { - # id of the Service - id = pagerduty_service.example.id - } + service = pagerduty_service.example.id sets { id = "start" rules { @@ -128,55 +78,53 @@ resource "pagerduty_event_orchestration_service" "www" { } } sets { - id = "step-two" - rules { - label = "All critical alerts should be treated as P1 incident" - conditions { - expression = "event.severity matches 'critical'" - } - actions { - annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" - priority = "P0IN2KQ" - suppress = false - } - } - rules { - label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" - conditions { - expression = "event.custom_details.hostname matches part 'canary'" - } - # create webhook action with parameters and headers - actions { - automation_actions { - name = "Canary Slack Notification" - url = "https://our-slack-listerner.test/canary-notification" - auto_send = true - parameters { - key = "channel" - value = "#my-team-channel" - } - parameters { - key = "message" - value = "something is wrong with the canary deployment" - } - headers { - key = "X-Notification-Source" - value = "PagerDuty Incident Webhook" - } - } - } - } - rules { - label = "Never bother the on-call for info-level events outside of work hours" - conditions { - expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" - } - actions { - suppress = true - } - } + id = "step-two" + rules { + label = "All critical alerts should be treated as P1 incident" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" + priority = "P0IN2KQ" + } + } + rules { + label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" + conditions { + expression = "event.custom_details.hostname matches part 'canary'" + } + # create webhook action with parameters and headers + actions { + automation_actions { + name = "Canary Slack Notification" + url = "https://our-slack-listerner.test/canary-notification" + auto_send = true + parameters { + key = "channel" + value = "#my-team-channel" + } + parameters { + key = "message" + value = "something is wrong with the canary deployment" + } + headers { + key = "X-Notification-Source" + value = "PagerDuty Incident Webhook" + } + } + } + } + rules { + label = "Never bother the on-call for info-level events outside of work hours" + conditions { + expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" + } + actions { + suppress = true + } + } } - # catch_all always sets suppressed action to true. Other actions like annotate, severity, priority, variables and extractions, webhooks can be set as well catch_all { actions { } } @@ -186,14 +134,10 @@ resource "pagerduty_event_orchestration_service" "www" { The following arguments are supported: -* `parent` - (Required) Parent (Service) to which this orchestration belongs to. +* `service` - (Required) ID of the Service to which this Service Orchestration belongs to. * `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. - -### Parent (`parent`) supports the following: -* `id` - (Required) ID of the Service to which this service orchestration belongs to. - ### Sets (`sets`) supports the following: * `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. * `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. @@ -205,10 +149,10 @@ The following arguments are supported: * `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. ### Conditions (`conditions`) supports the following: -* `expression`- (Required) A [PCL condition] (https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. +* `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. You can find the service you want to route to by calling the [Services API endpoint](https://developer.pagerduty.com/api-reference/e960cca205c0f-list-services). +* `route_to` - (Required) The ID of the target Service for the resulting alert. * `suppress` - (Optional) Set whether the resulting alert is suppressed. Suppressed alerts will not trigger an incident. * `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a `resolve` event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. * `priority` - (Optional) The ID of the priority you want to set on resulting incident. You can find the list of priority IDs for your account by calling the priorities endpoint. @@ -239,26 +183,19 @@ The following arguments are supported: * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. ### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for rules except `route_to` action. +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. ## Attributes Reference The following attributes are exported: -* `type` - Type of the orchestration. For service orchestrations, it is `service`. -* `parent` - * `type` - Type of the parent (Event Orchestration) reference for this Event Orchestration Path - * `self` - The URL at which the parent object (Event Orchestration) is accessible -* `self` - The URL at which the Service Orchestration path is accessible +* `self` - The URL at which the Service Orchestration is accessible. * `rules` * `id` - The ID of the rule within the `start` set. -* `catch_all` - * `actions` - * `suppress` - The suppress action for catch_all rule. This is always True. ## Import -Service Orchestrations can be imported using the `id` of the service, e.g. +Service Orchestration can be imported using the `id` of the Service, e.g. ``` $ terraform import pagerduty_event_orchestration_service PFEODA7 diff --git a/website/docs/r/event_orchestration_unrouted.html.markdown b/website/docs/r/event_orchestration_unrouted.html.markdown new file mode 100644 index 000000000..700a57d5d --- /dev/null +++ b/website/docs/r/event_orchestration_unrouted.html.markdown @@ -0,0 +1,107 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_event_orchestration_unrouted" +sidebar_current: "docs-pagerduty-resource-event-orchestration-unrouted" +description: |- + Creates and manages an Unrouted Orchestration for a Global Event Orchestration in PagerDuty. +--- + +# pagerduty_event_orchestration_unrouted + +An Unrouted Orchestration allows users to create a set of Event Rules that will be evaluated against all events that don't match any rules in the Orchestration's Router. + +The Unrouted Orchestration evaluates events sent to it against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Unrouted Orchestration for further processing. + +## Example of configuring a Unrouted Rules for an Orchestration + + In this example the user has defined the unrouted orchestration with two rules, each routing to a different service.This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource.As there is a single set, route_to is not defined for the rules. + + If there are more than one set, the rules in start set must define route_to with id of the next set + The first rule matches only if the condition is matched. The second rule matches always as there are no conditions. + + `catch_all` with empty `actions` block suppresses the alerts that do not match any rules. Using the `catch_all` to set severity, event_action, variables and extractions is also allowed. + +```hcl +resource "pagerduty_event_orchestration_unrouted" "unrouted" { + event_orchestration = pagerduty_event_orchestration.my_monitor.id + sets { + id = "start" + rules { + label = "Update the summary of un-matched Critical alerts so they're easier to spot" + conditions { + expression = "event.severity matches 'critical'" + } + actions { + severity = "info" + extractions { + target = "event.summary" + template = "[Critical Unrouted] {{event.summary}}" + } + } + } + rules { + label = "Reduce the severity of all other unrouted events" + actions { + severity = "info" + } + } + } + catch_all { + actions { } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `event_orchestration` - (Required) The Event Orchestration to which this Unrouted Orchestration belongs to. +* `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. + +### Sets (`sets`) supports the following: +* `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. +* `rules` - (Optional) The Unrouted Orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. + +### Rules (`rules`) supports the following: +* `label` - (Optional) A description of this rule's purpose. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. +* `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. + +### Conditions (`conditions`) supports the following: +* `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. + +### Actions (`actions`) supports the following: +* `route_to` - (Required) The ID of the target Service for the resulting alert. +* `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` +* `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` +* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. + * `name` - (Required) The name of the variable + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. + * `type` - (Required) Only `regex` is supported + * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. +* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. + * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. + * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. + * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. + * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + +### Catch All (`catch_all`) supports the following: +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. + +## Attributes Reference + +The following attributes are exported: +* `self` - The URL at which the Unrouted Event Orchestration is accessible. +* `rules` + * `id` - The ID of the rule within the `start` set. + +## Import + +Unrouted Orchestration can be imported using the `id` of the Event Orchestration, e.g. + +``` +$ terraform import pagerduty_event_orchestration_unrouted 1b49abe7-26db-4439-a715-c6d883acfb3e +``` From 064154f6cb3ea6760f906698deff569a6df1e905 Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Sun, 22 May 2022 08:18:02 -0400 Subject: [PATCH 39/51] cleanup --- .../event_orchestration_router.html.markdown | 14 ++-- .../event_orchestration_service.html.markdown | 67 +++++++++++-------- ...event_orchestration_unrouted.html.markdown | 46 ++++++------- 3 files changed, 69 insertions(+), 58 deletions(-) diff --git a/website/docs/r/event_orchestration_router.html.markdown b/website/docs/r/event_orchestration_router.html.markdown index e1dbcd074..22ab58b39 100644 --- a/website/docs/r/event_orchestration_router.html.markdown +++ b/website/docs/r/event_orchestration_router.html.markdown @@ -8,12 +8,13 @@ description: |- # pagerduty_event_orchestration_router -An Orchestration Router allows users to create a set of Event Rules. The Router evaluates events sent to this Orchestration against each of its rules, one at a time, and routes the event to a specific Service based on the first rule that matches. If an event doesn't match any rules, it'll be sent to service specified in the catch_all or to the "Unrouted" Orchestration if no service is specified. +An Orchestration Router allows users to create a set of Event Rules. The Router evaluates events sent to this Orchestration against each of its rules, one at a time, and routes the event to a specific Service based on the first rule that matches. If an event doesn't match any rules, it'll be sent to service specified in the `catch_all` or to the "Unrouted" Orchestration if no service is specified. ## Example of configuring Router rules for an Orchestration - In this example the user has defined the Router with two rules, each routing to a different service. - This example assumes services used in the `route_to` configuration already exists. So it does not show creation of service resource. +In this example the user has defined the Router with two rules, each routing to a different service. + +This example assumes services used in the `route_to` configuration already exists. So it does not show creation of service resource. ```hcl resource "pagerduty_event_orchestration_router" "router" { @@ -53,16 +54,16 @@ resource "pagerduty_event_orchestration_router" "router" { The following arguments are supported: * `event_orchestration` - (Required) ID of the Event Orchestration to which the Router belongs to. -* `sets` - (Required) The Router contains a single set of rules (the "start" set) +* `sets` - (Required) The Router contains a single set of rules (the "start" set). * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. ### Sets (`sets`) supports the following: -* `id` - (Required) ID of the start set. Router supports only one set and it's id has to be `start` +* `id` - (Required) ID of the `start` set. Router supports only one set and it's id has to be `start` * `rules` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. ### Rules (`rules`) supports the following: * `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will _always_ match against the rule. * `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. * `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. @@ -75,6 +76,7 @@ The following arguments are supported: ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. * `route_to` - (Required) Defines where an alert will be sent if doesn't match any rules. Can either be the ID of a Service _or_ the string `"unrouted"` to send events to the Unrouted Orchestration. + ## Attributes Reference The following attributes are exported: diff --git a/website/docs/r/event_orchestration_service.html.markdown b/website/docs/r/event_orchestration_service.html.markdown index ba4d570ca..7658f5823 100644 --- a/website/docs/r/event_orchestration_service.html.markdown +++ b/website/docs/r/event_orchestration_service.html.markdown @@ -8,31 +8,38 @@ description: |- # pagerduty_event_orchestration_service -When integrations exist on a service, [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) can be used to evaluate incoming events against each of its rules, beginning with the rules in the `"start"` set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. As a prerequisite, please ensure the service is set to evaluate orchestrations using the [Service Orchestration Active Status endpoint](https://developer.pagerduty.com/api-reference/855659be83d9e-update-the-service-orchestration-active-status-for-a-service) +A [Service Orchestration](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) allows you to create a set of Event Rules. The Service Orchestration evaluates Events sent to this Service against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Service Orchestration for further processing. + +**Note:** If you have a Service that uses [Service Event Rules](https://support.pagerduty.com/docs/rulesets#service-event-rules), you can switch to [Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#service-orchestrations) at any time. Please read the [Switch to Service Orchestrations](https://support.pagerduty.com/docs/event-orchestration#switch-to-service-orchestrations) instructions for more information. ## Example of configuring a Service Orchestration - This example shows creating `team`, `user`, `escalation policy` and `service` resources followed by the `service orchestration` resource. In this example the user has defined the service orchestration with nested rulesets. - The `start` set rule in this example routes to another set. - `catch_all` with empty `actions` block suppresses the alerts that do not match any rules. Other `actions` like `annotate`, `severity`, `priority`, `variables`, `extractions`, `webhooks`, `process automation` can be set in `catch_all` block. + +This example shows creating `Team`, `User`, `Escalation Policy`, and `Service` resources followed by creating a Service Orchestration to handle Events sent to that Service. + +This example also shows using `priority` [data source](https://registry.terraform.io/providers/PagerDuty/pagerduty/latest/docs/data-sources/priority) to configure `priority` action for a rule. If the Event matches the first rule in set "step-two" the resulting incident will have the Priority `P1`. + +This example shows a Service Orchestration that has nested sets: a rule in the "start" set has a `route_to` action pointing at the "step-two" set. + +The `catch_all` actions will be applied if an Event reaches the end of any set without matching any rules in that set. In this example the `catch_all` doesn't have any `actions` so it'll leave events as-is. + ```hcl resource "pagerduty_team" "engineering" { -name = "Engineering" + name = "Engineering" } resource "pagerduty_user" "example" { -name = "Earline Greenholt" -email = "125.greenholt.earline@graham.name" -teams = [pagerduty_team.engineering.id] + name = "Earline Greenholt" + email = "125.greenholt.earline@graham.name" + teams = [pagerduty_team.engineering.id] } resource "pagerduty_escalation_policy" "foo" { -name = "Engineering Escalation Policy" -num_loops = 2 + name = "Engineering Escalation Policy" + num_loops = 2 rule { - escalation_delay_in_minutes = 10 - + escalation_delay_in_minutes = 10 target { type = "user" id = pagerduty_user.example.id @@ -41,11 +48,15 @@ num_loops = 2 } resource "pagerduty_service" "example" { -name = "My Web App" -auto_resolve_timeout = 14400 -acknowledgement_timeout = 600 -escalation_policy = pagerduty_escalation_policy.example.id -alert_creation = "create_alerts_and_incidents" + name = "My Web App" + auto_resolve_timeout = 14400 + acknowledgement_timeout = 600 + escalation_policy = pagerduty_escalation_policy.example.id + alert_creation = "create_alerts_and_incidents" +} + +data "pagerduty_priority" "p1" { + name = "P1" } resource "pagerduty_event_orchestration_service" "www" { @@ -86,7 +97,7 @@ resource "pagerduty_event_orchestration_service" "www" { } actions { annotate = "Please use our P1 runbook: https://docs.test/p1-runbook" - priority = "P0IN2KQ" + priority = data.pagerduty_priority.p1.id } } rules { @@ -136,11 +147,11 @@ The following arguments are supported: * `service` - (Required) ID of the Service to which this Service Orchestration belongs to. * `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. -* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. +* `catch_all` - (Required) the `catch_all` actions will be applied if an Event reaches the end of any set without matching any rules in that set. ### Sets (`sets`) supports the following: * `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. +* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. ### Rules (`rules`) supports the following: * `label` - (Optional) A description of this rule's purpose. @@ -152,10 +163,10 @@ The following arguments are supported: * `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. +* `route_to` - (Optional) The ID of a Set from this Service Orchestration whose rules you also want to use with event that match this rule. * `suppress` - (Optional) Set whether the resulting alert is suppressed. Suppressed alerts will not trigger an incident. * `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a `resolve` event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. -* `priority` - (Optional) The ID of the priority you want to set on resulting incident. You can find the list of priority IDs for your account by calling the priorities endpoint. +* `priority` - (Optional) The ID of the priority you want to set on resulting incident. Consider using the [`pagerduty_priority`](https://registry.terraform.io/providers/PagerDuty/pagerduty/latest/docs/data-sources/priority) data source. * `annotate` - (Optional) Add this text as a note on the resulting incident. * `pagerduty_automation_actions` - (Optional) Configure a [Process Automation](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. * `action_id` - (Required) Id of the Process Automation action to be triggered. @@ -173,14 +184,16 @@ The following arguments are supported: * `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` * `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. * `name` - (Required) The name of the variable - * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use `raw_event.fieldname` to read from the original event `fieldname` data. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths). * `type` - (Required) Only `regex` is supported * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. * `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. - * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. - * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. - * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + * `template` - (Optional) A string that will be used to populate the `target` field. You can reference variables or event data within your template using double curly braces. For example: + * Use variables named `ip` and `subnet` with a template like: `{{variables.ip}}/{{variables.subnet}}` + * Combine the event severity & summary with template like: `{{event.severity}}:{{event.summary}}` + * `regex` - (Optional) A [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) that will be matched against field specified via the `source` argument. If the regex contains one or more capture groups, their values will be extracted and appended together. If it contains no capture groups, the whole match is used. This field can be ignored for `template` based extractions. + * `source` - The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. @@ -191,7 +204,7 @@ The following arguments are supported: The following attributes are exported: * `self` - The URL at which the Service Orchestration is accessible. * `rules` - * `id` - The ID of the rule within the `start` set. + * `id` - The ID of the rule within the set. ## Import diff --git a/website/docs/r/event_orchestration_unrouted.html.markdown b/website/docs/r/event_orchestration_unrouted.html.markdown index 700a57d5d..9c323ef03 100644 --- a/website/docs/r/event_orchestration_unrouted.html.markdown +++ b/website/docs/r/event_orchestration_unrouted.html.markdown @@ -12,14 +12,11 @@ An Unrouted Orchestration allows users to create a set of Event Rules that will The Unrouted Orchestration evaluates events sent to it against each of its rules, beginning with the rules in the "start" set. When a matching rule is found, it can modify and enhance the event and can route the event to another set of rules within this Unrouted Orchestration for further processing. -## Example of configuring a Unrouted Rules for an Orchestration +## Example of configuring Unrouted Rules for an Orchestration - In this example the user has defined the unrouted orchestration with two rules, each routing to a different service.This example assumes services used in the route_to configuration already exists. So it does not show creation of service resource.As there is a single set, route_to is not defined for the rules. - - If there are more than one set, the rules in start set must define route_to with id of the next set - The first rule matches only if the condition is matched. The second rule matches always as there are no conditions. - - `catch_all` with empty `actions` block suppresses the alerts that do not match any rules. Using the `catch_all` to set severity, event_action, variables and extractions is also allowed. +In this example of an Unrouted Orchestration, the rule matches only if the condition is matched. +Alerts created for events that do not match the rule will have severity level set to `info` as defined in `catch_all` block. +`catch_all` for Unrouted Orchestration always suppressess the alert so it is not required to define the `suppress` action. ```hcl resource "pagerduty_event_orchestration_unrouted" "unrouted" { @@ -32,22 +29,18 @@ resource "pagerduty_event_orchestration_unrouted" "unrouted" { expression = "event.severity matches 'critical'" } actions { - severity = "info" + severity = "critical" extractions { - target = "event.summary" - template = "[Critical Unrouted] {{event.summary}}" + target = "event.summary" + template = "[Critical Unrouted] {{event.summary}}" } } } - rules { - label = "Reduce the severity of all other unrouted events" - actions { - severity = "info" - } - } } catch_all { - actions { } + actions { + severity = "info" + } } } ``` @@ -58,11 +51,11 @@ The following arguments are supported: * `event_orchestration` - (Required) The Event Orchestration to which this Unrouted Orchestration belongs to. * `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. -* `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. +* `catch_all` - (Required) the `catch_all` actions will be applied if an Event reaches the end of any set without matching any rules in that set. ### Sets (`sets`) supports the following: * `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The Unrouted Orchestration evaluates Events against these Rules, one at a time, and routes each Event based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. +* `rules` - (Optional) The Unrouted Orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. ### Rules (`rules`) supports the following: * `label` - (Optional) A description of this rule's purpose. @@ -74,19 +67,22 @@ The following arguments are supported: * `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: -* `route_to` - (Required) The ID of the target Service for the resulting alert. +* `route_to` - (Optional) The ID of a Set from this Unrouted Orchestration whose rules you also want to use with event that match this rule. * `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` * `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` * `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. * `name` - (Required) The name of the variable - * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use raw_event.fieldname to read from the original event `fieldname` data. + * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use `raw_event.fieldname` to read from the original event `fieldname` data. * `type` - (Required) Only `regex` is supported * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. * `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. - * `template` - (Optional) A value that will be used to populate the `target` field. The configuration can include variables extracted from the payload by using string interpolation. Eg: If you have defined a variable called `hostname` you can set extraction `template` to `High CPU on variables.hostname server` to use the variable in extraction. This field can be ignored for `regex` based replacements. * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. - * `regex` - (Optional) The conditions that need to be met for the extraction to happen. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. This field can be ignored for `template` based replacements. - * `source` - (Optional) Field where the data is being copied from. Must be a PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field. This field can be ignored for `template` based replacements. + * `template` - (Optional) A string that will be used to populate the `target` field. You can reference variables or event data within your template using double curly braces. For example: + * Use variables named `ip` and `subnet` with a template like: `{{variables.ip}}/{{variables.subnet}}` + * Combine the event severity & summary with template like: `{{event.severity}}:{{event.summary}}` + * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. + * `regex` - (Optional) A [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) that will be matched against field specified via the `source` argument. If the regex contains one or more capture groups, their values will be extracted and appended together. If it contains no capture groups, the whole match is used. This field can be ignored for `template` based extractions. + * `source` - (Optional) The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. @@ -96,7 +92,7 @@ The following arguments are supported: The following attributes are exported: * `self` - The URL at which the Unrouted Event Orchestration is accessible. * `rules` - * `id` - The ID of the rule within the `start` set. + * `id` - The ID of the rule within the set. ## Import From 22fca15bacd7f7e6690195b27ad32f0ed41d1795 Mon Sep 17 00:00:00 2001 From: Marcos Wright-Kuhns Date: Tue, 24 May 2022 05:40:57 -0700 Subject: [PATCH 40/51] Remove mention of the suppress action from event_orchestration_unrouted docs --- website/docs/r/event_orchestration_unrouted.html.markdown | 1 - 1 file changed, 1 deletion(-) diff --git a/website/docs/r/event_orchestration_unrouted.html.markdown b/website/docs/r/event_orchestration_unrouted.html.markdown index 9c323ef03..dcf8a23fb 100644 --- a/website/docs/r/event_orchestration_unrouted.html.markdown +++ b/website/docs/r/event_orchestration_unrouted.html.markdown @@ -16,7 +16,6 @@ The Unrouted Orchestration evaluates events sent to it against each of its rules In this example of an Unrouted Orchestration, the rule matches only if the condition is matched. Alerts created for events that do not match the rule will have severity level set to `info` as defined in `catch_all` block. -`catch_all` for Unrouted Orchestration always suppressess the alert so it is not required to define the `suppress` action. ```hcl resource "pagerduty_event_orchestration_unrouted" "unrouted" { From cb459044012d7d5bb75bdc515cc9d03c7adeee82 Mon Sep 17 00:00:00 2001 From: Marcos Wright-Kuhns Date: Tue, 24 May 2022 05:41:26 -0700 Subject: [PATCH 41/51] Add "Optional" info to 1 attribute in event_orchestration_service docs --- website/docs/r/event_orchestration_service.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/event_orchestration_service.html.markdown b/website/docs/r/event_orchestration_service.html.markdown index 7658f5823..ff0acb3f7 100644 --- a/website/docs/r/event_orchestration_service.html.markdown +++ b/website/docs/r/event_orchestration_service.html.markdown @@ -193,7 +193,7 @@ The following arguments are supported: * Use variables named `ip` and `subnet` with a template like: `{{variables.ip}}/{{variables.subnet}}` * Combine the event severity & summary with template like: `{{event.severity}}:{{event.summary}}` * `regex` - (Optional) A [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) that will be matched against field specified via the `source` argument. If the regex contains one or more capture groups, their values will be extracted and appended together. If it contains no capture groups, the whole match is used. This field can be ignored for `template` based extractions. - * `source` - The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. + * `source` - (Optional) The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. ### Catch All (`catch_all`) supports the following: * `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. From 9219f51fe7e436e10da525a8d6b633d8928c570a Mon Sep 17 00:00:00 2001 From: Pari Dhanakoti Date: Tue, 24 May 2022 09:26:43 -0400 Subject: [PATCH 42/51] give a better datasource example --- .../docs/d/event_orchestration.html.markdown | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/website/docs/d/event_orchestration.html.markdown b/website/docs/d/event_orchestration.html.markdown index 2e5e53e8d..be836f916 100644 --- a/website/docs/d/event_orchestration.html.markdown +++ b/website/docs/d/event_orchestration.html.markdown @@ -11,14 +11,32 @@ description: |- Use this data source to get information about a specific Global [Event Orchestration][1] ## Example Usage - ```hcl -data "pagerduty_event_orchestration" "example" { - name = "My Global Event Orchestration" +resource "pagerduty_event_orchestration" "tf_orch_a" { + name = "Test Event Orchestration" +} + +data "pagerduty_event_orchestration" "tf_my_monitor" { + name = pagerduty_event_orchestration.tf_orch_a.name } -resource "pagerduty_event_orchestration" "foo" { - name = data.pagerduty_event_orchestration.example.name +resource "pagerduty_event_orchestration_router" "router" { + parent { + id = data.pagerduty_event_orchestration.tf_my_monitor.id + } + catch_all { + actions { + route_to = "unrouted" + } + } + sets { + id = "start" + rules { + actions { + route_to = pagerduty_service.db.id + } + } + } } ``` From 0d89d5d7952b4a6b3c94f94772d35a705dcb2a89 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 25 May 2022 12:58:52 -0400 Subject: [PATCH 43/51] cleanup --- go.mod | 3 --- .../heimweh/go-pagerduty/pagerduty/event_orchestration.go | 1 - vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go | 3 --- 3 files changed, 7 deletions(-) diff --git a/go.mod b/go.mod index ac8e1700a..dddc8d81a 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,3 @@ require ( google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb // indirect google.golang.org/grpc v1.33.2 // indirect ) - -// providing a relative path as "../../alenapan/go-pagerduty" doesn't work for some reason, leaving the path as is for now -replace github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go index 38c1ad0fa..0eeedbd5f 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration.go @@ -13,7 +13,6 @@ type EventOrchestration struct { Team *EventOrchestrationObject `json:"team"` Routes int `json:"routes,omitempty"` Integrations []*EventOrchestrationIntegration `json:"integrations,omitempty"` - // TODO: figure out if we need Updater, Creator / updated_by, created_by, updated_at, created_at, version } type EventOrchestrationObject struct { diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go index 69f22a44b..8716eb0f2 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/references.go @@ -49,8 +49,5 @@ type ExtensionSchemaReference resourceReference // RulesetReference represents a reference to a ruleset schema type RulesetReference resourceReference -// EventOrchestrationReference represents a reference to an event orchestration schema -type EventOrchestrationReference resourceReference - // SubscriberReference represents a reference to a subscriber schema type SubscriberReference resourceReference From 0cfb66de369245f778595bddecf72f6eb625f2b4 Mon Sep 17 00:00:00 2001 From: Marcos Wright-Kuhns Date: Fri, 27 May 2022 06:37:25 -0700 Subject: [PATCH 44/51] Add Event Orchestration info to the CHANGELOG (release date TBD) (#514) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab8225a49..037aa900f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.5.0 (Unreleased) + +FEATURES: +* Support for Event Orchestration via several new resources. ([#512](https://github.com/PagerDuty/terraform-provider-pagerduty/pull/512)) + * `resource/pagerduty_event_orchestration` + * `resource/pagerduty_event_orchestration_router` + * `resource/pagerduty_event_orchestration_unrouted` + * `resource/pagerduty_event_orchestration_service` + ## 2.4.2 (May 20, 2022) IMPROVEMENTS: From 3ad7c3b761312011789658e62b9f0358e4cb6140 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Fri, 27 May 2022 16:17:52 -0400 Subject: [PATCH 45/51] update go-pagerduty package --- go.mod | 2 +- go.sum | 2 ++ .../go.mongodb.org/mongo-driver/mongo/options/datakeyoptions.go | 2 +- vendor/modules.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dddc8d81a..c5f0bc0d2 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( cloud.google.com/go v0.71.0 // indirect github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1 - github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 + github.com/heimweh/go-pagerduty v0.0.0-20220527195341-4e587aa9b58e golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd // indirect google.golang.org/api v0.35.0 // indirect google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb // indirect diff --git a/go.sum b/go.sum index cf2737f7e..dd09ff741 100644 --- a/go.sum +++ b/go.sum @@ -288,6 +288,8 @@ github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f h1:NLk7iDq85F github.com/heimweh/go-pagerduty v0.0.0-20220422231448-43095fe5ba3f/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 h1:ETKxW+KSjOPaRzZU9f+QrjCkrL7hQqtMPKDv8DnLDO4= github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= +github.com/heimweh/go-pagerduty v0.0.0-20220527195341-4e587aa9b58e h1:xit0rQWTVlM9ohz4IzrddDKglC7jey+m3GSI/bz3TIw= +github.com/heimweh/go-pagerduty v0.0.0-20220527195341-4e587aa9b58e/go.mod h1:JtJGtgN0y9KOCaqFMZFaBCWskpO/KK3Ro9TwjP9ss6w= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/vendor/go.mongodb.org/mongo-driver/mongo/options/datakeyoptions.go b/vendor/go.mongodb.org/mongo-driver/mongo/options/datakeyoptions.go index 3da8f652a..c6a17f9e0 100644 --- a/vendor/go.mongodb.org/mongo-driver/mongo/options/datakeyoptions.go +++ b/vendor/go.mongodb.org/mongo-driver/mongo/options/datakeyoptions.go @@ -22,7 +22,7 @@ func DataKey() *DataKeyOptions { // If being used with a local KMS provider, this option is not applicable and should not be specified. // // For the AWS, Azure, and GCP KMS providers, this option is required and must be a document. For each, the value of the -// "endpoint" or "keyVaultEndpoint" must be a host name with an optional port number (e.g. "foo.test" or "foo.test:443"). +// "endpoint" or "keyVaultEndpoint" must be a host name with an optional port number (e.g. "foo.com" or "foo.com:443"). // // When using AWS, the document must have the format: // { diff --git a/vendor/modules.txt b/vendor/modules.txt index 0838b566b..0fd9953e9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -124,7 +124,7 @@ github.com/hashicorp/terraform-registry-address github.com/hashicorp/terraform-svchost # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20220428180718-5a69bb821163 => /Users/apantuzenko/Documents/workspace/go/src/github.com/alenapan/go-pagerduty +# github.com/heimweh/go-pagerduty v0.0.0-20220527195341-4e587aa9b58e ## explicit github.com/heimweh/go-pagerduty/pagerduty # github.com/klauspost/compress v1.11.2 From 623b2a5d52a9e3b02ae4d1fcb99ebd00fa0859f4 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Tue, 31 May 2022 21:46:13 -0400 Subject: [PATCH 46/51] Router - make sets, rules, conditions singular --- ...gerduty_event_orchestration_path_router.go | 30 +++++----- ...ty_event_orchestration_path_router_test.go | 56 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router.go b/pagerduty/resource_pagerduty_event_orchestration_path_router.go index b8a763b2b..d535e14a2 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router.go @@ -24,7 +24,7 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { Type: schema.TypeString, Required: true, }, - "sets": { + "set": { Type: schema.TypeList, Required: true, MaxItems: 1, // Router can only have 'start' set @@ -34,7 +34,7 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { Type: schema.TypeString, Required: true, }, - "rules": { + "rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -47,7 +47,7 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "conditions": { + "condition": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -126,7 +126,7 @@ func resourcePagerDutyEventOrchestrationPathRouterRead(d *schema.ResourceData, m d.Set("event_orchestration", routerPath.Parent.ID) if routerPath.Sets != nil { - d.Set("sets", flattenSets(routerPath.Sets)) + d.Set("set", flattenSets(routerPath.Sets)) } if routerPath.CatchAll != nil { @@ -174,7 +174,7 @@ func performRouterPathUpdate(d *schema.ResourceData, routerPath *pagerduty.Event d.Set("event_orchestration", routerPath.Parent.ID) if routerPath.Sets != nil { - d.Set("sets", flattenSets(routerPath.Sets)) + d.Set("set", flattenSets(routerPath.Sets)) } if updatedPath.CatchAll != nil { d.Set("catch_all", flattenCatchAll(updatedPath.CatchAll)) @@ -196,7 +196,7 @@ func buildRouterPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOrch }, } - if attr, ok := d.GetOk("sets"); ok { + if attr, ok := d.GetOk("set"); ok { orchPath.Sets = expandSets(attr) } @@ -215,7 +215,7 @@ func expandSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { orchPathSet := &pagerduty.EventOrchestrationPathSet{ ID: s["id"].(string), - Rules: expandRules(s["rules"]), + Rules: expandRules(s["rule"]), } sets = append(sets, orchPathSet) @@ -235,7 +235,7 @@ func expandRules(v interface{}) []*pagerduty.EventOrchestrationPathRule { ID: r["id"].(string), Label: r["label"].(string), Disabled: r["disabled"].(bool), - Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Conditions: expandEventOrchestrationPathConditions(r["condition"]), Actions: expandRouterActions(r["actions"]), } @@ -269,8 +269,8 @@ func flattenSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interfac var flattenedSets []interface{} for _, set := range orchPathSets { flattenedSet := map[string]interface{}{ - "id": set.ID, - "rules": flattenRules(set.Rules), + "id": set.ID, + "rule": flattenRules(set.Rules), } flattenedSets = append(flattenedSets, flattenedSet) } @@ -282,11 +282,11 @@ func flattenRules(rules []*pagerduty.EventOrchestrationPathRule) []interface{} { for _, rule := range rules { flattenedRule := map[string]interface{}{ - "id": rule.ID, - "label": rule.Label, - "disabled": rule.Disabled, - "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), - "actions": flattenRouterActions(rule.Actions), + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "condition": flattenEventOrchestrationPathConditions(rule.Conditions), + "actions": flattenRouterActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go index d38480e18..3e03a1428 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_router_test.go @@ -34,7 +34,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( "pagerduty_event_orchestration_router.router", "unrouted", true), //test for catch_all route_to prop, by default it should be unrouted resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "0"), + "pagerduty_event_orchestration_router.router", "set.0.rule.#", "0"), ), }, { @@ -52,7 +52,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'database'"), + "pagerduty_event_orchestration_router.router", "set.0.rule.0.condition.0.expression", "event.summary matches part 'database'"), ), }, { @@ -60,11 +60,11 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "2"), + "pagerduty_event_orchestration_router.router", "set.0.rule.#", "2"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'database'"), + "pagerduty_event_orchestration_router.router", "set.0.rule.0.condition.0.expression", "event.summary matches part 'database'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.1.conditions.0.expression", "event.severity matches part 'critical'"), + "pagerduty_event_orchestration_router.router", "set.0.rule.1.condition.0.expression", "event.severity matches part 'critical'"), ), }, { @@ -72,7 +72,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "1"), + "pagerduty_event_orchestration_router.router", "set.0.rule.#", "1"), testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", true), //test for catch_all routing to service if provided ), @@ -82,9 +82,9 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "1"), + "pagerduty_event_orchestration_router.router", "set.0.rule.#", "1"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.0.conditions.#", "0"), + "pagerduty_event_orchestration_router.router", "set.0.rule.0.condition.#", "0"), ), }, { @@ -92,7 +92,7 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_router.router", "sets.0.rules.#", "0"), + "pagerduty_event_orchestration_router.router", "set.0.rule.#", "0"), testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch( "pagerduty_event_orchestration_router.router", "pagerduty_service.bar", true), ), @@ -212,7 +212,7 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigNoRules(t, ep, s, o stri route_to = "unrouted" } } - sets { + set { id = "start" } } @@ -229,9 +229,9 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfig(t, ep, s, o string) str route_to = "unrouted" } } - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { @@ -253,15 +253,15 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(t, ep, s, route_to = "unrouted" } } - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { route_to = pagerduty_service.bar.id } - conditions { + condition { expression = "event.summary matches part 'database'" } } @@ -291,29 +291,29 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigWithMultipleRules(t, ep, route_to = "unrouted" } } - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { route_to = pagerduty_service.bar.id } - conditions { + condition { expression = "event.summary matches part 'database'" } - conditions { + condition { expression = "event.severity matches part 'critical'" } } - rules { + rule { disabled = false label = "rule2 label" actions { route_to = pagerduty_service.bar2.id } - conditions { + condition { expression = "event.severity matches part 'critical'" } } @@ -332,9 +332,9 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigNoConditions(t, ep, s, o route_to = pagerduty_service.bar.id } } - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { @@ -356,15 +356,15 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigWithCatchAllToService(t, route_to = pagerduty_service.bar.id } } - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { route_to = pagerduty_service.bar.id } - conditions { + condition { expression = "event.severity matches part 'critical'" } } @@ -383,7 +383,7 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfigDeleteAllRulesInSet(t, e route_to = pagerduty_service.bar.id } } - sets { + set { id = "start" } } @@ -405,7 +405,7 @@ func testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(router, servi if catchAll == true { rRouteToId = r.Primary.Attributes["catch_all.0.actions.0.route_to"] } else { - rRouteToId = r.Primary.Attributes["sets.0.rules.0.actions.0.route_to"] + rRouteToId = r.Primary.Attributes["set.0.rule.0.actions.0.route_to"] } var sId = "" From d8bf3380336d69192a66f595dd0f0835190b2339 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Tue, 31 May 2022 23:02:21 -0400 Subject: [PATCH 47/51] Unrouted, Service - make sets, rules, conditions, variables, extractions, pd_automation_actions, automations_action (headers, params) singular --- pagerduty/event_orchestration_path_util.go | 14 +- ...erduty_event_orchestration_path_service.go | 70 +++---- ...y_event_orchestration_path_service_test.go | 178 +++++++++--------- ...rduty_event_orchestration_path_unrouted.go | 54 +++--- ..._event_orchestration_path_unrouted_test.go | 140 +++++++------- 5 files changed, 228 insertions(+), 228 deletions(-) diff --git a/pagerduty/event_orchestration_path_util.go b/pagerduty/event_orchestration_path_util.go index 728dabebd..7f5bc6f65 100644 --- a/pagerduty/event_orchestration_path_util.go +++ b/pagerduty/event_orchestration_path_util.go @@ -55,14 +55,14 @@ var eventOrchestrationPathExtractionsSchema = map[string]*schema.Schema{ func invalidExtractionRegexTemplateNilConfig() string { return ` - extractions { + extraction { target = "event.summary" }` } func invalidExtractionRegexTemplateValConfig() string { return ` - extractions { + extraction { regex = ".*" template = "hi" target = "event.summary" @@ -71,7 +71,7 @@ func invalidExtractionRegexTemplateValConfig() string { func invalidExtractionRegexNilSourceConfig() string { return ` - extractions { + extraction { regex = ".*" target = "event.summary" }` @@ -94,18 +94,18 @@ func validateEventOrchestrationPathEventAction() schema.SchemaValidateFunc { } func checkExtractions(context context.Context, diff *schema.ResourceDiff, i interface{}) error { - sn := diff.Get("sets.#").(int) + sn := diff.Get("set.#").(int) for si := 0; si < sn; si++ { - rn := diff.Get(fmt.Sprintf("sets.%d.rules.#", si)).(int) + rn := diff.Get(fmt.Sprintf("set.%d.rule.#", si)).(int) for ri := 0; ri < rn; ri++ { - res := checkExtractionAttributes(diff, fmt.Sprintf("sets.%d.rules.%d.actions.0.extractions", si, ri)) + res := checkExtractionAttributes(diff, fmt.Sprintf("set.%d.rule.%d.actions.0.extraction", si, ri)) if res != nil { return res } } } - return checkExtractionAttributes(diff, "catch_all.0.actions.0.extractions") + return checkExtractionAttributes(diff, "catch_all.0.actions.0.extraction") } func checkExtractionAttributes(diff *schema.ResourceDiff, loc string) error { diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service.go b/pagerduty/resource_pagerduty_event_orchestration_path_service.go index fb7dcd199..a956bb8f4 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service.go @@ -37,7 +37,7 @@ var eventOrchestrationPathServiceCatchAllActionsSchema = map[string]*schema.Sche Type: schema.TypeString, Optional: true, }, - "pagerduty_automation_actions": { + "pagerduty_automation_action": { Type: schema.TypeList, Optional: true, MaxItems: 1, @@ -50,7 +50,7 @@ var eventOrchestrationPathServiceCatchAllActionsSchema = map[string]*schema.Sche }, }, }, - "automation_actions": { + "automation_action": { Type: schema.TypeList, Optional: true, MaxItems: 1, @@ -69,14 +69,14 @@ var eventOrchestrationPathServiceCatchAllActionsSchema = map[string]*schema.Sche Optional: true, Default: false, }, - "headers": { + "header": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: eventOrchestrationAutomationActionObjectSchema, }, }, - "parameters": { + "parameter": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -96,14 +96,14 @@ var eventOrchestrationPathServiceCatchAllActionsSchema = map[string]*schema.Sche Optional: true, ValidateFunc: validateEventOrchestrationPathEventAction(), }, - "variables": { + "variable": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: eventOrchestrationPathVariablesSchema, }, }, - "extractions": { + "extraction": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -139,7 +139,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Type: schema.TypeString, Required: true, }, - "sets": { + "set": { Type: schema.TypeList, Required: true, Elem: &schema.Resource{ @@ -148,7 +148,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Type: schema.TypeString, Required: true, }, - "rules": { + "rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -161,7 +161,7 @@ func resourcePagerDutyEventOrchestrationPathService() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "conditions": { + "condition": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -292,7 +292,7 @@ func buildServicePathStruct(d *schema.ResourceData) *pagerduty.EventOrchestratio Parent: &pagerduty.EventOrchestrationPathReference{ ID: d.Get("service").(string), }, - Sets: expandServicePathSets(d.Get("sets")), + Sets: expandServicePathSets(d.Get("set")), CatchAll: expandServicePathCatchAll(d.Get("catch_all")), } } @@ -305,7 +305,7 @@ func expandServicePathSets(v interface{}) []*pagerduty.EventOrchestrationPathSet orchPathSet := &pagerduty.EventOrchestrationPathSet{ ID: s["id"].(string), - Rules: expandServicePathRules(s["rules"].(interface{})), + Rules: expandServicePathRules(s["rule"].(interface{})), } sets = append(sets, orchPathSet) @@ -325,7 +325,7 @@ func expandServicePathRules(v interface{}) []*pagerduty.EventOrchestrationPathRu ID: r["id"].(string), Label: r["label"].(string), Disabled: r["disabled"].(bool), - Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Conditions: expandEventOrchestrationPathConditions(r["condition"]), Actions: expandServicePathActions(r["actions"]), } @@ -368,10 +368,10 @@ func expandServicePathActions(v interface{}) *pagerduty.EventOrchestrationPathRu actions.Annotate = a["annotate"].(string) actions.Severity = a["severity"].(string) actions.EventAction = a["event_action"].(string) - actions.PagerdutyAutomationActions = expandServicePathPagerDutyAutomationActions(a["pagerduty_automation_actions"]) - actions.AutomationActions = expandServicePathAutomationActions(a["automation_actions"]) - actions.Variables = expandEventOrchestrationPathVariables(a["variables"]) - actions.Extractions = expandEventOrchestrationPathExtractions(a["extractions"]) + actions.PagerdutyAutomationActions = expandServicePathPagerDutyAutomationActions(a["pagerduty_automation_action"]) + actions.AutomationActions = expandServicePathAutomationActions(a["automation_action"]) + actions.Variables = expandEventOrchestrationPathVariables(a["variable"]) + actions.Extractions = expandEventOrchestrationPathExtractions(a["extraction"]) } return actions @@ -401,8 +401,8 @@ func expandServicePathAutomationActions(v interface{}) []*pagerduty.EventOrchest Name: a["name"].(string), Url: a["url"].(string), AutoSend: a["auto_send"].(bool), - Headers: expandEventOrchestrationAutomationActionObjects(a["headers"]), - Parameters: expandEventOrchestrationAutomationActionObjects(a["parameters"]), + Headers: expandEventOrchestrationAutomationActionObjects(a["header"]), + Parameters: expandEventOrchestrationAutomationActionObjects(a["parameter"]), } result = append(result, aa) @@ -430,7 +430,7 @@ func expandEventOrchestrationAutomationActionObjects(v interface{}) []*pagerduty func setEventOrchestrationPathServiceProps(d *schema.ResourceData, p *pagerduty.EventOrchestrationPath) error { d.SetId(p.Parent.ID) d.Set("service", p.Parent.ID) - d.Set("sets", flattenServicePathSets(p.Sets)) + d.Set("set", flattenServicePathSets(p.Sets)) d.Set("catch_all", flattenServicePathCatchAll(p.CatchAll)) return nil } @@ -440,8 +440,8 @@ func flattenServicePathSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) for _, set := range orchPathSets { flattenedSet := map[string]interface{}{ - "id": set.ID, - "rules": flattenServicePathRules(set.Rules), + "id": set.ID, + "rule": flattenServicePathRules(set.Rules), } flattenedSets = append(flattenedSets, flattenedSet) } @@ -464,11 +464,11 @@ func flattenServicePathRules(rules []*pagerduty.EventOrchestrationPathRule) []in for _, rule := range rules { flattenedRule := map[string]interface{}{ - "id": rule.ID, - "label": rule.Label, - "disabled": rule.Disabled, - "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), - "actions": flattenServicePathActions(rule.Actions), + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "condition": flattenEventOrchestrationPathConditions(rule.Conditions), + "actions": flattenServicePathActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) } @@ -490,16 +490,16 @@ func flattenServicePathActions(actions *pagerduty.EventOrchestrationPathRuleActi } if actions.Variables != nil { - flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) + flattenedAction["variable"] = flattenEventOrchestrationPathVariables(actions.Variables) } if actions.Extractions != nil { - flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) + flattenedAction["extraction"] = flattenEventOrchestrationPathExtractions(actions.Extractions) } if actions.PagerdutyAutomationActions != nil { - flattenedAction["pagerduty_automation_actions"] = flattenServicePathPagerDutyAutomationActions(actions.PagerdutyAutomationActions) + flattenedAction["pagerduty_automation_action"] = flattenServicePathPagerDutyAutomationActions(actions.PagerdutyAutomationActions) } if actions.AutomationActions != nil { - flattenedAction["automation_actions"] = flattenServicePathAutomationActions(actions.AutomationActions) + flattenedAction["automation_action"] = flattenServicePathAutomationActions(actions.AutomationActions) } actionsMap = append(actionsMap, flattenedAction) @@ -526,11 +526,11 @@ func flattenServicePathAutomationActions(v []*pagerduty.EventOrchestrationPathAu for _, i := range v { pdaa := map[string]interface{}{ - "name": i.Name, - "url": i.Url, - "auto_send": i.AutoSend, - "headers": flattenServicePathAutomationActionObjects(i.Headers), - "parameters": flattenServicePathAutomationActionObjects(i.Parameters), + "name": i.Name, + "url": i.Url, + "auto_send": i.AutoSend, + "header": flattenServicePathAutomationActionObjects(i.Headers), + "parameter": flattenServicePathAutomationActionObjects(i.Parameters), } result = append(result, pdaa) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go index 74ae61d80..700bf32ea 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_service_test.go @@ -42,13 +42,13 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { Config: testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(escalationPolicy, service), Check: resource.ComposeTestCheckFunc(baseChecks...), }, - // Adding/updating/deleting automation_actions properties + // Adding/updating/deleting automation_action properties { Config: testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(escalationPolicy, service), Check: resource.ComposeTestCheckFunc( append( baseChecks, - resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.0.rule.0.id"), )..., ), }, @@ -58,7 +58,7 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { append( baseChecks, resource.TestCheckResourceAttr( - resourceName, "sets.0.rules.0.actions.0.automation_actions.0.auto_send", "false", + resourceName, "set.0.rule.0.actions.0.automation_action.0.auto_send", "false", ), )..., ), @@ -73,21 +73,21 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { escalationPolicy, service, invalidExtractionRegexTemplateNilConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both be null"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: regex and template cannot both be null"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( escalationPolicy, service, invalidExtractionRegexTemplateValConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: regex and template cannot both have values"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( escalationPolicy, service, invalidExtractionRegexNilSourceConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: source can't be blank"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: source can't be blank"), }, // Providing invalid extractions attributes for the catch_all rule { @@ -95,21 +95,21 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { escalationPolicy, service, "", invalidExtractionRegexTemplateNilConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both be null"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: regex and template cannot both be null"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( escalationPolicy, service, "", invalidExtractionRegexTemplateValConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both have values"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: regex and template cannot both have values"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( escalationPolicy, service, "", invalidExtractionRegexNilSourceConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: source can't be blank"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: source can't be blank"), }, // Adding/updating/deleting all actions { @@ -118,9 +118,9 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { append( baseChecks, []resource.TestCheckFunc{ - resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.0.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.1.id"), }..., )..., ), @@ -131,9 +131,9 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { append( baseChecks, []resource.TestCheckFunc{ - resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.0.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.1.id"), }..., )..., ), @@ -144,9 +144,9 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { append( baseChecks, []resource.TestCheckFunc{ - resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.0.id"), - resource.TestCheckResourceAttrSet(resourceName, "sets.1.rules.1.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.0.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.1.rule.1.id"), }..., )..., ), @@ -157,7 +157,7 @@ func TestAccPagerDutyEventOrchestrationPathService_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append( baseChecks, - resource.TestCheckResourceAttrSet(resourceName, "sets.0.rules.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "set.0.rule.0.id"), )..., ), }, @@ -282,7 +282,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceDefaultConfig(ep, s strin `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" } @@ -298,30 +298,30 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(e `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1" actions { - automation_actions { + automation_action { name = "test" url = "https://test.com" auto_send = true - headers { + header { key = "foo" value = "bar" } - headers { + header { key = "baz" value = "buz" } - parameters { + parameter { key = "source" value = "orch" } - parameters { + parameter { key = "region" value = "us" } @@ -332,25 +332,25 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsConfig(e catch_all { actions { - automation_actions { + automation_action { name = "catch-all test" url = "https://catch-all-test.com" auto_send = true - headers { + header { key = "foo1" value = "bar1" } - headers { + header { key = "baz1" value = "buz1" } - parameters { + parameter { key = "source1" value = "orch1" } - parameters { + parameter { key = "region1" value = "us1" } @@ -366,20 +366,20 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUp `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1" actions { - automation_actions { + automation_action { name = "test1" url = "https://test1.com" - headers { + header { key = "foo1" value = "bar1" } - parameters { + parameter { key = "source_region" value = "eu" } @@ -390,16 +390,16 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsUp catch_all { actions { - automation_actions { + automation_action { name = "catch-all test upd" url = "https://catch-all-test-upd.com" - headers { + header { key = "baz2" value = "buz2" } - parameters { + parameter { key = "source2" value = "orch2" } @@ -415,12 +415,12 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsDe `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1" actions { - automation_actions { + automation_action { name = "test" url = "https://test.com" } @@ -430,7 +430,7 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAutomationActionsParamsDe catch_all { actions { - automation_actions { + automation_action { name = "catch-all test upd" url = "https://catch-all-test-upd.com" } @@ -447,9 +447,9 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceInvalidExtractionsConfig( fmt.Sprintf(`resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { actions { %s } @@ -470,42 +470,42 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s st `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1" - conditions { + condition { expression = "event.summary matches part 'timeout'" } - conditions { + condition { expression = "event.custom_details.timeout_err exists" } actions { route_to = "set-1" priority = "P0IN2KQ" annotate = "Routed through an event orchestration" - pagerduty_automation_actions { + pagerduty_automation_action { action_id = "01CSB5SMOKCKVRI5GN0LJG7SMB" } severity = "critical" event_action = "trigger" - variables { + variable { name = "hostname" path = "event.source" type = "regex" value = "Source host: (.*)" } - variables { + variable { name = "cpu_val" path = "event.custom_details.cpu" type = "regex" value = "(.*)" } - extractions { + extraction { target = "event.summary" template = "High CPU usage on {{variables.hostname}}" } - extractions { + extraction { regex = ".*" source = "event.group" target = "event.custom_details.message" @@ -513,17 +513,17 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s st } } } - sets { + set { id = "set-1" - rules { + rule { label = "set-1 rule 1" actions { suspend = 300 } } - rules { + rule { label = "set-1 rule 2" - conditions { + condition { expression = "event.source matches part 'stg-'" } actions { @@ -537,28 +537,28 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsConfig(ep, s st suspend = 120 priority = "P0IN2KW" annotate = "Routed through an event orchestration - catch-all rule" - pagerduty_automation_actions { + pagerduty_automation_action { action_id = "01CSB5SMOKCKVRI5GN0LJG7SMC" } severity = "warning" event_action = "trigger" - variables { + variable { name = "user_id" path = "event.custom_details.user_id" type = "regex" value = "Source host: (.*)" } - variables { + variable { name = "updated_at" path = "event.custom_details.updated_at" type = "regex" value = "(.*)" } - extractions { + extraction { target = "event.custom_details.message" template = "Last modified by {{variables.user_id}} on {{variables.updated_at}}" } - extractions { + extraction { regex = ".*" source = "event.custom_details.region" target = "event.group" @@ -574,71 +574,71 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(ep `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1 updated" - conditions { + condition { expression = "event.custom_details.timeout_err matches part 'timeout'" } actions { route_to = "set-2" priority = "P0IN2KR" annotate = "Routed through a service orchestration!" - pagerduty_automation_actions { + pagerduty_automation_action { action_id = "01CSB5SMOKCKVRI5GN0LJG7SMBUPDATED" } severity = "warning" event_action = "resolve" - variables { + variable { name = "cpu_val_upd" path = "event.custom_details.cpu_upd" type = "regex" value = "CPU:(.*)" } - extractions { + extraction { regex = ".*" source = "event.custom_details.region_upd" target = "event.source" } - extractions { + extraction { target = "event.custom_details.message_upd" template = "[UPD] High CPU usage on {{variables.hostname}}: {{variables.cpu_val}}" } } } } - sets { + set { id = "set-2" - rules { + rule { label = "set-2 rule 1" actions { suspend = 15 } } - rules { + rule { label = "set-2 rule 2" - conditions { + condition { expression = "event.source matches part 'test-'" } actions { annotate = "Matched set-2 rule 2" - variables { + variable { name = "host_name" path = "event.custom_details.memory" type = "regex" value = "High memory usage on (.*) server" } - extractions { + extraction { target = "event.summary" template = "High memory usage on {{variables.hostname}} server: {{event.custom_details.max_memory}}" } - extractions { + extraction { regex = ".*" source = "event.custom_details.region" target = "event.group" } - extractions { + extraction { regex = ".*" source = "event.custom_details.hostname" target = "event.source" @@ -653,18 +653,18 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsUpdateConfig(ep suppress = true priority = "P0IN2KX" annotate = "[UPD] Routed through an event orchestration - catch-all rule" - pagerduty_automation_actions { + pagerduty_automation_action { action_id = "01CSB5SMOKCKVRI5GN0LJG7SMD" } severity = "info" event_action = "resolve" - variables { + variable { name = "updated_at_upd" path = "event.custom_details.updated_at" type = "regex" value = "UPD (.*)" } - extractions { + extraction { regex = ".*" source = "event.custom_details.region_upd" target = "event.class" @@ -680,22 +680,22 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceAllActionsDeleteConfig(ep `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1 updated" actions { route_to = "set-2" } } } - sets { + set { id = "set-2" - rules { + rule { label = "set-2 rule 1" actions { } } - rules { + rule { label = "set-2 rule 2" actions { } } @@ -713,9 +713,9 @@ func testAccCheckPagerDutyEventOrchestrationPathServiceOneSetNoActionsConfig(ep, `resource "pagerduty_event_orchestration_service" "serviceA" { service = pagerduty_service.bar.id - sets { + set { id = "start" - rules { + rule { label = "rule 1 updated" actions {} } diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go index 70e54d3e5..2fc4cc787 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted.go @@ -25,7 +25,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Type: schema.TypeString, Required: true, }, - "sets": { + "set": { Type: schema.TypeList, Required: true, MinItems: 1, // An Unrouted Orchestration must contain at least a "start" set @@ -35,7 +35,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Type: schema.TypeString, Required: true, }, - "rules": { + "rule": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -48,7 +48,7 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "conditions": { + "condition": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -75,14 +75,14 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { Optional: true, ValidateFunc: validateEventOrchestrationPathEventAction(), }, - "variables": { + "variable": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: eventOrchestrationPathVariablesSchema, }, }, - "extractions": { + "extraction": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -136,14 +136,14 @@ func resourcePagerDutyEventOrchestrationPathUnrouted() *schema.Resource { "resolve", }), }, - "variables": { + "variable": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ Schema: eventOrchestrationPathVariablesSchema, }, }, - "extractions": { + "extraction": { Type: schema.TypeList, Optional: true, Elem: &schema.Resource{ @@ -175,7 +175,7 @@ func resourcePagerDutyEventOrchestrationPathUnroutedRead(d *schema.ResourceData, return resource.RetryableError(err) } else if unroutedPath != nil { if unroutedPath.Sets != nil { - d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) + d.Set("set", flattenUnroutedSets(unroutedPath.Sets)) } if unroutedPath.CatchAll != nil { @@ -223,7 +223,7 @@ func performUnroutedPathUpdate(d *schema.ResourceData, unroutedPath *pagerduty.E d.SetId(unroutedPath.Parent.ID) d.Set("event_orchestration", unroutedPath.Parent.ID) if unroutedPath.Sets != nil { - d.Set("sets", flattenUnroutedSets(unroutedPath.Sets)) + d.Set("set", flattenUnroutedSets(unroutedPath.Sets)) } if updatedPath.CatchAll != nil { d.Set("catch_all", flattenUnroutedCatchAll(updatedPath.CatchAll)) @@ -245,7 +245,7 @@ func buildUnroutedPathStructForUpdate(d *schema.ResourceData) *pagerduty.EventOr }, } - if attr, ok := d.GetOk("sets"); ok { + if attr, ok := d.GetOk("set"); ok { orchPath.Sets = expandUnroutedSets(attr.([]interface{})) } @@ -264,7 +264,7 @@ func expandUnroutedSets(v interface{}) []*pagerduty.EventOrchestrationPathSet { orchPathSet := &pagerduty.EventOrchestrationPathSet{ ID: s["id"].(string), - Rules: expandUnroutedRules(s["rules"]), + Rules: expandUnroutedRules(s["rule"]), } sets = append(sets, orchPathSet) @@ -284,7 +284,7 @@ func expandUnroutedRules(v interface{}) []*pagerduty.EventOrchestrationPathRule ID: r["id"].(string), Label: r["label"].(string), Disabled: r["disabled"].(bool), - Conditions: expandEventOrchestrationPathConditions(r["conditions"]), + Conditions: expandEventOrchestrationPathConditions(r["condition"]), Actions: expandUnroutedActions(r["actions"]), } @@ -305,8 +305,8 @@ func expandUnroutedActions(v interface{}) *pagerduty.EventOrchestrationPathRuleA actions.RouteTo = am["route_to"].(string) actions.Severity = am["severity"].(string) actions.EventAction = am["event_action"].(string) - actions.Variables = expandEventOrchestrationPathVariables(am["variables"]) - actions.Extractions = expandEventOrchestrationPathExtractions(am["extractions"]) + actions.Variables = expandEventOrchestrationPathVariables(am["variable"]) + actions.Extractions = expandEventOrchestrationPathExtractions(am["extraction"]) } } @@ -333,8 +333,8 @@ func expandUnroutedCatchAllActions(v interface{}) *pagerduty.EventOrchestrationP am := ai.(map[string]interface{}) actions.Severity = am["severity"].(string) actions.EventAction = am["event_action"].(string) - actions.Variables = expandEventOrchestrationPathVariables(am["variables"]) - actions.Extractions = expandEventOrchestrationPathExtractions(am["extractions"]) + actions.Variables = expandEventOrchestrationPathVariables(am["variable"]) + actions.Extractions = expandEventOrchestrationPathExtractions(am["extraction"]) } } @@ -346,8 +346,8 @@ func flattenUnroutedSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) [] for _, set := range orchPathSets { flattenedSet := map[string]interface{}{ - "id": set.ID, - "rules": flattenUnroutedRules(set.Rules), + "id": set.ID, + "rule": flattenUnroutedRules(set.Rules), } flattenedSets = append(flattenedSets, flattenedSet) } @@ -359,11 +359,11 @@ func flattenUnroutedRules(rules []*pagerduty.EventOrchestrationPathRule) []inter for _, rule := range rules { flattenedRule := map[string]interface{}{ - "id": rule.ID, - "label": rule.Label, - "disabled": rule.Disabled, - "conditions": flattenEventOrchestrationPathConditions(rule.Conditions), - "actions": flattenUnroutedActions(rule.Actions), + "id": rule.ID, + "label": rule.Label, + "disabled": rule.Disabled, + "condition": flattenEventOrchestrationPathConditions(rule.Conditions), + "actions": flattenUnroutedActions(rule.Actions), } flattenedRules = append(flattenedRules, flattenedRule) } @@ -381,10 +381,10 @@ func flattenUnroutedActions(actions *pagerduty.EventOrchestrationPathRuleActions } if actions.Variables != nil { - flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) + flattenedAction["variable"] = flattenEventOrchestrationPathVariables(actions.Variables) } if actions.Extractions != nil { - flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) + flattenedAction["extraction"] = flattenEventOrchestrationPathExtractions(actions.Extractions) } actionsMap = append(actionsMap, flattenedAction) @@ -413,10 +413,10 @@ func flattenUnroutedCatchAllActions(actions *pagerduty.EventOrchestrationPathRul } if actions.Variables != nil { - flattenedAction["variables"] = flattenEventOrchestrationPathVariables(actions.Variables) + flattenedAction["variable"] = flattenEventOrchestrationPathVariables(actions.Variables) } if actions.Variables != nil { - flattenedAction["extractions"] = flattenEventOrchestrationPathExtractions(actions.Extractions) + flattenedAction["extraction"] = flattenEventOrchestrationPathExtractions(actions.Extractions) } actionsMap = append(actionsMap, flattenedAction) diff --git a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go index b790a32c4..4d2180ec0 100644 --- a/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go +++ b/pagerduty/resource_pagerduty_event_orchestration_path_unrouted_test.go @@ -33,7 +33,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.#", "0"), ), }, { @@ -41,7 +41,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'rds'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.0.expression", "event.summary matches part 'rds'"), ), }, { @@ -49,13 +49,13 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.#", "2"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.summary matches part 'rds'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.0.expression", "event.summary matches part 'rds'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.1.expression", "event.severity matches part 'warning'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.1.expression", "event.severity matches part 'warning'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.1.conditions.0.expression", "event.severity matches part 'info'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.1.condition.0.expression", "event.severity matches part 'info'"), ), }, { @@ -63,27 +63,27 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.#", "2"), //Set #1 resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.id", "start"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.id", "start"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.#", "2"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.route_to", "child-1"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.actions.0.route_to", "child-1"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.0.expression", "event.severity matches part 'info'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.0.expression", "event.severity matches part 'info'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.conditions.1.expression", "event.severity matches part 'warning'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.condition.1.expression", "event.severity matches part 'warning'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.severity", "info"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.actions.0.severity", "info"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.event_action", "trigger"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.actions.0.event_action", "trigger"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.variables.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.actions.0.variable.#", "2"), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "sets.0.rules.0.actions.0.variables.*", + "set.0.rule.0.actions.0.variable.*", map[string]string{ "name": "server_name_cpu", "path": "event.summary", @@ -93,7 +93,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { ), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "sets.0.rules.0.actions.0.variables.*", + "set.0.rule.0.actions.0.variable.*", map[string]string{ "name": "server_name_memory", "path": "event.custom_details", @@ -102,11 +102,11 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { }, ), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.0.actions.0.extractions.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.0.actions.0.extraction.#", "2"), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "sets.0.rules.0.actions.0.extractions.*", + "set.0.rule.0.actions.0.extraction.*", map[string]string{ "target": "event.summary", "template": "High memory usage on {{variables.hostname}} server", @@ -114,7 +114,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { ), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "sets.0.rules.0.actions.0.extractions.*", + "set.0.rule.0.actions.0.extraction.*", map[string]string{ "target": "event.custom_details", "template": "High memory usage on {{variables.hostname}} server", @@ -122,23 +122,23 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { ), //Set #2 resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.id", "child-1"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.1.id", "child-1"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.0.conditions.0.expression", "event.severity matches part 'warning'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.1.rule.0.condition.0.expression", "event.severity matches part 'warning'"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.0.actions.0.event_action", "resolve"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.1.rule.0.actions.0.event_action", "resolve"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.1.rules.1.conditions.0.expression", "event.severity matches part 'critical'"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.1.rule.1.condition.0.expression", "event.severity matches part 'critical'"), // Catch All resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.severity", "critical"), resource.TestCheckResourceAttr( "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.event_action", "trigger"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variables.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.variable.#", "2"), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "catch_all.0.actions.0.variables.*", + "catch_all.0.actions.0.variable.*", map[string]string{ "name": "server_name_cpu", "path": "event.summary", @@ -148,7 +148,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { ), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "catch_all.0.actions.0.variables.*", + "catch_all.0.actions.0.variable.*", map[string]string{ "name": "server_name_memory", "path": "event.custom_details", @@ -157,11 +157,11 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { }, ), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extractions.#", "2"), + "pagerduty_event_orchestration_unrouted.unrouted", "catch_all.0.actions.0.extraction.#", "2"), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "catch_all.0.actions.0.extractions.*", + "catch_all.0.actions.0.extraction.*", map[string]string{ "target": "event.summary", "template": "High memory usage on {{variables.hostname}} server", @@ -169,7 +169,7 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { ), resource.TestCheckTypeSetElemNestedAttrs( "pagerduty_event_orchestration_unrouted.unrouted", - "catch_all.0.actions.0.extractions.*", + "catch_all.0.actions.0.extraction.*", map[string]string{ "target": "event.custom_details", "template": "High memory usage on {{variables.hostname}} server", @@ -183,21 +183,21 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { team, escalationPolicy, service, orchestration, invalidExtractionRegexTemplateValConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: regex and template cannot both have values"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( team, escalationPolicy, service, orchestration, invalidExtractionRegexTemplateValConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: regex and template cannot both have values"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: regex and template cannot both have values"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( team, escalationPolicy, service, orchestration, invalidExtractionRegexNilSourceConfig(), "", ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in sets.0.rules.0.actions.0.extractions.0: source can't be blank"), + ExpectError: regexp.MustCompile("Invalid configuration in set.0.rule.0.actions.0.extraction.0: source can't be blank"), }, // Providing invalid extractions attributes for the catch_all rule { @@ -205,28 +205,28 @@ func TestAccPagerDutyEventOrchestrationPathUnrouted_Basic(t *testing.T) { team, escalationPolicy, service, orchestration, "", invalidExtractionRegexTemplateNilConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both be null"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: regex and template cannot both be null"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( team, escalationPolicy, service, orchestration, "", invalidExtractionRegexTemplateValConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: regex and template cannot both have values"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: regex and template cannot both have values"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig( team, escalationPolicy, service, orchestration, "", invalidExtractionRegexNilSourceConfig(), ), PlanOnly: true, - ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extractions.0: source can't be blank"), + ExpectError: regexp.MustCompile("Invalid configuration in catch_all.0.actions.0.extraction.0: source can't be blank"), }, { Config: testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(team, escalationPolicy, service, orchestration), Check: resource.ComposeTestCheckFunc( testAccCheckPagerDutyEventOrchestrationPathUnroutedExists("pagerduty_event_orchestration_unrouted.unrouted"), resource.TestCheckResourceAttr( - "pagerduty_event_orchestration_unrouted.unrouted", "sets.0.rules.#", "0"), + "pagerduty_event_orchestration_unrouted.unrouted", "set.0.rule.#", "0"), ), }, { @@ -337,7 +337,7 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigNoRules(t, ep, s, `resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.orch.id - sets { + set { id = "start" } catch_all { @@ -352,13 +352,13 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithConditions(t, `resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.orch.id - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { } - conditions { + condition { expression = "event.summary matches part 'rds'" } } @@ -375,25 +375,25 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedConfigWithMultipleRules( `resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.orch.id - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" actions { } - conditions { + condition { expression = "event.summary matches part 'rds'" } - conditions { + condition { expression = "event.severity matches part 'warning'" } } - rules { + rule { disabled = false label = "rule2 label" actions { } - conditions { + condition { expression = "event.severity matches part 'info'" } } @@ -410,83 +410,83 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, `resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.orch.id - sets { + set { id = "start" - rules { + rule { disabled = false label = "rule1 label" - conditions { + condition { expression = "event.severity matches part 'info'" } - conditions { + condition { expression = "event.severity matches part 'warning'" } actions { route_to = "child-1" severity = "info" event_action = "trigger" - variables { + variable { name = "server_name_cpu" path = "event.summary" type = "regex" value = "High CPU on (.*) server" } - variables { + variable { name = "server_name_memory" path = "event.custom_details" type = "regex" value = "High memory usage on (.*) server" } - extractions { + extraction { target = "event.summary" template = "High memory usage on {{variables.hostname}} server" } - extractions { + extraction { target = "event.custom_details" template = "High memory usage on {{variables.hostname}} server" } } } } - sets { + set { id = "child-1" - rules { + rule { disabled = false label = "rule2 label1" - conditions { + condition { expression = "event.severity matches part 'warning'" } actions { severity = "warning" event_action = "resolve" - variables { + variable { name = "server_name_cpu" path = "event.summary" type = "regex" value = "High CPU on (.*) server" } - extractions { + extraction { target = "event.summary" template = "High CPU on {{event.custom_details.hostname}} server" } } } - rules { + rule { disabled = false label = "rule2 label2" - conditions { + condition { expression = "event.severity matches part 'critical'" } actions { severity = "warning" event_action = "trigger" - variables { + variable { name = "server_name_cpu" path = "event.summary" type = "regex" value = "High CPU on (.*) server" } - extractions { + extraction { target = "event.summary" template = "High CPU on {{event.custom_details.hostname}} server" } @@ -497,23 +497,23 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedWithAllConfig(t, ep, s, actions { severity = "critical" event_action = "trigger" - variables { + variable { name = "server_name_cpu" path = "event.summary" type = "regex" value = "High CPU on (.*) server" } - variables { + variable { name = "server_name_memory" path = "event.custom_details" type = "regex" value = "High memory usage on (.*) server" } - extractions { + extraction { target = "event.summary" template = "High memory usage on {{variables.hostname}} server" } - extractions { + extraction { target = "event.custom_details" template = "High memory usage on {{variables.hostname}} server" } @@ -530,9 +530,9 @@ func testAccCheckPagerDutyEventOrchestrationPathUnroutedInvalidExtractionsConfig fmt.Sprintf(`resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.orch.id - sets { + set { id = "start" - rules { + rule { actions { %s } From ab1294a0b4af8fc3bb8aed045f861afacf0b8a10 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Tue, 31 May 2022 23:23:45 -0400 Subject: [PATCH 48/51] Event Orchestration - make integrations singular --- pagerduty/data_source_pagerduty_event_orchestration.go | 4 ++-- pagerduty/data_source_pagerduty_event_orchestration_test.go | 2 +- pagerduty/resource_pagerduty_event_orchestration.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index b36c05709..7e5a19c8e 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -19,7 +19,7 @@ func dataSourcePagerDutyEventOrchestration() *schema.Resource { Type: schema.TypeString, Required: true, }, - "integrations": { + "integration": { Type: schema.TypeList, Computed: true, Optional: true, // Tests keep failing if "Optional: true" is not provided @@ -105,7 +105,7 @@ func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta inte d.Set("name", orch.Name) if len(orch.Integrations) > 0 { - d.Set("integrations", flattenEventOrchestrationIntegrations(orch.Integrations)) + d.Set("integration", flattenEventOrchestrationIntegrations(orch.Integrations)) } return nil diff --git a/pagerduty/data_source_pagerduty_event_orchestration_test.go b/pagerduty/data_source_pagerduty_event_orchestration_test.go index 0850b94ee..554c19037 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration_test.go +++ b/pagerduty/data_source_pagerduty_event_orchestration_test.go @@ -39,7 +39,7 @@ func testAccDataSourcePagerDutyEventOrchestration(src, n string) resource.TestCh return fmt.Errorf("Expected to get an Event Orchestration ID from PagerDuty") } - testAtts := []string{"id", "name", "intergations"} + testAtts := []string{"id", "name", "integration"} for _, att := range testAtts { if a[att] != srcA[att] { diff --git a/pagerduty/resource_pagerduty_event_orchestration.go b/pagerduty/resource_pagerduty_event_orchestration.go index 154b0bbb0..8e876c1cb 100644 --- a/pagerduty/resource_pagerduty_event_orchestration.go +++ b/pagerduty/resource_pagerduty_event_orchestration.go @@ -35,7 +35,7 @@ func resourcePagerDutyEventOrchestration() *schema.Resource { Type: schema.TypeInt, Computed: true, }, - "integrations": { + "integration": { Type: schema.TypeList, Computed: true, Optional: true, // Tests keep failing if "Optional: true" is not provided @@ -233,7 +233,7 @@ func setEventOrchestrationProps(d *schema.ResourceData, o *pagerduty.EventOrches } if len(o.Integrations) > 0 { - d.Set("integrations", flattenEventOrchestrationIntegrations(o.Integrations)) + d.Set("integration", flattenEventOrchestrationIntegrations(o.Integrations)) } return nil From ff5d3c91a7805b267b3a1d383e2e038c22637a09 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Tue, 31 May 2022 23:57:45 -0400 Subject: [PATCH 49/51] update Event Orchestration documentation --- .../docs/d/event_orchestration.html.markdown | 6 +- .../docs/r/event_orchestration.html.markdown | 2 +- .../event_orchestration_router.html.markdown | 28 ++++----- .../event_orchestration_service.html.markdown | 62 +++++++++---------- ...event_orchestration_unrouted.html.markdown | 28 ++++----- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/website/docs/d/event_orchestration.html.markdown b/website/docs/d/event_orchestration.html.markdown index be836f916..e9cb650ca 100644 --- a/website/docs/d/event_orchestration.html.markdown +++ b/website/docs/d/event_orchestration.html.markdown @@ -29,9 +29,9 @@ resource "pagerduty_event_orchestration_router" "router" { route_to = "unrouted" } } - sets { + set { id = "start" - rules { + rule { actions { route_to = pagerduty_service.db.id } @@ -50,7 +50,7 @@ The following arguments are supported: * `id` - The ID of the found Event Orchestration. * `name` - The name of the found Event Orchestration. -* `integrations` - List of integrations for the Event Orchestration. +* `integration` - An integration for the Event Orchestration. * `id` - ID of the integration * `parameters` * `routing_key` - Routing key that routes to this Orchestration. diff --git a/website/docs/r/event_orchestration.html.markdown b/website/docs/r/event_orchestration.html.markdown index f25acf083..1fcb07d33 100644 --- a/website/docs/r/event_orchestration.html.markdown +++ b/website/docs/r/event_orchestration.html.markdown @@ -37,7 +37,7 @@ The following arguments are supported: The following attributes are exported: * `id` - The ID of the Event Orchestration. -* `integrations` - List of integrations for the Event Orchestration. +* `integration` - An integration for the Event Orchestration. * `id` - ID of the integration * `parameters` * `routing_key` - Routing key that routes to this Orchestration. diff --git a/website/docs/r/event_orchestration_router.html.markdown b/website/docs/r/event_orchestration_router.html.markdown index 22ab58b39..822588006 100644 --- a/website/docs/r/event_orchestration_router.html.markdown +++ b/website/docs/r/event_orchestration_router.html.markdown @@ -19,21 +19,21 @@ This example assumes services used in the `route_to` configuration already exist ```hcl resource "pagerduty_event_orchestration_router" "router" { event_orchestration = pagerduty_event_orchestration.my_monitor.id - sets { - rules { + set { + rule { label = "Events relating to our relational database" - conditions { + condition { expression = "event.summary matches part 'database'" } - conditions { + condition { expression = "event.source matches regex 'db[0-9]+-server'" } actions { route_to = pageduty_service.database.id } } - rules { - conditions { + rule { + condition { expression = "event.summary matches part 'www'" } actions { @@ -53,21 +53,21 @@ resource "pagerduty_event_orchestration_router" "router" { The following arguments are supported: -* `event_orchestration` - (Required) ID of the Event Orchestration to which the Router belongs to. -* `sets` - (Required) The Router contains a single set of rules (the "start" set). +* `event_orchestration` - (Required) ID of the Event Orchestration to which the Router belongs. +* `set` - (Required) The Router contains a single set of rules (the "start" set). * `catch_all` - (Required) When none of the rules match an event, the event will be routed according to the catch_all settings. -### Sets (`sets`) supports the following: +### Set (`set`) supports the following: * `id` - (Required) ID of the `start` set. Router supports only one set and it's id has to be `start` -* `rules` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. +* `rule` - (Optional) The Router evaluates Events against these Rules, one at a time, and routes each Event to a specific Service based on the first rule that matches. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. -### Rules (`rules`) supports the following: +### Rule (`rule`) supports the following: * `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will _always_ match against the rule. +* `condition` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will _always_ match against the rule. * `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. * `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. -### Conditions (`conditions`) supports the following: +### Condition (`condition`) supports the following: * `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: @@ -81,7 +81,7 @@ The following arguments are supported: The following attributes are exported: * `self` - The URL at which the Router Orchestration is accessible. -* `rules` +* `rule` * `id` - The ID of the rule within the `start` set. ## Import diff --git a/website/docs/r/event_orchestration_service.html.markdown b/website/docs/r/event_orchestration_service.html.markdown index ff0acb3f7..cda7a031d 100644 --- a/website/docs/r/event_orchestration_service.html.markdown +++ b/website/docs/r/event_orchestration_service.html.markdown @@ -61,24 +61,24 @@ data "pagerduty_priority" "p1" { resource "pagerduty_event_orchestration_service" "www" { service = pagerduty_service.example.id - sets { + set { id = "start" - rules { + rule { label = "Always apply some consistent event transformations to all events" actions { - variables { + variable { name = "hostname" path = "event.component" value = "hostname: (.*)" type = "regex" } - extractions { + extraction { # Demonstrating a template-style extraction template = "{{variables.hostname}}" target = "event.custom_details.hostname" } - extractions { - # Demonstrating a regex-style extractions + extraction { + # Demonstrating a regex-style extraction source = "event.source" regex = "www (.*) service" target = "event.source" @@ -88,11 +88,11 @@ resource "pagerduty_event_orchestration_service" "www" { } } } - sets { + set { id = "step-two" - rules { + rule { label = "All critical alerts should be treated as P1 incident" - conditions { + condition { expression = "event.severity matches 'critical'" } actions { @@ -100,35 +100,35 @@ resource "pagerduty_event_orchestration_service" "www" { priority = data.pagerduty_priority.p1.id } } - rules { + rule { label = "If there's something wrong on the canary let the team know about it in our deployments Slack channel" - conditions { + condition { expression = "event.custom_details.hostname matches part 'canary'" } # create webhook action with parameters and headers actions { - automation_actions { + automation_action { name = "Canary Slack Notification" url = "https://our-slack-listerner.test/canary-notification" auto_send = true - parameters { + parameter { key = "channel" value = "#my-team-channel" } - parameters { + parameter { key = "message" value = "something is wrong with the canary deployment" } - headers { + header { key = "X-Notification-Source" value = "PagerDuty Incident Webhook" } } } } - rules { + rule { label = "Never bother the on-call for info-level events outside of work hours" - conditions { + condition { expression = "event.severity matches 'info' and not (now in Mon,Tue,Wed,Thu,Fri 09:00:00 to 17:00:00 America/Los_Angeles)" } actions { @@ -146,20 +146,20 @@ resource "pagerduty_event_orchestration_service" "www" { The following arguments are supported: * `service` - (Required) ID of the Service to which this Service Orchestration belongs to. -* `sets` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `set` - (Required) A Service Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. * `catch_all` - (Required) the `catch_all` actions will be applied if an Event reaches the end of any set without matching any rules in that set. -### Sets (`sets`) supports the following: +### Set (`set`) supports the following: * `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. +* `rule` - (Optional) The service orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. -### Rules (`rules`) supports the following: +### Rule (`rule`) supports the following: * `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `condition` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. * `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. * `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. -### Conditions (`conditions`) supports the following: +### Condition (`condition`) supports the following: * `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: @@ -168,26 +168,26 @@ The following arguments are supported: * `suspend` - (Optional) The number of seconds to suspend the resulting alert before triggering. This effectively pauses incident notifications. If a `resolve` event arrives before the alert triggers then PagerDuty won't create an incident for this the resulting alert. * `priority` - (Optional) The ID of the priority you want to set on resulting incident. Consider using the [`pagerduty_priority`](https://registry.terraform.io/providers/PagerDuty/pagerduty/latest/docs/data-sources/priority) data source. * `annotate` - (Optional) Add this text as a note on the resulting incident. -* `pagerduty_automation_actions` - (Optional) Configure a [Process Automation](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. +* `pagerduty_automation_action` - (Optional) Configure a [Process Automation](https://support.pagerduty.com/docs/event-orchestration#process-automation) associated with the resulting incident. * `action_id` - (Required) Id of the Process Automation action to be triggered. -* `automation_actions` - (Optional) Create a [Webhook](https://support.pagerduty.com/docs/event-orchestration#webhooks) associated with the resulting incident. +* `automation_action` - (Optional) Create a [Webhook](https://support.pagerduty.com/docs/event-orchestration#webhooks) associated with the resulting incident. * `name` - (Required) Name of this Webhook. * `url` - (Required) The API endpoint where PagerDuty's servers will send the webhook request. * `auto_send` - (Optional) When true, PagerDuty's servers will automatically send this webhook request as soon as the resulting incident is created. When false, your incident responder will be able to manually trigger the Webhook via the PagerDuty website and mobile app. - * `headers` - (Optional) Specify custom key/value pairs that'll be sent with the webhook request as request headers. + * `header` - (Optional) Specify custom key/value pairs that'll be sent with the webhook request as request headers. * `key` - (Required) Name to identify the header * `value` - (Required) Value of this header - * `parameters` - (Optional) Specify custom key/value pairs that'll be included in the webhook request's JSON payload. + * `parameter` - (Optional) Specify custom key/value pairs that'll be included in the webhook request's JSON payload. * `key` - (Required) Name to identify the parameter * `value` - (Required) Value of this parameter * `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` * `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` -* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. +* `variable` - (Optional) Populate variables from event payloads and use those variables in other event actions. * `name` - (Required) The name of the variable * `path` - (Required) Path to a field in an event, in dot-notation. This supports both PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use `raw_event.fieldname` to read from the original event `fieldname` data. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths). * `type` - (Required) Only `regex` is supported * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. -* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. +* `extraction` - (Optional) Replace any CEF field or Custom Details object field using custom variables. * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. * `template` - (Optional) A string that will be used to populate the `target` field. You can reference variables or event data within your template using double curly braces. For example: * Use variables named `ip` and `subnet` with a template like: `{{variables.ip}}/{{variables.subnet}}` @@ -196,14 +196,14 @@ The following arguments are supported: * `source` - (Optional) The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. ### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rule` _except_ `route_to` action. ## Attributes Reference The following attributes are exported: * `self` - The URL at which the Service Orchestration is accessible. -* `rules` +* `rule` * `id` - The ID of the rule within the set. ## Import diff --git a/website/docs/r/event_orchestration_unrouted.html.markdown b/website/docs/r/event_orchestration_unrouted.html.markdown index dcf8a23fb..0ae8f084d 100644 --- a/website/docs/r/event_orchestration_unrouted.html.markdown +++ b/website/docs/r/event_orchestration_unrouted.html.markdown @@ -20,16 +20,16 @@ Alerts created for events that do not match the rule will have severity level se ```hcl resource "pagerduty_event_orchestration_unrouted" "unrouted" { event_orchestration = pagerduty_event_orchestration.my_monitor.id - sets { + set { id = "start" - rules { + rule { label = "Update the summary of un-matched Critical alerts so they're easier to spot" - conditions { + condition { expression = "event.severity matches 'critical'" } actions { severity = "critical" - extractions { + extraction { target = "event.summary" template = "[Critical Unrouted] {{event.summary}}" } @@ -49,32 +49,32 @@ resource "pagerduty_event_orchestration_unrouted" "unrouted" { The following arguments are supported: * `event_orchestration` - (Required) The Event Orchestration to which this Unrouted Orchestration belongs to. -* `sets` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. +* `set` - (Required) An Unrouted Orchestration must contain at least a "start" set, but can contain any number of additional sets that are routed to by other rules to form a directional graph. * `catch_all` - (Required) the `catch_all` actions will be applied if an Event reaches the end of any set without matching any rules in that set. -### Sets (`sets`) supports the following: +### Set (`set`) supports the following: * `id` - (Required) The ID of this set of rules. Rules in other sets can route events into this set using the rule's `route_to` property. -* `rules` - (Optional) The Unrouted Orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. +* `rule` - (Optional) The Unrouted Orchestration evaluates Events against these Rules, one at a time, and applies all the actions for first rule it finds where the event matches the rule's conditions. If no rules are provided as part of Terraform configuration, the API returns empty list of rules. -### Rules (`rules`) supports the following: +### Rule (`rule`) supports the following: * `label` - (Optional) A description of this rule's purpose. -* `conditions` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. +* `condition` - (Optional) Each of these conditions is evaluated to check if an event matches this rule. The rule is considered a match if any of these conditions match. If none are provided, the event will `always` match against the rule. * `actions` - (Required) Actions that will be taken to change the resulting alert and incident, when an event matches this rule. * `disabled` - (Optional) Indicates whether the rule is disabled and would therefore not be evaluated. -### Conditions (`conditions`) supports the following: +### Condition (`condition`) supports the following: * `expression`- (Required) A [PCL condition](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) string. ### Actions (`actions`) supports the following: * `route_to` - (Optional) The ID of a Set from this Unrouted Orchestration whose rules you also want to use with event that match this rule. * `severity` - (Optional) sets Severity of the resulting alert. Allowed values are: `info`, `error`, `warning`, `critical` * `event_action` - (Optional) sets whether the resulting alert status is trigger or resolve. Allowed values are: `trigger`, `resolve` -* `variables` - (Optional) Populate variables from event payloads and use those variables in other event actions. +* `variable` - (Optional) Populate variables from event payloads and use those variables in other event actions. * `name` - (Required) The name of the variable * `path` - (Required) Path to a field in an event, in dot-notation. This supports both [PD-CEF](https://support.pagerduty.com/docs/pd-cef) and non-CEF fields. Eg: Use `event.summary` for the `summary` CEF field. Use `raw_event.fieldname` to read from the original event `fieldname` data. * `type` - (Required) Only `regex` is supported * `value` - (Required) The Regex expression to match against. Must use valid [RE2 regular expression](https://github.com/google/re2/wiki/Syntax) syntax. -* `extractions` - (Optional) Replace any CEF field or Custom Details object field using custom variables. +* `extraction` - (Optional) Replace any CEF field or Custom Details object field using custom variables. * `target` - (Required) The PagerDuty Common Event Format [PD-CEF](https://support.pagerduty.com/docs/pd-cef) field that will be set with the value from the `template` or based on `regex` and `source` fields. * `template` - (Optional) A string that will be used to populate the `target` field. You can reference variables or event data within your template using double curly braces. For example: * Use variables named `ip` and `subnet` with a template like: `{{variables.ip}}/{{variables.subnet}}` @@ -84,13 +84,13 @@ The following arguments are supported: * `source` - (Optional) The path to the event field where the `regex` will be applied to extract a value. You can use any valid [PCL path](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview#paths) like `event.summary` and you can reference previously-defined variables using a path like `variables.hostname`. This field can be ignored for `template` based extractions. ### Catch All (`catch_all`) supports the following: -* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rules` _except_ `route_to` action. +* `actions` - (Required) These are the actions that will be taken to change the resulting alert and incident. `catch_all` supports all actions described above for `rule` _except_ `route_to` action. ## Attributes Reference The following attributes are exported: * `self` - The URL at which the Unrouted Event Orchestration is accessible. -* `rules` +* `rule` * `id` - The ID of the rule within the set. ## Import From 9636f8c89e77f4ce6cbb12c6c23134def06f4d9a Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 1 Jun 2022 16:21:50 -0400 Subject: [PATCH 50/51] EO data source - retry on any error --- CHANGELOG.md | 2 +- pagerduty/data_source_pagerduty_event_orchestration.go | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 037aa900f..b5dfe244f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.5.0 (Unreleased) +## 2.5.0 (June 1, 2022) FEATURES: * Support for Event Orchestration via several new resources. ([#512](https://github.com/PagerDuty/terraform-provider-pagerduty/pull/512)) diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index 7e5a19c8e..c4fe06ad8 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -94,11 +94,7 @@ func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta inte // since the list ndpoint does not return it orch, _, err := client.EventOrchestrations.Get(found.ID) if err != nil { - if isErrCode(err, 429) { - return resource.RetryableError(err) - } - - return resource.NonRetryableError(err) + return resource.RetryableError(err) } d.SetId(orch.ID) From 67e1f0ac2062e2b892d532981b4cb079ebbdbdb4 Mon Sep 17 00:00:00 2001 From: Alena Pantuzenko Date: Wed, 1 Jun 2022 16:26:44 -0400 Subject: [PATCH 51/51] EO data source - retry on any error --- pagerduty/data_source_pagerduty_event_orchestration.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pagerduty/data_source_pagerduty_event_orchestration.go b/pagerduty/data_source_pagerduty_event_orchestration.go index c4fe06ad8..0e42d5a80 100644 --- a/pagerduty/data_source_pagerduty_event_orchestration.go +++ b/pagerduty/data_source_pagerduty_event_orchestration.go @@ -65,14 +65,7 @@ func dataSourcePagerDutyEventOrchestrationRead(d *schema.ResourceData, meta inte return resource.Retry(5*time.Minute, func() *resource.RetryError { resp, _, err := client.EventOrchestrations.List() if err != nil { - if isErrCode(err, 429) { - // Delaying retry by 30s as recommended by PagerDuty - // https://developer.pagerduty.com/docs/rest-api-v2/rate-limiting/#what-are-possible-workarounds-to-the-events-api-rate-limit - time.Sleep(30 * time.Second) - return resource.RetryableError(err) - } - - return resource.NonRetryableError(err) + return resource.RetryableError(err) } var found *pagerduty.EventOrchestration