diff --git a/pagerduty/resource_pagerduty_slack_connection.go b/pagerduty/resource_pagerduty_slack_connection.go index 58165934c..4557dcfb8 100644 --- a/pagerduty/resource_pagerduty_slack_connection.go +++ b/pagerduty/resource_pagerduty_slack_connection.go @@ -12,6 +12,7 @@ import ( ) const AppBaseUrl = "https://app.pagerduty.com" +const StarWildcardConfig = "*" func resourcePagerDutySlackConnection() *schema.Resource { return &schema.Resource{ @@ -215,7 +216,7 @@ func expandConnectionConfig(v interface{}) pagerduty.ConnectionConfig { config = pagerduty.ConnectionConfig{ Events: expandConfigList(c["events"].([]interface{})), - Priorities: expandConfigList(c["priorities"].([]interface{})), + Priorities: expandStarWildcardConfig(expandConfigList(c["priorities"].([]interface{}))), Urgency: nil, } if val, ok := c["urgency"]; ok { @@ -228,18 +229,30 @@ func expandConnectionConfig(v interface{}) pagerduty.ConnectionConfig { } func expandConfigList(v interface{}) []string { - var items []string + items := []string{} for _, i := range v.([]interface{}) { items = append(items, i.(string)) } return items } +//Expands the use of star wildcard ("*") configuration for an attribute to its +//matching expected value by PagerDuty's API, which is nil. This is necessary +//when the API accepts and interprets nil and empty configurations as valid +//settings. The state produced by this kind of config can be reverted to the API +//expected values with sibbling function `flattenStarWildcardConfig`. +func expandStarWildcardConfig(c []string) []string { + if isUsingStarWildcardConfig := len(c) == 1 && c[0] == StarWildcardConfig; isUsingStarWildcardConfig { + c = nil + } + return c +} + func flattenConnectionConfig(config pagerduty.ConnectionConfig) []map[string]interface{} { var configs []map[string]interface{} configMap := map[string]interface{}{ "events": flattenConfigList(config.Events), - "priorities": flattenConfigList(config.Priorities), + "priorities": flattenConfigList(flattenStarWildcardConfig(config.Priorities)), } if config.Urgency != nil { configMap["urgency"] = *config.Urgency @@ -258,6 +271,17 @@ func flattenConfigList(list []string) interface{} { return items } +// Flattens a `nil` configuration to its corresponding star wildcard ("*") +// configuration value for an attribute which is meant to be accepting this kind +// of configuration, with the only purpose to match the config stored in the +// Terraform's state. +func flattenStarWildcardConfig(c []string) []string { + if hasStarWildcardConfigSet := c[:] == nil; hasStarWildcardConfigSet { + c = append(c, StarWildcardConfig) + } + return c +} + func resourcePagerDutySlackConnectionImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { client, err := meta.(*Config).SlackClient() if err != nil { diff --git a/pagerduty/resource_pagerduty_slack_connection_test.go b/pagerduty/resource_pagerduty_slack_connection_test.go index 147ca848c..bb80620d0 100644 --- a/pagerduty/resource_pagerduty_slack_connection_test.go +++ b/pagerduty/resource_pagerduty_slack_connection_test.go @@ -103,6 +103,41 @@ func TestAccPagerDutySlackConnection_Envar(t *testing.T) { }) } +func TestAccPagerDutySlackConnection_NonAndAnyPriorities(t *testing.T) { + username := fmt.Sprintf("tf-%s", acctest.RandString(5)) + email := fmt.Sprintf("%s@foo.test", username) + 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: testAccCheckPagerDutySlackConnectionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutySlackConnectionConfigNonAndAnyPriorities(username, email, escalationPolicy, service, workspaceID, channelID), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutySlackConnectionExists("pagerduty_slack_connection.foo"), + resource.TestCheckResourceAttr( + "pagerduty_slack_connection.foo", "source_name", service), + resource.TestCheckResourceAttr( + "pagerduty_slack_connection.foo", "config.0.priorities.#", "0"), + ), + }, + { + Config: testAccCheckPagerDutySlackConnectionConfigNonAndAnyPrioritiesUpdated(username, email, escalationPolicy, service, workspaceID, channelID), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutySlackConnectionExists("pagerduty_slack_connection.foo"), + resource.TestCheckResourceAttr( + "pagerduty_slack_connection.foo", "config.0.priorities.#", "1"), + resource.TestCheckResourceAttr( + "pagerduty_slack_connection.foo", "config.0.priorities.0", "*"), + ), + }, + }, + }) +} + func testAccCheckPagerDutySlackConnectionDestroy(s *terraform.State) error { config := &pagerduty.Config{ Token: os.Getenv("PAGERDUTY_USER_TOKEN"), @@ -388,3 +423,129 @@ func testAccCheckPagerDutySlackConnectionConfigEnvar(team, channelID string) str } `, team, channelID) } + +func testAccCheckPagerDutySlackConnectionConfigNonAndAnyPriorities(username, useremail, escalationPolicy, service, workspaceID, channelID string) string { + return fmt.Sprintf(` + resource "pagerduty_user" "foo" { + name = "%s" + email = "%s" + } + + resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "foo" + num_loops = 1 + + rule { + escalation_delay_in_minutes = 10 + + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } + } + + resource "pagerduty_service" "foo" { + name = "%s" + description = "foo" + auto_resolve_timeout = 1800 + acknowledgement_timeout = 1800 + escalation_policy = pagerduty_escalation_policy.foo.id + + incident_urgency_rule { + type = "constant" + urgency = "high" + } + } + resource "pagerduty_slack_connection" "foo" { + source_id = pagerduty_service.foo.id + source_type = "service_reference" + workspace_id = "%s" + channel_id = "%s" + notification_type = "responder" + config { + events = [ + "incident.triggered", + "incident.acknowledged", + "incident.escalated", + "incident.resolved", + "incident.reassigned", + "incident.annotated", + "incident.unacknowledged", + "incident.delegated", + "incident.priority_updated", + "incident.responder.added", + "incident.responder.replied", + "incident.status_update_published", + "incident.reopened" + ] + priorities = [] + urgency = "high" + } + } + `, username, useremail, escalationPolicy, service, workspaceID, channelID) +} + +func testAccCheckPagerDutySlackConnectionConfigNonAndAnyPrioritiesUpdated(username, email, escalationPolicy, service, workspaceID, channelID string) string { + return fmt.Sprintf(` + resource "pagerduty_user" "foo" { + name = "%s" + email = "%s" + } + + resource "pagerduty_escalation_policy" "foo" { + name = "%s" + description = "foo" + num_loops = 1 + + rule { + escalation_delay_in_minutes = 10 + + target { + type = "user_reference" + id = pagerduty_user.foo.id + } + } + } + + resource "pagerduty_service" "foo" { + name = "%s" + description = "foo" + auto_resolve_timeout = 1800 + acknowledgement_timeout = 1800 + escalation_policy = pagerduty_escalation_policy.foo.id + + incident_urgency_rule { + type = "constant" + urgency = "high" + } + } + resource "pagerduty_slack_connection" "foo" { + source_id = pagerduty_service.foo.id + source_type = "service_reference" + workspace_id = "%s" + channel_id = "%s" + notification_type = "responder" + config { + events = [ + "incident.triggered", + "incident.acknowledged", + "incident.escalated", + "incident.resolved", + "incident.reassigned", + "incident.annotated", + "incident.unacknowledged", + "incident.delegated", + "incident.priority_updated", + "incident.responder.added", + "incident.responder.replied", + "incident.status_update_published", + "incident.reopened" + ] + priorities = ["*"] + urgency = "high" + } + } + `, username, email, escalationPolicy, service, workspaceID, channelID) +} diff --git a/website/docs/r/slack_connection.html.markdown b/website/docs/r/slack_connection.html.markdown index 94fa09194..7c63d56e5 100644 --- a/website/docs/r/slack_connection.html.markdown +++ b/website/docs/r/slack_connection.html.markdown @@ -80,6 +80,8 @@ The following arguments are supported: - `incident.status_update_published` - `incident.reopened` * `priorities` - (Optional) Allows you to filter events by priority. Needs to be an array of PagerDuty priority IDs. Available through [pagerduty_priority](https://registry.terraform.io/providers/PagerDuty/pagerduty/latest/docs/data-sources/priority) data source. + - When omitted or set to an empty array (`[]`) in the configuration for a Slack Connection, its default behaviour is to set `priorities` to `No Priority` value. + - When set to `["*"]` its corresponding value for `priorities` in Slack Connection's configuration will be `Any Priority`. * `urgency` - (Optional) Allows you to filter events by urgency. Either `high` or `low`. ## Attributes Reference