diff --git a/pagerduty/data_source_pagerduty_incident_workflow.go b/pagerduty/data_source_pagerduty_incident_workflow.go index 646ae805c..7f7a1aafa 100644 --- a/pagerduty/data_source_pagerduty_incident_workflow.go +++ b/pagerduty/data_source_pagerduty_incident_workflow.go @@ -68,7 +68,7 @@ func dataSourcePagerDutyIncidentWorkflowRead(ctx context.Context, d *schema.Reso ) } - err = flattenIncidentWorkflow(d, found, false, nil) + err = flattenIncidentWorkflow(d, found, false, nil, false) if err != nil { return retry.NonRetryableError(err) } diff --git a/pagerduty/resource_pagerduty_incident_workflow.go b/pagerduty/resource_pagerduty_incident_workflow.go index f590ce5ae..613ff9729 100644 --- a/pagerduty/resource_pagerduty_incident_workflow.go +++ b/pagerduty/resource_pagerduty_incident_workflow.go @@ -50,7 +50,7 @@ func resourcePagerDutyIncidentWorkflow() *schema.Resource { DeleteContext: resourcePagerDutyIncidentWorkflowDelete, CreateContext: resourcePagerDutyIncidentWorkflowCreate, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: resourcePagerDutyIncidentWorkflowImport, }, CustomizeDiff: customizeIncidentWorkflowDiff(), Schema: map[string]*schema.Schema{ @@ -287,9 +287,7 @@ func customizeIncidentWorkflowDiff() schema.CustomizeDiffFunc { // 6. Any remaining new inputs that were not already matched to old inputs should now be added to the result. // This lets new inputs that do not have default values (which are already cached as generated=true) maintain // their state in the diff, while not disrupting ordering of unchanged inputs. - for _, newInput := range newInputs { - result = append(result, newInput) - } + result = append(result, newInputs...) return result } @@ -370,7 +368,7 @@ func resourcePagerDutyIncidentWorkflowCreate(ctx context.Context, d *schema.Reso return diag.FromErr(err) } - err = flattenIncidentWorkflow(d, createdWorkflow, true, specifiedSteps) + err = flattenIncidentWorkflow(d, createdWorkflow, true, specifiedSteps, false) if err != nil { return diag.FromErr(err) } @@ -379,7 +377,7 @@ func resourcePagerDutyIncidentWorkflowCreate(ctx context.Context, d *schema.Reso func resourcePagerDutyIncidentWorkflowRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { log.Printf("[INFO] Reading PagerDuty incident workflow %s", d.Id()) - err := fetchIncidentWorkflow(ctx, d, meta, handleNotFoundError) + err := fetchIncidentWorkflow(ctx, d, meta, handleNotFoundError, false) if err != nil { return diag.FromErr(err) } @@ -404,7 +402,7 @@ func resourcePagerDutyIncidentWorkflowUpdate(ctx context.Context, d *schema.Reso return diag.FromErr(err) } - err = flattenIncidentWorkflow(d, updatedWorkflow, true, specifiedSteps) + err = flattenIncidentWorkflow(d, updatedWorkflow, true, specifiedSteps, false) if err != nil { return diag.FromErr(err) } @@ -424,7 +422,12 @@ func resourcePagerDutyIncidentWorkflowDelete(ctx context.Context, d *schema.Reso return nil } -func fetchIncidentWorkflow(ctx context.Context, d *schema.ResourceData, meta interface{}, errorCallback func(error, *schema.ResourceData) error) error { +func resourcePagerDutyIncidentWorkflowImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + err := fetchIncidentWorkflow(ctx, d, m, handleNotFoundError, true) + return []*schema.ResourceData{d}, err +} + +func fetchIncidentWorkflow(ctx context.Context, d *schema.ResourceData, meta interface{}, errorCallback func(error, *schema.ResourceData) error, isImport bool) error { client, err := meta.(*Config).Client() if err != nil { return err @@ -452,7 +455,7 @@ func fetchIncidentWorkflow(ctx context.Context, d *schema.ResourceData, meta int return nil } - if err := flattenIncidentWorkflow(d, iw, true, specifiedSteps); err != nil { + if err := flattenIncidentWorkflow(d, iw, true, specifiedSteps, isImport); err != nil { return retry.NonRetryableError(err) } return nil @@ -464,6 +467,7 @@ func flattenIncidentWorkflow( iw *pagerduty.IncidentWorkflow, includeSteps bool, specifiedSteps []*SpecifiedStep, + isImport bool, ) error { d.SetId(iw.ID) d.Set("name", iw.Name) @@ -475,33 +479,43 @@ func flattenIncidentWorkflow( } if includeSteps { - steps := flattenIncidentWorkflowSteps(iw, specifiedSteps) + steps := flattenIncidentWorkflowSteps(iw, specifiedSteps, isImport) d.Set("step", steps) } return nil } -func flattenIncidentWorkflowSteps(iw *pagerduty.IncidentWorkflow, specifiedSteps []*SpecifiedStep) []map[string]interface{} { +func flattenIncidentWorkflowSteps(iw *pagerduty.IncidentWorkflow, specifiedSteps []*SpecifiedStep, isImport bool) []map[string]interface{} { newSteps := make([]map[string]interface{}, len(iw.Steps)) for i, s := range iw.Steps { m := make(map[string]interface{}) - specifiedStep := *specifiedSteps[i] m["id"] = s.ID m["name"] = s.Name m["action"] = s.Configuration.ActionID - m["input"] = flattenIncidentWorkflowStepInput(s.Configuration.Inputs, specifiedStep.SpecifiedInputNames) + + var inputNames []string + inlineInputs := make(map[string][]*SpecifiedStep) + if !isImport { + specifiedStep := *specifiedSteps[i] + inputNames = specifiedStep.SpecifiedInputNames + inlineInputs = specifiedStep.SpecifiedInlineInputs + } + + m["input"] = flattenIncidentWorkflowStepInput(s.Configuration.Inputs, inputNames, isImport) m["inline_steps_input"] = flattenIncidentWorkflowStepInlineStepsInput( s.Configuration.InlineStepsInputs, - specifiedStep.SpecifiedInlineInputs, + inlineInputs, + isImport, ) newSteps[i] = m } + return newSteps } -func flattenIncidentWorkflowStepInput(inputs []*pagerduty.IncidentWorkflowActionInput, specifiedInputNames []string) *[]interface{} { +func flattenIncidentWorkflowStepInput(inputs []*pagerduty.IncidentWorkflowActionInput, specifiedInputNames []string, isImport bool) *[]interface{} { newInputs := make([]interface{}, len(inputs)) for i, v := range inputs { @@ -509,7 +523,7 @@ func flattenIncidentWorkflowStepInput(inputs []*pagerduty.IncidentWorkflowAction m["name"] = v.Name m["value"] = v.Value - if !isInputInNonGeneratedInputNames(v, specifiedInputNames) { + if !isImport && !isInputInNonGeneratedInputNames(v, specifiedInputNames) { m["generated"] = true } @@ -521,13 +535,14 @@ func flattenIncidentWorkflowStepInput(inputs []*pagerduty.IncidentWorkflowAction func flattenIncidentWorkflowStepInlineStepsInput( inlineStepsInputs []*pagerduty.IncidentWorkflowActionInlineStepsInput, specifiedInlineInputs map[string][]*SpecifiedStep, + isImport bool, ) *[]interface{} { newInlineStepsInputs := make([]interface{}, len(inlineStepsInputs)) for i, v := range inlineStepsInputs { m := make(map[string]interface{}) m["name"] = v.Name - m["step"] = flattenIncidentWorkflowStepInlineStepsInputSteps(v.Value.Steps, specifiedInlineInputs[v.Name]) + m["step"] = flattenIncidentWorkflowStepInlineStepsInputSteps(v.Value.Steps, specifiedInlineInputs[v.Name], isImport) newInlineStepsInputs[i] = m } @@ -537,22 +552,32 @@ func flattenIncidentWorkflowStepInlineStepsInput( func flattenIncidentWorkflowStepInlineStepsInputSteps( inlineSteps []*pagerduty.IncidentWorkflowActionInlineStep, specifiedSteps []*SpecifiedStep, + isImport bool, ) *[]interface{} { newInlineSteps := make([]interface{}, len(inlineSteps)) for i, v := range inlineSteps { m := make(map[string]interface{}) - specifiedStep := *specifiedSteps[i] m["name"] = v.Name m["action"] = v.Configuration.ActionID - m["input"] = flattenIncidentWorkflowStepInput(v.Configuration.Inputs, specifiedStep.SpecifiedInputNames) + + var inputNames []string + inlineInputs := make(map[string][]*SpecifiedStep) + if !isImport { + specifiedStep := *specifiedSteps[i] + inputNames = specifiedStep.SpecifiedInputNames + inlineInputs = specifiedStep.SpecifiedInlineInputs + } + + m["input"] = flattenIncidentWorkflowStepInput(v.Configuration.Inputs, inputNames, isImport) if v.Configuration.InlineStepsInputs != nil && len(v.Configuration.InlineStepsInputs) > 0 { // We should prefer to not set inline_steps_input if the array is empty. This doubles as a schema edge guard // and prevents an invalid set if we try to set inline_steps_input to an empty array where the schema // disallows setting any value whatsoever. m["inline_steps_input"] = flattenIncidentWorkflowStepInlineStepsInput( v.Configuration.InlineStepsInputs, - specifiedStep.SpecifiedInlineInputs, + inlineInputs, + isImport, ) } diff --git a/pagerduty/resource_pagerduty_incident_workflow_test.go b/pagerduty/resource_pagerduty_incident_workflow_test.go index 2fe882569..ecd686074 100644 --- a/pagerduty/resource_pagerduty_incident_workflow_test.go +++ b/pagerduty/resource_pagerduty_incident_workflow_test.go @@ -440,7 +440,6 @@ func testAccCheckPagerDutyIncidentWorkflowExists(n string) resource.TestCheckFun } func TestFlattenIncidentWorkflowStepsOneGenerated(t *testing.T) { - iw := &pagerduty.IncidentWorkflow{ Steps: []*pagerduty.IncidentWorkflowStep{ { @@ -536,7 +535,7 @@ func TestFlattenIncidentWorkflowStepsOneGenerated(t *testing.T) { }, }, } - flattenedSteps := flattenIncidentWorkflowSteps(iw, specifiedSteps) + flattenedSteps := flattenIncidentWorkflowSteps(iw, specifiedSteps, false) step1Inputs := flattenedSteps[0]["input"].(*[]interface{}) if len(*step1Inputs) != 3 { t.Errorf("flattened step1 had wrong number of inputs. want 3 got %v", len(*step1Inputs)) @@ -592,6 +591,71 @@ func TestFlattenIncidentWorkflowStepsOneGenerated(t *testing.T) { } } +func TestFlattenIncidentWorkflowStepsWithoutSpecifiedSteps(t *testing.T) { + iw := &pagerduty.IncidentWorkflow{ + Steps: []*pagerduty.IncidentWorkflowStep{ + { + ID: "abc-123", + Name: "step1", + Configuration: &pagerduty.IncidentWorkflowActionConfiguration{ + ActionID: "step1-action-id", + Inputs: []*pagerduty.IncidentWorkflowActionInput{ + { + Name: "step1-input1", + Value: "test1-value", + }, + }, + InlineStepsInputs: []*pagerduty.IncidentWorkflowActionInlineStepsInput{ + { + Name: "step1-inlineinput1", + Value: &pagerduty.IncidentWorkflowActionInlineStepsInputValue{ + Steps: []*pagerduty.IncidentWorkflowActionInlineStep{ + { + Name: "step1a", + Configuration: &pagerduty.IncidentWorkflowActionConfiguration{ + ActionID: "step1a-action-id", + Inputs: []*pagerduty.IncidentWorkflowActionInput{ + { + Name: "step1a-input1", + Value: "inlineval1", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + flattenedSteps := flattenIncidentWorkflowSteps(iw, nil, true) + step1Inputs := flattenedSteps[0]["input"].(*[]interface{}) + if len(*step1Inputs) != 1 { + t.Errorf("flattened step1 had wrong number of inputs. want 1 got %v", len(*step1Inputs)) + } + for i, v := range *step1Inputs { + if _, hadGen := v.(map[string]interface{})["generated"]; hadGen { + t.Errorf("was not expecting step1a input %v to have generated key set", i) + } + } + + step1aInlineStepInputs := flattenedSteps[0]["inline_steps_input"].(*[]interface{}) + step1aInlineStepInputs1 := (*step1aInlineStepInputs)[0].(map[string]interface{}) + step1aInlineStepInputs1Steps := step1aInlineStepInputs1["step"].(*[]interface{}) + step1aInputs := (*step1aInlineStepInputs1Steps)[0].(map[string]interface{})["input"].(*[]interface{}) + if len(*step1aInputs) != 1 { + t.Errorf("flattened step1a had wrong number of inputs. want 1 got %v", len(*step1aInputs)) + } + for i, v := range *step1aInputs { + if _, hadGen := v.(map[string]interface{})["generated"]; hadGen { + t.Errorf("was not expecting step1a input %v to have generated key set", i) + } + } +} + func testAccPreCheckIncidentWorkflows(t *testing.T) { if v := os.Getenv("PAGERDUTY_ACC_INCIDENT_WORKFLOWS"); v == "" { t.Skip("PAGERDUTY_ACC_INCIDENT_WORKFLOWS not set. Skipping Incident Workflows-related test")