Skip to content

Conversation

@simonrw
Copy link
Contributor

@simonrw simonrw commented Sep 4, 2025

Motivation

For a very long time, the LocalStack CloudFormation engine has been frustrating to use. In particular it did not correctly the resource update process. This lead to the common advice of "restart LocalStack" if you want to make a change to your stack.

LocalStack excels at providing a local first experience, particularly for devops and IaC with its ability to emulate the cloud locally. However with larger stacks or regular changes being required, it was a slow and frustrating experience needing to regularly restart LocalStack because CloudFormation resources did not update.

This PR finishes a long journey implementing the internals (the "engine") of CloudFormation with a focus on correctness, parity with AWS and modelling which resources are and are not updated.

The new engine models the changes to a stack as a whole, rather than attempting to work out which resources should and should not be updated as an operation that requires two static and poorly defined templates. We strongly type the concepts of a pair of stacks and build an internal representation that can be traversed, or "visited".

We primarily achieve this with

  • the ChangeSetModel which is a visitor over a pair of templates, and constructs
  • the UpdateModel our internal representation (a graph) of the templates, where each node in the graph has a ChangeType representing if it is
    • Unchanged
    • Created
    • Modified
    • Deleted
  • a class heirarchy of visitors (see diagram below) that operate on this UpdateModel and through depth first search perform one of a few operations:
    • transforming the target template
    • performing template level validations
    • supporting describing the change set
    • deploying the target template
flowchart TD
    ChangeSetModelVisitor --> ChangeSetModelPreproc
    ChangeSetModelPreproc --> ChangeSetModelTransformer
    ChangeSetModelPreproc --> ChangeSetModelValidator
    ChangeSetModelPreproc --> ChangeSetModelDescriber
    ChangeSetModelPreproc --> ChangeSetModelExecutor
Loading

Where the previous engine would order resources based on their dependencies (topological sort) and hope that the resources deployed correctly, this engine visits the update model in a depth first order and therefore fully resolves resource dependencies (such as intrinsic function calls) before deploying parent resources.

This new engine passes all of the current (now legacy) engine's tests, and passes over 100 parity tests that the legacy engine does not.

Tip

Should you experience issues with this new engine, please submit a bug report. You can continue to opt in to using the legacy engine by setting

PROVIDER_OVERRIDE_CLOUDFORMATION=engine-legacy localstack start
PRs that contributed to this change

A huge thanks to @MEPalma , @pinzon and @dominikschubert for collaborating on this work 🎉

Changes

  • Switch the default engine version to the previous engine-v2
  • Update CI to continue to run the CloudFormation test suite against the legacy engine in the specific Test CloudFormation Engine legacy step
  • Remove the temporary test skip reporting from the CloudFormation test directory

@simonrw simonrw added semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases docs: needed Pull request requires documentation updates labels Sep 4, 2025
@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results - Preflight, Unit

22 117 tests  ±0   20 379 ✅ ±0   6m 30s ⏱️ +9s
     1 suites ±0    1 738 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results (MA/MR) - Preflight, Unit

22 117 tests  ±0   20 379 ✅ ±0   6m 59s ⏱️ +24s
     1 suites ±0    1 738 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results (amd64, MA/MR) - Acceptance

7 tests  ±0   5 ✅ ±0   3m 12s ⏱️ +7s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results (amd64) - Acceptance

7 tests  ±0   5 ✅ ±0   3m 16s ⏱️ +4s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results (amd64) - Integration, Bootstrap

    5 files  ±0      5 suites  ±0   2h 34m 9s ⏱️ + 13m 27s
5 009 tests  - 1  4 519 ✅ +111  490 💤  - 112  0 ❌ ±0 
5 015 runs   - 1  4 519 ✅ +111  496 💤  - 112  0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

This pull request removes 1 test.
tests.aws.services.cloudformation.engine.test_conditions.TestCloudFormationConditions ‑ test_dependency_in_non_evaluated_if_branch[true-FallbackParamValue]

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

Test Results (amd64, MA/MR) - Integration, Bootstrap

    5 files  ±0      5 suites  ±0   2h 34m 29s ⏱️ + 12m 42s
5 009 tests  - 1  4 519 ✅ +111  490 💤  - 112  0 ❌ ±0 
5 015 runs   - 1  4 519 ✅ +111  496 💤  - 112  0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

This pull request removes 1 test.
tests.aws.services.cloudformation.engine.test_conditions.TestCloudFormationConditions ‑ test_dependency_in_non_evaluated_if_branch[true-FallbackParamValue]

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 4, 2025

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 55m 45s ⏱️ + 11m 44s
4 636 tests  - 1  4 305 ✅ +111  331 💤  - 112  0 ❌ ±0 
4 638 runs   - 1  4 305 ✅ +111  333 💤  - 112  0 ❌ ±0 

Results for commit 1b454ad. ± Comparison against base commit 9043813.

This pull request removes 1 test.
tests.aws.services.cloudformation.engine.test_conditions.TestCloudFormationConditions ‑ test_dependency_in_non_evaluated_if_branch[true-FallbackParamValue]

♻️ This comment has been updated with latest results.

@simonrw simonrw force-pushed the cfn/v2/switch-default branch from 5ef40c3 to 7e45ad4 Compare September 4, 2025 20:44
@simonrw simonrw added this to the 4.8 milestone Sep 5, 2025
@simonrw simonrw marked this pull request as ready for review September 5, 2025 15:06
Copy link
Contributor

@k-a-il k-a-il left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excited to see the new CloudFormation engine, kudos to the team! 🚀

Copy link
Member

@pinzon pinzon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What a journey, so thankful to have been part of this project! 😃

@simonrw simonrw merged commit f31c010 into main Sep 8, 2025
82 checks passed
@simonrw simonrw deleted the cfn/v2/switch-default branch September 8, 2025 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: needed Pull request requires documentation updates semver: minor Non-breaking changes which can be included in minor releases, but not in patch releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants