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

[Bug fix] fix expanding process for operation_preferences.region_order in CloudFormation StackSet #41810

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

tabito-hara
Copy link
Contributor

@tabito-hara tabito-hara commented Mar 12, 2025

Description

  • To resolve the issue reported by [Enhancement]: aws_cloudformation_stack_set_instance #41767.

  • fix a process of expanding (i.e. deserializing from terraform configuration) "region_order" in operation_preferences used in aws_cloudformation_stack_set, aws_cloudformation_stack_instances and aws_cloudformation_stack_set_instance.

    • It used to be deserialized as TypeSet, but it should be an ordered list.
      tabito-hara@bff75ff
      The original one:
     if v, ok := tfMap["region_order"].(*schema.Set); ok && v.Len() > 0 {
     	apiObject.RegionOrder = flex.ExpandStringValueSet(v)
     }

    It has been modified as:

     if v, ok := tfMap["region_order"].([]interface{}); ok && len(v) > 0 {
     	for _, region := range v {
     		apiObject.RegionOrder = append(apiObject.RegionOrder, region.(string))
     	}
     }
  • Add acctests for the region_order attribute.

    • Note that passing the newly added tests does not necessarily mean that processes related to region_order are correctly implemented. (Even without the modifications in this branch, the acctests still pass.) However, these tests help observe changes in behavior, such as modifications to the request body of actions.
      • The operational_preferences block (which includes region_order) is not refreshed during Terraform's read process; it exists solely as an internal attribute within Terraform.
        • The acctests only verify that region_order is correctly retained in the Terraform state (tfstate), not that the resource is created according to the configuration specified in the operation_preference block.
          • These are not resource attributes but rather operational configurations specified for a particular execution.
          • As a result, actions that describe resource attributes do not return these attributes.
          • DescribeStackSetOperation returns attributes in operational_preferences, but only during operations. This action describes the operational configuration of a specific operation, requiring an operationId to request it.
  • region_order is effective only when auto_deployment is set to false. In tests related to region_order, auto_deployment is explicitly set to false.

Verification

The following acctests were conducted with TF_LOG=DEBUG environment variables.

TF_LOG=DEBUG  make testacc TESTS=TestAccCloudFormationStackSetInstance_regionOrder PKG=cloudformation 
  • Without the modification, the request body of CreateStackInstances in TestAccCloudFormationStackSetInstance_regionOrder is as follows:
 http.request.body=
 | Action=CreateStackInstances&CallAs=SELF&DeploymentTargets.OrganizationalUnitIds.member.1=r-rcxe&OperationId=terraform-20250312215258287600000004&OperationPreferences.ConcurrencyMode=SOFT_FAILURE_TOLERANCE&OperationPreferences.FailureToleranceCount=1&OperationPreferences.MaxConcurrentCount=10&OperationPreferences.RegionConcurrencyType=SEQUENTIAL&Regions.member.1=us-west-2&StackSetName=tf-acc-test-2172309617782508679&Version=2010-05-15

You do not find "OperationPreferences.RegionOrder" in the request parameters.

And the response of DescribeStackSetOperation, called to check progress in the test, includes empty RegionOrder as follows:

  |       <OperationPreferences>
  |         <RegionOrder/>
  |         <RegionConcurrencyType>SEQUENTIAL</RegionConcurrencyType>
  |         <FailureToleranceCount>1</FailureToleranceCount>
  |         <MaxConcurrentCount>10</MaxConcurrentCount>
  |       </OperationPreferences>

RegionOrder is empty.

On the other hand, with the modification of this branch, "OperationPreferences.RegionOrder" is included in the request body of CreateStackInstances:

  http.request.body=
  | Action=CreateStackInstances&CallAs=SELF&DeploymentTargets.OrganizationalUnitIds.member.1=r-rcxe&OperationId=terraform-20250312214525917300000004&OperationPreferences.ConcurrencyMode=SOFT_FAILURE_TOLERANCE&OperationPreferences.FailureToleranceCount=1&OperationPreferences.MaxConcurrentCount=10&OperationPreferences.RegionConcurrencyType=SEQUENTIAL&OperationPreferences.RegionOrder.member.1=us-west-2&OperationPreferences.RegionOrder.member.2=us-east-1&Regions.member.1=us-west-2&StackSetName=tf-acc-test-491068053307654715&Version=2010-05-15

the response of DescribeStackSetOperation shows RegionOrders as expected.

  |       <OperationPreferences>
  |         <RegionOrder>
  |           <member>us-west-2</member>
  |           <member>us-east-1</member>
  |         </RegionOrder>
  |         <RegionConcurrencyType>SEQUENTIAL</RegionConcurrencyType>
  |         <FailureToleranceCount>1</FailureToleranceCount>
  |         <MaxConcurrentCount>10</MaxConcurrentCount>
  |       </OperationPreferences>

You can find the same result in running TestAccCloudFormationStackInstances_regionOrder.

Relations

Closes #41767

References

Cloudformation API Reference -- StackSetOperationPreferences

Output from Acceptance Testing

CloudFormationStackSet

$ AWS_ALTERNATE_PROFILE=admin-non-org AWS_PROFILE=admin make testacc TESTS=TestAccCloudFormationStackSet_ PKG=cloudformation
make: Verifying source code with gofmt...
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go1.23.7 test ./internal/service/cloudformation/... -v -count 1 -parallel 20 -run='TestAccCloudFormationStackSet_'  -timeout 360m -vet=off
2025/03/13 22:45:05 Initializing Terraform AWS Provider...
=== RUN   TestAccCloudFormationStackSet_basic
=== PAUSE TestAccCloudFormationStackSet_basic
=== RUN   TestAccCloudFormationStackSet_disappears
=== PAUSE TestAccCloudFormationStackSet_disappears
=== RUN   TestAccCloudFormationStackSet_administrationRoleARN
=== PAUSE TestAccCloudFormationStackSet_administrationRoleARN
=== RUN   TestAccCloudFormationStackSet_description
=== PAUSE TestAccCloudFormationStackSet_description
=== RUN   TestAccCloudFormationStackSet_executionRoleName
=== PAUSE TestAccCloudFormationStackSet_executionRoleName
=== RUN   TestAccCloudFormationStackSet_managedExecution
=== PAUSE TestAccCloudFormationStackSet_managedExecution
=== RUN   TestAccCloudFormationStackSet_name
=== PAUSE TestAccCloudFormationStackSet_name
=== RUN   TestAccCloudFormationStackSet_operationPreferences
=== PAUSE TestAccCloudFormationStackSet_operationPreferences
=== RUN   TestAccCloudFormationStackSet_parameters
=== PAUSE TestAccCloudFormationStackSet_parameters
=== RUN   TestAccCloudFormationStackSet_Parameters_default
    stack_set_test.go:479: this resource does not currently ignore unconfigured CloudFormation template parameters with the Default property
--- SKIP: TestAccCloudFormationStackSet_Parameters_default (0.00s)
=== RUN   TestAccCloudFormationStackSet_Parameters_noEcho
    stack_set_test.go:533: this resource does not currently ignore CloudFormation template parameters with the NoEcho property
--- SKIP: TestAccCloudFormationStackSet_Parameters_noEcho (0.00s)
=== RUN   TestAccCloudFormationStackSet_PermissionModel_serviceManaged
    stack_set_test.go:579: API does not support enabling Organizations access (in particular, creating the Stack Sets IAM Service-Linked Role)
--- SKIP: TestAccCloudFormationStackSet_PermissionModel_serviceManaged (0.00s)
=== RUN   TestAccCloudFormationStackSet_tags
=== PAUSE TestAccCloudFormationStackSet_tags
=== RUN   TestAccCloudFormationStackSet_templateBody
=== PAUSE TestAccCloudFormationStackSet_templateBody
=== RUN   TestAccCloudFormationStackSet_templateURL
=== PAUSE TestAccCloudFormationStackSet_templateURL
=== RUN   TestAccCloudFormationStackSet_autoDeploymentEnabled
=== PAUSE TestAccCloudFormationStackSet_autoDeploymentEnabled
=== RUN   TestAccCloudFormationStackSet_autoDeploymentDisabled
=== PAUSE TestAccCloudFormationStackSet_autoDeploymentDisabled
=== RUN   TestAccCloudFormationStackSet_regionOrder
=== PAUSE TestAccCloudFormationStackSet_regionOrder
=== RUN   TestAccCloudFormationStackSet_delegatedAdministrator
=== PAUSE TestAccCloudFormationStackSet_delegatedAdministrator
=== CONT  TestAccCloudFormationStackSet_basic
=== CONT  TestAccCloudFormationStackSet_executionRoleName
=== CONT  TestAccCloudFormationStackSet_name
=== CONT  TestAccCloudFormationStackSet_parameters
=== CONT  TestAccCloudFormationStackSet_disappears
=== CONT  TestAccCloudFormationStackSet_managedExecution
=== CONT  TestAccCloudFormationStackSet_autoDeploymentEnabled
=== CONT  TestAccCloudFormationStackSet_administrationRoleARN
=== CONT  TestAccCloudFormationStackSet_description
=== CONT  TestAccCloudFormationStackSet_operationPreferences
=== CONT  TestAccCloudFormationStackSet_templateURL
=== CONT  TestAccCloudFormationStackSet_templateBody
=== CONT  TestAccCloudFormationStackSet_tags
=== CONT  TestAccCloudFormationStackSet_regionOrder
=== CONT  TestAccCloudFormationStackSet_delegatedAdministrator
=== CONT  TestAccCloudFormationStackSet_autoDeploymentDisabled
=== NAME  TestAccCloudFormationStackSet_delegatedAdministrator
    stack_set_test.go:890: this AWS account must not be the management account of an AWS Organization
