localstack-core 4.5.1.dev61__py3-none-any.whl → 4.5.1.dev63__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.
Files changed (19) hide show
  1. localstack/services/cloudformation/engine/v2/change_set_model.py +22 -6
  2. localstack/services/cloudformation/engine/v2/change_set_model_describer.py +24 -4
  3. localstack/services/cloudformation/engine/v2/change_set_model_executor.py +2 -1
  4. localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +223 -210
  5. localstack/services/cloudformation/engine/v2/change_set_model_transform.py +33 -18
  6. localstack/services/cloudformation/v2/entities.py +7 -3
  7. localstack/services/cloudformation/v2/provider.py +104 -6
  8. localstack/version.py +2 -2
  9. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/METADATA +1 -1
  10. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/RECORD +18 -18
  11. localstack_core-4.5.1.dev63.dist-info/plux.json +1 -0
  12. localstack_core-4.5.1.dev61.dist-info/plux.json +0 -1
  13. {localstack_core-4.5.1.dev61.data → localstack_core-4.5.1.dev63.data}/scripts/localstack +0 -0
  14. {localstack_core-4.5.1.dev61.data → localstack_core-4.5.1.dev63.data}/scripts/localstack-supervisor +0 -0
  15. {localstack_core-4.5.1.dev61.data → localstack_core-4.5.1.dev63.data}/scripts/localstack.bat +0 -0
  16. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/WHEEL +0 -0
  17. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/entry_points.txt +0 -0
  18. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/licenses/LICENSE.txt +0 -0
  19. {localstack_core-4.5.1.dev61.dist-info → localstack_core-4.5.1.dev63.dist-info}/top_level.txt +0 -0
@@ -147,6 +147,22 @@ class ChangeSetNode(ChangeSetEntity, abc.ABC): ...
147
147
  class ChangeSetTerminal(ChangeSetEntity, abc.ABC): ...
148
148
 
149
149
 
150
+ class UpdateModel:
151
+ # TODO: may be expanded to keep track of other runtime values such as resolved_parameters.
152
+
153
+ node_template: Final[NodeTemplate]
154
+ before_runtime_cache: Final[dict]
155
+ after_runtime_cache: Final[dict]
156
+
157
+ def __init__(
158
+ self,
159
+ node_template: NodeTemplate,
160
+ ):
161
+ self.node_template = node_template
162
+ self.before_runtime_cache = dict()
163
+ self.after_runtime_cache = dict()
164
+
165
+
150
166
  class NodeTemplate(ChangeSetNode):
151
167
  transform: Final[NodeTransform]
152
168
  mappings: Final[NodeMappings]
@@ -515,9 +531,8 @@ class ChangeSetModel:
515
531
  )
516
532
  # TODO: need to do template preprocessing e.g. parameter resolution, conditions etc.
517
533
 
518
- def get_update_model(self) -> NodeTemplate:
519
- # TODO: rethink naming of this for outer utils
520
- return self._node_template
534
+ def get_update_model(self) -> UpdateModel:
535
+ return UpdateModel(node_template=self._node_template)
521
536
 
522
537
  def _visit_terminal_value(
523
538
  self, scope: Scope, before_value: Maybe[Any], after_value: Maybe[Any]
@@ -548,8 +563,9 @@ class ChangeSetModel:
548
563
  node_intrinsic_function = self._visited_scopes.get(scope)
549
564
  if isinstance(node_intrinsic_function, NodeIntrinsicFunction):
550
565
  return node_intrinsic_function
566
+ arguments_scope = scope.open_scope("args")
551
567
  arguments = self._visit_value(
552
- scope=scope, before_value=before_arguments, after_value=after_arguments
568
+ scope=arguments_scope, before_value=before_arguments, after_value=after_arguments
553
569
  )
554
570
  if is_created(before=before_arguments, after=after_arguments):
555
571
  change_type = ChangeType.CREATED
@@ -777,7 +793,7 @@ class ChangeSetModel:
777
793
  self._safe_access_in(scope, dominant_type_name, before_value, after_value)
778
794
  )
