Skip to content

add support for region ref in mappings inside condition CFn #11671

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

Merged
merged 2 commits into from
Oct 15, 2024

Conversation

pinzon
Copy link
Member

@pinzon pinzon commented Oct 10, 2024

Motivation

This PR adds support for AWS References inside a Mapping inside a Conditional of a CFn template

Changes

  • Extend resolving function

Testing

  • Extend previous test

@pinzon pinzon added the semver: patch Non-breaking changes which can be included in patch releases label Oct 10, 2024
Copy link

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 39m 45s ⏱️ -44s
3 492 tests ±0  3 079 ✅ ±0  413 💤 ±0  0 ❌ ±0 
3 494 runs  ±0  3 079 ✅ ±0  415 💤 ±0  0 ❌ ±0 

Results for commit 82dc432. ± Comparison against base commit 67f5698.

@pinzon pinzon marked this pull request as ready for review October 11, 2024 16:06
Copy link
Member

@dominikschubert dominikschubert left a comment

Choose a reason for hiding this comment

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

Generally LGTM!
I have some minor concerns around clarity in the extended code here.

Keeping those cases separate makes it easier for us to decompose this into utils at some point and refactor it when we can finally tackle a full engine rewrite.

As this is blocking some users, feel free to address this in a follow-up though!

Comment on lines +187 to +198
param = parameters.get(ref_name) or resolve_pseudo_parameter(
account_id, region_name, ref_name, stack_name
)
if not param:
raise TemplateError(
f"Invalid reference: '{ref_name}' does not exist in parameters: '{parameters}'"
)
map_name = param.get("ResolvedValue") or param.get("ParameterValue")
map_name = (
(param.get("ResolvedValue") or param.get("ParameterValue"))
if isinstance(param, dict)
else param
)
Copy link
Member

Choose a reason for hiding this comment

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

nit: I think it would be clearer here to keep those cases (parameters vs. pseudo-parameters) better separated for clarity. E.g. explicitly handling resolve_pseudo_parameter when the value starts with a AWS::... instead of using it as a fallback here. (same applies for the cases further below)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the suggestion. It's implemented int #11693

Copy link
Contributor

@simonrw simonrw left a comment

Choose a reason for hiding this comment

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

Looks good apart from some suggestions on refactoring. Thanks!

Edit: sorry just saw @dominikschubert picked up on the same thing as I did.

Comment on lines +187 to +189
param = parameters.get(ref_name) or resolve_pseudo_parameter(
account_id, region_name, ref_name, stack_name
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should be a bit more deliberate in trying to resolve pseudo parameters? E.g. only try to resolve pseudo parameters if ref_name starts with AWS::?

I don't really like the way we are treating two different data types (dicts when the map name is a parameter, or a str when the ref is a pseudo parameter) and trying the different options depending on the type. I would prefer to be more explicit that the two sources of information should be treated differently.

In that case, we can be more specific about the error message below as well. E.g. something like:

if ref_name.startswith("AWS::"):
    map_name = resolve_pseudo_parameter(...)
    if map_name is None:
        raise TemplateError(f"Invalid pseudo parameter '{ref_name}'")
else:
    param = parameters.get(ref_name)
    if not param:
        raise TemplateError(
            f"Invalid reference: '{ref_name}' does not exist in parameters: '{parameters}'"
        )
    map_name = param.get("ResolvedValue") or param.get("ParameterValue")

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

Awesome. It's a lot better. I put it in #11693

@@ -184,30 +184,50 @@ def resolve_condition(
map_name, top_level_key, second_level_key = v
if isinstance(map_name, dict) and "Ref" in map_name:
ref_name = map_name["Ref"]
param = parameters.get(ref_name)
param = parameters.get(ref_name) or resolve_pseudo_parameter(
Copy link
Contributor

Choose a reason for hiding this comment

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

Can the map name ever be a pseudo parameter?!

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. Takes a bit of work but AWS supports AWS:: in the mapping name. Please checkout #11693

@pinzon
Copy link
Member Author

pinzon commented Oct 15, 2024

Thank you for the reviews. I'm merging now to unblock the user and I will open a new PR with the suggested change.

@pinzon pinzon merged commit 4729a61 into master Oct 15, 2024
37 checks passed
@pinzon pinzon deleted the cfn-mappings-region branch October 15, 2024 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver: patch Non-breaking changes which can be included in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants