localstack-core 4.5.1.dev42__py3-none-any.whl → 4.5.1.dev44__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 -4
  2. localstack/services/cloudformation/engine/v2/change_set_model_executor.py +109 -61
  3. localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +16 -0
  4. localstack/services/cloudformation/engine/v2/change_set_model_transform.py +112 -10
  5. localstack/services/cloudformation/v2/entities.py +44 -2
  6. localstack/services/cloudformation/v2/provider.py +7 -2
  7. localstack/testing/pytest/cloudformation/fixtures.py +69 -8
  8. localstack/version.py +2 -2
  9. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/METADATA +1 -1
  10. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/RECORD +18 -18
  11. localstack_core-4.5.1.dev44.dist-info/plux.json +1 -0
  12. localstack_core-4.5.1.dev42.dist-info/plux.json +0 -1
  13. {localstack_core-4.5.1.dev42.data → localstack_core-4.5.1.dev44.data}/scripts/localstack +0 -0
  14. {localstack_core-4.5.1.dev42.data → localstack_core-4.5.1.dev44.data}/scripts/localstack-supervisor +0 -0
  15. {localstack_core-4.5.1.dev42.data → localstack_core-4.5.1.dev44.data}/scripts/localstack.bat +0 -0
  16. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/WHEEL +0 -0
  17. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/entry_points.txt +0 -0
  18. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/licenses/LICENSE.txt +0 -0
  19. {localstack_core-4.5.1.dev42.dist-info → localstack_core-4.5.1.dev44.dist-info}/top_level.txt +0 -0
@@ -802,6 +802,7 @@ class ChangeSetModel:
802
802
  node_property = self._visited_scopes.get(scope)
803
803
  if isinstance(node_property, NodeProperty):
804
804
  return node_property
805
+ # TODO: Review the use of Fn::Transform as resource properties.
805
806
  value = self._visit_value(
806
807
  scope=scope, before_value=before_property, after_value=after_property
807
808
  )
@@ -1156,14 +1157,30 @@ class ChangeSetModel:
1156
1157
  @staticmethod
1157
1158
  def _normalise_transformer_value(value: Maybe[str | list[Any]]) -> Maybe[list[Any]]:
1158
1159
  # To simplify downstream logics, reduce the type options to array of transformations.
1159
- # TODO: add validation logic
1160
+ # TODO: add further validation logic
1160
1161
  # TODO: should we sort to avoid detecting user-side ordering changes as template changes?
1161
1162
  if isinstance(value, NothingType):
1162
1163
  return value
1163
1164
  elif isinstance(value, str):
1164
1165
  value = [NormalisedGlobalTransformDefinition(Name=value, Parameters=Nothing)]
1165
- elif not isinstance(value, list):
1166
- raise RuntimeError(f"Invalid type for Transformer: '{value}'")
1166
+ elif isinstance(value, list):
1167
+ tmp_value = list()
1168
+ for item in value:
1169
+ if isinstance(item, str):
1170
+ tmp_value.append(
1171
+ NormalisedGlobalTransformDefinition(Name=item, Parameters=Nothing)
1172
+ )
1173
+ else:
1174
+ tmp_value.append(item)
1175
+ value = tmp_value
1176
+ elif isinstance(value, dict):
1177
+ if "Name" not in value:
1178
+ raise RuntimeError(f"Missing 'Name' field in Transform definition '{value}'")
1179
+ name = value["Name"]
1180
+ parameters = value.get("Parameters", Nothing)
1181
+ value = [NormalisedGlobalTransformDefinition(Name=name, Parameters=parameters)]
1182
+ else:
1183
+ raise RuntimeError(f"Invalid Transform definition: '{value}'")
1167
1184
  return value
1168
1185
 
