diff --git a/newrelic/resource_newrelic_workflow_test.go b/newrelic/resource_newrelic_workflow_test.go index dae374bf6..5bfa755ed 100644 --- a/newrelic/resource_newrelic_workflow_test.go +++ b/newrelic/resource_newrelic_workflow_test.go @@ -365,6 +365,33 @@ func TestNewRelicWorkflow_BooleanFlags_DisableOnCreation(t *testing.T) { }) } +func TestNewRelicWorkflow_NotificationTriggerShouldIgnoreOrder(t *testing.T) { + resourceName := "newrelic_workflow.foo" + rName := generateNameForIntegrationTestResource() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckEnvVars(t) }, + Providers: testAccProviders, + CheckDestroy: testAccNewRelicWorkflowDestroy, + Steps: []resource.TestStep{ + // Test: Create workflow with non-standard trigger order + { + Config: testAccNewRelicWorkflowConfigurationWithNotificationTriggers(testAccountID, rName, `["CLOSED", "ACTIVATED"]`), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicWorkflowExists(resourceName), + ), + }, + // Test: Update trigger order + { + Config: testAccNewRelicWorkflowConfigurationWithNotificationTriggers(testAccountID, rName, `["ACKNOWLEDGED", "ACTIVATED", "CLOSED"]`), + Check: resource.ComposeTestCheckFunc( + testAccCheckNewRelicWorkflowExists(resourceName), + ), + }, + }, + }) +} + func testAccNewRelicWorkflowConfigurationMinimal(accountID int, name string) string { return fmt.Sprintf(` resource "newrelic_notification_destination" "foo" { diff --git a/newrelic/structures_newrelic_workflow.go b/newrelic/structures_newrelic_workflow.go index 6b6b5c883..77a438c6e 100644 --- a/newrelic/structures_newrelic_workflow.go +++ b/newrelic/structures_newrelic_workflow.go @@ -3,7 +3,6 @@ package newrelic import ( "context" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/newrelic/newrelic-client-go/v2/pkg/ai" "github.com/newrelic/newrelic-client-go/v2/pkg/workflows" @@ -335,7 +334,7 @@ func flattenWorkflow(workflow *workflows.AiWorkflowsWorkflow, d *schema.Resource return err } - destinationConfigurations, destinationConfigurationsErr := flattenWorkflowDestinationConfigurations(&workflow.DestinationConfigurations) + destinationConfigurations, destinationConfigurationsErr := flattenWorkflowDestinationConfigurations(d, &workflow.DestinationConfigurations) if destinationConfigurationsErr != nil { return destinationConfigurationsErr } @@ -371,23 +370,33 @@ func flattenWorkflow(workflow *workflows.AiWorkflowsWorkflow, d *schema.Resource return nil } -func flattenWorkflowDestinationConfigurations(d *[]workflows.AiWorkflowsDestinationConfiguration) ([]map[string]interface{}, error) { +func flattenWorkflowDestinationConfigurations(d *schema.ResourceData, configurations *[]workflows.AiWorkflowsDestinationConfiguration) ([]map[string]interface{}, error) { if d == nil { return nil, nil } - var destinationConfigurations []map[string]interface{} + currentStates := d.Get("destination").(*schema.Set).List() - for _, destinationConfiguration := range *d { - if val, err := flattenWorkflowDestinationConfiguration(&destinationConfiguration); err == nil { - destinationConfigurations = append(destinationConfigurations, val) + var destinationConfigurations []map[string]interface{} + for _, config := range *configurations { + var currentState map[string]interface{} + for _, rawState := range currentStates { + state := rawState.(map[string]interface{}) + if state["channel_id"] == config.ChannelId { + currentState = state + } } + flattened, err := flattenWorkflowDestinationConfiguration(&config, currentState) + if err != nil { + return nil, err + } + destinationConfigurations = append(destinationConfigurations, flattened) } return destinationConfigurations, nil } -func flattenWorkflowDestinationConfiguration(d *workflows.AiWorkflowsDestinationConfiguration) (map[string]interface{}, error) { +func flattenWorkflowDestinationConfiguration(d *workflows.AiWorkflowsDestinationConfiguration, currentState map[string]interface{}) (map[string]interface{}, error) { if d == nil { return nil, nil } @@ -397,11 +406,51 @@ func flattenWorkflowDestinationConfiguration(d *workflows.AiWorkflowsDestination destinationConfigurationResult["channel_id"] = d.ChannelId destinationConfigurationResult["name"] = d.Name destinationConfigurationResult["type"] = d.Type - destinationConfigurationResult["notification_triggers"] = d.NotificationTriggers + + if currentState == nil || currentState["notification_triggers"] == nil { + destinationConfigurationResult["notification_triggers"] = d.NotificationTriggers + } else { + destinationConfigurationResult["notification_triggers"] = normaliseTriggerList( + d.NotificationTriggers, + currentState["notification_triggers"].([]interface{}), + ) + } return destinationConfigurationResult, nil } +// preserve the state order to avoid state drift as trigger order is not preserved +func normaliseTriggerList(triggers []workflows.AiWorkflowsNotificationTrigger, currentState []interface{}) []workflows.AiWorkflowsNotificationTrigger { + var result []workflows.AiWorkflowsNotificationTrigger + for _, trigger := range currentState { + triggerStillExists := false + for _, actualTrigger := range triggers { + if string(actualTrigger) == trigger { + triggerStillExists = true + } + } + + if triggerStillExists { + result = append(result, workflows.AiWorkflowsNotificationTrigger(trigger.(string))) + } + } + + for _, actualTrigger := range triggers { + triggerExistedBefore := false + for _, trigger := range currentState { + if string(actualTrigger) == trigger { + triggerExistedBefore = true + } + } + + if !triggerExistedBefore { + result = append(result, actualTrigger) + } + } + + return result +} + func flattenWorkflowIssuesFilter(f *workflows.AiWorkflowsFilter) (interface{}, error) { if f == nil { return nil, nil