779
795
  value = self._visit_intrinsic_function(
780
- scope=scope,
796
+ scope=intrinsic_function_scope,
781
797
  intrinsic_function=dominant_type_name,
782
798
  before_arguments=before_arguments,
783
799
  after_arguments=after_arguments,
@@ -937,7 +953,7 @@ class ChangeSetModel:
937
953
  scope, mapping_name, before_mappings, after_mappings
938
954
  )
939
955
  mapping = self._visit_mapping(
940
- scope=scope,
956
+ scope=scope_mapping,
941
957
  name=mapping_name,
942
958
  before_mapping=before_mapping,
943
959
  after_mapping=after_mapping,
@@ -8,6 +8,7 @@ from localstack.services.cloudformation.engine.v2.change_set_model import (
8
8
  NodeIntrinsicFunction,
9
9
  NodeProperty,
10
10
  NodeResource,
11
+ NodeResources,
11
12
  PropertiesKey,
12
13
  is_nothing,
13
14
  )
@@ -40,6 +41,20 @@ class ChangeSetModelDescriber(ChangeSetModelPreproc):
40
41
  self.process()
41
42
  return self._changes
42
43
 
44
+ def _setup_runtime_cache(self) -> None:
45
+ # The describer can output {{changeSet:KNOWN_AFTER_APPLY}} values as not every field
46
+ # is computable at describe time. Until a filtering logic or executor override logic
47
+ # is available, the describer cannot benefit of previous evaluations to compute
48
+ # change set resource changes.
49
+ pass
50
+
51
+ def _save_runtime_cache(self) -> None:
52
+ # The describer can output {{changeSet:KNOWN_AFTER_APPLY}} values as not every field
53
+ # is computable at describe time. Until a filtering logic or executor override logic
54
+ # is available, there are no benefits in having the describer saving its runtime cache
55
+ # for future changes chains.
56
+ pass
57
+
43
58
  def _resolve_attribute(self, arguments: str | list[str], select_before: bool) -> str:
44
59
  if select_before:
45
60
  return super()._resolve_attribute(arguments=arguments, select_before=select_before)
@@ -57,7 +72,8 @@ class ChangeSetModelDescriber(ChangeSetModelPreproc):
57
72
  attribute_name = arguments_list[1]
58
73
 
59
74
  node_resource = self._get_node_resource_for(
60
- resource_name=logical_name_of_resource, node_template=self._node_template
75
+ resource_name=logical_name_of_resource,
76
+ node_template=self._change_set.update_model.node_template,
61
77
  )
62
78
  node_property: Optional[NodeProperty] = self._get_node_property_for(
63
79
  property_name=attribute_name, node_resource=node_resource
@@ -182,6 +198,13 @@ class ChangeSetModelDescriber(ChangeSetModelPreproc):
182
198
  after_properties=after.properties,
183
199
  )
184
200
 
201
+ def visit_node_resources(self, node_resources: NodeResources) -> None:
202
+ for node_resource in node_resources.resources:
203
+ delta_resource = self.visit(node_resource)
204
+ self._describe_resource_change(
205
+ name=node_resource.name, before=delta_resource.before, after=delta_resource.after
206
+ )
207
+
185
208
  def visit_node_resource(
186
209
  self, node_resource: NodeResource
187
210
  ) -> PreprocEntityDelta[PreprocResource, PreprocResource]:
@@ -189,7 +212,4 @@ class ChangeSetModelDescriber(ChangeSetModelPreproc):
189
212
  after_resource = delta.after
190
213
  if not is_nothing(after_resource) and after_resource.physical_resource_id is None:
191
214
  after_resource.physical_resource_id = CHANGESET_KNOWN_AFTER_APPLY
192
- self._describe_resource_change(
193
- name=node_resource.name, before=delta.before, after=delta.after
194
- )
195
215
  return delta
@@ -159,7 +159,8 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
159
159
  depends_on_resource_logical_ids.update(array_identifiers_delta.after)
160
160
  for depends_on_resource_logical_id in depends_on_resource_logical_ids:
161
161
  node_resource = self._get_node_resource_for(
162
- resource_name=depends_on_resource_logical_id, node_template=self._node_template
162
+ resource_name=depends_on_resource_logical_id,
163
+ node_template=self._change_set.update_model.node_template,
163
164
  )
164
165
  self.visit(node_resource)
165
166