Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[ORCA-4811] Add support for dynamic_route_to action to pagerduty_event_orchestration_router #1

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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,5 @@ require (
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

replace github.com/heimweh/go-pagerduty => github.com/alexzakabluk/go-pagerduty v0.0.0-20240607142119-ac9a64bba6da
Copy link
Owner Author

@alenapan alenapan Jun 12, 2024

Choose a reason for hiding this comment

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

Annotation: This change as well as the changes in go.sum, vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_path.go, and vendor/modules.txt is the result of temporarily pointing the provider to a feature branch of github.com/heimweh/go-pagerduty:

 $ go mod edit -replace "github.com/heimweh/go-pagerduty=github.com/alexzakabluk/go-pagerduty@rule-actions-updates"
 $ go mod tidy
 $ go mod vendor

We can merge this change into the base branch and upgrade to the latest go-pagerduty version before merging into https://github.com/PagerDuty/terraform-provider-pagerduty. If we don't merge this change the base branch won't compile since the DynamicRouteTo property will be missing in the API Client.

4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alexzakabluk/go-pagerduty v0.0.0-20240607142119-ac9a64bba6da h1:O2mVKSglj/gEz+Z7GX+L4Y1zGRIiDxPHdfp6Ri7klww=
github.com/alexzakabluk/go-pagerduty v0.0.0-20240607142119-ac9a64bba6da/go.mod h1:r59w5iyN01Qvi734yA5hZldbSeJJmsJzee/1kQ/MK7s=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
Expand Down Expand Up @@ -95,8 +97,6 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715 h1:DbdS2LIPkhsqgRcQzOAux0RpTJSH8VYOrN4rZZgznak=
github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715/go.mod h1:r59w5iyN01Qvi734yA5hZldbSeJJmsJzee/1kQ/MK7s=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
Expand Down
58 changes: 55 additions & 3 deletions pagerduty/resource_pagerduty_event_orchestration_path_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,29 @@ func resourcePagerDutyEventOrchestrationPathRouter() *schema.Resource {
MaxItems: 1, // there can only be one action for router
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dynamic_route_to": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"lookup_by": {
Type: schema.TypeString,
Required: true,
},
"regex": {
Type: schema.TypeString,
Required: true,
},
"source": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"route_to": {
Type: schema.TypeString,
Required: true,
Optional: true,
Copy link
Owner Author

Choose a reason for hiding this comment

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

Annotation: We can't have either dynamic_route_to or route_to required because they are mutually exclusive and a rule will have either one. Hopefully in the subsequent PR we can add a check for a rule to have one or the other.

ValidateFunc: func(v interface{}, key string) (warns []string, errs []error) {
value := v.(string)
if value == "unrouted" {
Expand Down Expand Up @@ -294,7 +314,12 @@ func expandRouterActions(v interface{}) *pagerduty.EventOrchestrationPathRuleAct
actions := new(pagerduty.EventOrchestrationPathRuleActions)
for _, ai := range v.([]interface{}) {
am := ai.(map[string]interface{})
actions.RouteTo = am["route_to"].(string)
dra := am["dynamic_route_to"]
if !isNilFunc(dra) && len(dra.([]interface{})) > 0 {
actions.DynamicRouteTo = expandRouterDynamicRouteToAction(dra)
} else {
actions.RouteTo = am["route_to"].(string)
}
Comment on lines +318 to +322
Copy link
Owner Author

Choose a reason for hiding this comment

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

Annotation: The dynamic_route_to action takes precedence over route_to but we can hopefully add validation for these actions to be mutually exclusive in the subsequent ticket (https://pagerduty.atlassian.net/browse/ORCA-4813).

}

return actions
Expand All @@ -311,6 +336,17 @@ func expandCatchAll(v interface{}) *pagerduty.EventOrchestrationPathCatchAll {
return catchAll
}

func expandRouterDynamicRouteToAction(v interface{}) *pagerduty.EventOrchestrationPathDynamicRouteTo {
dr := new(pagerduty.EventOrchestrationPathDynamicRouteTo)
for _, i := range v.([]interface{}) {
dra := i.(map[string]interface{})
dr.LookupBy = dra["lookup_by"].(string)
dr.Regex = dra["regex"].(string)
dr.Source = dra["source"].(string)
}
return dr
}

func flattenSets(orchPathSets []*pagerduty.EventOrchestrationPathSet) []interface{} {
var flattenedSets []interface{}
for _, set := range orchPathSets {
Expand Down Expand Up @@ -344,7 +380,11 @@ func flattenRouterActions(actions *pagerduty.EventOrchestrationPathRuleActions)
var actionsMap []map[string]interface{}

am := make(map[string]interface{})
am["route_to"] = actions.RouteTo
if actions.DynamicRouteTo != nil {
am["dynamic_route_to"] = flattenRouterDynamicRouteToAction(actions.DynamicRouteTo)
} else {
am["route_to"] = actions.RouteTo
}
actionsMap = append(actionsMap, am)
return actionsMap
}
Expand All @@ -360,6 +400,18 @@ func flattenCatchAll(catchAll *pagerduty.EventOrchestrationPathCatchAll) []map[s
return caMap
}

func flattenRouterDynamicRouteToAction(dra *pagerduty.EventOrchestrationPathDynamicRouteTo) []map[string]interface{} {
var dr []map[string]interface{}

dr = append(dr, map[string]interface{}{
"lookup_by": dra.LookupBy,
"regex": dra.Regex,
"source": dra.Source,
})

return dr
}

func resourcePagerDutyEventOrchestrationPathRouterImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client, err := meta.(*Config).Client()
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/heimweh/go-pagerduty/pagerduty"
)

func init() {
Expand All @@ -23,6 +24,17 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) {
service := fmt.Sprintf("tf-%s", acctest.RandString(5))
orchestration := fmt.Sprintf("tf-orchestration-%s", acctest.RandString(5))

dynamicRouteToByNameInput := &pagerduty.EventOrchestrationPathDynamicRouteTo{
LookupBy: "service_name",
Regex: ".*",
Source: "event.custom_details.pd_service_name",
}
dynamicRouteToByIDInput := &pagerduty.EventOrchestrationPathDynamicRouteTo{
LookupBy: "service_id",
Regex: "ID:(.*)",
Source: "event.custom_details.pd_service_id",
}
Comment on lines +27 to +36
Copy link
Owner Author

Choose a reason for hiding this comment

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

Annotation: I'm using these variables to 1. build the config and 2. use in the verification functions


resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Expand All @@ -48,6 +60,27 @@ func TestAccPagerDutyEventOrchestrationPathRouter_Basic(t *testing.T) {
"pagerduty_event_orchestration_router.router", "unrouted", true), //test for catch_all route_to prop, by default it should be unrouted
),
},
// Configure a Dynamic Routing rule:
{
Config: testAccCheckPagerDutyEventOrchestrationRouterDynamicRouteToConfig(team, escalationPolicy, service, orchestration, dynamicRouteToByNameInput),
Check: resource.ComposeTestCheckFunc(
testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"),
testAccCheckPagerDutyEventOrchestrationRouterPathDynamicRouteToMatch("pagerduty_event_orchestration_router.router", dynamicRouteToByNameInput),
testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(
"pagerduty_event_orchestration_router.router", "unrouted", true),
),
},
// Update the Dynamic Routing rule added in the previous test case:
{
Config: testAccCheckPagerDutyEventOrchestrationRouterDynamicRouteToConfig(team, escalationPolicy, service, orchestration, dynamicRouteToByIDInput),
Check: resource.ComposeTestCheckFunc(
testAccCheckPagerDutyEventOrchestrationRouterExists("pagerduty_event_orchestration_router.router"),
testAccCheckPagerDutyEventOrchestrationRouterPathDynamicRouteToMatch("pagerduty_event_orchestration_router.router", dynamicRouteToByIDInput),
testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(
"pagerduty_event_orchestration_router.router", "unrouted", true),
),
},
// Delete the Dynamic Routing rule added in the previous test cases:
{
Config: testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(team, escalationPolicy, service, orchestration),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -279,6 +312,42 @@ func testAccCheckPagerDutyEventOrchestrationRouterConfig(t, ep, s, o string) str
`)
}

func testAccCheckPagerDutyEventOrchestrationRouterDynamicRouteToConfig(t, ep, s, o string, dynamicRouteToByNameInput *pagerduty.EventOrchestrationPathDynamicRouteTo) string {
routerConfig := fmt.Sprintf(
`resource "pagerduty_event_orchestration_router" "router" {
event_orchestration = pagerduty_event_orchestration.orch.id

catch_all {
actions {
route_to = "unrouted"
}
}
set {
id = "start"
rule {
disabled = false
label = "dynamic routing rule"
actions {
dynamic_route_to {
lookup_by = "%s"
regex = "%s"
source = "%s"
}
}
}
rule {
label = "static routing rule"
actions {
route_to = pagerduty_service.bar.id
}
}
}
}
`, dynamicRouteToByNameInput.LookupBy, dynamicRouteToByNameInput.Regex, dynamicRouteToByNameInput.Source)

return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o), routerConfig)
}

func testAccCheckPagerDutyEventOrchestrationRouterConfigWithConditions(t, ep, s, o string) string {
return fmt.Sprintf("%s%s", createBaseConfig(t, ep, s, o),
`resource "pagerduty_event_orchestration_router" "router" {
Expand Down Expand Up @@ -510,3 +579,28 @@ func testAccCheckPagerDutyEventOrchestrationRouterPathRouteToMatch(router, servi
return nil
}
}

func testAccCheckPagerDutyEventOrchestrationRouterPathDynamicRouteToMatch(router string, expectedDynamicRouteTo *pagerduty.EventOrchestrationPathDynamicRouteTo) resource.TestCheckFunc {
return func(s *terraform.State) error {
r, rOk := s.RootModule().Resources[router]
if !rOk {
return fmt.Errorf("Not found: %s", router)
}

rLookupBy := r.Primary.Attributes["set.0.rule.0.actions.0.dynamic_route_to.0.lookup_by"]
rRegex := r.Primary.Attributes["set.0.rule.0.actions.0.dynamic_route_to.0.regex"]
rSource := r.Primary.Attributes["set.0.rule.0.actions.0.dynamic_route_to.0.source"]

if rLookupBy != expectedDynamicRouteTo.LookupBy {
return fmt.Errorf("Event Orchestration Router `dynamic_route_to.lookup_by` (%v) does not match expected value: %v", rLookupBy, expectedDynamicRouteTo.LookupBy)
}
if rRegex != expectedDynamicRouteTo.Regex {
return fmt.Errorf("Event Orchestration Router `dynamic_route_to.regex` (%v) does not match expected value: %v", rRegex, expectedDynamicRouteTo.Regex)
}
if rSource != expectedDynamicRouteTo.Source {
return fmt.Errorf("Event Orchestration Router `dynamic_route_to.source` (%v) does not match expected value: %v", rSource, expectedDynamicRouteTo.Source)
}

return nil
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ github.com/hashicorp/terraform-svchost
# github.com/hashicorp/yamux v0.1.1
## explicit; go 1.15
github.com/hashicorp/yamux
# github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715
# github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715 => github.com/alexzakabluk/go-pagerduty v0.0.0-20240607142119-ac9a64bba6da
## explicit; go 1.17
github.com/heimweh/go-pagerduty/pagerduty
github.com/heimweh/go-pagerduty/persistentconfig
Expand Down Expand Up @@ -558,3 +558,4 @@ google.golang.org/protobuf/types/known/timestamppb
# gopkg.in/ini.v1 v1.67.0
## explicit
gopkg.in/ini.v1
# github.com/heimweh/go-pagerduty => github.com/alexzakabluk/go-pagerduty v0.0.0-20240607142119-ac9a64bba6da