localstack-core 4.3.1.dev35__py3-none-any.whl → 4.3.1.dev37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- localstack/config.py +0 -6
- localstack/deprecations.py +14 -0
- localstack/services/cloudformation/engine/entities.py +9 -4
- localstack/services/cloudformation/engine/v2/change_set_model.py +32 -67
- localstack/services/cloudformation/engine/v2/change_set_model_describer.py +119 -487
- localstack/services/cloudformation/engine/v2/change_set_model_executor.py +107 -70
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +574 -0
- localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +6 -6
- localstack/services/cloudformation/v2/provider.py +39 -5
- localstack/services/cloudformation/v2/utils.py +5 -0
- localstack/services/sns/resource_providers/aws_sns_topic.py +1 -0
- localstack/testing/pytest/cloudformation/__init__.py +0 -0
- localstack/testing/pytest/cloudformation/fixtures.py +169 -0
- localstack/version.py +2 -2
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/METADATA +1 -1
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/RECORD +24 -20
- localstack_core-4.3.1.dev37.dist-info/plux.json +1 -0
- localstack_core-4.3.1.dev35.dist-info/plux.json +0 -1
- {localstack_core-4.3.1.dev35.data → localstack_core-4.3.1.dev37.data}/scripts/localstack +0 -0
- {localstack_core-4.3.1.dev35.data → localstack_core-4.3.1.dev37.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.3.1.dev35.data → localstack_core-4.3.1.dev37.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/WHEEL +0 -0
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/entry_points.txt +0 -0
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/licenses/LICENSE.txt +0 -0
- {localstack_core-4.3.1.dev35.dist-info → localstack_core-4.3.1.dev37.dist-info}/top_level.txt +0 -0
localstack/config.py
CHANGED
@@ -1089,11 +1089,6 @@ LAMBDA_EVENT_SOURCE_MAPPING_MAX_BACKOFF_ON_EMPTY_POLL_SEC = float(
|
|
1089
1089
|
os.environ.get("LAMBDA_EVENT_SOURCE_MAPPING_MAX_BACKOFF_ON_EMPTY_POLL_SEC") or 10
|
1090
1090
|
)
|
1091
1091
|
|
1092
|
-
# Adding Stepfunctions default port
|
1093
|
-
LOCAL_PORT_STEPFUNCTIONS = int(os.environ.get("LOCAL_PORT_STEPFUNCTIONS") or 8083)
|
1094
|
-
# Stepfunctions lambda endpoint override
|
1095
|
-
STEPFUNCTIONS_LAMBDA_ENDPOINT = os.environ.get("STEPFUNCTIONS_LAMBDA_ENDPOINT", "").strip()
|
1096
|
-
|
1097
1092
|
# path prefix for windows volume mounting
|
1098
1093
|
WINDOWS_DOCKER_MOUNT_PREFIX = os.environ.get("WINDOWS_DOCKER_MOUNT_PREFIX", "/host_mnt")
|
1099
1094
|
|
@@ -1364,7 +1359,6 @@ CONFIG_ENV_VARS = [
|
|
1364
1359
|
"SQS_ENDPOINT_STRATEGY",
|
1365
1360
|
"SQS_DISABLE_CLOUDWATCH_METRICS",
|
1366
1361
|
"SQS_CLOUDWATCH_METRICS_REPORT_INTERVAL",
|
1367
|
-
"STEPFUNCTIONS_LAMBDA_ENDPOINT",
|
1368
1362
|
"STRICT_SERVICE_LOADING",
|
1369
1363
|
"TF_COMPAT_MODE",
|
1370
1364
|
"USE_SSL",
|
localstack/deprecations.py
CHANGED
@@ -311,6 +311,20 @@ DEPRECATIONS = [
|
|
311
311
|
" is faster, achieves great AWS parity, and fixes compatibility issues with the StepFunctions JSONata feature."
|
312
312
|
" Please remove EVENT_RULE_ENGINE.",
|
313
313
|
),
|
314
|
+
EnvVarDeprecation(
|
315
|
+
"STEPFUNCTIONS_LAMBDA_ENDPOINT",
|
316
|
+
"4.0.0",
|
317
|
+
"This is only supported for the legacy provider. URL to use as the Lambda service endpoint in Step Functions. "
|
318
|
+
"By default this is the LocalStack Lambda endpoint. Use default to select the original AWS Lambda endpoint.",
|
319
|
+
),
|
320
|
+
EnvVarDeprecation(
|
321
|
+
"LOCAL_PORT_STEPFUNCTIONS",
|
322
|
+
"4.0.0",
|
323
|
+
"This is only supported for the legacy provider."
|
324
|
+
"It defines the local port to which Step Functions traffic is redirected."
|
325
|
+
"By default, LocalStack routes Step Functions traffic to its internal runtime. "
|
326
|
+
"Use this variable only if you need to redirect traffic to a different local Step Functions runtime.",
|
327
|
+
),
|
314
328
|
]
|
315
329
|
|
316
330
|
|
@@ -422,12 +422,17 @@ class StackChangeSet(Stack):
|
|
422
422
|
return result
|
423
423
|
|
424
424
|
# V2 only
|
425
|
-
def populate_update_graph(
|
425
|
+
def populate_update_graph(
|
426
|
+
self,
|
427
|
+
before_template: Optional[dict],
|
428
|
+
after_template: Optional[dict],
|
429
|
+
before_parameters: Optional[dict],
|
430
|
+
after_parameters: Optional[dict],
|
431
|
+
) -> None:
|
426
432
|
change_set_model = ChangeSetModel(
|
427
433
|
before_template=before_template,
|
428
434
|
after_template=after_template,
|
429
|
-
|
430
|
-
|
431
|
-
after_parameters=None,
|
435
|
+
before_parameters=before_parameters,
|
436
|
+
after_parameters=after_parameters,
|
432
437
|
)
|
433
438
|
self.update_graph = change_set_model.get_update_model()
|
@@ -7,7 +7,6 @@ from typing import Any, Final, Generator, Optional, Union, cast
|
|
7
7
|
|
8
8
|
from typing_extensions import TypeVar
|
9
9
|
|
10
|
-
from localstack.aws.api.cloudformation import ChangeAction
|
11
10
|
from localstack.utils.strings import camel_to_snake_case
|
12
11
|
|
13
12
|
T = TypeVar("T")
|
@@ -67,15 +66,6 @@ class ChangeType(enum.Enum):
|
|
67
66
|
def __str__(self):
|
68
67
|
return self.value
|
69
68
|
|
70
|
-
def to_action(self) -> ChangeAction | None:
|
71
|
-
match self:
|
72
|
-
case self.CREATED:
|
73
|
-
return ChangeAction.Add
|
74
|
-
case self.MODIFIED:
|
75
|
-
return ChangeAction.Modify
|
76
|
-
case self.REMOVED:
|
77
|
-
return ChangeAction.Remove
|
78
|
-
|
79
69
|
def for_child(self, child_change_type: ChangeType) -> ChangeType:
|
80
70
|
if child_change_type == self:
|
81
71
|
return self
|
@@ -525,7 +515,7 @@ class ChangeSetModel:
|
|
525
515
|
|
526
516
|
node_parameter = self._retrieve_parameter_if_exists(parameter_name=logical_id)
|
527
517
|
if isinstance(node_parameter, NodeParameter):
|
528
|
-
return node_parameter.
|
518
|
+
return node_parameter.change_type
|
529
519
|
|
530
520
|
# TODO: this should check the replacement flag for a resource update.
|
531
521
|
node_resource = self._retrieve_or_visit_resource(resource_name=logical_id)
|
@@ -584,19 +574,16 @@ class ChangeSetModel:
|
|
584
574
|
def _visit_array(
|
585
575
|
self, scope: Scope, before_array: Maybe[list], after_array: Maybe[list]
|
586
576
|
) -> NodeArray:
|
587
|
-
change_type = ChangeType.UNCHANGED
|
588
577
|
array: list[ChangeSetEntity] = list()
|
589
578
|
for index, (before_value, after_value) in enumerate(
|
590
579
|
zip_longest(before_array, after_array, fillvalue=Nothing)
|
591
580
|
):
|
592
|
-
# TODO: should extract this scoping logic.
|
593
581
|
value_scope = scope.open_index(index=index)
|
594
582
|
value = self._visit_value(
|
595
583
|
scope=value_scope, before_value=before_value, after_value=after_value
|
596
584
|
)
|
597
585
|
array.append(value)
|
598
|
-
|
599
|
-
change_type = ChangeType.MODIFIED
|
586
|
+
change_type = self._change_type_for_parent_of([value.change_type for value in array])
|
600
587
|
return NodeArray(scope=scope, change_type=change_type, array=array)
|
601
588
|
|
602
589
|
def _visit_object(
|
@@ -695,28 +682,12 @@ class ChangeSetModel:
|
|
695
682
|
node_property = self._visited_scopes.get(scope)
|
696
683
|
if isinstance(node_property, NodeProperty):
|
697
684
|
return node_property
|
698
|
-
|
699
685
|
value = self._visit_value(
|
700
686
|
scope=scope, before_value=before_property, after_value=after_property
|
701
687
|
)
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
change_type=ChangeType.CREATED,
|
706
|
-
name=property_name,
|
707
|
-
value=value,
|
708
|
-
)
|
709
|
-
elif self._is_removed(before=before_property, after=after_property):
|
710
|
-
node_property = NodeProperty(
|
711
|
-
scope=scope,
|
712
|
-
change_type=ChangeType.REMOVED,
|
713
|
-
name=property_name,
|
714
|
-
value=value,
|
715
|
-
)
|
716
|
-
else:
|
717
|
-
node_property = NodeProperty(
|
718
|
-
scope=scope, change_type=value.change_type, name=property_name, value=value
|
719
|
-
)
|
688
|
+
node_property = NodeProperty(
|
689
|
+
scope=scope, change_type=value.change_type, name=property_name, value=value
|
690
|
+
)
|
720
691
|
self._visited_scopes[scope] = node_property
|
721
692
|
return node_property
|
722
693
|
|
@@ -748,6 +719,13 @@ class ChangeSetModel:
|
|
748
719
|
self._visited_scopes[scope] = node_properties
|
749
720
|
return node_properties
|
750
721
|
|
722
|
+
def _visit_type(self, scope: Scope, before_type: Any, after_type: Any) -> TerminalValue:
|
723
|
+
value = self._visit_value(scope=scope, before_value=before_type, after_value=after_type)
|
724
|
+
if not isinstance(value, TerminalValue):
|
725
|
+
# TODO: decide where template schema validation should occur.
|
726
|
+
raise RuntimeError()
|
727
|
+
return value
|
728
|
+
|
751
729
|
def _visit_resource(
|
752
730
|
self,
|
753
731
|
scope: Scope,
|
@@ -766,8 +744,12 @@ class ChangeSetModel:
|
|
766
744
|
else:
|
767
745
|
change_type = ChangeType.UNCHANGED
|
768
746
|
|
769
|
-
|
770
|
-
|
747
|
+
scope_type, (before_type, after_type) = self._safe_access_in(
|
748
|
+
scope, TypeKey, before_resource, after_resource
|
749
|
+
)
|
750
|
+
terminal_value_type = self._visit_type(
|
751
|
+
scope=scope_type, before_type=before_type, after_type=after_type
|
752
|
+
)
|
771
753
|
|
772
754
|
condition_reference = None
|
773
755
|
scope_condition, (before_condition, after_condition) = self._safe_access_in(
|
@@ -792,7 +774,7 @@ class ChangeSetModel:
|
|
792
774
|
scope=scope,
|
793
775
|
change_type=change_type,
|
794
776
|
name=resource_name,
|
795
|
-
type_=
|
777
|
+
type_=terminal_value_type,
|
796
778
|
condition_reference=condition_reference,
|
797
779
|
properties=properties,
|
798
780
|
)
|
@@ -872,36 +854,19 @@ class ChangeSetModel:
|
|
872
854
|
return node_parameter
|
873
855
|
# TODO: add logic to compute defaults already in the graph building process?
|
874
856
|
dynamic_value = self._visit_dynamic_parameter(parameter_name=parameter_name)
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
value=TerminalValueRemoved(scope=scope, value=before_parameter),
|
889
|
-
dynamic_value=dynamic_value,
|
890
|
-
)
|
891
|
-
else:
|
892
|
-
value = self._visit_value(
|
893
|
-
scope=scope, before_value=before_parameter, after_value=after_parameter
|
894
|
-
)
|
895
|
-
change_type = self._change_type_for_parent_of(
|
896
|
-
change_types=[dynamic_value.change_type, value.change_type]
|
897
|
-
)
|
898
|
-
node_parameter = NodeParameter(
|
899
|
-
scope=scope,
|
900
|
-
change_type=change_type,
|
901
|
-
name=parameter_name,
|
902
|
-
value=value,
|
903
|
-
dynamic_value=dynamic_value,
|
904
|
-
)
|
857
|
+
value = self._visit_value(
|
858
|
+
scope=scope, before_value=before_parameter, after_value=after_parameter
|
859
|
+
)
|
860
|
+
change_type = self._change_type_for_parent_of(
|
861
|
+
change_types=[dynamic_value.change_type, value.change_type]
|
862
|
+
)
|
863
|
+
node_parameter = NodeParameter(
|
864
|
+
scope=scope,
|
865
|
+
change_type=change_type,
|
866
|
+
name=parameter_name,
|
867
|
+
value=value,
|
868
|
+
dynamic_value=dynamic_value,
|
869
|
+
)
|
905
870
|
self._visited_scopes[scope] = node_parameter
|
906
871
|
return node_parameter
|
907
872
|
|