--- SKIP: TestAccCloudFormationStackSet_delegatedAdministrator (12.99s)
--- PASS: TestAccCloudFormationStackSet_autoDeploymentDisabled (66.50s)
--- PASS: TestAccCloudFormationStackSet_managedExecution (70.15s)
--- PASS: TestAccCloudFormationStackSet_regionOrder (72.63s)
--- PASS: TestAccCloudFormationStackSet_autoDeploymentEnabled (81.47s)
--- PASS: TestAccCloudFormationStackSet_basic (82.63s)
--- PASS: TestAccCloudFormationStackSet_disappears (86.52s)
--- PASS: TestAccCloudFormationStackSet_administrationRoleARN (100.46s)
--- PASS: TestAccCloudFormationStackSet_executionRoleName (110.16s)
--- PASS: TestAccCloudFormationStackSet_description (110.23s)
--- PASS: TestAccCloudFormationStackSet_templateBody (114.18s)
--- PASS: TestAccCloudFormationStackSet_name (130.64s)
--- PASS: TestAccCloudFormationStackSet_templateURL (134.55s)
--- PASS: TestAccCloudFormationStackSet_tags (142.28s)
--- PASS: TestAccCloudFormationStackSet_parameters (164.80s)
--- PASS: TestAccCloudFormationStackSet_operationPreferences (221.36s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/cloudformation     226.907s

CloudFormationStackInstances

$ AWS_ALTERNATE_PROFILE=admin-non-org AWS_PROFILE=admin make testacc TESTS=TestAccCloudFormationStackInstances PKG=cloudformation
make: Verifying source code with gofmt...
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go1.23.7 test ./internal/service/cloudformation/... -v -count 1 -parallel 20 -run='TestAccCloudFormationStackInstances'  -timeout 360m -vet=off
2025/03/13 09:19:21 Initializing Terraform AWS Provider...
=== RUN   TestAccCloudFormationStackInstances_basic
=== PAUSE TestAccCloudFormationStackInstances_basic
=== RUN   TestAccCloudFormationStackInstances_disappears
=== PAUSE TestAccCloudFormationStackInstances_disappears
=== RUN   TestAccCloudFormationStackInstances_Disappears_stackSet
=== PAUSE TestAccCloudFormationStackInstances_Disappears_stackSet
=== RUN   TestAccCloudFormationStackInstances_Multi_increaseRegions
=== PAUSE TestAccCloudFormationStackInstances_Multi_increaseRegions
=== RUN   TestAccCloudFormationStackInstances_Multi_decreaseRegions
=== PAUSE TestAccCloudFormationStackInstances_Multi_decreaseRegions
=== RUN   TestAccCloudFormationStackInstances_Multi_swapRegions
=== PAUSE TestAccCloudFormationStackInstances_Multi_swapRegions
=== RUN   TestAccCloudFormationStackInstances_parameterOverrides
=== PAUSE TestAccCloudFormationStackInstances_parameterOverrides
=== RUN   TestAccCloudFormationStackInstances_deploymentTargets
=== PAUSE TestAccCloudFormationStackInstances_deploymentTargets
=== RUN   TestAccCloudFormationStackInstances_DeploymentTargets_emptyOU
=== PAUSE TestAccCloudFormationStackInstances_DeploymentTargets_emptyOU
=== RUN   TestAccCloudFormationStackInstances_operationPreferences
=== PAUSE TestAccCloudFormationStackInstances_operationPreferences
=== RUN   TestAccCloudFormationStackInstances_concurrencyMode
=== PAUSE TestAccCloudFormationStackInstances_concurrencyMode
=== RUN   TestAccCloudFormationStackInstances_regionOrder
=== PAUSE TestAccCloudFormationStackInstances_regionOrder
=== RUN   TestAccCloudFormationStackInstances_delegatedAdministrator
=== PAUSE TestAccCloudFormationStackInstances_delegatedAdministrator
=== CONT  TestAccCloudFormationStackInstances_basic
=== CONT  TestAccCloudFormationStackInstances_deploymentTargets
=== CONT  TestAccCloudFormationStackInstances_concurrencyMode
=== CONT  TestAccCloudFormationStackInstances_parameterOverrides
=== CONT  TestAccCloudFormationStackInstances_Multi_decreaseRegions
=== CONT  TestAccCloudFormationStackInstances_Multi_increaseRegions
=== CONT  TestAccCloudFormationStackInstances_Multi_swapRegions
=== CONT  TestAccCloudFormationStackInstances_Disappears_stackSet
=== CONT  TestAccCloudFormationStackInstances_disappears
=== CONT  TestAccCloudFormationStackInstances_delegatedAdministrator
=== CONT  TestAccCloudFormationStackInstances_regionOrder
=== CONT  TestAccCloudFormationStackInstances_DeploymentTargets_emptyOU
=== CONT  TestAccCloudFormationStackInstances_operationPreferences
=== NAME  TestAccCloudFormationStackInstances_delegatedAdministrator
    stack_instances_test.go:525: this AWS account must not be the management account of an AWS Organization
--- SKIP: TestAccCloudFormationStackInstances_delegatedAdministrator (4.72s)
--- PASS: TestAccCloudFormationStackInstances_regionOrder (95.67s)
--- PASS: TestAccCloudFormationStackInstances_operationPreferences (100.25s)
--- PASS: TestAccCloudFormationStackInstances_Disappears_stackSet (100.60s)
--- PASS: TestAccCloudFormationStackInstances_concurrencyMode (100.80s)
--- PASS: TestAccCloudFormationStackInstances_DeploymentTargets_emptyOU (103.03s)
--- PASS: TestAccCloudFormationStackInstances_deploymentTargets (132.38s)
--- PASS: TestAccCloudFormationStackInstances_Multi_increaseRegions (143.40s)
--- PASS: TestAccCloudFormationStackInstances_Multi_swapRegions (149.88s)
--- PASS: TestAccCloudFormationStackInstances_parameterOverrides (207.62s)
--- PASS: TestAccCloudFormationStackInstances_basic (244.95s)
--- PASS: TestAccCloudFormationStackInstances_disappears (268.16s)
--- PASS: TestAccCloudFormationStackInstances_Multi_decreaseRegions (298.10s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/cloudformation     303.806s

CloudFormationStackSetInstance

 AWS_ALTERNATE_PROFILE=admin-non-org AWS_PROFILE=admin make testacc TESTS=TestAccCloudFormationStackSetInstance PKG=cloudformation              
make: Verifying source code with gofmt...
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go1.23.7 test ./internal/service/cloudformation/... -v -count 1 -parallel 20 -run='TestAccCloudFormationStackSetInstance'  -timeout 360m -vet=off
2025/03/13 09:29:11 Initializing Terraform AWS Provider...
=== RUN   TestAccCloudFormationStackSetInstance_basic
=== PAUSE TestAccCloudFormationStackSetInstance_basic
=== RUN   TestAccCloudFormationStackSetInstance_disappears
=== PAUSE TestAccCloudFormationStackSetInstance_disappears
=== RUN   TestAccCloudFormationStackSetInstance_Disappears_stackSet
=== PAUSE TestAccCloudFormationStackSetInstance_Disappears_stackSet
=== RUN   TestAccCloudFormationStackSetInstance_parameterOverrides
=== PAUSE TestAccCloudFormationStackSetInstance_parameterOverrides
=== RUN   TestAccCloudFormationStackSetInstance_deploymentTargets
=== PAUSE TestAccCloudFormationStackSetInstance_deploymentTargets
=== RUN   TestAccCloudFormationStackSetInstance_DeploymentTargets_emptyOU
=== PAUSE TestAccCloudFormationStackSetInstance_DeploymentTargets_emptyOU
=== RUN   TestAccCloudFormationStackSetInstance_operationPreferences
=== PAUSE TestAccCloudFormationStackSetInstance_operationPreferences
=== RUN   TestAccCloudFormationStackSetInstance_concurrencyMode
=== PAUSE TestAccCloudFormationStackSetInstance_concurrencyMode
=== RUN   TestAccCloudFormationStackSetInstance_regionOrder
=== PAUSE TestAccCloudFormationStackSetInstance_regionOrder
=== RUN   TestAccCloudFormationStackSetInstance_delegatedAdministrator
=== PAUSE TestAccCloudFormationStackSetInstance_delegatedAdministrator
=== CONT  TestAccCloudFormationStackSetInstance_basic
=== CONT  TestAccCloudFormationStackSetInstance_DeploymentTargets_emptyOU
=== CONT  TestAccCloudFormationStackSetInstance_regionOrder
=== CONT  TestAccCloudFormationStackSetInstance_delegatedAdministrator
=== CONT  TestAccCloudFormationStackSetInstance_concurrencyMode
=== CONT  TestAccCloudFormationStackSetInstance_parameterOverrides
=== CONT  TestAccCloudFormationStackSetInstance_deploymentTargets
=== CONT  TestAccCloudFormationStackSetInstance_Disappears_stackSet
=== CONT  TestAccCloudFormationStackSetInstance_operationPreferences
=== CONT  TestAccCloudFormationStackSetInstance_disappears
=== NAME  TestAccCloudFormationStackSetInstance_delegatedAdministrator
    stack_set_instance_test.go:413: this AWS account must not be the management account of an AWS Organization
--- SKIP: TestAccCloudFormationStackSetInstance_delegatedAdministrator (5.20s)
--- PASS: TestAccCloudFormationStackSetInstance_Disappears_stackSet (94.69s)
--- PASS: TestAccCloudFormationStackSetInstance_regionOrder (96.59s)
--- PASS: TestAccCloudFormationStackSetInstance_operationPreferences (98.41s)
--- PASS: TestAccCloudFormationStackSetInstance_concurrencyMode (98.60s)
--- PASS: TestAccCloudFormationStackSetInstance_basic (100.23s)
--- PASS: TestAccCloudFormationStackSetInstance_disappears (103.88s)
--- PASS: TestAccCloudFormationStackSetInstance_DeploymentTargets_emptyOU (108.80s)
--- PASS: TestAccCloudFormationStackSetInstance_deploymentTargets (124.36s)
--- PASS: TestAccCloudFormationStackSetInstance_parameterOverrides (192.91s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/cloudformation     198.778s

Copy link

Community Guidelines

This comment is added to every new Pull Request to provide quick reference to how the Terraform AWS Provider is maintained. Please review the information below, and thank you for contributing to the community that keeps the provider thriving! 🚀

Voting for Prioritization

  • Please vote on this Pull Request by adding a 👍 reaction to the original post to help the community and maintainers prioritize it.
  • Please see our prioritization guide for additional information on how the maintainers handle prioritization.
  • Please do not leave +1 or other comments that do not add relevant new information or questions; they generate extra noise for others following the Pull Request and do not help prioritize the request.

Pull Request Authors

  • Review the contribution guide relating to the type of change you are making to ensure all of the necessary steps have been taken.
  • Whether or not the branch has been rebased will not impact prioritization, but doing so is always a welcome surprise.

@github-actions github-actions bot added needs-triage Waiting for first response or review from a maintainer. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure. service/cloudformation Issues and PRs that pertain to the cloudformation service. size/L Managed by automation to categorize the size of a PR. labels Mar 12, 2025
@tabito-hara tabito-hara marked this pull request as ready for review March 13, 2025 14:02
@tabito-hara tabito-hara requested a review from a team as a code owner March 13, 2025 14:02
@justinretzolk justinretzolk added bug Addresses a defect in current functionality. and removed needs-triage Waiting for first response or review from a maintainer. labels Mar 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Addresses a defect in current functionality. service/cloudformation Issues and PRs that pertain to the cloudformation service. size/L Managed by automation to categorize the size of a PR. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Enhancement]: aws_cloudformation_stack_set_instance
2 participants