8000 CloudFormation v2 Engine: Base Support for Fn::GetAZs (#12699) · localstack/localstack@c4c7d90 · GitHub
[go: up one dir, main page]

Skip to content

Commit c4c7d90

Browse files
authored
CloudFormation v2 Engine: Base Support for Fn::GetAZs (#12699)
1 parent 6d23766 commit c4c7d90

File tree

5 files changed

+54
-5
lines changed

5 files changed

+54
-5
lines changed

localstack-core/localstack/services/cloudformation/engine/v2/change_set_model.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ def __init__(self, scope: Scope, value: Any):
425425
FnTransform: Final[str] = "Fn::Transform"
426426
FnSelect: Final[str] = "Fn::Select"
427427
FnSplit: Final[str] = "Fn::Split"
428+
FnGetAZs: Final[str] = "Fn::GetAZs"
428429
INTRINSIC_FUNCTIONS: Final[set[str]] = {
429430
RefKey,
430431
FnIfKey,
@@ -437,6 +438,7 @@ def __init__(self, scope: Scope, value: Any):
437438
FnTransform,
438439
FnSelect,
439440
FnSplit,
441+
FnGetAZs,
440442
}
441443

442444

localstack-core/localstack/services/cloudformation/engine/v2/change_set_model_preproc.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import re
44
from typing import Any, Final, Generic, Optional, TypeVar
55

6+
from botocore.exceptions import ClientError
7+
8+
from localstack.aws.api.ec2 import AvailabilityZoneList, DescribeAvailabilityZonesResult
9+
from localstack.aws.connect import connect_to
610
from localstack.services.cloudformation.engine.transformers import (
711
Transformer,
812
execute_macro,
@@ -677,7 +681,7 @@ def _compute_fn_select(args: list[Any]) -> Any:
677681

678682
def visit_node_intrinsic_function_fn_split(
679683
self, node_intrinsic_function: NodeIntrinsicFunction
680-
) -> PreprocEntityDelta:
684+
):
681685
# TODO: add further support for schema validation
682686
arguments_delta = self.visit(node_intrinsic_function.arguments)
683687
arguments_before = arguments_delta.before
@@ -703,6 +707,47 @@ def _compute_fn_split(args: list[Any]) -> Any:
703707

704708
return PreprocEntityDelta(before=before, after=after)
705709

710+
def visit_node_intrinsic_function_fn_get_a_zs(
711+
self, node_intrinsic_function: NodeIntrinsicFunction
712+
) -> PreprocEntityDelta:
713+
# TODO: add further support for schema validation
714+
arguments_delta = self.visit(node_intrinsic_function.arguments)
715+
arguments_before = arguments_delta.before
716+
arguments_after = arguments_delta.after
717+
718+
def _compute_fn_get_a_zs(region) -> Any:
719+
if not isinstance(region, str):
720+
raise RuntimeError(f"Invalid region value for Fn::GetAZs: '{region}'")
721+
722+
if not region:
723+
region = self._change_set.region_name
724+
725+
account_id = self._change_set.account_id
726+
ec2_client = connect_to(aws_access_key_id=account_id, region_name=region).ec2
727+
try:
728+
describe_availability_zones_result: DescribeAvailabilityZonesResult = (
729+
ec2_client.describe_availability_zones()
730+
)
731+
except ClientError:
732+
raise RuntimeError(
733+
"Could not describe zones availability whilst evaluating Fn::GetAZs"
734+
)
735+
availability_zones: AvailabilityZoneList = describe_availability_zones_result[
736+
"AvailabilityZones"
737+
]
738+
azs = [az["ZoneName"] for az in availability_zones]
739+
return azs
740+
741+
before = Nothing
742+
if not is_nothing(arguments_before):
743+
before = _compute_fn_get_a_zs(arguments_before)
744+
745+
after = Nothing
746+
if not is_nothing(arguments_after):
747+
after = _compute_fn_get_a_zs(arguments_after)
748+
749+
return PreprocEntityDelta(before=before, after=after)
750+
706751
def visit_node_intrinsic_function_fn_find_in_map(
707752
self, node_intrinsic_function: NodeIntrinsicFunction
708753
) -> PreprocEntityDelta:

localstack-core/localstack/services/cloudformation/engine/v2/change_set_model_visitor.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ def visit_node_intrinsic_function_fn_split(
128128
):
129129
self.visit_children(node_intrinsic_function)
130130

131+
def visit_node_intrinsic_function_fn_get_a_zs(
132+
self, node_intrinsic_function: NodeIntrinsicFunction
133+
):
134+
self.visit_children(node_intrinsic_function)
135+
131136
def visit_node_intrinsic_function_fn_sub(self, node_intrinsic_function: NodeIntrinsicFunction):
132137
self.visit_children(node_intrinsic_function)
133138

tests/aws/services/cloudformation/v2/ported_from_v1/resources/test_ec2.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def test_simple_route_table_creation(deploy_cfn_template, aws_client, snapshot):
7070
# ec2.describe_route_tables(RouteTableIds=[route_table_id])
7171

7272

73-
@pytest.mark.skip(reason="CFNV2:Fn::Select, CFNV2:Fn::GatAZs")
73+
@pytest.mark.skip(reason="CFNV2:Other")
7474
@markers.aws.validated
7575
def test_vpc_creates_default_sg(deploy_cfn_template, aws_client):
7676
result = deploy_cfn_template(
@@ -109,7 +109,6 @@ def test_cfn_with_multiple_route_tables(deploy_cfn_template, aws_client):
109109
assert len(resp["RouteTables"]) == 4
110110

111111

112-
@pytest.mark.skip(reason="CFNV2:Fn::Select, CFNV2:Fn::GatAZs")
113112
@markers.aws.validated
114113
@markers.snapshot.skip_snapshot_verify(
115114
paths=["$..PropagatingVgws", "$..Tags", "$..Tags..Key", "$..Tags..Value"]
@@ -165,7 +164,6 @@ def test_dhcp_options(aws_client, deploy_cfn_template, snapshot):
165164
snapshot.match("description", response["DhcpOptions"][0])
166165

167166

168-
@pytest.mark.skip(reason="CFNV2:Fn::Select, CFNV2:Fn::GatAZs")
169167
@markers.aws.validated
170168
@markers.snapshot.skip_snapshot_verify(
171169
paths=[

tests/aws/services/cloudformation/v2/ported_from_v1/test_template_engine.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ def test_cidr_function(self, deploy_cfn_template):
197197

198198
assert deployed.outputs["Address"] == "10.0.0.0/24"
199199

200-
@pytest.mark.skip(reason="CFNV2:Fn::GetAZs")
201200
@pytest.mark.parametrize(
202201
"region",
203202
[

0 commit comments

Comments
 (0)
0