diff --git a/go.mod b/go.mod index 3345e789c..f30298c2a 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/hashicorp/terraform-plugin-mux v0.13.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 github.com/hashicorp/terraform-plugin-testing v1.6.0 - github.com/heimweh/go-pagerduty v0.0.0-20240403153232-5876af2ce24a + github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715 ) require ( diff --git a/go.sum b/go.sum index ffc58c1a5..23cfe0968 100644 --- a/go.sum +++ b/go.sum @@ -95,8 +95,8 @@ 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-20240403153232-5876af2ce24a h1:upvfy2kYdl/poYpITYmq6ZqJb5mu9zHm4V0YeXlyNOM= -github.com/heimweh/go-pagerduty v0.0.0-20240403153232-5876af2ce24a/go.mod h1:r59w5iyN01Qvi734yA5hZldbSeJJmsJzee/1kQ/MK7s= +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= diff --git a/pagerduty/resource_pagerduty_incident_workflow_trigger.go b/pagerduty/resource_pagerduty_incident_workflow_trigger.go index 8d38aa948..1d779ad30 100644 --- a/pagerduty/resource_pagerduty_incident_workflow_trigger.go +++ b/pagerduty/resource_pagerduty_incident_workflow_trigger.go @@ -52,6 +52,25 @@ func resourcePagerDutyIncidentWorkflowTrigger() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "permissions": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "restricted": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "team_id": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, }, } } @@ -138,6 +157,16 @@ func validateIncidentWorkflowTrigger(_ context.Context, d *schema.ResourceDiff, return fmt.Errorf("when trigger type conditional is used, condition must be specified") } + // pagerduty_incident_workflow_trigger.permissions input validation + permissionRestricted := d.Get("permissions.0.restricted").(bool) + permissionTeamID := d.Get("permissions.0.team_id").(string) + if triggerType != "manual" && permissionRestricted { + return fmt.Errorf("restricted can only be true when trigger type is manual") + } + if !permissionRestricted && permissionTeamID != "" { + return fmt.Errorf("team_id not allowed when restricted is false") + } + s, hadServices := d.GetOk("services") all := d.Get("subscribed_to_all_services").(bool) if all && hadServices && len(s.([]interface{})) > 0 { @@ -186,6 +215,14 @@ func flattenIncidentWorkflowTrigger(d *schema.ResourceData, t *pagerduty.Inciden if t.Condition != nil { d.Set("condition", t.Condition) } + if t.Permissions != nil { + d.Set("permissions", []map[string]interface{}{ + { + "restricted": t.Permissions.Restricted, + "team_id": t.Permissions.TeamID, + }, + }) + } return nil } @@ -219,6 +256,14 @@ func buildIncidentWorkflowTriggerStruct(d *schema.ResourceData, forUpdate bool) iwt.Condition = &condStr } + if permissions, ok := d.GetOk("permissions"); ok { + p, err := expandIncidentWorkflowTriggerPermissions(permissions) + if err != nil { + return nil, err + } + iwt.Permissions = p + } + return &iwt, nil } @@ -232,3 +277,28 @@ func buildIncidentWorkflowTriggerServices(s interface{}) []*pagerduty.ServiceRef } return newServices } + +func expandIncidentWorkflowTriggerPermissions(v interface{}) (*pagerduty.IncidentWorkflowTriggerPermissions, error) { + var permissions *pagerduty.IncidentWorkflowTriggerPermissions + + permissionsData, ok := v.([]interface{}) + if ok && len(permissionsData) > 0 { + p := permissionsData[0].(map[string]interface{}) + + // Unfortunately this validatation can't be made during diff checking, since + // Diff Customization doesn't support computed/"known after apply" values + // like team_id in this case. Based on + // https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/customizing-differences + // because of this, it will only be returned during the apply phase. + if p["restricted"].(bool) && p["team_id"].(string) == "" { + return nil, fmt.Errorf("team_id must be specified when restricted is true") + } + + permissions = &pagerduty.IncidentWorkflowTriggerPermissions{ + Restricted: p["restricted"].(bool), + TeamID: p["team_id"].(string), + } + } + + return permissions, nil +} diff --git a/pagerduty/resource_pagerduty_incident_workflow_trigger_test.go b/pagerduty/resource_pagerduty_incident_workflow_trigger_test.go index f11484eef..b20eed3e2 100644 --- a/pagerduty/resource_pagerduty_incident_workflow_trigger_test.go +++ b/pagerduty/resource_pagerduty_incident_workflow_trigger_test.go @@ -228,6 +228,150 @@ func TestAccPagerDutyIncidentWorkflowTrigger_BasicConditionalAllServices(t *test }) } +func TestAccPagerDutyIncidentWorkflowTrigger_ManualWithTeamPermissions(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)) + workflow := fmt.Sprintf("tf-%s", acctest.RandString(5)) + teamName := fmt.Sprintf("tf-%s", acctest.RandString(5)) + teamIDTFRef := "pagerduty_team.foo.id" + emptyCondition := "" + dummyCondition := "event.summary matches 'foo'" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckIncidentWorkflows(t) + }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckPagerDutyIncidentWorkflowTriggerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissions(username, email, escalationPolicy, service, teamName, workflow), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyIncidentWorkflowTriggerExists("pagerduty_incident_workflow_trigger.test"), + resource.TestCheckResourceAttr( + "pagerduty_incident_workflow_trigger.test", "type", "manual"), + resource.TestCheckResourceAttr( + "pagerduty_incident_workflow_trigger.test", "permissions.0.restricted", "false"), + ), + }, + { + Config: testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissionsUpdated(username, email, escalationPolicy, service, teamName, workflow, "manual", emptyCondition, "true", teamIDTFRef), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyIncidentWorkflowTriggerExists("pagerduty_incident_workflow_trigger.test"), + resource.TestCheckResourceAttr( + "pagerduty_incident_workflow_trigger.test", "type", "manual"), + resource.TestCheckResourceAttr( + "pagerduty_incident_workflow_trigger.test", "permissions.0.restricted", "true"), + testAccCheckPagerDutyIncidentWorkflowTriggerCheckPermissionsTeamId("pagerduty_incident_workflow_trigger.test", "pagerduty_team.foo"), + ), + }, + // Check input validation conditions for permissions configuration + { + Config: testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissionsUpdated(username, email, escalationPolicy, service, teamName, workflow, "conditional", dummyCondition, "true", teamIDTFRef), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyIncidentWorkflowTriggerExists("pagerduty_incident_workflow_trigger.test"), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("restricted can only be true when trigger type is manual"), + }, + { + Config: testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissionsUpdated(username, email, escalationPolicy, service, teamName, workflow, "manual", emptyCondition, "false", teamIDTFRef), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyIncidentWorkflowTriggerExists("pagerduty_incident_workflow_trigger.test"), + ), + PlanOnly: true, + ExpectError: regexp.MustCompile("team_id not allowed when restricted is false"), + }, + { + Config: testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissionsUpdated(username, email, escalationPolicy, service, teamName, workflow, "manual", emptyCondition, "true", `""`), + Check: resource.ComposeTestCheckFunc( + testAccCheckPagerDutyIncidentWorkflowTriggerExists("pagerduty_incident_workflow_trigger.test"), + ), + ExpectError: regexp.MustCompile("team_id must be specified when restricted is true"), + }, + }, + }) +} + +func testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissions(username, email, escalationPolicy, service, workflow, team string) string { + return fmt.Sprintf(` +%s + +%s + +resource "pagerduty_team" "foo" { + name = %q +} + +resource "pagerduty_incident_workflow_trigger" "test" { + type = "manual" + workflow = pagerduty_incident_workflow.test.id + services = [pagerduty_service.foo.id] + subscribed_to_all_services = false +} +`, testAccCheckPagerDutyServiceConfig(username, email, escalationPolicy, service), testAccCheckPagerDutyIncidentWorkflowConfig(workflow), team) +} + +func testAccCheckPagerDutyIncidentWorkflowTriggerConfigManualWithPermissionsUpdated(username, email, escalationPolicy, service, workflow, team, triggerType, condition, isRestricted, teamId string) string { + return fmt.Sprintf(` +%s + +%s + +resource "pagerduty_team" "foo" { + name = "%s" +} + +resource "pagerduty_incident_workflow_trigger" "test" { + type = "%s" + condition = "%s" + workflow = pagerduty_incident_workflow.test.id + services = [pagerduty_service.foo.id] + subscribed_to_all_services = false + permissions { + restricted = %s + team_id = %s + } +} +`, testAccCheckPagerDutyServiceConfig(username, email, escalationPolicy, service), testAccCheckPagerDutyIncidentWorkflowConfig(workflow), team, triggerType, condition, isRestricted, teamId) +} + +func testAccCheckPagerDutyIncidentWorkflowTriggerCheckPermissionsTeamId(iwtName, teamName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rsIWT, ok := s.RootModule().Resources[iwtName] + if !ok { + return fmt.Errorf("not found: %s", iwtName) + } + if rsIWT.Primary.ID == "" { + return fmt.Errorf("no incident workflow trigger ID is set") + } + + rsTeam, ok := s.RootModule().Resources[teamName] + if !ok { + return fmt.Errorf("not found: %s", teamName) + } + if rsTeam.Primary.ID == "" { + return fmt.Errorf("no team ID is set") + } + + client, _ := testAccProvider.Meta().(*Config).Client() + + found, _, err := client.IncidentWorkflowTriggers.Get(rsIWT.Primary.ID) + if err != nil { + return err + } + + if found.Permissions.TeamID != rsTeam.Primary.ID { + return fmt.Errorf("incident workflow trigger team restriction wanted %q, but got %q", rsTeam.Primary.ID, found.Permissions.TeamID) + } + + return nil + } +} + func TestAccPagerDutyIncidentWorkflowTrigger_ChangeTypeCausesReplace(t *testing.T) { workflow := fmt.Sprintf("tf-%s", acctest.RandString(5)) diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_cache_variable.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_cache_variable.go index 6df0fa845..5d7232e40 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_cache_variable.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/event_orchestration_cache_variable.go @@ -23,15 +23,15 @@ type EventOrchestrationCacheVariableConfiguration struct { } type EventOrchestrationCacheVariable struct { - ID string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Disabled bool `json:"disabled"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Disabled bool `json:"disabled"` Conditions []*EventOrchestrationCacheVariableCondition `json:"conditions"` Configuration *EventOrchestrationCacheVariableConfiguration `json:"configuration,omitempty"` - CreatedAt string `json:"created_at,omitempty"` - CreatedBy *UserReference `json:"created_by,omitempty"` - UpdatedAt string `json:"updated_at,omitempty"` - UpdatedBy *UserReference `json:"updated_by,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + CreatedBy *UserReference `json:"created_by,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + UpdatedBy *UserReference `json:"updated_by,omitempty"` } type EventOrchestrationCacheVariablePayload struct { @@ -67,7 +67,7 @@ func (s *EventOrchestrationCacheVariableService) List(ctx context.Context, cache return v, resp, nil } -func (s *EventOrchestrationCacheVariableService) Create(ctx context.Context, cacheVariableType string, orchestrationId string, cacheVariable *EventOrchestrationCacheVariable) (*EventOrchestrationCacheVariable, *Response, error) { +func (s *EventOrchestrationCacheVariableService) Create(ctx context.Context, cacheVariableType string, orchestrationId string, cacheVariable *EventOrchestrationCacheVariable) (*EventOrchestrationCacheVariable, *Response, error) { u := buildEventOrchestrationCacheVariableUrl(cacheVariableType, orchestrationId, "") v := new(EventOrchestrationCacheVariablePayload) p := &EventOrchestrationCacheVariablePayload{CacheVariable: cacheVariable} 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 42bd64351..72b60e0f4 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 @@ -67,7 +67,7 @@ type EventOrchestrationPathRuleActions struct { } type EventOrchestrationPathIncidentCustomFieldUpdate struct { - ID string `json:"id,omitempty"` + ID string `json:"id,omitempty"` Value string `json:"value,omitempty"` } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow.go index 09b131c22..5fd58cb30 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow.go @@ -45,7 +45,7 @@ type IncidentWorkflowActionInput struct { // IncidentWorkflowActionInlineStepsInput represents the configuration for an incident workflow action input with a series of inlined steps as the value type IncidentWorkflowActionInlineStepsInput struct { - Name string `json:"name,omitempty"` + Name string `json:"name,omitempty"` Value *IncidentWorkflowActionInlineStepsInputValue `json:"value,omitempty"` } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow_trigger.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow_trigger.go index a5ef8debb..a9537e2cb 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow_trigger.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/incident_workflow_trigger.go @@ -11,13 +11,19 @@ type IncidentWorkflowTriggerService service // IncidentWorkflowTrigger represents an incident workflow. type IncidentWorkflowTrigger struct { - ID string `json:"id,omitempty"` - Type string `json:"type,omitempty"` - TriggerType IncidentWorkflowTriggerType `json:"trigger_type,omitempty"` - Workflow *IncidentWorkflow `json:"workflow,omitempty"` - Services []*ServiceReference `json:"services,omitempty"` - Condition *string `json:"condition,omitempty"` - SubscribedToAllServices bool `json:"is_subscribed_to_all_services,omitempty"` + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + TriggerType IncidentWorkflowTriggerType `json:"trigger_type,omitempty"` + Workflow *IncidentWorkflow `json:"workflow,omitempty"` + Services []*ServiceReference `json:"services,omitempty"` + Condition *string `json:"condition,omitempty"` + SubscribedToAllServices bool `json:"is_subscribed_to_all_services,omitempty"` + Permissions *IncidentWorkflowTriggerPermissions `json:"permissions,omitempty"` +} + +type IncidentWorkflowTriggerPermissions struct { + Restricted bool `json:"restricted"` + TeamID string `json:"team_id,omitempty"` } // ListIncidentWorkflowTriggerResponse represents a list response of incident workflow triggers. diff --git a/vendor/modules.txt b/vendor/modules.txt index 7c567239f..a66e2d30c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -255,7 +255,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-20240403153232-5876af2ce24a +# github.com/heimweh/go-pagerduty v0.0.0-20240503143637-3459408ac715 ## explicit; go 1.17 github.com/heimweh/go-pagerduty/pagerduty github.com/heimweh/go-pagerduty/persistentconfig diff --git a/website/docs/r/incident_workflow_trigger.html.markdown b/website/docs/r/incident_workflow_trigger.html.markdown index 854e13fcf..5382e743f 100644 --- a/website/docs/r/incident_workflow_trigger.html.markdown +++ b/website/docs/r/incident_workflow_trigger.html.markdown @@ -58,6 +58,9 @@ The following arguments are supported: * `workflow` - (Required) The workflow ID for the workflow to trigger. * `services` - (Optional) A list of service IDs. Incidents in any of the listed services are eligible to fire this trigger. * `subscribed_to_all_services` - (Required) Set to `true` if the trigger should be eligible for firing on all services. Only allowed to be `true` if the services list is not defined or empty. +* `permissions` - (Optional) Indicates who can start this Trigger. Applicable only to `manual`-type triggers. + * `restricted` - (Optional) If `true`, indicates that the Trigger can only be started by authorized Users. If `false` (default), any user can start this Trigger. Applicable only to `manual`-type triggers. + * `team_id` - (Optional) The ID of the Team whose members can manually start this Trigger. Required and allowed only if `restricted` is `true`. * `condition` - (Required for `conditional`-type triggers) A [PCL](https://developer.pagerduty.com/docs/ZG9jOjM1NTE0MDc0-pcl-overview) condition string which must be satisfied for the trigger to fire. ## Attributes Reference