1169
1186
  def _visit_transform(
@@ -1325,7 +1342,8 @@ class ChangeSetModel:
1325
1342
  def _safe_access_in(scope: Scope, key: str, *objects: Maybe[dict]) -> tuple[Scope, Maybe[Any]]:
1326
1343
  results = list()
1327
1344
  for obj in objects:
1328
- # TODO: raise errors if not dict
1345
+ if not isinstance(obj, (dict, NothingType)):
1346
+ raise RuntimeError(f"Invalid definition type at '{obj}'")
1329
1347
  if not isinstance(obj, NothingType):
1330
1348
  results.append(obj.get(key, Nothing))
1331
1349
  else:
@@ -36,6 +36,8 @@ from localstack.services.cloudformation.v2.entities import ChangeSet
36
36
 
37
37
  LOG = logging.getLogger(__name__)
38
38
 
39
+ EventOperationFromAction = {"Add": "CREATE", "Modify": "UPDATE", "Remove": "DELETE"}
40
+
39
41
 
40
42
  @dataclass
41
43
  class ChangeSetModelExecutorResult:
@@ -86,6 +88,50 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
86
88
  self.resolved_parameters[node_parameter.name] = delta.after
87
89
  return delta
88
90
 
91
+ def _get_physical_id(self, logical_resource_id, strict: bool = True) -> str | None:
92
+ physical_resource_id = None
93
+ try:
94
+ physical_resource_id = self._after_resource_physical_id(logical_resource_id)
95
+ except RuntimeError:
96
+ # The physical id is missing or is set to None, which is invalid.
97
+ pass
98
+ if physical_resource_id is None:
99
+ # The physical resource id is None after an update that didn't rewrite the resource, the previous
100
+ # resource id is therefore the current physical id of this resource.
101
+
102
+ try:
103
+ physical_resource_id = self._before_resource_physical_id(logical_resource_id)
104
+ except RuntimeError as e:
105
+ if strict:
106
+ raise e
107
+ return physical_resource_id
108
+
109
+ def _process_event(
110
+ self,
111
+ action: ChangeAction,
112
+ logical_resource_id,
113
+ event_status: OperationStatus,
114
+ special_action: str = None,
115
+ reason: str = None,
116
+ resource_type=None,
117
+ ):
118
+ status_from_action = special_action or EventOperationFromAction[action.value]
119
+ if event_status == OperationStatus.SUCCESS:
120
+ status = f"{status_from_action}_COMPLETE"
121
+ else:
122
+ status = f"{status_from_action}_{event_status.name}"
123
+
124
+ self._change_set.stack.set_resource_status(
125
+ logical_resource_id=logical_resource_id,
126
+ physical_resource_id=self._get_physical_id(logical_resource_id, False),
127
+ resource_type=resource_type,
128
+ status=ResourceStatus(status),
129
+ resource_status_reason=reason,
130
+ )
131
+
132
+ if event_status == OperationStatus.FAILED:
133
+ self._change_set.stack.set_stack_status(StackStatus(status))
134
+
89
135
  def _after_deployed_property_value_of(
90
136
  self, resource_logical_id: str, property_name: str
91
137
  ) -> str:
@@ -173,20 +219,29 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
173
219
  # XXX hacky, stick the previous resources' properties into the payload
174
220
  before_properties = self._merge_before_properties(name, before)
175
221
 
176
- self._execute_resource_action(
222
+ self._process_event(ChangeAction.Modify, name, OperationStatus.IN_PROGRESS)
223
+ event = self._execute_resource_action(
177
224
  action=ChangeAction.Modify,
178
225
  logical_resource_id=name,
179
226
  resource_type=before.resource_type,
180
227
  before_properties=before_properties,
181
228
  after_properties=after.properties,
182
229
  )
230
+ self._process_event(
231
+ ChangeAction.Modify,
232
+ name,
233
+ event.status,
234
+ reason=event.message,
235
+ resource_type=before.resource_type,
236
+ )
183
237
  # Case: type migration.
184
238
  # TODO: Add test to assert that on type change the resources are replaced.
185
239
  else:
186
240
  # XXX hacky, stick the previous resources' properties into the payload
187
241
  before_properties = self._merge_before_properties(name, before)
188
242
  # Register a Removed for the previous type.
189
- self._execute_resource_action(
243
+
244
+ event = self._execute_resource_action(
190
245
  action=ChangeAction.Remove,
191
246
  logical_resource_id=name,
192
247
  resource_type=before.resource_type,
@@ -194,35 +249,74 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
194
249
  after_properties=None,
195
250
  )
196
251
  # Register a Create for the next type.
197
- self._execute_resource_action(
252
+ self._process_event(
253
+ ChangeAction.Modify,
254
+ name,
255
+ event.status,
256
+ reason=event.message,
257
+ resource_type=before.resource_type,
258
+ )
259
+ event = self._execute_resource_action(
198
260
  action=ChangeAction.Add,
199
261
  logical_resource_id=name,
200
262
  resource_type=after.resource_type,
201
263
  before_properties=None,
202
264
  after_properties=after.properties,
203
265
  )
266
+ self._process_event(
267
+ ChangeAction.Modify,
268
+ name,
269
+ event.status,
270
+ reason=event.message,
271
+ resource_type=before.resource_type,
272
+ )
204
273
  elif not is_nothing(before):
205
274
  # Case: removal
206
275
  # XXX hacky, stick the previous resources' properties into the payload
207
276
  # XXX hacky, stick the previous resources' properties into the payload
208
277
  before_properties = self._merge_before_properties(name, before)
209
-
210
- self._execute_resource_action(
278
+ self._process_event(
279
+ ChangeAction.Remove,
280
+ name,
281
+ OperationStatus.IN_PROGRESS,
282
+ resource_type=before.resource_type,
283
+ )
284
+ event = self._execute_resource_action(
211
285
  action=ChangeAction.Remove,
212
286
  logical_resource_id=name,
213
287
  resource_type=before.resource_type,
214
288
  before_properties=before_properties,
215
289
  after_properties=None,
216
290
  )
291
+ self._process_event(
292
+ ChangeAction.Remove,
293
+ name,
294
+ event.status,
295
+ reason=event.message,
296
+ resource_type=before.resource_type,
297
+ )
217
298
  elif not is_nothing(after):
218
299
  # Case: addition
219
- self._execute_resource_action(
300
+ self._process_event(
301
+ ChangeAction.Add,
302
+ name,
303
+ OperationStatus.IN_PROGRESS,
304
+ resource_type=after.resource_type,
305
+ )
306
+ event = self._execute_resource_action(
220
307
  action=ChangeAction.Add,
221
308
  logical_resource_id=name,
222
309
  resource_type=after.resource_type,
223
310
  before_properties=None,
224
311
  after_properties=after.properties,
225
312
  )
313
+ self._process_event(
314
+ ChangeAction.Add,
315
+ name,
316
+ event.status,
317
+ reason=event.message,
318
+ resource_type=after.resource_type,
319
+ )
226
320
 
227
321
  def _merge_before_properties(
228
322
  self, name: str, preproc_resource: PreprocResource
@@ -242,7 +336,7 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
242
336
  resource_type: str,
243
337
  before_properties: Optional[PreprocProperties],
244
338
  after_properties: Optional[PreprocProperties],
245
- ) -> None:
339
+ ) -> ProgressEvent:
246
340
  LOG.debug("Executing resource action: %s for resource '%s'", action, logical_resource_id)
247
341
  resource_provider_executor = ResourceProviderExecutor(
248
342
  stack_name=self._change_set.stack.stack_name, stack_id=self._change_set.stack.stack_id
@@ -272,16 +366,6 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
272
366
  exc_info=LOG.isEnabledFor(logging.DEBUG),
273
367
  )
274
368
  stack = self._change_set.stack
275
- match stack.status:
276
- case StackStatus.CREATE_IN_PROGRESS:
277
- stack.set_stack_status(StackStatus.CREATE_FAILED, reason=reason)
278
- case StackStatus.UPDATE_IN_PROGRESS:
279
- stack.set_stack_status(StackStatus.UPDATE_FAILED, reason=reason)
280
- case StackStatus.DELETE_IN_PROGRESS:
281
- stack.set_stack_status(StackStatus.DELETE_FAILED, reason=reason)
282
- case _:
283
- raise NotImplementedError(f"Unexpected stack status: {stack.status}")
284
- # update resource status
285
369
  stack.set_resource_status(
286
370
  logical_resource_id=logical_resource_id,
287
371
  # TODO,
@@ -292,7 +376,11 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
292
376
  else ResourceStatus.UPDATE_FAILED,
293
377
  resource_status_reason=reason,
294
378
  )
295
- return
379
+ event = ProgressEvent(
380
+ OperationStatus.FAILED,
381
+ resource_model={},
382
+ message=f"Resource provider operation failed: {reason}",
383
+ )
296
384
 
297
385
  self.resources.setdefault(logical_resource_id, {"Properties": {}})
298
386
  match event.status:
@@ -313,28 +401,8 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
313
401
  self.resources[logical_resource_id]["LogicalResourceId"] = logical_resource_id
314
402
  self.resources[logical_resource_id]["Type"] = resource_type
315
403
 
316
- # TODO: review why the physical id is returned as None during updates
317
- # TODO: abstract this in member function of resource classes instead
318
- physical_resource_id = None
319
- try:
320
- physical_resource_id = self._after_resource_physical_id(logical_resource_id)
321
- except RuntimeError:
322
- # The physical id is missing or is set to None, which is invalid.
323
- pass
324
- if physical_resource_id is None:
325
- # The physical resource id is None after an update that didn't rewrite the resource, the previous
326
- # resource id is therefore the current physical id of this resource.
327
- physical_resource_id = self._before_resource_physical_id(logical_resource_id)
328
- self.resources[logical_resource_id]["PhysicalResourceId"] = physical_resource_id
329
-
330
- self._change_set.stack.set_resource_status(
331
- logical_resource_id=logical_resource_id,
332
- physical_resource_id=physical_resource_id,
333
- resource_type=resource_type,
334
- status=ResourceStatus.CREATE_COMPLETE
335
- if action == ChangeAction.Add
336
- else ResourceStatus.UPDATE_COMPLETE,
337
- )
404
+ physical_resource_id = self._get_physical_id(logical_resource_id)
405
+ self.resources[logical_resource_id]["PhysicalResourceId"] = physical_resource_id
338
406
 
339
407
  case OperationStatus.FAILED:
340
408
  reason = event.message
@@ -342,29 +410,9 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
342
410
  "Resource provider operation failed: '%s'",
343
411
  reason,
344
412
  )
345
- # TODO: duplication
346
- stack = self._change_set.stack
347
- match stack.status:
348
- case StackStatus.CREATE_IN_PROGRESS:
349
- stack.set_stack_status(StackStatus.CREATE_FAILED, reason=reason)
350
- case StackStatus.UPDATE_IN_PROGRESS:
351
- stack.set_stack_status(StackStatus.UPDATE_FAILED, reason=reason)
352
- case StackStatus.DELETE_IN_PROGRESS:
353
- stack.set_stack_status(StackStatus.DELETE_FAILED, reason=reason)
354
- case _:
355
- raise NotImplementedError(f"Unhandled stack status: '{stack.status}'")
356
- stack.set_resource_status(
357
- logical_resource_id=logical_resource_id,
358
- # TODO
359
- physical_resource_id="",
360
- resource_type=resource_type,
361
- status=ResourceStatus.CREATE_FAILED
362
- if action == ChangeAction.Add
363
- else ResourceStatus.UPDATE_FAILED,
364
- resource_status_reason=reason,
365
- )
366
413
  case other:
367
414
  raise NotImplementedError(f"Event status '{other}' not handled")
415
+ return event
368
416
 
369
417
  def create_resource_provider_payload(
370
418
  self,
@@ -27,6 +27,7 @@ from localstack.services.cloudformation.engine.v2.change_set_model import (
27
27
  NodeOutput,
28
28
  NodeOutputs,
29
29
  NodeParameter,
30
+ NodeParameters,
30
31
  NodeProperties,
31
32
  NodeProperty,
32
33
  NodeResource,
@@ -882,6 +883,21 @@ class ChangeSetModelPreproc(ChangeSetModelVisitor):
882
883
  bindings_delta = self.visit(node_mapping.bindings)
883
884
  return bindings_delta
884
885
 
886
+ def visit_node_parameters(
887
+ self, node_parameters: NodeParameters
888
+ ) -> PreprocEntityDelta[dict[str, Any], dict[str, Any]]:
889
+ before_parameters = dict()
890
+ after_parameters = dict()
891
+ for parameter in node_parameters.parameters:
892
+ parameter_delta = self.visit(parameter)
893
+ parameter_before = parameter_delta.before
894
+ if not is_nothing(parameter_before):
895
+ before_parameters[parameter.name] = parameter_before
896
+ parameter_after = parameter_delta.after
897
+ if not is_nothing(parameter_after):
898
+ after_parameters[parameter.name] = parameter_after
899
+ return PreprocEntityDelta(before=before_parameters, after=after_parameters)
900
+
885
901
  def visit_node_parameter(self, node_parameter: NodeParameter) -> PreprocEntityDelta:
886
902
  dynamic_value = node_parameter.dynamic_value
887
903
  dynamic_delta = self.visit(dynamic_value)
@@ -1,16 +1,21 @@
1
1
  import copy
2
+ import logging
2
3
  import os
3
- from typing import Final, Optional
4
+ from typing import Any, Final, Optional, TypedDict
4
5
 
5
6
  import boto3
6
7
  from samtranslator.translator.transform import transform as transform_sam
7
8
 
8
9
  from localstack.services.cloudformation.engine.policy_loader import create_policy_loader
9
- from localstack.services.cloudformation.engine.transformers import FailedTransformationException
10
+ from localstack.services.cloudformation.engine.transformers import (
11
+ FailedTransformationException,
12
+ execute_macro,
13
+ )
10
14
  from localstack.services.cloudformation.engine.v2.change_set_model import (
11
15
  ChangeType,
12
16
  Maybe,
13
17
  NodeGlobalTransform,
18
+ NodeParameter,
14
19
  NodeTransform,
15
20
  Nothing,
16
21
  is_nothing,
@@ -19,9 +24,14 @@ from localstack.services.cloudformation.engine.v2.change_set_model_preproc impor
19
24
  ChangeSetModelPreproc,
20
25
  PreprocEntityDelta,
21
26
  )
27
+ from localstack.services.cloudformation.stores import get_cloudformation_store
22
28
  from localstack.services.cloudformation.v2.entities import ChangeSet
23
29
 
30
+ LOG = logging.getLogger(__name__)
31
+
24
32
  SERVERLESS_TRANSFORM = "AWS::Serverless-2016-10-31"
33
+ EXTENSIONS_TRANSFORM = "AWS::LanguageExtensions"
34
+ SECRETSMANAGER_TRANSFORM = "AWS::SecretsManager-2020-07-23"
25
35
 
26
36
 
27
37
  # TODO: evaluate the use of subtypes to represent and validate types of transforms
@@ -34,6 +44,13 @@ class GlobalTransform:
34
44
  self.parameters = parameters
35
45
 
36
46
 
47
+ class TransformPreprocParameter(TypedDict):
48
+ # TODO: expand
49
+ ParameterKey: str
50
+ ParameterValue: Any
51
+ ParameterType: Optional[str]
52
+
53
+
37
54
  class ChangeSetModelTransform(ChangeSetModelPreproc):
38
55
  _before_parameters: Final[dict]
39
56
  _after_parameters: Final[dict]
@@ -54,9 +71,48 @@ class ChangeSetModelTransform(ChangeSetModelPreproc):
54
71
  self._before_template = before_template or Nothing
55
72
  self._after_template = after_template or Nothing
56
73
 
74
+ def visit_node_parameter(
75
+ self, node_parameter: NodeParameter
76
+ ) -> PreprocEntityDelta[
77
+ dict[str, TransformPreprocParameter], dict[str, TransformPreprocParameter]
78
+ ]:
79
+ # Enable compatability with v1 util.
80
+ # TODO: port v1's SSM parameter resolution
81
+
82
+ parameter_value_delta = super().visit_node_parameter(node_parameter=node_parameter)
83
+ parameter_value_before = parameter_value_delta.before
84
+ parameter_value_after = parameter_value_delta.after
85
+
86
+ parameter_type_delta = self.visit(node_parameter.type_)
87
+ parameter_type_before = parameter_type_delta.before
88
+ parameter_type_after = parameter_type_delta.after
89
+
90
+ parameter_key = node_parameter.name
91
+
92
+ before = Nothing
93
+ if not is_nothing(parameter_value_before):
94
+ before = TransformPreprocParameter(
95
+ ParameterKey=parameter_key,
96
+ ParameterValue=parameter_value_before,
97
+ ParameterType=parameter_type_before
98
+ if not is_nothing(parameter_type_before)
99
+ else None,
100
+ )
101
+ after = Nothing
102
+ if not is_nothing(parameter_value_after):
103
+ after = TransformPreprocParameter(
104
+ ParameterKey=parameter_key,
105
+ ParameterValue=parameter_value_after,
106
+ ParameterType=parameter_type_after
107
+ if not is_nothing(parameter_type_after)
108
+ else None,
109
+ )
110
+
111
+ return PreprocEntityDelta(before=before, after=after)
112
+
57
113
  # Ported from v1:
58
114
  @staticmethod
59
- def _apply_serverless_transformation(
115
+ def _apply_global_serverless_transformation(
60
116
  region_name: str, template: dict, parameters: dict
61
117
  ) -> dict:
62
118
  """only returns string when parsing SAM template, otherwise None"""
@@ -79,19 +135,65 @@ class ChangeSetModelTransform(ChangeSetModelPreproc):
79
135
  if region_before is not None:
80
136
  os.environ["AWS_DEFAULT_REGION"] = region_before
81
137
 
138
+ @staticmethod
139
+ def _apply_global_macro_transformation(
140
+ account_id: str,
141
+ region_name,
142
+ global_transform: GlobalTransform,
143
+ template: dict,
144
+ parameters: dict,
145
+ ) -> Optional[dict]:
146
+ macro_name = global_transform.name
147
+ macros_store = get_cloudformation_store(
148
+ account_id=account_id, region_name=region_name
149
+ ).macros
150
+ macro = macros_store.get(macro_name)
151
+ if macro is None:
152
+ raise RuntimeError(f"No definitions for global transform '{macro_name}'")
153
+ transformation_parameters = global_transform.parameters or dict()
154
+ transformed_template = execute_macro(
155
+ account_id,
156
+ region_name,
157
+ parsed_template=template,
158
+ macro=macro,
159
+ stack_parameters=parameters,
160
+ transformation_parameters=transformation_parameters,
161
+ )
162
+ # The type annotation on the v1 util appears to be incorrect.
163
+ return transformed_template # noqa
164
+
82
165
  def _apply_global_transform(
83
166
  self, global_transform: GlobalTransform, template: dict, parameters: dict
84
167
  ) -> dict:
85
- if global_transform.name == SERVERLESS_TRANSFORM:
86
- return self._apply_serverless_transformation(
168
+ transform_name = global_transform.name
169
+ if transform_name == EXTENSIONS_TRANSFORM:
170
+ # Applied lazily in downstream tasks (see ChangeSetModelPreproc).
171
+ transformed_template = template
172
+ elif transform_name == SERVERLESS_TRANSFORM:
173
+ transformed_template = self._apply_global_serverless_transformation(
87
174
  region_name=self._change_set.region_name,
88
175
  template=template,
89
176
  parameters=parameters,
90
177
  )
91
- # TODO: expand support
92
- raise RuntimeError(f"Unsupported global transform '{global_transform.name}'")
178
+ elif transform_name == SECRETSMANAGER_TRANSFORM:
179
+ # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-aws-secretsmanager.html
180
+ LOG.warning("%s is not yet supported. Ignoring.", SECRETSMANAGER_TRANSFORM)
181
+ transformed_template = template
182
+ else:
183
+ transformed_template = self._apply_global_macro_transformation(
184
+ account_id=self._change_set.account_id,
185
+ region_name=self._change_set.region_name,
186
+ global_transform=global_transform,
187
+ template=template,
188
+ parameters=parameters,
189
+ )
190
+ return transformed_template
93
191
 
94
192
  def transform(self) -> tuple[dict, dict]:
193
+ parameters_delta = self.visit_node_parameters(self._node_template.parameters)
194
+ parameters_before = parameters_delta.before
195
+ parameters_after = parameters_delta.after
196
+
95
197
  transform_delta: PreprocEntityDelta[list[GlobalTransform], list[GlobalTransform]] = (
96
198
  self.visit_node_transform(self._node_template.transform)
97
199
  )
@@ -104,17 +206,17 @@ class ChangeSetModelTransform(ChangeSetModelPreproc):
104
206
  for before_global_transform in transform_before:
105
207
  transformed_before_template = self._apply_global_transform(
106
208
  global_transform=before_global_transform,
107
- parameters=self._before_parameters,
209
+ parameters=parameters_before,
108
210
  template=transformed_before_template,
109
211
  )
110
212
 
111
213
  transformed_after_template = self._after_template
112
- if not is_nothing(transform_before) and not is_nothing(self._after_template):
214
+ if not is_nothing(transform_after) and not is_nothing(self._after_template):
113
215
  transformed_after_template = self._after_template
114
216
  for after_global_transform in transform_after:
115
217
  transformed_after_template = self._apply_global_transform(
116
218
  global_transform=after_global_transform,
117
- parameters=self._after_parameters,
219
+ parameters=parameters_after,
118
220
  template=transformed_after_template,
119
221
  )
120
222
 
@@ -11,6 +11,7 @@ from localstack.aws.api.cloudformation import (
11
11
  ResourceStatus,
12
12
  StackDriftInformation,
13
13
  StackDriftStatus,
14
+ StackEvent,
14
15
  StackResource,
15
16
  StackStatus,
16
17
  StackStatusReason,
@@ -26,7 +27,7 @@ from localstack.services.cloudformation.engine.v2.change_set_model import (
26
27
  NodeTemplate,
27
28
  )
28
29
  from localstack.utils.aws import arns
29
- from localstack.utils.strings import short_uid
30
+ from localstack.utils.strings import long_uid, short_uid
30
31
 
31
32
 
32
33
  class ResolvedResource(TypedDict):
@@ -43,6 +44,7 @@ class Stack:
43
44
  stack_id: str
44
45
  creation_time: datetime
45
46
  deletion_time: datetime | None
47
+ events = list[StackEvent]
46
48
 
47
49
  # state after deploy
48
50
  resolved_parameters: dict[str, str]
@@ -89,12 +91,15 @@ class Stack:
89
91
  self.resolved_resources = {}
90
92
  self.resolved_outputs = {}
91
93
  self.resource_states = {}
94
+ self.events = []
92
95
 
93
96
  def set_stack_status(self, status: StackStatus, reason: StackStatusReason | None = None):
94
97
  self.status = status
95
98
  if reason:
96
99
  self.status_reason = reason
97
100
 
101
+ self._store_event(self.stack_name, self.stack_id, status.value, status_reason=reason)
102
+
98
103
  def set_resource_status(
99
104
  self,
100
105
  *,
@@ -104,7 +109,7 @@ class Stack:
104
109
  status: ResourceStatus,
105
110
  resource_status_reason: str | None = None,
106
111
  ):
107
- self.resource_states[logical_resource_id] = StackResource(
112
+ resource_description = StackResource(
108
113
  StackName=self.stack_name,
109
114
  StackId=self.stack_id,
110
115
  LogicalResourceId=logical_resource_id,
@@ -115,6 +120,43 @@ class Stack:
115
120
  ResourceStatusReason=resource_status_reason,
116
121
  )
117
122
 
123
+ if not resource_status_reason:
124
+ resource_description.pop("ResourceStatusReason")
125
+
126
+ self.resource_states[logical_resource_id] = resource_description
127
+ self._store_event(logical_resource_id, physical_resource_id, status, resource_status_reason)
128
+
129
+ def _store_event(
130
+ self,
131
+ resource_id: str = None,
132
+ physical_res_id: str = None,
133
+ status: str = "",
134
+ status_reason: str = "",
135
+ ):
136
+ resource_id = resource_id
137
+ physical_res_id = physical_res_id
138
+ resource_type = (
139
+ self.template.get("Resources", {})
140
+ .get(resource_id, {})
141
+ .get("Type", "AWS::CloudFormation::Stack")
142
+ )
143
+
144
+ event: StackEvent = {
145
+ "EventId": long_uid(),
146
+ "Timestamp": datetime.now(tz=timezone.utc),
147
+ "StackId": self.stack_id,
148
+ "StackName": self.stack_name,
149
+ "LogicalResourceId": resource_id,
150
+ "PhysicalResourceId": physical_res_id,
151
+ "ResourceStatus": status,
152
+ "ResourceType": resource_type,
153
+ }
154
+
155
+ if status_reason:
156
+ event["ResourceStatusReason"] = status_reason
157
+
158
+ self.events.insert(0, event)
159
+
118
160
  def describe_details(self) -> ApiStack:
119
161
  result = {
120
162
  "ChangeSetId": self.change_set_id,
@@ -236,7 +236,10 @@ class CloudformationProviderV2(CloudformationProvider):
236
236
  raise ValidationError(f"Stack '{stack_name}' does not exist.")
237
237
  stack = active_stack_candidates[0]
238
238
 
239
- stack.set_stack_status(StackStatus.REVIEW_IN_PROGRESS)
239
+ if stack.status in [StackStatus.CREATE_COMPLETE, StackStatus.UPDATE_COMPLETE]:
240
+ stack.set_stack_status(StackStatus.UPDATE_IN_PROGRESS)
241
+ else:
242
+ stack.set_stack_status(StackStatus.REVIEW_IN_PROGRESS)
240
243
 
241
244
  # TODO: test if rollback status is allowed as well
242
245
  if (
@@ -472,7 +475,9 @@ class CloudformationProviderV2(CloudformationProvider):
472
475
  next_token: NextToken = None,
473
476
  **kwargs,
474
477
  ) -> DescribeStackEventsOutput:
475
- return DescribeStackEventsOutput(StackEvents=[])
478
+ state = get_cloudformation_store(context.account_id, context.region)
479
+ stack = find_stack_v2(state, stack_name)
480
+ return DescribeStackEventsOutput(StackEvents=stack.events)
476
481
 
477
482
  @handler("DeleteStack")
478
483
  def delete_stack(
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from collections import defaultdict
3
- from typing import Callable
3
+ from typing import Callable, Optional, TypedDict
4
4
 
5
5
  import pytest
6
6
 
@@ -9,22 +9,83 @@ from localstack.aws.connect import ServiceLevelClientFactory
9
9
  from localstack.utils.functions import call_safe
10
10
  from localstack.utils.strings import short_uid
11
11
 
12
- PerResourceStackEvents = dict[str, list[StackEvent]]
12
+
13
+ class NormalizedEvent(TypedDict):
14
+ PhysicalResourceId: Optional[str]
15
+ LogicalResourceId: str
16
+ ResourceType: str
17
+ ResourceStatus: str
18
+ Timestamp: str
19
+
20
+
21
+ PerResourceStackEvents = dict[str, list[NormalizedEvent]]
22
+
23
+
24
+ def normalize_event(event: StackEvent) -> NormalizedEvent:
25
+ return NormalizedEvent(
26
+ PhysicalResourceId=event.get("PhysicalResourceId"),
27
+ LogicalResourceId=event.get("LogicalResourceId"),
28
+ ResourceType=event.get("ResourceType"),
29
+ ResourceStatus=event.get("ResourceStatus"),
30
+ Timestamp=event.get("Timestamp"),
31
+ )
13
32
 
14
33
 
15
34
  @pytest.fixture
16
35
  def capture_per_resource_events(
17
36
  aws_client: ServiceLevelClientFactory,
18
37
  ) -> Callable[[str], PerResourceStackEvents]:
19
- def capture(stack_name: str) -> PerResourceStackEvents:
38
+ def capture(stack_name: str) -> dict:
20
39
  events = aws_client.cloudformation.describe_stack_events(StackName=stack_name)[
21
40
  "StackEvents"
22
41
  ]
23
42
  per_resource_events = defaultdict(list)
24
43
  for event in events:
44
+ # TODO: not supported events
45
+ if event.get("ResourceStatus") in {
46
+ "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
47
+ "DELETE_IN_PROGRESS",
48
+ "DELETE_COMPLETE",
49
+ }:
50
+ continue
51
+
25
52
  if logical_resource_id := event.get("LogicalResourceId"):
26
- per_resource_events[logical_resource_id].append(event)
27
- return per_resource_events
53
+ resource_name = (
54
+ logical_resource_id
55
+ if logical_resource_id != event.get("StackName")
56
+ else "Stack"
57
+ )
58
+ normalized_event = normalize_event(event)
59
+ per_resource_events[resource_name].append(normalized_event)
60
+
61
+ for resource_id in per_resource_events:
62
+ per_resource_events[resource_id].sort(key=lambda event: event["Timestamp"])
63
+
64
+ filtered_per_resource_events = {}
65
+ for resource_id in per_resource_events:
66
+ events = []
67
+ last: tuple[str, str, str] | None = None
68
+
69
+ for event in per_resource_events[resource_id]:
70
+ unique_key = (
71
+ event["LogicalResourceId"],
72
+ event["ResourceStatus"],
73
+ event["ResourceType"],
74
+ )
75
+ if last is None:
76
+ events.append(event)
77
+ last = unique_key
78
+ continue
79
+
80
+ if unique_key == last:
81
+ continue
82
+
83
+ events.append(event)
84
+ last = unique_key
85
+
86
+ filtered_per_resource_events[resource_id] = events
87
+
88
+ return filtered_per_resource_events
28
89
 
29
90
  return capture
30
91
 
@@ -165,9 +226,6 @@ def capture_update_process(aws_client_no_retry, cleanups, capture_per_resource_e
165
226
  ]
166
227
  snapshot.match("post-create-2-describe", describe)
167
228
 
168
- events = capture_per_resource_events(stack_name)
169
- snapshot.match("per-resource-events", events)
170
-
171
229
  # delete stack
172
230
  aws_client_no_retry.cloudformation.delete_stack(StackName=stack_id)
173
231
  aws_client_no_retry.cloudformation.get_waiter("stack_delete_complete").wait(
@@ -178,4 +236,7 @@ def capture_update_process(aws_client_no_retry, cleanups, capture_per_resource_e
178
236
  ]
179
237
  snapshot.match("delete-describe", describe)
180
238
 
239
+ events = capture_per_resource_events(stack_id)
240
+ snapshot.match("per-resource-events", events)
241
+
181
242
  yield inner
localstack/version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '4.5.1.dev42'
21
- __version_tuple__ = version_tuple = (4, 5, 1, 'dev42')
20
+ __version__ = version = '4.5.1.dev44'
21
+ __version_tuple__ = version_tuple = (4, 5, 1, 'dev44')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack-core
3
- Version: 4.5.1.dev42
3
+ Version: 4.5.1.dev44
4
4
  Summary: The core library and runtime of LocalStack
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ localstack/deprecations.py,sha256=mNXTebZ8kSbQjFKz0LbT-g1Kdr0CE8bhEgZfHV3IX0s,15
4
4
  localstack/openapi.yaml,sha256=B803NmpwsxG8PHpHrdZYBrUYjnrRh7B_JX0XuNynuFs,30237
5
5
  localstack/plugins.py,sha256=BIJC9dlo0WbP7lLKkCiGtd_2q5oeqiHZohvoRTcejXM,2457
6
6
  localstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- localstack/version.py,sha256=pbB1u8iQIjRwYSqSO505ZISFRqulqEpROOMSXDAkeks,526
7
+ localstack/version.py,sha256=cTI4oJnaBUkedGAEuql92SMOzL7rBqu_Q4XoY-wBzK8,526
8
8
  localstack/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  localstack/aws/accounts.py,sha256=102zpGowOxo0S6UGMpfjw14QW7WCLVAGsnFK5xFMLoo,3043
10
10
  localstack/aws/app.py,sha256=n9bJCfJRuMz_gLGAH430c3bIQXgUXeWO5NPfcdL2MV8,5145
@@ -310,11 +310,11 @@ localstack/services/cloudformation/engine/types.py,sha256=YIhmTrO__obIviYvzzCovK
310
310
  localstack/services/cloudformation/engine/validations.py,sha256=brq7s8O8exA5kvnfzR9ulOtQ7i4konrWQs07-0h_ByE,2847
311
311
  localstack/services/cloudformation/engine/yaml_parser.py,sha256=LQpAVq9Syze9jXUGen9Mz8SjosBuodpV5XvsCSn9bDg,2164
312
312
  localstack/services/cloudformation/engine/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
313
- localstack/services/cloudformation/engine/v2/change_set_model.py,sha256=FnRCaiCCj16ofuXEIAVfYTTbTil2Lce-CPSBoNjoGu8,53736
313
+ localstack/services/cloudformation/engine/v2/change_set_model.py,sha256=Jt_ersgkciAIWhGde9qm0MllIRA4K3vBZE1V04RJ6XQ,54613
314
314
  localstack/services/cloudformation/engine/v2/change_set_model_describer.py,sha256=J2OibRDuVXu-rnLxHmxtjqOD4Q489F9An_6-fkTTAm8,8057
315
- localstack/services/cloudformation/engine/v2/change_set_model_executor.py,sha256=kwExKaHG9DpbSd4aUnD1fkbYv2gE0_Zono8FoFCaMpc,19052
316
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py,sha256=2VvveGHH8uE-ei2bQCqb9dUEYl4NwP6V9J7nwb0DYHA,48953
317
- localstack/services/cloudformation/engine/v2/change_set_model_transform.py,sha256=1ibOGuSZpZwiLt2dEPwptsNVQTBjuRk2R4_Wy06FkvI,6676
315
+ localstack/services/cloudformation/engine/v2/change_set_model_executor.py,sha256=kykv7hPUOvzeaUPs1NA1FHQyUyKcrqRcVK6C-R-sb2E,19943
316
+ localstack/services/cloudformation/engine/v2/change_set_model_preproc.py,sha256=lwSdkqF05IkafWGXVLuZ37dugBGB7_hNpX4e-xtZShY,49709
317
+ localstack/services/cloudformation/engine/v2/change_set_model_transform.py,sha256=TLQmK2WE0NzjSn0-0h0WfOZEwH1ULAJD34eQLEG3F7w,10655
318
318
  localstack/services/cloudformation/engine/v2/change_set_model_visitor.py,sha256=JERT55YkPF-UHzG-sk958mpyEq2Gxz4smY8xwDbhIRQ,7666
319
319
  localstack/services/cloudformation/models/__init__.py,sha256=da1PTClDMl-IBkrSvq6JC1lnS-K_BASzCvxVhNxN5Ls,13
320
320
  localstack/services/cloudformation/resource_providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -333,8 +333,8 @@ localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcon
333
333
  localstack/services/cloudformation/scaffolding/__main__.py,sha256=zjedOdqvnfN99WzQ43gxtGZxLDitSnbFGA-zpWbyMQ0,30960
334
334
  localstack/services/cloudformation/scaffolding/propgen.py,sha256=9YsSCkDegcU_Yp8Sfw8eNV26N5ibOlLC6Hg6lxPeBBM,7949
335
335
  localstack/services/cloudformation/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
336
- localstack/services/cloudformation/v2/entities.py,sha256=WJod0UgwaIXmLbb-fh3ZNweqF2kiv0gDJiy1gW1vIQU,6498
337
- localstack/services/cloudformation/v2/provider.py,sha256=mpcdRne444-OAoC3ymZncNZqQUh9LV29q3sNHG_8Fz8,22824
336
+ localstack/services/cloudformation/v2/entities.py,sha256=3PpR83D-d1dF9QKTawopgmJh2Jaj6Guw3XX27P8Gvi8,7863
337
+ localstack/services/cloudformation/v2/provider.py,sha256=bx-YjLzBYmWpA79KBDGtqbJ25byK9zyRghjIsHvlmeE,23132
338
338
  localstack/services/cloudformation/v2/utils.py,sha256=xy4Lcp4X8XGJ0OKfnsE7pnfMcFrtIH0Chw35qwjhZuw,148
339
339
  localstack/services/cloudwatch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
340
340
  localstack/services/cloudwatch/alarm_scheduler.py,sha256=XFllg0gI_WNV7cNxOcgXifzmbNA07OPpuEUuf37keP4,15663
@@ -1179,7 +1179,7 @@ localstack/testing/pytest/path_filter.py,sha256=U1V5qy23H7yZ6Tznr-MdveeH7TvCM_u4
1179
1179
  localstack/testing/pytest/util.py,sha256=TQAAb_Cj5gTSX0VkenAbSabvyCkl7THxEj70PrT_H7Y,941
1180
1180
  localstack/testing/pytest/validation_tracking.py,sha256=zGYn2r2n1xEe2Xq2JLPhS5dQJ9s29pIQEFpiF7ifehM,5630
1181
1181
  localstack/testing/pytest/cloudformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1182
- localstack/testing/pytest/cloudformation/fixtures.py,sha256=q0dyZlcjUwNlhlZuxCCxWJFhgq9HQF9jt_WjFxdHHJk,7029
1182
+ localstack/testing/pytest/cloudformation/fixtures.py,sha256=JDuRf6joMhR60GwLhRT9NWCpXghvf5JNAVNVws9wWqk,8978
1183
1183
  localstack/testing/pytest/stepfunctions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1184
1184
  localstack/testing/pytest/stepfunctions/fixtures.py,sha256=m9gdU7opK1LoDKuUDTJKcuUfWi4LWHw0idL0_GNlkfo,32817
1185
1185
  localstack/testing/pytest/stepfunctions/utils.py,sha256=L_Zc6-iDC76E5JsGAXltBIi_ZB3-vrCBTGcOcmfEO3g,32819
@@ -1284,13 +1284,13 @@ localstack/utils/server/tcp_proxy.py,sha256=rR6d5jR0ozDvIlpHiqW0cfyY9a2fRGdOzyA8
1284
1284
  localstack/utils/xray/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1285
1285
  localstack/utils/xray/trace_header.py,sha256=ahXk9eonq7LpeENwlqUEPj3jDOCiVRixhntQuxNor-Q,6209
1286
1286
  localstack/utils/xray/traceid.py,sha256=SQSsMV2rhbTNK6ceIoozZYuGU7Fg687EXcgqxoDl1Fw,1106
1287
- localstack_core-4.5.1.dev42.data/scripts/localstack,sha256=WyL11vp5CkuP79iIR-L8XT7Cj8nvmxX7XRAgxhbmXNE,529
1288
- localstack_core-4.5.1.dev42.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1289
- localstack_core-4.5.1.dev42.data/scripts/localstack.bat,sha256=tlzZTXtveHkMX_s_fa7VDfvdNdS8iVpEz2ER3uk9B_c,29
1290
- localstack_core-4.5.1.dev42.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1291
- localstack_core-4.5.1.dev42.dist-info/METADATA,sha256=Vl2T7jQFh65F5SEP2NCrYGqNPDKBS3-AlxyUYcl8lts,5539
1292
- localstack_core-4.5.1.dev42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1293
- localstack_core-4.5.1.dev42.dist-info/entry_points.txt,sha256=tsZ2TeV3-omCfAUEXmTWXu_D40b_17a9FDAEpbeaoNw,20571
1294
- localstack_core-4.5.1.dev42.dist-info/plux.json,sha256=rlkYLtqjI1zim5Ilb1WyceskrcaD2lBnYr8yQiFwuNQ,20793
1295
- localstack_core-4.5.1.dev42.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1296
- localstack_core-4.5.1.dev42.dist-info/RECORD,,
1287
+ localstack_core-4.5.1.dev44.data/scripts/localstack,sha256=WyL11vp5CkuP79iIR-L8XT7Cj8nvmxX7XRAgxhbmXNE,529
1288
+ localstack_core-4.5.1.dev44.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1289
+ localstack_core-4.5.1.dev44.data/scripts/localstack.bat,sha256=tlzZTXtveHkMX_s_fa7VDfvdNdS8iVpEz2ER3uk9B_c,29
1290
+ localstack_core-4.5.1.dev44.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1291
+ localstack_core-4.5.1.dev44.dist-info/METADATA,sha256=WdOh_xyorE8dL7Sc929V3QsaPgiAz--ctgpu8yJo-M0,5539
1292
+ localstack_core-4.5.1.dev44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1293
+ localstack_core-4.5.1.dev44.dist-info/entry_points.txt,sha256=tsZ2TeV3-omCfAUEXmTWXu_D40b_17a9FDAEpbeaoNw,20571
1294
+ localstack_core-4.5.1.dev44.dist-info/plux.json,sha256=ibXItsqTpha2z2C9Uq_8dIjBjnzd35UkcdH1xaZgY0U,20793
1295
+ localstack_core-4.5.1.dev44.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1296
+ localstack_core-4.5.1.dev44.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ {"localstack.cloudformation.resource_providers": ["AWS::ApiGateway::UsagePlan=localstack.services.apigateway.resource_providers.aws_apigateway_usageplan_plugin:ApiGatewayUsagePlanProviderPlugin", "AWS::Logs::LogStream=localstack.services.logs.resource_providers.aws_logs_logstream_plugin:LogsLogStreamProviderPlugin", "AWS::Route53::HealthCheck=localstack.services.route53.resource_providers.aws_route53_healthcheck_plugin:Route53HealthCheckProviderPlugin", "AWS::Lambda::EventSourceMapping=localstack.services.lambda_.resource_providers.aws_lambda_eventsourcemapping_plugin:LambdaEventSourceMappingProviderPlugin", "AWS::EC2::PrefixList=localstack.services.ec2.resource_providers.aws_ec2_prefixlist_plugin:EC2PrefixListProviderPlugin", "AWS::EC2::TransitGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_transitgatewayattachment_plugin:EC2TransitGatewayAttachmentProviderPlugin", "AWS::ApiGateway::BasePathMapping=localstack.services.apigateway.resource_providers.aws_apigateway_basepathmapping_plugin:ApiGatewayBasePathMappingProviderPlugin", "AWS::Lambda::Permission=localstack.services.lambda_.resource_providers.aws_lambda_permission_plugin:LambdaPermissionProviderPlugin", "AWS::IAM::Policy=localstack.services.iam.resource_providers.aws_iam_policy_plugin:IAMPolicyProviderPlugin", "AWS::SNS::TopicPolicy=localstack.services.sns.resource_providers.aws_sns_topicpolicy_plugin:SNSTopicPolicyProviderPlugin", "AWS::Lambda::LayerVersion=localstack.services.lambda_.resource_providers.aws_lambda_layerversion_plugin:LambdaLayerVersionProviderPlugin", "AWS::ResourceGroups::Group=localstack.services.resource_groups.resource_providers.aws_resourcegroups_group_plugin:ResourceGroupsGroupProviderPlugin", "AWS::Events::Connection=localstack.services.events.resource_providers.aws_events_connection_plugin:EventsConnectionProviderPlugin", "AWS::EC2::VPCEndpoint=localstack.services.ec2.resource_providers.aws_ec2_vpcendpoint_plugin:EC2VPCEndpointProviderPlugin", "AWS::IAM::User=localstack.services.iam.resource_providers.aws_iam_user_plugin:IAMUserProviderPlugin", "AWS::Lambda::Url=localstack.services.lambda_.resource_providers.aws_lambda_url_plugin:LambdaUrlProviderPlugin", "AWS::ApiGateway::DomainName=localstack.services.apigateway.resource_providers.aws_apigateway_domainname_plugin:ApiGatewayDomainNameProviderPlugin", "AWS::EC2::Instance=localstack.services.ec2.resource_providers.aws_ec2_instance_plugin:EC2InstanceProviderPlugin", "AWS::IAM::AccessKey=localstack.services.iam.resource_providers.aws_iam_accesskey_plugin:IAMAccessKeyProviderPlugin", "AWS::KinesisFirehose::DeliveryStream=localstack.services.kinesisfirehose.resource_providers.aws_kinesisfirehose_deliverystream_plugin:KinesisFirehoseDeliveryStreamProviderPlugin", "AWS::CloudFormation::Stack=localstack.services.cloudformation.resource_providers.aws_cloudformation_stack_plugin:CloudFormationStackProviderPlugin", "AWS::Redshift::Cluster=localstack.services.redshift.resource_providers.aws_redshift_cluster_plugin:RedshiftClusterProviderPlugin", "AWS::KMS::Alias=localstack.services.kms.resource_providers.aws_kms_alias_plugin:KMSAliasProviderPlugin", "AWS::SecretsManager::ResourcePolicy=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_resourcepolicy_plugin:SecretsManagerResourcePolicyProviderPlugin", "AWS::EC2::Route=localstack.services.ec2.resource_providers.aws_ec2_route_plugin:EC2RouteProviderPlugin", "AWS::EC2::SubnetRouteTableAssociation=localstack.services.ec2.resource_providers.aws_ec2_subnetroutetableassociation_plugin:EC2SubnetRouteTableAssociationProviderPlugin", "AWS::SQS::QueuePolicy=localstack.services.sqs.resource_providers.aws_sqs_queuepolicy_plugin:SQSQueuePolicyProviderPlugin", "AWS::EC2::RouteTable=localstack.services.ec2.resource_providers.aws_ec2_routetable_plugin:EC2RouteTableProviderPlugin", "AWS::ApiGateway::Resource=localstack.services.apigateway.resource_providers.aws_apigateway_resource_plugin:ApiGatewayResourceProviderPlugin", "AWS::ApiGateway::Deployment=localstack.services.apigateway.resource_providers.aws_apigateway_deployment_plugin:ApiGatewayDeploymentProviderPlugin", "AWS::Logs::SubscriptionFilter=localstack.services.logs.resource_providers.aws_logs_subscriptionfilter_plugin:LogsSubscriptionFilterProviderPlugin", "AWS::Elasticsearch::Domain=localstack.services.opensearch.resource_providers.aws_elasticsearch_domain_plugin:ElasticsearchDomainProviderPlugin", "AWS::IAM::ServiceLinkedRole=localstack.services.iam.resource_providers.aws_iam_servicelinkedrole_plugin:IAMServiceLinkedRoleProviderPlugin", "AWS::IAM::ManagedPolicy=localstack.services.iam.resource_providers.aws_iam_managedpolicy_plugin:IAMManagedPolicyProviderPlugin", "AWS::Events::EventBusPolicy=localstack.services.events.resource_providers.aws_events_eventbuspolicy_plugin:EventsEventBusPolicyProviderPlugin", "AWS::EC2::VPC=localstack.services.ec2.resource_providers.aws_ec2_vpc_plugin:EC2VPCProviderPlugin", "AWS::EC2::NatGateway=localstack.services.ec2.resource_providers.aws_ec2_natgateway_plugin:EC2NatGatewayProviderPlugin", "AWS::ApiGateway::Account=localstack.services.apigateway.resource_providers.aws_apigateway_account_plugin:ApiGatewayAccountProviderPlugin", "AWS::IAM::Group=localstack.services.iam.resource_providers.aws_iam_group_plugin:IAMGroupProviderPlugin", "AWS::CloudFormation::WaitConditionHandle=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitconditionhandle_plugin:CloudFormationWaitConditionHandleProviderPlugin", "AWS::SNS::Subscription=localstack.services.sns.resource_providers.aws_sns_subscription_plugin:SNSSubscriptionProviderPlugin", "AWS::Route53::RecordSet=localstack.services.route53.resource_providers.aws_route53_recordset_plugin:Route53RecordSetProviderPlugin", "AWS::Lambda::Function=localstack.services.lambda_.resource_providers.aws_lambda_function_plugin:LambdaFunctionProviderPlugin", "AWS::Lambda::Alias=localstack.services.lambda_.resource_providers.lambda_alias_plugin:LambdaAliasProviderPlugin", "AWS::Events::ApiDestination=localstack.services.events.resource_providers.aws_events_apidestination_plugin:EventsApiDestinationProviderPlugin", "AWS::Kinesis::Stream=localstack.services.kinesis.resource_providers.aws_kinesis_stream_plugin:KinesisStreamProviderPlugin", "AWS::EC2::InternetGateway=localstack.services.ec2.resource_providers.aws_ec2_internetgateway_plugin:EC2InternetGatewayProviderPlugin", "AWS::Logs::LogGroup=localstack.services.logs.resource_providers.aws_logs_loggroup_plugin:LogsLogGroupProviderPlugin", "AWS::ApiGateway::UsagePlanKey=localstack.services.apigateway.resource_providers.aws_apigateway_usageplankey_plugin:ApiGatewayUsagePlanKeyProviderPlugin", "AWS::EC2::Subnet=localstack.services.ec2.resource_providers.aws_ec2_subnet_plugin:EC2SubnetProviderPlugin", "AWS::Lambda::LayerVersionPermission=localstack.services.lambda_.resource_providers.aws_lambda_layerversionpermission_plugin:LambdaLayerVersionPermissionProviderPlugin", "AWS::IAM::ServerCertificate=localstack.services.iam.resource_providers.aws_iam_servercertificate_plugin:IAMServerCertificateProviderPlugin", "AWS::CloudWatch::Alarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_alarm_plugin:CloudWatchAlarmProviderPlugin", "AWS::ApiGateway::ApiKey=localstack.services.apigateway.resource_providers.aws_apigateway_apikey_plugin:ApiGatewayApiKeyProviderPlugin", "AWS::ApiGateway::Model=localstack.services.apigateway.resource_providers.aws_apigateway_model_plugin:ApiGatewayModelProviderPlugin", "AWS::CloudWatch::CompositeAlarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_compositealarm_plugin:CloudWatchCompositeAlarmProviderPlugin", "AWS::OpenSearchService::Domain=localstack.services.opensearch.resource_providers.aws_opensearchservice_domain_plugin:OpenSearchServiceDomainProviderPlugin", "AWS::SecretsManager::RotationSchedule=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_rotationschedule_plugin:SecretsManagerRotationScheduleProviderPlugin", "AWS::ApiGateway::Method=localstack.services.apigateway.resource_providers.aws_apigateway_method_plugin:ApiGatewayMethodProviderPlugin", "AWS::DynamoDB::GlobalTable=localstack.services.dynamodb.resource_providers.aws_dynamodb_globaltable_plugin:DynamoDBGlobalTableProviderPlugin", "AWS::Lambda::CodeSigningConfig=localstack.services.lambda_.resource_providers.aws_lambda_codesigningconfig_plugin:LambdaCodeSigningConfigProviderPlugin", "AWS::SSM::Parameter=localstack.services.ssm.resource_providers.aws_ssm_parameter_plugin:SSMParameterProviderPlugin", "AWS::EC2::NetworkAcl=localstack.services.ec2.resource_providers.aws_ec2_networkacl_plugin:EC2NetworkAclProviderPlugin", "AWS::SSM::MaintenanceWindowTarget=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtarget_plugin:SSMMaintenanceWindowTargetProviderPlugin", "AWS::IAM::InstanceProfile=localstack.services.iam.resource_providers.aws_iam_instanceprofile_plugin:IAMInstanceProfileProviderPlugin", "AWS::EC2::KeyPair=localstack.services.ec2.resource_providers.aws_ec2_keypair_plugin:EC2KeyPairProviderPlugin", "AWS::ECR::Repository=localstack.services.ecr.resource_providers.aws_ecr_repository_plugin:ECRRepositoryProviderPlugin", "AWS::DynamoDB::Table=localstack.services.dynamodb.resource_providers.aws_dynamodb_table_plugin:DynamoDBTableProviderPlugin", "AWS::SecretsManager::SecretTargetAttachment=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secrettargetattachment_plugin:SecretsManagerSecretTargetAttachmentProviderPlugin", "AWS::KMS::Key=localstack.services.kms.resource_providers.aws_kms_key_plugin:KMSKeyProviderPlugin", "AWS::SSM::MaintenanceWindowTask=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtask_plugin:SSMMaintenanceWindowTaskProviderPlugin", "AWS::Scheduler::Schedule=localstack.services.scheduler.resource_providers.aws_scheduler_schedule_plugin:SchedulerScheduleProviderPlugin", "AWS::EC2::DHCPOptions=localstack.services.ec2.resource_providers.aws_ec2_dhcpoptions_plugin:EC2DHCPOptionsProviderPlugin", "AWS::SQS::Queue=localstack.services.sqs.resource_providers.aws_sqs_queue_plugin:SQSQueueProviderPlugin", "AWS::ApiGateway::RequestValidator=localstack.services.apigateway.resource_providers.aws_apigateway_requestvalidator_plugin:ApiGatewayRequestValidatorProviderPlugin", "AWS::SSM::MaintenanceWindow=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindow_plugin:SSMMaintenanceWindowProviderPlugin", "AWS::ApiGateway::Stage=localstack.services.apigateway.resource_providers.aws_apigateway_stage_plugin:ApiGatewayStageProviderPlugin", "AWS::SSM::PatchBaseline=localstack.services.ssm.resource_providers.aws_ssm_patchbaseline_plugin:SSMPatchBaselineProviderPlugin", "AWS::CDK::Metadata=localstack.services.cdk.resource_providers.cdk_metadata_plugin:LambdaAliasProviderPlugin", "AWS::StepFunctions::Activity=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_activity_plugin:StepFunctionsActivityProviderPlugin", "AWS::SNS::Topic=localstack.services.sns.resource_providers.aws_sns_topic_plugin:SNSTopicProviderPlugin", "AWS::S3::Bucket=localstack.services.s3.resource_providers.aws_s3_bucket_plugin:S3BucketProviderPlugin", "AWS::CertificateManager::Certificate=localstack.services.certificatemanager.resource_providers.aws_certificatemanager_certificate_plugin:CertificateManagerCertificateProviderPlugin", "AWS::EC2::SecurityGroup=localstack.services.ec2.resource_providers.aws_ec2_securitygroup_plugin:EC2SecurityGroupProviderPlugin", "AWS::S3::BucketPolicy=localstack.services.s3.resource_providers.aws_s3_bucketpolicy_plugin:S3BucketPolicyProviderPlugin", "AWS::Events::EventBus=localstack.services.events.resource_providers.aws_events_eventbus_plugin:EventsEventBusProviderPlugin", "AWS::Lambda::Version=localstack.services.lambda_.resource_providers.aws_lambda_version_plugin:LambdaVersionProviderPlugin", "AWS::SES::EmailIdentity=localstack.services.ses.resource_providers.aws_ses_emailidentity_plugin:SESEmailIdentityProviderPlugin", "AWS::ApiGateway::RestApi=localstack.services.apigateway.resource_providers.aws_apigateway_restapi_plugin:ApiGatewayRestApiProviderPlugin", "AWS::CloudFormation::Macro=localstack.services.cloudformation.resource_providers.aws_cloudformation_macro_plugin:CloudFormationMacroProviderPlugin", "AWS::Lambda::EventInvokeConfig=localstack.services.lambda_.resource_providers.aws_lambda_eventinvokeconfig_plugin:LambdaEventInvokeConfigProviderPlugin", "AWS::Events::Rule=localstack.services.events.resource_providers.aws_events_rule_plugin:EventsRuleProviderPlugin", "AWS::ApiGateway::GatewayResponse=localstack.services.apigateway.resource_providers.aws_apigateway_gatewayresponse_plugin:ApiGatewayGatewayResponseProviderPlugin", "AWS::IAM::Role=localstack.services.iam.resource_providers.aws_iam_role_plugin:IAMRoleProviderPlugin", "AWS::CloudFormation::WaitCondition=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitcondition_plugin:CloudFormationWaitConditionProviderPlugin", "AWS::StepFunctions::StateMachine=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_statemachine_plugin:StepFunctionsStateMachineProviderPlugin", "AWS::Scheduler::ScheduleGroup=localstack.services.scheduler.resource_providers.aws_scheduler_schedulegroup_plugin:SchedulerScheduleGroupProviderPlugin", "AWS::EC2::TransitGateway=localstack.services.ec2.resource_providers.aws_ec2_transitgateway_plugin:EC2TransitGatewayProviderPlugin", "AWS::Kinesis::StreamConsumer=localstack.services.kinesis.resource_providers.aws_kinesis_streamconsumer_plugin:KinesisStreamConsumerProviderPlugin", "AWS::SecretsManager::Secret=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secret_plugin:SecretsManagerSecretProviderPlugin", "AWS::EC2::VPCGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_vpcgatewayattachment_plugin:EC2VPCGatewayAttachmentProviderPlugin"], "localstack.hooks.configure_localstack_container": ["_mount_machine_file=localstack.utils.analytics.metadata:_mount_machine_file"], "localstack.hooks.prepare_host": ["prepare_host_machine_id=localstack.utils.analytics.metadata:prepare_host_machine_id"], "localstack.hooks.on_infra_shutdown": ["run_on_after_service_shutdown_handlers=localstack.runtime.shutdown:run_on_after_service_shutdown_handlers", "run_shutdown_handlers=localstack.runtime.shutdown:run_shutdown_handlers", "shutdown_services=localstack.runtime.shutdown:shutdown_services", "stop_server=localstack.dns.plugins:stop_server", "publish_metrics=localstack.utils.analytics.metrics.publisher:publish_metrics", "_run_init_scripts_on_shutdown=localstack.runtime.init:_run_init_scripts_on_shutdown", "remove_custom_endpoints=localstack.services.lambda_.plugins:remove_custom_endpoints"], "localstack.hooks.on_infra_start": ["setup_dns_configuration_on_host=localstack.dns.plugins:setup_dns_configuration_on_host", "start_dns_server=localstack.dns.plugins:start_dns_server", "conditionally_enable_debugger=localstack.dev.debugger.plugins:conditionally_enable_debugger", "apply_runtime_patches=localstack.runtime.patches:apply_runtime_patches", "eager_load_services=localstack.services.plugins:eager_load_services", "delete_cached_certificate=localstack.plugins:delete_cached_certificate", "deprecation_warnings=localstack.plugins:deprecation_warnings", "_publish_config_as_analytics_event=localstack.runtime.analytics:_publish_config_as_analytics_event", "_publish_container_info=localstack.runtime.analytics:_publish_container_info", "_patch_botocore_endpoint_in_memory=localstack.aws.client:_patch_botocore_endpoint_in_memory", "_patch_botocore_json_parser=localstack.aws.client:_patch_botocore_json_parser", "_patch_cbor2=localstack.aws.client:_patch_cbor2", "_run_init_scripts_on_start=localstack.runtime.init:_run_init_scripts_on_start", "register_swagger_endpoints=localstack.http.resources.swagger.plugins:register_swagger_endpoints", "register_cloudformation_deploy_ui=localstack.services.cloudformation.plugins:register_cloudformation_deploy_ui", "apply_aws_runtime_patches=localstack.aws.patches:apply_aws_runtime_patches", "register_custom_endpoints=localstack.services.lambda_.plugins:register_custom_endpoints", "validate_configuration=localstack.services.lambda_.plugins:validate_configuration"], "localstack.packages": ["kinesis-mock/community=localstack.services.kinesis.plugins:kinesismock_package", "opensearch/community=localstack.services.opensearch.plugins:opensearch_package", "dynamodb-local/community=localstack.services.dynamodb.plugins:dynamodb_local_package", "ffmpeg/community=localstack.packages.plugins:ffmpeg_package", "java/community=localstack.packages.plugins:java_package", "terraform/community=localstack.packages.plugins:terraform_package", "vosk/community=localstack.services.transcribe.plugins:vosk_package", "elasticsearch/community=localstack.services.es.plugins:elasticsearch_package", "jpype-jsonata/community=localstack.services.stepfunctions.plugins:jpype_jsonata_package", "lambda-java-libs/community=localstack.services.lambda_.plugins:lambda_java_libs", "lambda-runtime/community=localstack.services.lambda_.plugins:lambda_runtime_package"], "localstack.runtime.server": ["hypercorn=localstack.runtime.server.plugins:HypercornRuntimeServerPlugin", "twisted=localstack.runtime.server.plugins:TwistedRuntimeServerPlugin"], "localstack.openapi.spec": ["localstack=localstack.plugins:CoreOASPlugin"], "localstack.aws.provider": ["acm:default=localstack.services.providers:acm", "apigateway:default=localstack.services.providers:apigateway", "apigateway:legacy=localstack.services.providers:apigateway_legacy", "apigateway:next_gen=localstack.services.providers:apigateway_next_gen", "config:default=localstack.services.providers:awsconfig", "cloudformation:default=localstack.services.providers:cloudformation", "cloudformation:engine-v2=localstack.services.providers:cloudformation_v2", "cloudwatch:default=localstack.services.providers:cloudwatch", "cloudwatch:v1=localstack.services.providers:cloudwatch_v1", "cloudwatch:v2=localstack.services.providers:cloudwatch_v2", "dynamodb:default=localstack.services.providers:dynamodb", "dynamodb:v2=localstack.services.providers:dynamodb_v2", "dynamodbstreams:default=localstack.services.providers:dynamodbstreams", "dynamodbstreams:v2=localstack.services.providers:dynamodbstreams_v2", "ec2:default=localstack.services.providers:ec2", "es:default=localstack.services.providers:es", "events:default=localstack.services.providers:events", "events:legacy=localstack.services.providers:events_legacy", "events:v1=localstack.services.providers:events_v1", "events:v2=localstack.services.providers:events_v2", "firehose:default=localstack.services.providers:firehose", "iam:default=localstack.services.providers:iam", "kinesis:default=localstack.services.providers:kinesis", "kms:default=localstack.services.providers:kms", "lambda:default=localstack.services.providers:lambda_", "lambda:asf=localstack.services.providers:lambda_asf", "lambda:v2=localstack.services.providers:lambda_v2", "logs:default=localstack.services.providers:logs", "opensearch:default=localstack.services.providers:opensearch", "redshift:default=localstack.services.providers:redshift", "resource-groups:default=localstack.services.providers:resource_groups", "resourcegroupstaggingapi:default=localstack.services.providers:resourcegroupstaggingapi", "route53:default=localstack.services.providers:route53", "route53resolver:default=localstack.services.providers:route53resolver", "s3:default=localstack.services.providers:s3", "s3control:default=localstack.services.providers:s3control", "scheduler:default=localstack.services.providers:scheduler", "secretsmanager:default=localstack.services.providers:secretsmanager", "ses:default=localstack.services.providers:ses", "sns:default=localstack.services.providers:sns", "sqs:default=localstack.services.providers:sqs", "ssm:default=localstack.services.providers:ssm", "stepfunctions:default=localstack.services.providers:stepfunctions", "stepfunctions:v2=localstack.services.providers:stepfunctions_v2", "sts:default=localstack.services.providers:sts", "support:default=localstack.services.providers:support", "swf:default=localstack.services.providers:swf", "transcribe:default=localstack.services.providers:transcribe"], "localstack.init.runner": ["py=localstack.runtime.init:PythonScriptRunner", "sh=localstack.runtime.init:ShellScriptRunner"], "localstack.hooks.on_infra_ready": ["_run_init_scripts_on_ready=localstack.runtime.init:_run_init_scripts_on_ready"], "localstack.lambda.runtime_executor": ["docker=localstack.services.lambda_.invocation.plugins:DockerRuntimeExecutorPlugin"], "localstack.runtime.components": ["aws=localstack.aws.components:AwsComponents"]}
@@ -1 +0,0 @@
1
- {"localstack.cloudformation.resource_providers": ["AWS::SSM::MaintenanceWindow=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindow_plugin:SSMMaintenanceWindowProviderPlugin", "AWS::CloudFormation::WaitConditionHandle=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitconditionhandle_plugin:CloudFormationWaitConditionHandleProviderPlugin", "AWS::S3::BucketPolicy=localstack.services.s3.resource_providers.aws_s3_bucketpolicy_plugin:S3BucketPolicyProviderPlugin", "AWS::SQS::QueuePolicy=localstack.services.sqs.resource_providers.aws_sqs_queuepolicy_plugin:SQSQueuePolicyProviderPlugin", "AWS::OpenSearchService::Domain=localstack.services.opensearch.resource_providers.aws_opensearchservice_domain_plugin:OpenSearchServiceDomainProviderPlugin", "AWS::CDK::Metadata=localstack.services.cdk.resource_providers.cdk_metadata_plugin:LambdaAliasProviderPlugin", "AWS::StepFunctions::StateMachine=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_statemachine_plugin:StepFunctionsStateMachineProviderPlugin", "AWS::CloudWatch::Alarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_alarm_plugin:CloudWatchAlarmProviderPlugin", "AWS::CertificateManager::Certificate=localstack.services.certificatemanager.resource_providers.aws_certificatemanager_certificate_plugin:CertificateManagerCertificateProviderPlugin", "AWS::SNS::Subscription=localstack.services.sns.resource_providers.aws_sns_subscription_plugin:SNSSubscriptionProviderPlugin", "AWS::SQS::Queue=localstack.services.sqs.resource_providers.aws_sqs_queue_plugin:SQSQueueProviderPlugin", "AWS::Lambda::Function=localstack.services.lambda_.resource_providers.aws_lambda_function_plugin:LambdaFunctionProviderPlugin", "AWS::Redshift::Cluster=localstack.services.redshift.resource_providers.aws_redshift_cluster_plugin:RedshiftClusterProviderPlugin", "AWS::ECR::Repository=localstack.services.ecr.resource_providers.aws_ecr_repository_plugin:ECRRepositoryProviderPlugin", "AWS::IAM::AccessKey=localstack.services.iam.resource_providers.aws_iam_accesskey_plugin:IAMAccessKeyProviderPlugin", "AWS::Logs::LogGroup=localstack.services.logs.resource_providers.aws_logs_loggroup_plugin:LogsLogGroupProviderPlugin", "AWS::Lambda::EventInvokeConfig=localstack.services.lambda_.resource_providers.aws_lambda_eventinvokeconfig_plugin:LambdaEventInvokeConfigProviderPlugin", "AWS::IAM::User=localstack.services.iam.resource_providers.aws_iam_user_plugin:IAMUserProviderPlugin", "AWS::ApiGateway::Deployment=localstack.services.apigateway.resource_providers.aws_apigateway_deployment_plugin:ApiGatewayDeploymentProviderPlugin", "AWS::SES::EmailIdentity=localstack.services.ses.resource_providers.aws_ses_emailidentity_plugin:SESEmailIdentityProviderPlugin", "AWS::SNS::Topic=localstack.services.sns.resource_providers.aws_sns_topic_plugin:SNSTopicProviderPlugin", "AWS::EC2::TransitGateway=localstack.services.ec2.resource_providers.aws_ec2_transitgateway_plugin:EC2TransitGatewayProviderPlugin", "AWS::Route53::HealthCheck=localstack.services.route53.resource_providers.aws_route53_healthcheck_plugin:Route53HealthCheckProviderPlugin", "AWS::CloudFormation::Stack=localstack.services.cloudformation.resource_providers.aws_cloudformation_stack_plugin:CloudFormationStackProviderPlugin", "AWS::SSM::MaintenanceWindowTarget=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtarget_plugin:SSMMaintenanceWindowTargetProviderPlugin", "AWS::Lambda::CodeSigningConfig=localstack.services.lambda_.resource_providers.aws_lambda_codesigningconfig_plugin:LambdaCodeSigningConfigProviderPlugin", "AWS::Kinesis::StreamConsumer=localstack.services.kinesis.resource_providers.aws_kinesis_streamconsumer_plugin:KinesisStreamConsumerProviderPlugin", "AWS::Lambda::Alias=localstack.services.lambda_.resource_providers.lambda_alias_plugin:LambdaAliasProviderPlugin", "AWS::Lambda::LayerVersion=localstack.services.lambda_.resource_providers.aws_lambda_layerversion_plugin:LambdaLayerVersionProviderPlugin", "AWS::ApiGateway::UsagePlanKey=localstack.services.apigateway.resource_providers.aws_apigateway_usageplankey_plugin:ApiGatewayUsagePlanKeyProviderPlugin", "AWS::ApiGateway::GatewayResponse=localstack.services.apigateway.resource_providers.aws_apigateway_gatewayresponse_plugin:ApiGatewayGatewayResponseProviderPlugin", "AWS::SecretsManager::Secret=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secret_plugin:SecretsManagerSecretProviderPlugin", "AWS::ApiGateway::UsagePlan=localstack.services.apigateway.resource_providers.aws_apigateway_usageplan_plugin:ApiGatewayUsagePlanProviderPlugin", "AWS::EC2::KeyPair=localstack.services.ec2.resource_providers.aws_ec2_keypair_plugin:EC2KeyPairProviderPlugin", "AWS::ApiGateway::DomainName=localstack.services.apigateway.resource_providers.aws_apigateway_domainname_plugin:ApiGatewayDomainNameProviderPlugin", "AWS::KinesisFirehose::DeliveryStream=localstack.services.kinesisfirehose.resource_providers.aws_kinesisfirehose_deliverystream_plugin:KinesisFirehoseDeliveryStreamProviderPlugin", "AWS::Scheduler::ScheduleGroup=localstack.services.scheduler.resource_providers.aws_scheduler_schedulegroup_plugin:SchedulerScheduleGroupProviderPlugin", "AWS::IAM::InstanceProfile=localstack.services.iam.resource_providers.aws_iam_instanceprofile_plugin:IAMInstanceProfileProviderPlugin", "AWS::ApiGateway::Model=localstack.services.apigateway.resource_providers.aws_apigateway_model_plugin:ApiGatewayModelProviderPlugin", "AWS::EC2::RouteTable=localstack.services.ec2.resource_providers.aws_ec2_routetable_plugin:EC2RouteTableProviderPlugin", "AWS::IAM::ServiceLinkedRole=localstack.services.iam.resource_providers.aws_iam_servicelinkedrole_plugin:IAMServiceLinkedRoleProviderPlugin", "AWS::EC2::Route=localstack.services.ec2.resource_providers.aws_ec2_route_plugin:EC2RouteProviderPlugin", "AWS::S3::Bucket=localstack.services.s3.resource_providers.aws_s3_bucket_plugin:S3BucketProviderPlugin", "AWS::KMS::Alias=localstack.services.kms.resource_providers.aws_kms_alias_plugin:KMSAliasProviderPlugin", "AWS::ApiGateway::Resource=localstack.services.apigateway.resource_providers.aws_apigateway_resource_plugin:ApiGatewayResourceProviderPlugin", "AWS::StepFunctions::Activity=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_activity_plugin:StepFunctionsActivityProviderPlugin", "AWS::CloudFormation::WaitCondition=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitcondition_plugin:CloudFormationWaitConditionProviderPlugin", "AWS::Logs::LogStream=localstack.services.logs.resource_providers.aws_logs_logstream_plugin:LogsLogStreamProviderPlugin", "AWS::Scheduler::Schedule=localstack.services.scheduler.resource_providers.aws_scheduler_schedule_plugin:SchedulerScheduleProviderPlugin", "AWS::DynamoDB::GlobalTable=localstack.services.dynamodb.resource_providers.aws_dynamodb_globaltable_plugin:DynamoDBGlobalTableProviderPlugin", "AWS::IAM::ManagedPolicy=localstack.services.iam.resource_providers.aws_iam_managedpolicy_plugin:IAMManagedPolicyProviderPlugin", "AWS::SSM::MaintenanceWindowTask=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtask_plugin:SSMMaintenanceWindowTaskProviderPlugin", "AWS::Route53::RecordSet=localstack.services.route53.resource_providers.aws_route53_recordset_plugin:Route53RecordSetProviderPlugin", "AWS::EC2::SubnetRouteTableAssociation=localstack.services.ec2.resource_providers.aws_ec2_subnetroutetableassociation_plugin:EC2SubnetRouteTableAssociationProviderPlugin", "AWS::Events::Rule=localstack.services.events.resource_providers.aws_events_rule_plugin:EventsRuleProviderPlugin", "AWS::CloudFormation::Macro=localstack.services.cloudformation.resource_providers.aws_cloudformation_macro_plugin:CloudFormationMacroProviderPlugin", "AWS::DynamoDB::Table=localstack.services.dynamodb.resource_providers.aws_dynamodb_table_plugin:DynamoDBTableProviderPlugin", "AWS::ApiGateway::BasePathMapping=localstack.services.apigateway.resource_providers.aws_apigateway_basepathmapping_plugin:ApiGatewayBasePathMappingProviderPlugin", "AWS::IAM::Role=localstack.services.iam.resource_providers.aws_iam_role_plugin:IAMRoleProviderPlugin", "AWS::ApiGateway::Method=localstack.services.apigateway.resource_providers.aws_apigateway_method_plugin:ApiGatewayMethodProviderPlugin", "AWS::IAM::ServerCertificate=localstack.services.iam.resource_providers.aws_iam_servercertificate_plugin:IAMServerCertificateProviderPlugin", "AWS::EC2::VPCEndpoint=localstack.services.ec2.resource_providers.aws_ec2_vpcendpoint_plugin:EC2VPCEndpointProviderPlugin", "AWS::EC2::NatGateway=localstack.services.ec2.resource_providers.aws_ec2_natgateway_plugin:EC2NatGatewayProviderPlugin", "AWS::EC2::Instance=localstack.services.ec2.resource_providers.aws_ec2_instance_plugin:EC2InstanceProviderPlugin", "AWS::EC2::SecurityGroup=localstack.services.ec2.resource_providers.aws_ec2_securitygroup_plugin:EC2SecurityGroupProviderPlugin", "AWS::IAM::Policy=localstack.services.iam.resource_providers.aws_iam_policy_plugin:IAMPolicyProviderPlugin", "AWS::SecretsManager::SecretTargetAttachment=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secrettargetattachment_plugin:SecretsManagerSecretTargetAttachmentProviderPlugin", "AWS::Events::EventBusPolicy=localstack.services.events.resource_providers.aws_events_eventbuspolicy_plugin:EventsEventBusPolicyProviderPlugin", "AWS::Lambda::Permission=localstack.services.lambda_.resource_providers.aws_lambda_permission_plugin:LambdaPermissionProviderPlugin", "AWS::Lambda::LayerVersionPermission=localstack.services.lambda_.resource_providers.aws_lambda_layerversionpermission_plugin:LambdaLayerVersionPermissionProviderPlugin", "AWS::ApiGateway::ApiKey=localstack.services.apigateway.resource_providers.aws_apigateway_apikey_plugin:ApiGatewayApiKeyProviderPlugin", "AWS::Elasticsearch::Domain=localstack.services.opensearch.resource_providers.aws_elasticsearch_domain_plugin:ElasticsearchDomainProviderPlugin", "AWS::ApiGateway::RestApi=localstack.services.apigateway.resource_providers.aws_apigateway_restapi_plugin:ApiGatewayRestApiProviderPlugin", "AWS::Events::ApiDestination=localstack.services.events.resource_providers.aws_events_apidestination_plugin:EventsApiDestinationProviderPlugin", "AWS::ApiGateway::Account=localstack.services.apigateway.resource_providers.aws_apigateway_account_plugin:ApiGatewayAccountProviderPlugin", "AWS::CloudWatch::CompositeAlarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_compositealarm_plugin:CloudWatchCompositeAlarmProviderPlugin", "AWS::Events::Connection=localstack.services.events.resource_providers.aws_events_connection_plugin:EventsConnectionProviderPlugin", "AWS::Kinesis::Stream=localstack.services.kinesis.resource_providers.aws_kinesis_stream_plugin:KinesisStreamProviderPlugin", "AWS::Lambda::Url=localstack.services.lambda_.resource_providers.aws_lambda_url_plugin:LambdaUrlProviderPlugin", "AWS::SSM::Parameter=localstack.services.ssm.resource_providers.aws_ssm_parameter_plugin:SSMParameterProviderPlugin", "AWS::EC2::NetworkAcl=localstack.services.ec2.resource_providers.aws_ec2_networkacl_plugin:EC2NetworkAclProviderPlugin", "AWS::EC2::InternetGateway=localstack.services.ec2.resource_providers.aws_ec2_internetgateway_plugin:EC2InternetGatewayProviderPlugin", "AWS::ApiGateway::RequestValidator=localstack.services.apigateway.resource_providers.aws_apigateway_requestvalidator_plugin:ApiGatewayRequestValidatorProviderPlugin", "AWS::EC2::PrefixList=localstack.services.ec2.resource_providers.aws_ec2_prefixlist_plugin:EC2PrefixListProviderPlugin", "AWS::EC2::VPC=localstack.services.ec2.resource_providers.aws_ec2_vpc_plugin:EC2VPCProviderPlugin", "AWS::EC2::VPCGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_vpcgatewayattachment_plugin:EC2VPCGatewayAttachmentProviderPlugin", "AWS::ResourceGroups::Group=localstack.services.resource_groups.resource_providers.aws_resourcegroups_group_plugin:ResourceGroupsGroupProviderPlugin", "AWS::SNS::TopicPolicy=localstack.services.sns.resource_providers.aws_sns_topicpolicy_plugin:SNSTopicPolicyProviderPlugin", "AWS::Lambda::Version=localstack.services.lambda_.resource_providers.aws_lambda_version_plugin:LambdaVersionProviderPlugin", "AWS::ApiGateway::Stage=localstack.services.apigateway.resource_providers.aws_apigateway_stage_plugin:ApiGatewayStageProviderPlugin", "AWS::EC2::TransitGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_transitgatewayattachment_plugin:EC2TransitGatewayAttachmentProviderPlugin", "AWS::Logs::SubscriptionFilter=localstack.services.logs.resource_providers.aws_logs_subscriptionfilter_plugin:LogsSubscriptionFilterProviderPlugin", "AWS::KMS::Key=localstack.services.kms.resource_providers.aws_kms_key_plugin:KMSKeyProviderPlugin", "AWS::Lambda::EventSourceMapping=localstack.services.lambda_.resource_providers.aws_lambda_eventsourcemapping_plugin:LambdaEventSourceMappingProviderPlugin", "AWS::SSM::PatchBaseline=localstack.services.ssm.resource_providers.aws_ssm_patchbaseline_plugin:SSMPatchBaselineProviderPlugin", "AWS::IAM::Group=localstack.services.iam.resource_providers.aws_iam_group_plugin:IAMGroupProviderPlugin", "AWS::EC2::Subnet=localstack.services.ec2.resource_providers.aws_ec2_subnet_plugin:EC2SubnetProviderPlugin", "AWS::EC2::DHCPOptions=localstack.services.ec2.resource_providers.aws_ec2_dhcpoptions_plugin:EC2DHCPOptionsProviderPlugin", "AWS::Events::EventBus=localstack.services.events.resource_providers.aws_events_eventbus_plugin:EventsEventBusProviderPlugin", "AWS::SecretsManager::RotationSchedule=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_rotationschedule_plugin:SecretsManagerRotationScheduleProviderPlugin", "AWS::SecretsManager::ResourcePolicy=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_resourcepolicy_plugin:SecretsManagerResourcePolicyProviderPlugin"], "localstack.packages": ["vosk/community=localstack.services.transcribe.plugins:vosk_package", "jpype-jsonata/community=localstack.services.stepfunctions.plugins:jpype_jsonata_package", "dynamodb-local/community=localstack.services.dynamodb.plugins:dynamodb_local_package", "opensearch/community=localstack.services.opensearch.plugins:opensearch_package", "ffmpeg/community=localstack.packages.plugins:ffmpeg_package", "java/community=localstack.packages.plugins:java_package", "terraform/community=localstack.packages.plugins:terraform_package", "elasticsearch/community=localstack.services.es.plugins:elasticsearch_package", "lambda-java-libs/community=localstack.services.lambda_.plugins:lambda_java_libs", "lambda-runtime/community=localstack.services.lambda_.plugins:lambda_runtime_package", "kinesis-mock/community=localstack.services.kinesis.plugins:kinesismock_package"], "localstack.hooks.on_infra_start": ["register_swagger_endpoints=localstack.http.resources.swagger.plugins:register_swagger_endpoints", "eager_load_services=localstack.services.plugins:eager_load_services", "_publish_config_as_analytics_event=localstack.runtime.analytics:_publish_config_as_analytics_event", "_publish_container_info=localstack.runtime.analytics:_publish_container_info", "delete_cached_certificate=localstack.plugins:delete_cached_certificate", "deprecation_warnings=localstack.plugins:deprecation_warnings", "apply_runtime_patches=localstack.runtime.patches:apply_runtime_patches", "_patch_botocore_endpoint_in_memory=localstack.aws.client:_patch_botocore_endpoint_in_memory", "_patch_botocore_json_parser=localstack.aws.client:_patch_botocore_json_parser", "_patch_cbor2=localstack.aws.client:_patch_cbor2", "apply_aws_runtime_patches=localstack.aws.patches:apply_aws_runtime_patches", "register_custom_endpoints=localstack.services.lambda_.plugins:register_custom_endpoints", "validate_configuration=localstack.services.lambda_.plugins:validate_configuration", "register_cloudformation_deploy_ui=localstack.services.cloudformation.plugins:register_cloudformation_deploy_ui", "_run_init_scripts_on_start=localstack.runtime.init:_run_init_scripts_on_start", "conditionally_enable_debugger=localstack.dev.debugger.plugins:conditionally_enable_debugger", "setup_dns_configuration_on_host=localstack.dns.plugins:setup_dns_configuration_on_host", "start_dns_server=localstack.dns.plugins:start_dns_server"], "localstack.hooks.on_infra_shutdown": ["run_on_after_service_shutdown_handlers=localstack.runtime.shutdown:run_on_after_service_shutdown_handlers", "run_shutdown_handlers=localstack.runtime.shutdown:run_shutdown_handlers", "shutdown_services=localstack.runtime.shutdown:shutdown_services", "publish_metrics=localstack.utils.analytics.metrics.publisher:publish_metrics", "remove_custom_endpoints=localstack.services.lambda_.plugins:remove_custom_endpoints", "_run_init_scripts_on_shutdown=localstack.runtime.init:_run_init_scripts_on_shutdown", "stop_server=localstack.dns.plugins:stop_server"], "localstack.lambda.runtime_executor": ["docker=localstack.services.lambda_.invocation.plugins:DockerRuntimeExecutorPlugin"], "localstack.openapi.spec": ["localstack=localstack.plugins:CoreOASPlugin"], "localstack.runtime.server": ["hypercorn=localstack.runtime.server.plugins:HypercornRuntimeServerPlugin", "twisted=localstack.runtime.server.plugins:TwistedRuntimeServerPlugin"], "localstack.runtime.components": ["aws=localstack.aws.components:AwsComponents"], "localstack.hooks.configure_localstack_container": ["_mount_machine_file=localstack.utils.analytics.metadata:_mount_machine_file"], "localstack.hooks.prepare_host": ["prepare_host_machine_id=localstack.utils.analytics.metadata:prepare_host_machine_id"], "localstack.init.runner": ["py=localstack.runtime.init:PythonScriptRunner", "sh=localstack.runtime.init:ShellScriptRunner"], "localstack.hooks.on_infra_ready": ["_run_init_scripts_on_ready=localstack.runtime.init:_run_init_scripts_on_ready"], "localstack.aws.provider": ["acm:default=localstack.services.providers:acm", "apigateway:default=localstack.services.providers:apigateway", "apigateway:legacy=localstack.services.providers:apigateway_legacy", "apigateway:next_gen=localstack.services.providers:apigateway_next_gen", "config:default=localstack.services.providers:awsconfig", "cloudformation:default=localstack.services.providers:cloudformation", "cloudformation:engine-v2=localstack.services.providers:cloudformation_v2", "cloudwatch:default=localstack.services.providers:cloudwatch", "cloudwatch:v1=localstack.services.providers:cloudwatch_v1", "cloudwatch:v2=localstack.services.providers:cloudwatch_v2", "dynamodb:default=localstack.services.providers:dynamodb", "dynamodb:v2=localstack.services.providers:dynamodb_v2", "dynamodbstreams:default=localstack.services.providers:dynamodbstreams", "dynamodbstreams:v2=localstack.services.providers:dynamodbstreams_v2", "ec2:default=localstack.services.providers:ec2", "es:default=localstack.services.providers:es", "events:default=localstack.services.providers:events", "events:legacy=localstack.services.providers:events_legacy", "events:v1=localstack.services.providers:events_v1", "events:v2=localstack.services.providers:events_v2", "firehose:default=localstack.services.providers:firehose", "iam:default=localstack.services.providers:iam", "kinesis:default=localstack.services.providers:kinesis", "kms:default=localstack.services.providers:kms", "lambda:default=localstack.services.providers:lambda_", "lambda:asf=localstack.services.providers:lambda_asf", "lambda:v2=localstack.services.providers:lambda_v2", "logs:default=localstack.services.providers:logs", "opensearch:default=localstack.services.providers:opensearch", "redshift:default=localstack.services.providers:redshift", "resource-groups:default=localstack.services.providers:resource_groups", "resourcegroupstaggingapi:default=localstack.services.providers:resourcegroupstaggingapi", "route53:default=localstack.services.providers:route53", "route53resolver:default=localstack.services.providers:route53resolver", "s3:default=localstack.services.providers:s3", "s3control:default=localstack.services.providers:s3control", "scheduler:default=localstack.services.providers:scheduler", "secretsmanager:default=localstack.services.providers:secretsmanager", "ses:default=localstack.services.providers:ses", "sns:default=localstack.services.providers:sns", "sqs:default=localstack.services.providers:sqs", "ssm:default=localstack.services.providers:ssm", "stepfunctions:default=localstack.services.providers:stepfunctions", "stepfunctions:v2=localstack.services.providers:stepfunctions_v2", "sts:default=localstack.services.providers:sts", "support:default=localstack.services.providers:support", "swf:default=localstack.services.providers:swf", "transcribe:default=localstack.services.providers:transcribe"]}