localstack-core 4.6.1.dev74__py3-none-any.whl → 4.10.1.dev7__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.

Potentially problematic release.


This version of localstack-core might be problematic. Click here for more details.

Files changed (672) hide show
  1. localstack/aws/api/apigateway/__init__.py +87 -110
  2. localstack/aws/api/cloudformation/__init__.py +18 -4
  3. localstack/aws/api/cloudwatch/__init__.py +41 -1
  4. localstack/aws/api/config/__init__.py +4 -0
  5. localstack/aws/api/core.py +8 -5
  6. localstack/aws/api/dynamodb/__init__.py +30 -0
  7. localstack/aws/api/ec2/__init__.py +1524 -64
  8. localstack/aws/api/events/__init__.py +12 -16
  9. localstack/aws/api/iam/__init__.py +7 -0
  10. localstack/aws/api/kinesis/__init__.py +19 -0
  11. localstack/aws/api/kms/__init__.py +6 -0
  12. localstack/aws/api/lambda_/__init__.py +13 -0
  13. localstack/aws/api/logs/__init__.py +20 -8
  14. localstack/aws/api/opensearch/__init__.py +16 -0
  15. localstack/aws/api/pipes/__init__.py +24 -32
  16. localstack/aws/api/redshift/__init__.py +9 -3
  17. localstack/aws/api/route53/__init__.py +5 -0
  18. localstack/aws/api/s3/__init__.py +12 -0
  19. localstack/aws/api/s3control/__init__.py +56 -0
  20. localstack/aws/api/scheduler/__init__.py +14 -16
  21. localstack/aws/api/ssm/__init__.py +2 -0
  22. localstack/aws/api/stepfunctions/__init__.py +88 -114
  23. localstack/aws/api/support/__init__.py +8 -9
  24. localstack/aws/api/transcribe/__init__.py +17 -0
  25. localstack/aws/chain.py +2 -2
  26. localstack/aws/client.py +14 -11
  27. localstack/aws/connect.py +42 -41
  28. localstack/aws/forwarder.py +57 -9
  29. localstack/aws/gateway.py +1 -3
  30. localstack/aws/handlers/analytics.py +2 -3
  31. localstack/aws/handlers/cors.py +4 -5
  32. localstack/aws/handlers/internal_requests.py +6 -1
  33. localstack/aws/handlers/logging.py +13 -4
  34. localstack/aws/handlers/metric_handler.py +44 -5
  35. localstack/aws/handlers/service.py +48 -28
  36. localstack/aws/mocking.py +18 -27
  37. localstack/aws/patches.py +2 -2
  38. localstack/aws/protocol/op_router.py +11 -10
  39. localstack/aws/protocol/parser.py +475 -49
  40. localstack/aws/protocol/serializer.py +723 -106
  41. localstack/aws/protocol/service_router.py +133 -33
  42. localstack/aws/protocol/validate.py +6 -6
  43. localstack/aws/scaffold.py +9 -10
  44. localstack/aws/serving/edge.py +5 -6
  45. localstack/aws/serving/hypercorn.py +2 -2
  46. localstack/aws/serving/twisted.py +1 -2
  47. localstack/aws/serving/werkzeug.py +2 -2
  48. localstack/aws/skeleton.py +12 -11
  49. localstack/aws/spec-patches.json +58 -0
  50. localstack/aws/spec.py +66 -46
  51. localstack/cli/exceptions.py +1 -1
  52. localstack/cli/localstack.py +11 -11
  53. localstack/cli/lpm.py +4 -5
  54. localstack/cli/plugins.py +1 -1
  55. localstack/cli/profiles.py +1 -2
  56. localstack/config.py +40 -31
  57. localstack/constants.py +4 -29
  58. localstack/deprecations.py +5 -5
  59. localstack/dev/kubernetes/__main__.py +85 -5
  60. localstack/dev/run/__main__.py +5 -5
  61. localstack/dev/run/configurators.py +1 -4
  62. localstack/dev/run/paths.py +6 -6
  63. localstack/dns/models.py +2 -1
  64. localstack/dns/plugins.py +5 -1
  65. localstack/dns/server.py +16 -6
  66. localstack/http/dispatcher.py +1 -2
  67. localstack/http/response.py +2 -2
  68. localstack/http/router.py +1 -1
  69. localstack/http/trace.py +2 -1
  70. localstack/logging/format.py +6 -6
  71. localstack/packages/api.py +13 -12
  72. localstack/packages/core.py +4 -4
  73. localstack/packages/debugpy.py +1 -3
  74. localstack/packages/ffmpeg.py +1 -2
  75. localstack/packages/java.py +38 -12
  76. localstack/packages/plugins.py +0 -8
  77. localstack/runtime/analytics.py +3 -0
  78. localstack/runtime/hooks.py +1 -1
  79. localstack/runtime/init.py +8 -9
  80. localstack/runtime/main.py +5 -5
  81. localstack/runtime/patches.py +2 -2
  82. localstack/runtime/shutdown.py +2 -1
  83. localstack/services/apigateway/exporter.py +1 -2
  84. localstack/services/apigateway/helpers.py +7 -10
  85. localstack/services/apigateway/legacy/context.py +21 -21
  86. localstack/services/apigateway/legacy/helpers.py +27 -28
  87. localstack/services/apigateway/legacy/integration.py +11 -10
  88. localstack/services/apigateway/legacy/invocations.py +6 -5
  89. localstack/services/apigateway/legacy/provider.py +148 -68
  90. localstack/services/apigateway/legacy/router_asf.py +2 -2
  91. localstack/services/apigateway/legacy/templates.py +6 -6
  92. localstack/services/apigateway/models.py +16 -16
  93. localstack/services/apigateway/next_gen/execute_api/api.py +2 -2
  94. localstack/services/apigateway/next_gen/execute_api/context.py +25 -25
  95. localstack/services/apigateway/next_gen/execute_api/handlers/api_key_validation.py +2 -5
  96. localstack/services/apigateway/next_gen/execute_api/handlers/method_request.py +7 -2
  97. localstack/services/apigateway/next_gen/execute_api/handlers/parse.py +1 -2
  98. localstack/services/apigateway/next_gen/execute_api/handlers/resource_router.py +2 -3
  99. localstack/services/apigateway/next_gen/execute_api/header_utils.py +1 -1
  100. localstack/services/apigateway/next_gen/execute_api/helpers.py +2 -2
  101. localstack/services/apigateway/next_gen/execute_api/integrations/aws.py +9 -6
  102. localstack/services/apigateway/next_gen/execute_api/integrations/http.py +12 -12
  103. localstack/services/apigateway/next_gen/execute_api/router.py +31 -0
  104. localstack/services/apigateway/next_gen/execute_api/template_mapping.py +2 -2
  105. localstack/services/apigateway/next_gen/execute_api/test_invoke.py +114 -9
  106. localstack/services/apigateway/next_gen/execute_api/variables.py +63 -63
  107. localstack/services/apigateway/next_gen/provider.py +5 -0
  108. localstack/services/apigateway/resource_providers/aws_apigateway_account.py +3 -3
  109. localstack/services/apigateway/resource_providers/aws_apigateway_account_plugin.py +1 -3
  110. localstack/services/apigateway/resource_providers/aws_apigateway_apikey.py +14 -14
  111. localstack/services/apigateway/resource_providers/aws_apigateway_apikey_plugin.py +1 -3
  112. localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping.py +5 -5
  113. localstack/services/apigateway/resource_providers/aws_apigateway_basepathmapping_plugin.py +1 -3
  114. localstack/services/apigateway/resource_providers/aws_apigateway_deployment.py +46 -46
  115. localstack/services/apigateway/resource_providers/aws_apigateway_deployment_plugin.py +1 -3
  116. localstack/services/apigateway/resource_providers/aws_apigateway_domainname.py +18 -18
  117. localstack/services/apigateway/resource_providers/aws_apigateway_domainname_plugin.py +1 -3
  118. localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse.py +7 -7
  119. localstack/services/apigateway/resource_providers/aws_apigateway_gatewayresponse_plugin.py +1 -3
  120. localstack/services/apigateway/resource_providers/aws_apigateway_method.py +36 -36
  121. localstack/services/apigateway/resource_providers/aws_apigateway_method_plugin.py +1 -3
  122. localstack/services/apigateway/resource_providers/aws_apigateway_model.py +6 -6
  123. localstack/services/apigateway/resource_providers/aws_apigateway_model_plugin.py +1 -3
  124. localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator.py +6 -6
  125. localstack/services/apigateway/resource_providers/aws_apigateway_requestvalidator_plugin.py +1 -3
  126. localstack/services/apigateway/resource_providers/aws_apigateway_resource.py +6 -6
  127. localstack/services/apigateway/resource_providers/aws_apigateway_resource_plugin.py +1 -3
  128. localstack/services/apigateway/resource_providers/aws_apigateway_restapi.py +26 -26
  129. localstack/services/apigateway/resource_providers/aws_apigateway_restapi_plugin.py +1 -3
  130. localstack/services/apigateway/resource_providers/aws_apigateway_stage.py +33 -33
  131. localstack/services/apigateway/resource_providers/aws_apigateway_stage_plugin.py +1 -3
  132. localstack/services/apigateway/resource_providers/aws_apigateway_usageplan.py +18 -18
  133. localstack/services/apigateway/resource_providers/aws_apigateway_usageplan_plugin.py +1 -3
  134. localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey.py +5 -5
  135. localstack/services/apigateway/resource_providers/aws_apigateway_usageplankey_plugin.py +1 -3
  136. localstack/services/cdk/resource_providers/cdk_metadata.py +4 -3
  137. localstack/services/cdk/resource_providers/cdk_metadata_plugin.py +1 -3
  138. localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate.py +14 -14
  139. localstack/services/certificatemanager/resource_providers/aws_certificatemanager_certificate_plugin.py +1 -3
  140. localstack/services/cloudformation/api_utils.py +4 -8
  141. localstack/services/cloudformation/cfn_utils.py +2 -2
  142. localstack/services/cloudformation/deployment_utils.py +14 -12
  143. localstack/services/cloudformation/engine/changes.py +3 -3
  144. localstack/services/cloudformation/engine/entities.py +27 -17
  145. localstack/services/cloudformation/engine/parameters.py +4 -4
  146. localstack/services/cloudformation/engine/template_deployer.py +15 -14
  147. localstack/services/cloudformation/engine/template_utils.py +34 -12
  148. localstack/services/cloudformation/engine/transformers.py +11 -8
  149. localstack/services/cloudformation/engine/types.py +5 -4
  150. localstack/services/cloudformation/engine/v2/change_set_model.py +336 -39
  151. localstack/services/cloudformation/engine/v2/change_set_model_describer.py +96 -17
  152. localstack/services/cloudformation/engine/v2/change_set_model_executor.py +286 -139
  153. localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +315 -146
  154. localstack/services/cloudformation/engine/v2/change_set_model_transform.py +380 -105
  155. localstack/services/cloudformation/engine/v2/change_set_model_validator.py +161 -31
  156. localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +6 -0
  157. localstack/services/cloudformation/engine/v2/resolving.py +102 -0
  158. localstack/services/cloudformation/engine/yaml_parser.py +9 -2
  159. localstack/services/cloudformation/provider.py +8 -6
  160. localstack/services/cloudformation/provider_utils.py +34 -4
  161. localstack/services/cloudformation/resource_provider.py +31 -21
  162. localstack/services/cloudformation/resource_providers/aws_cloudformation_macro.py +7 -7
  163. localstack/services/cloudformation/resource_providers/aws_cloudformation_macro_plugin.py +1 -3
  164. localstack/services/cloudformation/resource_providers/aws_cloudformation_stack.py +9 -9
  165. localstack/services/cloudformation/resource_providers/aws_cloudformation_stack_plugin.py +1 -3
  166. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition.py +6 -6
  167. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitcondition_plugin.py +1 -3
  168. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle.py +2 -2
  169. localstack/services/cloudformation/resource_providers/aws_cloudformation_waitconditionhandle_plugin.py +1 -3
  170. localstack/services/cloudformation/resources.py +24149 -0
  171. localstack/services/cloudformation/scaffolding/__main__.py +13 -12
  172. localstack/services/cloudformation/scaffolding/propgen.py +2 -2
  173. localstack/services/cloudformation/service_models.py +2 -2
  174. localstack/services/cloudformation/stores.py +31 -22
  175. localstack/services/cloudformation/v2/entities.py +65 -92
  176. localstack/services/cloudformation/v2/provider.py +553 -128
  177. localstack/services/cloudformation/v2/types.py +38 -0
  178. localstack/services/cloudformation/v2/utils.py +4 -1
  179. localstack/services/cloudwatch/alarm_scheduler.py +11 -8
  180. localstack/services/cloudwatch/cloudwatch_database_helper.py +4 -5
  181. localstack/services/cloudwatch/models.py +5 -7
  182. localstack/services/cloudwatch/provider.py +30 -25
  183. localstack/services/cloudwatch/provider_v2.py +27 -32
  184. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm.py +40 -40
  185. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_alarm_plugin.py +1 -3
  186. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm.py +12 -12
  187. localstack/services/cloudwatch/resource_providers/aws_cloudwatch_compositealarm_plugin.py +1 -3
  188. localstack/services/dynamodb/packages.py +3 -3
  189. localstack/services/dynamodb/provider.py +49 -8
  190. localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable.py +63 -63
  191. localstack/services/dynamodb/resource_providers/aws_dynamodb_globaltable_plugin.py +1 -3
  192. localstack/services/dynamodb/resource_providers/aws_dynamodb_table.py +57 -57
  193. localstack/services/dynamodb/resource_providers/aws_dynamodb_table_plugin.py +1 -3
  194. localstack/services/dynamodb/server.py +2 -2
  195. localstack/services/dynamodb/utils.py +13 -14
  196. localstack/services/dynamodb/v2/provider.py +48 -7
  197. localstack/services/dynamodbstreams/dynamodbstreams_api.py +2 -2
  198. localstack/services/dynamodbstreams/models.py +1 -3
  199. localstack/services/ec2/patches.py +26 -5
  200. localstack/services/ec2/provider.py +3 -3
  201. localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions.py +10 -10
  202. localstack/services/ec2/resource_providers/aws_ec2_dhcpoptions_plugin.py +1 -3
  203. localstack/services/ec2/resource_providers/aws_ec2_instance.py +96 -96
  204. localstack/services/ec2/resource_providers/aws_ec2_instance_plugin.py +1 -3
  205. localstack/services/ec2/resource_providers/aws_ec2_internetgateway.py +5 -5
  206. localstack/services/ec2/resource_providers/aws_ec2_internetgateway_plugin.py +1 -3
  207. localstack/services/ec2/resource_providers/aws_ec2_keypair.py +10 -10
  208. localstack/services/ec2/resource_providers/aws_ec2_keypair_plugin.py +1 -3
  209. localstack/services/ec2/resource_providers/aws_ec2_natgateway.py +13 -13
  210. localstack/services/ec2/resource_providers/aws_ec2_natgateway_plugin.py +1 -3
  211. localstack/services/ec2/resource_providers/aws_ec2_networkacl.py +6 -6
  212. localstack/services/ec2/resource_providers/aws_ec2_networkacl_plugin.py +1 -3
  213. localstack/services/ec2/resource_providers/aws_ec2_prefixlist.py +14 -14
  214. localstack/services/ec2/resource_providers/aws_ec2_prefixlist_plugin.py +1 -3
  215. localstack/services/ec2/resource_providers/aws_ec2_route.py +15 -15
  216. localstack/services/ec2/resource_providers/aws_ec2_route_plugin.py +1 -3
  217. localstack/services/ec2/resource_providers/aws_ec2_routetable.py +6 -6
  218. localstack/services/ec2/resource_providers/aws_ec2_routetable_plugin.py +1 -3
  219. localstack/services/ec2/resource_providers/aws_ec2_securitygroup.py +29 -29
  220. localstack/services/ec2/resource_providers/aws_ec2_securitygroup_plugin.py +1 -3
  221. localstack/services/ec2/resource_providers/aws_ec2_subnet.py +19 -19
  222. localstack/services/ec2/resource_providers/aws_ec2_subnet_plugin.py +1 -3
  223. localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation.py +4 -4
  224. localstack/services/ec2/resource_providers/aws_ec2_subnetroutetableassociation_plugin.py +1 -3
  225. localstack/services/ec2/resource_providers/aws_ec2_transitgateway.py +16 -16
  226. localstack/services/ec2/resource_providers/aws_ec2_transitgateway_plugin.py +1 -3
  227. localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment.py +9 -9
  228. localstack/services/ec2/resource_providers/aws_ec2_transitgatewayattachment_plugin.py +1 -3
  229. localstack/services/ec2/resource_providers/aws_ec2_vpc.py +15 -15
  230. localstack/services/ec2/resource_providers/aws_ec2_vpc_plugin.py +1 -3
  231. localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint.py +29 -22
  232. localstack/services/ec2/resource_providers/aws_ec2_vpcendpoint_plugin.py +1 -3
  233. localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment.py +5 -5
  234. localstack/services/ec2/resource_providers/aws_ec2_vpcgatewayattachment_plugin.py +1 -3
  235. localstack/services/ecr/resource_providers/aws_ecr_repository.py +22 -19
  236. localstack/services/ecr/resource_providers/aws_ecr_repository_plugin.py +1 -3
  237. localstack/services/edge.py +6 -6
  238. localstack/services/es/provider.py +21 -21
  239. localstack/services/events/archive.py +2 -2
  240. localstack/services/events/connection.py +5 -5
  241. localstack/services/events/event_bus.py +9 -9
  242. localstack/services/events/event_rule_engine.py +31 -13
  243. localstack/services/events/models.py +29 -30
  244. localstack/services/events/provider.py +29 -26
  245. localstack/services/events/replay.py +3 -3
  246. localstack/services/events/resource_providers/aws_events_apidestination.py +8 -8
  247. localstack/services/events/resource_providers/aws_events_apidestination_plugin.py +1 -3
  248. localstack/services/events/resource_providers/aws_events_connection.py +27 -27
  249. localstack/services/events/resource_providers/aws_events_connection_plugin.py +1 -3
  250. localstack/services/events/resource_providers/aws_events_eventbus.py +9 -9
  251. localstack/services/events/resource_providers/aws_events_eventbus_plugin.py +1 -3
  252. localstack/services/events/resource_providers/aws_events_eventbuspolicy.py +11 -11
  253. localstack/services/events/resource_providers/aws_events_eventbuspolicy_plugin.py +1 -3
  254. localstack/services/events/resource_providers/aws_events_rule.py +82 -82
  255. localstack/services/events/resource_providers/aws_events_rule_plugin.py +1 -3
  256. localstack/services/events/rule.py +15 -15
  257. localstack/services/events/target.py +21 -13
  258. localstack/services/events/utils.py +7 -7
  259. localstack/services/events/v1/models.py +1 -3
  260. localstack/services/events/v1/provider.py +15 -15
  261. localstack/services/firehose/models.py +1 -3
  262. localstack/services/firehose/provider.py +25 -16
  263. localstack/services/iam/iam_patches.py +5 -6
  264. localstack/services/iam/provider.py +14 -119
  265. localstack/services/iam/resource_providers/aws_iam_accesskey.py +6 -6
  266. localstack/services/iam/resource_providers/aws_iam_accesskey_plugin.py +1 -3
  267. localstack/services/iam/resource_providers/aws_iam_group.py +9 -9
  268. localstack/services/iam/resource_providers/aws_iam_group_plugin.py +1 -3
  269. localstack/services/iam/resource_providers/aws_iam_instanceprofile.py +5 -5
  270. localstack/services/iam/resource_providers/aws_iam_instanceprofile_plugin.py +1 -3
  271. localstack/services/iam/resource_providers/aws_iam_managedpolicy.py +9 -9
  272. localstack/services/iam/resource_providers/aws_iam_managedpolicy_plugin.py +1 -3
  273. localstack/services/iam/resource_providers/aws_iam_policy.py +7 -7
  274. localstack/services/iam/resource_providers/aws_iam_policy_plugin.py +1 -3
  275. localstack/services/iam/resource_providers/aws_iam_role.py +16 -16
  276. localstack/services/iam/resource_providers/aws_iam_role_plugin.py +1 -3
  277. localstack/services/iam/resource_providers/aws_iam_servercertificate.py +10 -10
  278. localstack/services/iam/resource_providers/aws_iam_servercertificate_plugin.py +1 -3
  279. localstack/services/iam/resource_providers/aws_iam_servicelinkedrole.py +5 -5
  280. localstack/services/iam/resource_providers/aws_iam_servicelinkedrole_plugin.py +1 -3
  281. localstack/services/iam/resource_providers/aws_iam_user.py +17 -17
  282. localstack/services/iam/resource_providers/aws_iam_user_plugin.py +1 -3
  283. localstack/services/iam/resources/policy_simulator.py +133 -0
  284. localstack/services/kinesis/kinesis_mock_server.py +7 -8
  285. localstack/services/kinesis/models.py +17 -5
  286. localstack/services/kinesis/packages.py +3 -3
  287. localstack/services/kinesis/provider.py +86 -3
  288. localstack/services/kinesis/resource_providers/aws_kinesis_stream.py +13 -13
  289. localstack/services/kinesis/resource_providers/aws_kinesis_stream_plugin.py +1 -3
  290. localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer.py +7 -7
  291. localstack/services/kinesis/resource_providers/aws_kinesis_streamconsumer_plugin.py +1 -3
  292. localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream.py +191 -191
  293. localstack/services/kinesisfirehose/resource_providers/aws_kinesisfirehose_deliverystream_plugin.py +1 -3
  294. localstack/services/kms/models.py +21 -18
  295. localstack/services/kms/provider.py +17 -11
  296. localstack/services/kms/resource_providers/aws_kms_alias.py +3 -3
  297. localstack/services/kms/resource_providers/aws_kms_alias_plugin.py +1 -3
  298. localstack/services/kms/resource_providers/aws_kms_key.py +14 -14
  299. localstack/services/kms/resource_providers/aws_kms_key_plugin.py +1 -3
  300. localstack/services/kms/utils.py +4 -3
  301. localstack/services/lambda_/api_utils.py +19 -16
  302. localstack/services/lambda_/custom_endpoints.py +2 -2
  303. localstack/services/lambda_/event_source_mapping/esm_worker_factory.py +4 -7
  304. localstack/services/lambda_/event_source_mapping/pipe_utils.py +2 -2
  305. localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
  306. localstack/services/lambda_/event_source_mapping/senders/sender_utils.py +2 -1
  307. localstack/services/lambda_/hooks.py +6 -1
  308. localstack/services/lambda_/invocation/assignment.py +1 -2
  309. localstack/services/lambda_/invocation/docker_runtime_executor.py +7 -11
  310. localstack/services/lambda_/invocation/event_manager.py +1 -1
  311. localstack/services/lambda_/invocation/execution_environment.py +4 -4
  312. localstack/services/lambda_/invocation/executor_endpoint.py +8 -11
  313. localstack/services/lambda_/invocation/internal_sqs_queue.py +6 -10
  314. localstack/services/lambda_/invocation/lambda_models.py +33 -30
  315. localstack/services/lambda_/invocation/lambda_service.py +12 -5
  316. localstack/services/lambda_/invocation/logs.py +2 -3
  317. localstack/services/lambda_/invocation/runtime_executor.py +3 -3
  318. localstack/services/lambda_/invocation/version_manager.py +31 -8
  319. localstack/services/lambda_/ldm.py +14 -0
  320. localstack/services/lambda_/packages.py +3 -4
  321. localstack/services/lambda_/provider.py +9 -26
  322. localstack/services/lambda_/provider_utils.py +1 -1
  323. localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig.py +8 -8
  324. localstack/services/lambda_/resource_providers/aws_lambda_codesigningconfig_plugin.py +1 -3
  325. localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig.py +11 -11
  326. localstack/services/lambda_/resource_providers/aws_lambda_eventinvokeconfig_plugin.py +1 -3
  327. localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping.py +39 -39
  328. localstack/services/lambda_/resource_providers/aws_lambda_eventsourcemapping_plugin.py +1 -3
  329. localstack/services/lambda_/resource_providers/aws_lambda_function.py +54 -54
  330. localstack/services/lambda_/resource_providers/aws_lambda_function_plugin.py +1 -3
  331. localstack/services/lambda_/resource_providers/aws_lambda_layerversion.py +11 -11
  332. localstack/services/lambda_/resource_providers/aws_lambda_layerversion_plugin.py +1 -3
  333. localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission.py +6 -6
  334. localstack/services/lambda_/resource_providers/aws_lambda_layerversionpermission_plugin.py +1 -3
  335. localstack/services/lambda_/resource_providers/aws_lambda_permission.py +10 -10
  336. localstack/services/lambda_/resource_providers/aws_lambda_permission_plugin.py +1 -3
  337. localstack/services/lambda_/resource_providers/aws_lambda_url.py +15 -15
  338. localstack/services/lambda_/resource_providers/aws_lambda_url_plugin.py +1 -3
  339. localstack/services/lambda_/resource_providers/aws_lambda_version.py +8 -8
  340. localstack/services/lambda_/resource_providers/aws_lambda_version_plugin.py +1 -3
  341. localstack/services/lambda_/resource_providers/lambda_alias.py +12 -12
  342. localstack/services/lambda_/resource_providers/lambda_alias_plugin.py +1 -3
  343. localstack/services/lambda_/runtimes.py +1 -3
  344. localstack/services/lambda_/urlrouter.py +14 -1
  345. localstack/services/logs/models.py +1 -3
  346. localstack/services/logs/provider.py +4 -4
  347. localstack/services/logs/resource_providers/aws_logs_loggroup.py +9 -9
  348. localstack/services/logs/resource_providers/aws_logs_loggroup_plugin.py +1 -3
  349. localstack/services/logs/resource_providers/aws_logs_logstream.py +4 -4
  350. localstack/services/logs/resource_providers/aws_logs_logstream_plugin.py +1 -3
  351. localstack/services/logs/resource_providers/aws_logs_subscriptionfilter.py +7 -7
  352. localstack/services/logs/resource_providers/aws_logs_subscriptionfilter_plugin.py +1 -3
  353. localstack/services/moto.py +5 -4
  354. localstack/services/opensearch/cluster.py +28 -20
  355. localstack/services/opensearch/cluster_manager.py +13 -14
  356. localstack/services/opensearch/models.py +1 -3
  357. localstack/services/opensearch/packages.py +27 -9
  358. localstack/services/opensearch/provider.py +15 -10
  359. localstack/services/opensearch/resource_providers/aws_elasticsearch_domain.py +61 -61
  360. localstack/services/opensearch/resource_providers/aws_elasticsearch_domain_plugin.py +1 -3
  361. localstack/services/opensearch/resource_providers/aws_opensearchservice_domain.py +89 -89
  362. localstack/services/opensearch/resource_providers/aws_opensearchservice_domain_plugin.py +1 -3
  363. localstack/services/opensearch/versions.py +57 -10
  364. localstack/services/plugins.py +37 -32
  365. localstack/services/providers.py +10 -2
  366. localstack/services/redshift/provider.py +0 -21
  367. localstack/services/redshift/resource_providers/aws_redshift_cluster.py +57 -57
  368. localstack/services/redshift/resource_providers/aws_redshift_cluster_plugin.py +1 -3
  369. localstack/services/resource_groups/resource_providers/aws_resourcegroups_group.py +21 -21
  370. localstack/services/resource_groups/resource_providers/aws_resourcegroups_group_plugin.py +1 -3
  371. localstack/services/route53/models.py +1 -3
  372. localstack/services/route53/provider.py +1 -2
  373. localstack/services/route53/resource_providers/aws_route53_healthcheck.py +6 -6
  374. localstack/services/route53/resource_providers/aws_route53_healthcheck_plugin.py +1 -3
  375. localstack/services/route53/resource_providers/aws_route53_recordset.py +27 -27
  376. localstack/services/route53/resource_providers/aws_route53_recordset_plugin.py +1 -3
  377. localstack/services/route53resolver/models.py +8 -10
  378. localstack/services/route53resolver/provider.py +12 -12
  379. localstack/services/s3/codec.py +2 -2
  380. localstack/services/s3/constants.py +5 -2
  381. localstack/services/s3/cors.py +8 -8
  382. localstack/services/s3/models.py +73 -73
  383. localstack/services/s3/notifications.py +74 -58
  384. localstack/services/s3/presigned_url.py +41 -59
  385. localstack/services/s3/provider.py +86 -29
  386. localstack/services/s3/resource_providers/aws_s3_bucket.py +180 -180
  387. localstack/services/s3/resource_providers/aws_s3_bucket_plugin.py +1 -3
  388. localstack/services/s3/resource_providers/aws_s3_bucketpolicy.py +4 -4
  389. localstack/services/s3/resource_providers/aws_s3_bucketpolicy_plugin.py +1 -3
  390. localstack/services/s3/storage/core.py +4 -3
  391. localstack/services/s3/storage/ephemeral.py +7 -6
  392. localstack/services/s3/utils.py +51 -31
  393. localstack/services/s3/validation.py +47 -33
  394. localstack/services/s3/website_hosting.py +9 -7
  395. localstack/services/scheduler/resource_providers/aws_scheduler_schedule.py +60 -60
  396. localstack/services/scheduler/resource_providers/aws_scheduler_schedule_plugin.py +1 -3
  397. localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup.py +9 -9
  398. localstack/services/scheduler/resource_providers/aws_scheduler_schedulegroup_plugin.py +1 -3
  399. localstack/services/secretsmanager/provider.py +10 -12
  400. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy.py +5 -5
  401. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_resourcepolicy_plugin.py +1 -3
  402. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule.py +21 -21
  403. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_rotationschedule_plugin.py +1 -3
  404. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret.py +23 -23
  405. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secret_plugin.py +1 -3
  406. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment.py +5 -5
  407. localstack/services/secretsmanager/resource_providers/aws_secretsmanager_secrettargetattachment_plugin.py +1 -3
  408. localstack/services/ses/models.py +8 -1
  409. localstack/services/ses/provider.py +128 -55
  410. localstack/services/ses/resource_providers/aws_ses_emailidentity.py +21 -21
  411. localstack/services/ses/resource_providers/aws_ses_emailidentity_plugin.py +1 -3
  412. localstack/services/sns/constants.py +7 -1
  413. localstack/services/sns/executor.py +9 -2
  414. localstack/services/sns/models.py +25 -25
  415. localstack/services/sns/provider.py +9 -7
  416. localstack/services/sns/publisher.py +37 -23
  417. localstack/services/sns/resource_providers/aws_sns_subscription.py +13 -13
  418. localstack/services/sns/resource_providers/aws_sns_subscription_plugin.py +1 -3
  419. localstack/services/sns/resource_providers/aws_sns_topic.py +16 -16
  420. localstack/services/sns/resource_providers/aws_sns_topic_plugin.py +1 -3
  421. localstack/services/sns/resource_providers/aws_sns_topicpolicy.py +4 -4
  422. localstack/services/sns/resource_providers/aws_sns_topicpolicy_plugin.py +1 -3
  423. localstack/services/sns/v2/models.py +167 -0
  424. localstack/services/sns/v2/provider.py +867 -0
  425. localstack/services/sns/v2/utils.py +130 -0
  426. localstack/services/sqs/constants.py +2 -2
  427. localstack/services/sqs/developer_api.py +205 -0
  428. localstack/services/sqs/models.py +71 -36
  429. localstack/services/sqs/provider.py +56 -332
  430. localstack/services/sqs/query_api.py +8 -5
  431. localstack/services/sqs/resource_providers/aws_sqs_queue.py +21 -21
  432. localstack/services/sqs/resource_providers/aws_sqs_queue_plugin.py +1 -3
  433. localstack/services/sqs/resource_providers/aws_sqs_queuepolicy.py +4 -4
  434. localstack/services/sqs/resource_providers/aws_sqs_queuepolicy_plugin.py +1 -3
  435. localstack/services/sqs/utils.py +123 -4
  436. localstack/services/ssm/provider.py +3 -4
  437. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow.py +15 -15
  438. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindow_plugin.py +1 -3
  439. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget.py +10 -10
  440. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtarget_plugin.py +1 -3
  441. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask.py +48 -48
  442. localstack/services/ssm/resource_providers/aws_ssm_maintenancewindowtask_plugin.py +1 -3
  443. localstack/services/ssm/resource_providers/aws_ssm_parameter.py +10 -10
  444. localstack/services/ssm/resource_providers/aws_ssm_parameter_plugin.py +1 -3
  445. localstack/services/ssm/resource_providers/aws_ssm_patchbaseline.py +29 -29
  446. localstack/services/ssm/resource_providers/aws_ssm_patchbaseline_plugin.py +1 -3
  447. localstack/services/stepfunctions/asl/antlt4utils/antlr4utils.py +3 -4
  448. localstack/services/stepfunctions/asl/component/common/assign/assign_decl.py +1 -1
  449. localstack/services/stepfunctions/asl/component/common/assign/assign_decl_binding.py +1 -1
  450. localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_array.py +1 -1
  451. localstack/services/stepfunctions/asl/component/common/assign/assign_template_value_object.py +1 -1
  452. localstack/services/stepfunctions/asl/component/common/catch/catcher_decl.py +9 -9
  453. localstack/services/stepfunctions/asl/component/common/error_name/custom_error_name.py +2 -2
  454. localstack/services/stepfunctions/asl/component/common/error_name/error_name.py +4 -4
  455. localstack/services/stepfunctions/asl/component/common/error_name/failure_event.py +8 -8
  456. localstack/services/stepfunctions/asl/component/common/error_name/states_error_name_type.py +1 -1
  457. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_binding.py +2 -2
  458. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_array.py +1 -1
  459. localstack/services/stepfunctions/asl/component/common/jsonata/jsonata_template_value_object.py +1 -1
  460. localstack/services/stepfunctions/asl/component/common/path/input_path.py +4 -4
  461. localstack/services/stepfunctions/asl/component/common/path/output_path.py +4 -4
  462. localstack/services/stepfunctions/asl/component/common/path/result_path.py +3 -3
  463. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadarr/payload_arr.py +1 -1
  464. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadbinding/payload_binding.py +3 -3
  465. localstack/services/stepfunctions/asl/component/common/payload/payloadvalue/payloadtmpl/payload_tmpl.py +1 -1
  466. localstack/services/stepfunctions/asl/component/common/retry/retrier_decl.py +8 -8
  467. localstack/services/stepfunctions/asl/component/common/string/string_expression.py +3 -3
  468. localstack/services/stepfunctions/asl/component/common/timeouts/timeout.py +3 -3
  469. localstack/services/stepfunctions/asl/component/eval_component.py +2 -3
  470. localstack/services/stepfunctions/asl/component/intrinsic/argument/argument.py +4 -4
  471. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/array/array_partition.py +1 -1
  472. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/generic/string_format.py +1 -1
  473. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_array.py +1 -1
  474. localstack/services/stepfunctions/asl/component/intrinsic/function/statesfunction/states_function_format.py +1 -1
  475. localstack/services/stepfunctions/asl/component/intrinsic/jsonata.py +3 -3
  476. localstack/services/stepfunctions/asl/component/intrinsic/member.py +1 -1
  477. localstack/services/stepfunctions/asl/component/program/program.py +9 -9
  478. localstack/services/stepfunctions/asl/component/program/states.py +1 -1
  479. localstack/services/stepfunctions/asl/component/state/state.py +10 -11
  480. localstack/services/stepfunctions/asl/component/state/state_choice/choice_rule.py +11 -11
  481. localstack/services/stepfunctions/asl/component/state/state_choice/comparison/comparison.py +5 -11
  482. localstack/services/stepfunctions/asl/component/state/state_choice/comparison/operator/implementations/is_operator.py +2 -2
  483. localstack/services/stepfunctions/asl/component/state/state_choice/state_choice.py +3 -5
  484. localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +9 -9
  485. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/item_reader_decl.py +7 -7
  486. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/reader_config/reader_config_decl.py +5 -5
  487. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_eval_s3.py +2 -1
  488. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/item_reader/resource_eval/resource_output_transformer/resource_output_transformer_csv.py +2 -2
  489. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/distributed_iteration_component.py +8 -8
  490. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/inline_iteration_component.py +7 -7
  491. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/distributed_item_processor_worker.py +4 -4
  492. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/inline_item_processor_worker.py +5 -5
  493. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/itemprocessor/map_run_record.py +10 -10
  494. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_component.py +3 -3
  495. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_declaration.py +3 -3
  496. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iteration_worker.py +2 -2
  497. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/distributed_iterator_worker.py +3 -5
  498. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator.py +1 -2
  499. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/iterator/inline_iterator_worker.py +5 -5
  500. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/iteration/job.py +9 -9
  501. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/result_writer/resource_eval/resource_eval_s3.py +2 -1
  502. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +12 -13
  503. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branch_worker.py +3 -3
  504. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/branches_decl.py +7 -7
  505. localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/state_parallel.py +2 -3
  506. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +7 -7
  507. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/resource.py +3 -3
  508. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +10 -10
  509. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_api_gateway.py +18 -18
  510. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_aws_sdk.py +1 -1
  511. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_batch.py +8 -7
  512. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +18 -17
  513. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_dynamodb.py +2 -2
  514. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_ecs.py +5 -4
  515. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_events.py +4 -4
  516. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_glue.py +7 -6
  517. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_lambda.py +4 -4
  518. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sfn.py +9 -8
  519. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sns.py +2 -2
  520. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_sqs.py +4 -4
  521. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task.py +5 -5
  522. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task_lambda.py +2 -2
  523. localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +3 -5
  524. localstack/services/stepfunctions/asl/component/state/state_pass/state_pass.py +5 -7
  525. localstack/services/stepfunctions/asl/component/state/state_succeed/state_succeed.py +1 -1
  526. localstack/services/stepfunctions/asl/component/state/state_wait/state_wait.py +1 -1
  527. localstack/services/stepfunctions/asl/component/state/state_wait/wait_function/timestamp.py +2 -2
  528. localstack/services/stepfunctions/asl/eval/callback/callback.py +18 -18
  529. localstack/services/stepfunctions/asl/eval/environment.py +22 -24
  530. localstack/services/stepfunctions/asl/eval/evaluation_details.py +3 -5
  531. localstack/services/stepfunctions/asl/eval/event/event_manager.py +10 -10
  532. localstack/services/stepfunctions/asl/eval/event/logging.py +3 -3
  533. localstack/services/stepfunctions/asl/eval/program_state.py +8 -8
  534. localstack/services/stepfunctions/asl/eval/states.py +12 -12
  535. localstack/services/stepfunctions/asl/eval/test_state/environment.py +3 -5
  536. localstack/services/stepfunctions/asl/eval/variable_store.py +6 -6
  537. localstack/services/stepfunctions/asl/jsonata/jsonata.py +7 -6
  538. localstack/services/stepfunctions/asl/parse/asl_parser.py +1 -1
  539. localstack/services/stepfunctions/asl/parse/intrinsic/preprocessor.py +2 -3
  540. localstack/services/stepfunctions/asl/parse/preprocessor.py +44 -44
  541. localstack/services/stepfunctions/asl/parse/typed_props.py +2 -2
  542. localstack/services/stepfunctions/asl/static_analyser/intrinsic/variable_names_intrinsic_static_analyser.py +1 -1
  543. localstack/services/stepfunctions/asl/static_analyser/variable_references_static_analyser.py +2 -2
  544. localstack/services/stepfunctions/asl/utils/encoding.py +2 -2
  545. localstack/services/stepfunctions/asl/utils/json_path.py +2 -2
  546. localstack/services/stepfunctions/backend/activity.py +4 -4
  547. localstack/services/stepfunctions/backend/alias.py +8 -8
  548. localstack/services/stepfunctions/backend/execution.py +29 -30
  549. localstack/services/stepfunctions/backend/execution_worker.py +7 -7
  550. localstack/services/stepfunctions/backend/state_machine.py +28 -28
  551. localstack/services/stepfunctions/backend/test_state/execution.py +3 -4
  552. localstack/services/stepfunctions/backend/test_state/execution_worker.py +1 -3
  553. localstack/services/stepfunctions/mocking/mock_config.py +9 -9
  554. localstack/services/stepfunctions/mocking/mock_config_file.py +10 -10
  555. localstack/services/stepfunctions/packages.py +14 -5
  556. localstack/services/stepfunctions/provider.py +34 -44
  557. localstack/services/stepfunctions/quotas.py +2 -3
  558. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity.py +6 -6
  559. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_activity_plugin.py +1 -3
  560. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine.py +25 -25
  561. localstack/services/stepfunctions/resource_providers/aws_stepfunctions_statemachine_plugin.py +1 -3
  562. localstack/services/stepfunctions/stepfunctions_utils.py +1 -2
  563. localstack/services/stores.py +8 -8
  564. localstack/services/transcribe/packages.py +1 -3
  565. localstack/services/transcribe/provider.py +8 -3
  566. localstack/state/codecs.py +61 -0
  567. localstack/state/core.py +11 -5
  568. localstack/state/inspect.py +4 -4
  569. localstack/state/pickle.py +22 -60
  570. localstack/testing/aws/asf_utils.py +3 -2
  571. localstack/testing/aws/cloudformation_utils.py +1 -1
  572. localstack/testing/aws/lambda_utils.py +15 -14
  573. localstack/testing/aws/util.py +3 -2
  574. localstack/testing/pytest/cloudformation/fixtures.py +68 -18
  575. localstack/testing/pytest/container.py +5 -5
  576. localstack/testing/pytest/filters.py +1 -3
  577. localstack/testing/pytest/fixtures.py +188 -55
  578. localstack/testing/pytest/in_memory_localstack.py +1 -3
  579. localstack/testing/pytest/marking.py +42 -15
  580. localstack/testing/pytest/path_filter.py +1 -1
  581. localstack/testing/pytest/stepfunctions/fixtures.py +4 -4
  582. localstack/testing/pytest/stepfunctions/utils.py +11 -10
  583. localstack/testing/pytest/util.py +1 -1
  584. localstack/testing/pytest/validation_tracking.py +3 -4
  585. localstack/testing/scenario/provisioning.py +11 -10
  586. localstack/testing/snapshots/transformer_utility.py +8 -3
  587. localstack/testing/testselection/matching.py +2 -2
  588. localstack/testing/testselection/opt_out.py +1 -1
  589. localstack/testing/testselection/scripts/filter_by_test_selection.py +1 -1
  590. localstack/testing/testselection/scripts/generate_test_selection.py +1 -1
  591. localstack/testing/testselection/testselection.py +2 -2
  592. localstack/utils/analytics/cli.py +2 -3
  593. localstack/utils/analytics/client.py +5 -5
  594. localstack/utils/analytics/events.py +2 -2
  595. localstack/utils/analytics/metadata.py +6 -4
  596. localstack/utils/analytics/metrics/counter.py +11 -18
  597. localstack/utils/analytics/metrics/registry.py +2 -2
  598. localstack/utils/analytics/publisher.py +4 -5
  599. localstack/utils/analytics/service_providers.py +19 -0
  600. localstack/utils/analytics/service_request_aggregator.py +4 -4
  601. localstack/utils/archives.py +12 -12
  602. localstack/utils/asyncio.py +2 -2
  603. localstack/utils/aws/arns.py +26 -31
  604. localstack/utils/aws/aws_responses.py +21 -28
  605. localstack/utils/aws/aws_stack.py +7 -12
  606. localstack/utils/aws/dead_letter_queue.py +4 -9
  607. localstack/utils/aws/message_forwarding.py +8 -11
  608. localstack/utils/aws/request_context.py +5 -6
  609. localstack/utils/aws/resources.py +1 -1
  610. localstack/utils/aws/templating.py +4 -4
  611. localstack/utils/batch_policy.py +4 -4
  612. localstack/utils/bootstrap.py +37 -30
  613. localstack/utils/catalog/catalog.py +139 -0
  614. localstack/utils/catalog/catalog_loader.py +11 -0
  615. localstack/utils/catalog/common.py +58 -0
  616. localstack/utils/catalog/plugins.py +28 -0
  617. localstack/utils/cloudwatch/cloudwatch_util.py +5 -5
  618. localstack/utils/collections.py +33 -27
  619. localstack/utils/config_listener.py +2 -2
  620. localstack/utils/container_networking.py +5 -6
  621. localstack/utils/container_utils/container_client.py +156 -160
  622. localstack/utils/container_utils/docker_cmd_client.py +97 -81
  623. localstack/utils/container_utils/docker_sdk_client.py +75 -72
  624. localstack/utils/crypto.py +12 -13
  625. localstack/utils/diagnose.py +11 -12
  626. localstack/utils/docker_utils.py +11 -7
  627. localstack/utils/files.py +34 -15
  628. localstack/utils/functions.py +5 -4
  629. localstack/utils/http.py +14 -14
  630. localstack/utils/iputils.py +2 -1
  631. localstack/utils/json.py +21 -7
  632. localstack/utils/kinesis/kinesis_connector.py +2 -1
  633. localstack/utils/net.py +25 -17
  634. localstack/utils/no_exit_argument_parser.py +2 -2
  635. localstack/utils/numbers.py +9 -2
  636. localstack/utils/objects.py +15 -14
  637. localstack/utils/patch.py +14 -7
  638. localstack/utils/platform.py +2 -2
  639. localstack/utils/run.py +15 -14
  640. localstack/utils/scheduler.py +13 -12
  641. localstack/utils/server/tcp_proxy.py +2 -2
  642. localstack/utils/serving.py +3 -4
  643. localstack/utils/strings.py +15 -16
  644. localstack/utils/sync.py +126 -1
  645. localstack/utils/tagging.py +10 -8
  646. localstack/utils/testutil.py +17 -17
  647. localstack/utils/threads.py +3 -3
  648. localstack/utils/time.py +12 -4
  649. localstack/utils/urls.py +1 -3
  650. localstack/utils/xml.py +1 -1
  651. localstack/utils/xray/traceid.py +1 -1
  652. localstack/version.py +16 -3
  653. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/METADATA +18 -14
  654. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/RECORD +663 -656
  655. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/entry_points.txt +8 -4
  656. localstack_core-4.10.1.dev7.dist-info/plux.json +1 -0
  657. localstack/packages/terraform.py +0 -47
  658. localstack/services/cloudformation/deploy.html +0 -144
  659. localstack/services/cloudformation/deploy_ui.py +0 -47
  660. localstack/services/cloudformation/plugins.py +0 -12
  661. localstack/services/lambda_/lambda_debug_mode/ldm.py +0 -375
  662. localstack/services/lambda_/lambda_debug_mode/ldm_config_file.py +0 -178
  663. localstack/services/lambda_/lambda_debug_mode/ldm_types.py +0 -11
  664. localstack/services/lambda_/lambda_debug_mode/ldm_utils.py +0 -43
  665. localstack_core-4.6.1.dev74.dist-info/plux.json +0 -1
  666. /localstack/{services/lambda_/lambda_debug_mode/__init__.py → testing/pytest/cloudformation/transformers.py} +0 -0
  667. {localstack_core-4.6.1.dev74.data → localstack_core-4.10.1.dev7.data}/scripts/localstack +0 -0
  668. {localstack_core-4.6.1.dev74.data → localstack_core-4.10.1.dev7.data}/scripts/localstack-supervisor +0 -0
  669. {localstack_core-4.6.1.dev74.data → localstack_core-4.10.1.dev7.data}/scripts/localstack.bat +0 -0
  670. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/WHEEL +0 -0
  671. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/licenses/LICENSE.txt +0 -0
  672. {localstack_core-4.6.1.dev74.dist-info → localstack_core-4.10.1.dev7.dist-info}/top_level.txt +0 -0
@@ -1,28 +1,31 @@
1
1
  import copy
2
2
  import logging
3
+ import os
4
+ import re
3
5
  import uuid
6
+ from collections.abc import Callable
4
7
  from dataclasses import dataclass
5
- from datetime import datetime, timezone
6
- from typing import Final, Optional
8
+ from datetime import UTC, datetime
9
+ from typing import Final, Protocol, TypeVar
7
10
 
8
11
  from localstack import config
9
12
  from localstack.aws.api.cloudformation import (
10
13
  ChangeAction,
14
+ Output,
11
15
  ResourceStatus,
12
16
  StackStatus,
13
17
  )
14
18
  from localstack.constants import INTERNAL_AWS_SECRET_ACCESS_KEY
15
19
  from localstack.services.cloudformation.analytics import track_resource_operation
16
20
  from localstack.services.cloudformation.deployment_utils import log_not_available_message
17
- from localstack.services.cloudformation.engine.parameters import resolve_ssm_parameter
18
21
  from localstack.services.cloudformation.engine.v2.change_set_model import (
19
22
  NodeDependsOn,
20
23
  NodeOutput,
21
- NodeParameter,
22
24
  NodeResource,
23
25
  is_nothing,
24
26
  )
25
27
  from localstack.services.cloudformation.engine.v2.change_set_model_preproc import (
28
+ _AWS_URL_SUFFIX,
26
29
  MOCKED_REFERENCE,
27
30
  ChangeSetModelPreproc,
28
31
  PreprocEntityDelta,
@@ -43,55 +46,94 @@ LOG = logging.getLogger(__name__)
43
46
 
44
47
  EventOperationFromAction = {"Add": "CREATE", "Modify": "UPDATE", "Remove": "DELETE"}
45
48
 
49
+ REGEX_OUTPUT_APIGATEWAY = re.compile(
50
+ rf"^(https?://.+\.execute-api\.)(?:[^-]+-){{2,3}}\d\.(amazonaws\.com|{_AWS_URL_SUFFIX})/?(.*)$"
51
+ )
52
+
53
+ _T = TypeVar("_T")
54
+
46
55
 
47
56
  @dataclass
48
57
  class ChangeSetModelExecutorResult:
49
58
  resources: dict[str, ResolvedResource]
50
- parameters: dict
51
- outputs: dict
59
+ outputs: list[Output]
60
+ failure_message: str | None = None
61
+
62
+
63
+ class DeferredAction(Protocol):
64
+ def __call__(self) -> None: ...
65
+
66
+
67
+ @dataclass
68
+ class Deferred:
69
+ name: str
70
+ action: DeferredAction
71
+
72
+
73
+ class TriggerRollback(Exception):
74
+ """
75
+ Sentinel exception to signal that the deployment should be stopped for a reason
76
+ """
77
+
78
+ def __init__(self, logical_resource_id: str, reason: str | None):
79
+ self.logical_resource_id = logical_resource_id
80
+ self.reason = reason
52
81
 
53
82
 
54
83
  class ChangeSetModelExecutor(ChangeSetModelPreproc):
55
84
  # TODO: add typing for resolved resources and parameters.
56
85
  resources: Final[dict[str, ResolvedResource]]
57
- outputs: Final[dict]
58
- resolved_parameters: Final[dict]
86
+ outputs: Final[list[Output]]
87
+ _deferred_actions: list[Deferred]
59
88
 
60
89
  def __init__(self, change_set: ChangeSet):
61
90
  super().__init__(change_set=change_set)
62
- self.resources = dict()
63
- self.outputs = dict()
64
- self.resolved_parameters = dict()
91
+ self.resources = {}
92
+ self.outputs = []
93
+ self._deferred_actions = []
94
+ self.resource_provider_executor = ResourceProviderExecutor(
95
+ stack_name=change_set.stack.stack_name,
96
+ stack_id=change_set.stack.stack_id,
97
+ )
65
98
 
66
- # TODO: use a structured type for the return value
67
99
  def execute(self) -> ChangeSetModelExecutorResult:
68
- self.process()
100
+ # constructive process
101
+ failure_message = None
102
+ try:
103
+ self.process()
104
+ except TriggerRollback as e:
105
+ failure_message = e.reason
106
+ except Exception as e:
107
+ failure_message = str(e)
108
+
109
+ is_deletion = self._change_set.stack.status == StackStatus.DELETE_IN_PROGRESS
110
+ if self._deferred_actions:
111
+ if not is_deletion:
112
+ # TODO: correct status
113
+ # TODO: differentiate between update and create
114
+ self._change_set.stack.set_stack_status(
115
+ StackStatus.ROLLBACK_IN_PROGRESS
116
+ if failure_message
117
+ else StackStatus.UPDATE_COMPLETE_CLEANUP_IN_PROGRESS
118
+ )
119
+
120
+ # perform all deferred actions such as deletions. These must happen in reverse from their
121
+ # defined order so that resource dependencies are honoured
122
+ # TODO: errors will stop all rollbacks; get parity on this behaviour
123
+ for deferred in self._deferred_actions[::-1]:
124
+ LOG.debug("executing deferred action: '%s'", deferred.name)
125
+ deferred.action()
126
+
127
+ if failure_message and not is_deletion:
128
+ # TODO: differentiate between update and create
129
+ self._change_set.stack.set_stack_status(StackStatus.ROLLBACK_COMPLETE)
130
+
69
131
  return ChangeSetModelExecutorResult(
70
- resources=self.resources, parameters=self.resolved_parameters, outputs=self.outputs
132
+ resources=self.resources, outputs=self.outputs, failure_message=failure_message
71
133
  )
72
134
 
73
- def visit_node_parameter(self, node_parameter: NodeParameter) -> PreprocEntityDelta:
74
- delta = super().visit_node_parameter(node_parameter)
75
-
76
- # handle dynamic references, e.g. references to SSM parameters
77
- # TODO: support more parameter types
78
- parameter_type: str = node_parameter.type_.value
79
- if parameter_type.startswith("AWS::SSM"):
80
- if parameter_type in [
81
- "AWS::SSM::Parameter::Value<String>",
82
- "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
83
- "AWS::SSM::Parameter::Value<CommaDelimitedList>",
84
- ]:
85
- delta.after = resolve_ssm_parameter(
86
- account_id=self._change_set.account_id,
87
- region_name=self._change_set.region_name,
88
- stack_parameter_value=delta.after,
89
- )
90
- else:
91
- raise Exception(f"Unsupported stack parameter type: {parameter_type}")
92
-
93
- self.resolved_parameters[node_parameter.name] = delta.after
94
- return delta
135
+ def _defer_action(self, name: str, action: DeferredAction):
136
+ self._deferred_actions.append(Deferred(name=name, action=action))
95
137
 
96
138
  def _get_physical_id(self, logical_resource_id, strict: bool = True) -> str | None:
97
139
  physical_resource_id = None
@@ -113,12 +155,13 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
113
155
 
114
156
  def _process_event(
115
157
  self,
158
+ *,
116
159
  action: ChangeAction,
117
160
  logical_resource_id,
118
161
  event_status: OperationStatus,
162
+ resource_type: str,
119
163
  special_action: str = None,
120
164
  reason: str = None,
121
- resource_type=None,
122
165
  ):
123
166
  status_from_action = special_action or EventOperationFromAction[action.value]
124
167
  if event_status == OperationStatus.SUCCESS:
@@ -126,9 +169,10 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
126
169
  else:
127
170
  status = f"{status_from_action}_{event_status.name}"
128
171
 
172
+ physical_resource_id = self._get_physical_id(logical_resource_id, False)
129
173
  self._change_set.stack.set_resource_status(
130
174
  logical_resource_id=logical_resource_id,
131
- physical_resource_id=self._get_physical_id(logical_resource_id, False),
175
+ physical_resource_id=physical_resource_id,
132
176
  resource_type=resource_type,
133
177
  status=ResourceStatus(status),
134
178
  resource_status_reason=reason,
@@ -181,12 +225,18 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
181
225
  try:
182
226
  delta = super().visit_node_resource(node_resource=node_resource)
183
227
  except Exception as e:
184
- self._process_event(
185
- node_resource.change_type.to_change_action(),
228
+ LOG.debug(
229
+ "preprocessing resource '%s' failed: %s",
186
230
  node_resource.name,
187
- OperationStatus.FAILED,
188
- reason=str(e),
231
+ e,
232
+ exc_info=LOG.isEnabledFor(logging.DEBUG) and config.CFN_VERBOSE_ERRORS,
233
+ )
234
+ self._process_event(
235
+ action=node_resource.change_type.to_change_action(),
236
+ logical_resource_id=node_resource.name,
237
+ event_status=OperationStatus.FAILED,
189
238
  resource_type=node_resource.type_.value,
239
+ reason=str(e),
190
240
  )
191
241
  raise e
192
242
 
@@ -202,16 +252,30 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
202
252
  # references or other downstream operations.
203
253
  if not is_nothing(before):
204
254
  before_logical_id = delta.before.logical_id
205
- before_resource = self._before_resolved_resources.get(before_logical_id, dict())
255
+ before_resource = self._before_resolved_resources.get(before_logical_id, {})
206
256
  self.resources[before_logical_id] = before_resource
207
257
 
208
258
  # Update the latest version of this resource for downstream references.
209
259
  if not is_nothing(after):
210
260
  after_logical_id = after.logical_id
211
- after_physical_id: str = self._after_resource_physical_id(
212
- resource_logical_id=after_logical_id
213
- )
214
- after.physical_resource_id = after_physical_id
261
+ resource = self.resources[after_logical_id]
262
+ resource_failed_to_deploy = resource["ResourceStatus"] in {
263
+ ResourceStatus.CREATE_FAILED,
264
+ ResourceStatus.UPDATE_FAILED,
265
+ }
266
+ if not resource_failed_to_deploy:
267
+ after_physical_id: str = self._after_resource_physical_id(
268
+ resource_logical_id=after_logical_id
269
+ )
270
+ after.physical_resource_id = after_physical_id
271
+ after.status = resource["ResourceStatus"]
272
+
273
+ # terminate the deployment process
274
+ if resource_failed_to_deploy:
275
+ raise TriggerRollback(
276
+ logical_resource_id=after_logical_id,
277
+ reason=resource.get("ResourceStatusReason"),
278
+ )
215
279
  return delta
216
280
 
217
281
  def visit_node_output(
@@ -221,11 +285,20 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
221
285
  after = delta.after
222
286
  if is_nothing(after) or (isinstance(after, PreprocOutput) and after.condition is False):
223
287
  return delta
224
- self.outputs[delta.after.name] = delta.after.value
288
+
289
+ output = Output(
290
+ OutputKey=delta.after.name,
291
+ OutputValue=delta.after.value,
292
+ # TODO
293
+ # Description=delta.after.description
294
+ )
295
+ if after.export:
296
+ output["ExportName"] = after.export["Name"]
297
+ self.outputs.append(output)
225
298
  return delta
226
299
 
227
300
  def _execute_resource_change(
228
- self, name: str, before: Optional[PreprocResource], after: Optional[PreprocResource]
301
+ self, name: str, before: PreprocResource | None, after: PreprocResource | None
229
302
  ) -> None:
230
303
  # Changes are to be made about this resource.
231
304
  # TODO: this logic is a POC and should be revised.
@@ -236,21 +309,67 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
236
309
  # XXX hacky, stick the previous resources' properties into the payload
237
310
  before_properties = self._merge_before_properties(name, before)
238
311
 
239
- self._process_event(ChangeAction.Modify, name, OperationStatus.IN_PROGRESS)
240
- event = self._execute_resource_action(
312
+ self._process_event(
241
313
  action=ChangeAction.Modify,
242
314
  logical_resource_id=name,
243
- resource_type=before.resource_type,
244
- before_properties=before_properties,
245
- after_properties=after.properties,
246
- )
247
- self._process_event(
248
- ChangeAction.Modify,
249
- name,
250
- event.status,
251
- reason=event.message,
315
+ event_status=OperationStatus.IN_PROGRESS,
252
316
  resource_type=before.resource_type,
253
317
  )
318
+ if after.requires_replacement:
319
+ event = self._execute_resource_action(
320
+ action=ChangeAction.Add,
321
+ logical_resource_id=name,
322
+ resource_type=before.resource_type,
323
+ before_properties=None,
324
+ after_properties=after.properties,
325
+ )
326
+ self._process_event(
327
+ action=ChangeAction.Modify,
328
+ logical_resource_id=name,
329
+ event_status=event.status,
330
+ resource_type=before.resource_type,
331
+ reason=event.message,
332
+ )
333
+
334
+ def cleanup():
335
+ self._process_event(
336
+ action=ChangeAction.Remove,
337
+ logical_resource_id=name,
338
+ event_status=OperationStatus.IN_PROGRESS,
339
+ resource_type=before.resource_type,
340
+ )
341
+ event = self._execute_resource_action(
342
+ action=ChangeAction.Remove,
343
+ logical_resource_id=name,
344
+ resource_type=before.resource_type,
345
+ before_properties=before_properties,
346
+ after_properties=None,
347
+ part_of_replacement=True,
348
+ )
349
+ self._process_event(
350
+ action=ChangeAction.Remove,
351
+ logical_resource_id=name,
352
+ event_status=event.status,
353
+ resource_type=before.resource_type,
354
+ reason=event.message,
355
+ )
356
+
357
+ self._defer_action(f"cleanup-from-replacement-{name}", cleanup)
358
+ else:
359
+ event = self._execute_resource_action(
360
+ action=ChangeAction.Modify,
361
+ logical_resource_id=name,
362
+ resource_type=before.resource_type,
363
+ before_properties=before_properties,
364
+ after_properties=after.properties,
365
+ )
366
+ self._process_event(
367
+ action=ChangeAction.Modify,
368
+ logical_resource_id=name,
369
+ event_status=event.status,
370
+ resource_type=before.resource_type,
371
+ reason=event.message,
372
+ )
254
373
  # Case: type migration.
255
374
  # TODO: Add test to assert that on type change the resources are replaced.
256
375
  else:
@@ -258,21 +377,24 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
258
377
  before_properties = self._merge_before_properties(name, before)
259
378
  # Register a Removed for the previous type.
260
379
 
261
- event = self._execute_resource_action(
262
- action=ChangeAction.Remove,
263
- logical_resource_id=name,
264
- resource_type=before.resource_type,
265
- before_properties=before_properties,
266
- after_properties=None,
267
- )
268
- # Register a Create for the next type.
269
- self._process_event(
270
- ChangeAction.Modify,
271
- name,
272
- event.status,
273
- reason=event.message,
274
- resource_type=before.resource_type,
275
- )
380
+ def perform_deletion():
381
+ event = self._execute_resource_action(
382
+ action=ChangeAction.Remove,
383
+ logical_resource_id=name,
384
+ resource_type=before.resource_type,
385
+ before_properties=before_properties,
386
+ after_properties=None,
387
+ )
388
+ self._process_event(
389
+ action=ChangeAction.Modify,
390
+ logical_resource_id=name,
391
+ event_status=event.status,
392
+ resource_type=before.resource_type,
393
+ reason=event.message,
394
+ )
395
+
396
+ self._defer_action(f"type-migration-{name}", perform_deletion)
397
+
276
398
  event = self._execute_resource_action(
277
399
  action=ChangeAction.Add,
278
400
  logical_resource_id=name,
@@ -281,43 +403,47 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
281
403
  after_properties=after.properties,
282
404
  )
283
405
  self._process_event(
284
- ChangeAction.Modify,
285
- name,
286
- event.status,
287
- reason=event.message,
406
+ action=ChangeAction.Modify,
407
+ logical_resource_id=name,
408
+ event_status=event.status,
288
409
  resource_type=before.resource_type,
410
+ reason=event.message,
289
411
  )
290
412
  elif not is_nothing(before):
291
413
  # Case: removal
292
414
  # XXX hacky, stick the previous resources' properties into the payload
293
415
  # XXX hacky, stick the previous resources' properties into the payload
294
416
  before_properties = self._merge_before_properties(name, before)
295
- self._process_event(
296
- ChangeAction.Remove,
297
- name,
298
- OperationStatus.IN_PROGRESS,
299
- resource_type=before.resource_type,
300
- )
301
- event = self._execute_resource_action(
302
- action=ChangeAction.Remove,
303
- logical_resource_id=name,
304
- resource_type=before.resource_type,
305
- before_properties=before_properties,
306
- after_properties=None,
307
- )
308
- self._process_event(
309
- ChangeAction.Remove,
310
- name,
311
- event.status,
312
- reason=event.message,
313
- resource_type=before.resource_type,
314
- )
417
+
418
+ def perform_deletion():
419
+ self._process_event(
420
+ action=ChangeAction.Remove,
421
+ logical_resource_id=name,
422
+ resource_type=before.resource_type,
423
+ event_status=OperationStatus.IN_PROGRESS,
424
+ )
425
+ event = self._execute_resource_action(
426
+ action=ChangeAction.Remove,
427
+ logical_resource_id=name,
428
+ resource_type=before.resource_type,
429
+ before_properties=before_properties,
430
+ after_properties=None,
431
+ )
432
+ self._process_event(
433
+ action=ChangeAction.Remove,
434
+ logical_resource_id=name,
435
+ event_status=event.status,
436
+ resource_type=before.resource_type,
437
+ reason=event.message,
438
+ )
439
+
440
+ self._defer_action(f"remove-{name}", perform_deletion)
315
441
  elif not is_nothing(after):
316
442
  # Case: addition
317
443
  self._process_event(
318
- ChangeAction.Add,
319
- name,
320
- OperationStatus.IN_PROGRESS,
444
+ action=ChangeAction.Add,
445
+ logical_resource_id=name,
446
+ event_status=OperationStatus.IN_PROGRESS,
321
447
  resource_type=after.resource_type,
322
448
  )
323
449
  event = self._execute_resource_action(
@@ -328,11 +454,11 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
328
454
  after_properties=after.properties,
329
455
  )
330
456
  self._process_event(
331
- ChangeAction.Add,
332
- name,
333
- event.status,
334
- reason=event.message,
457
+ action=ChangeAction.Add,
458
+ logical_resource_id=name,
459
+ event_status=event.status,
335
460
  resource_type=after.resource_type,
461
+ reason=event.message,
336
462
  )
337
463
 
338
464
  def _merge_before_properties(
@@ -351,13 +477,11 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
351
477
  action: ChangeAction,
352
478
  logical_resource_id: str,
353
479
  resource_type: str,
354
- before_properties: Optional[PreprocProperties],
355
- after_properties: Optional[PreprocProperties],
480
+ before_properties: PreprocProperties | None,
481
+ after_properties: PreprocProperties | None,
482
+ part_of_replacement: bool = False,
356
483
  ) -> ProgressEvent:
357
484
  LOG.debug("Executing resource action: %s for resource '%s'", action, logical_resource_id)
358
- resource_provider_executor = ResourceProviderExecutor(
359
- stack_name=self._change_set.stack.stack_name, stack_id=self._change_set.stack.stack_id
360
- )
361
485
  payload = self.create_resource_provider_payload(
362
486
  action=action,
363
487
  logical_resource_id=logical_resource_id,
@@ -365,13 +489,15 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
365
489
  before_properties=before_properties,
366
490
  after_properties=after_properties,
367
491
  )
368
- resource_provider = resource_provider_executor.try_load_resource_provider(resource_type)
492
+ resource_provider = self.resource_provider_executor.try_load_resource_provider(
493
+ resource_type
494
+ )
369
495
  track_resource_operation(action, resource_type, missing=resource_provider is not None)
370
496
 
371
497
  extra_resource_properties = {}
372
498
  if resource_provider is not None:
373
499
  try:
374
- event = resource_provider_executor.deploy_loop(
500
+ event = self.resource_provider_executor.deploy_loop(
375
501
  resource_provider, extra_resource_properties, payload
376
502
  )
377
503
  except Exception as e:
@@ -379,7 +505,7 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
379
505
  LOG.warning(
380
506
  "Resource provider operation failed: '%s'",
381
507
  reason,
382
- exc_info=LOG.isEnabledFor(logging.DEBUG),
508
+ exc_info=LOG.isEnabledFor(logging.DEBUG) and config.CFN_VERBOSE_ERRORS,
383
509
  )
384
510
  event = ProgressEvent(
385
511
  OperationStatus.FAILED,
@@ -391,9 +517,11 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
391
517
  resource_type,
392
518
  f'No resource provider found for "{resource_type}"',
393
519
  )
394
- LOG.warning(
395
- "Deployment of resource type %s successful due to config CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES"
396
- )
520
+ if "CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES" not in os.environ:
521
+ LOG.warning(
522
+ "Deployment of resource type %s succeeded, but will fail in upcoming LocalStack releases unless CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES is explicitly enabled.",
523
+ resource_type,
524
+ )
397
525
  event = ProgressEvent(
398
526
  OperationStatus.SUCCESS,
399
527
  resource_model={},
@@ -410,6 +538,19 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
410
538
  message=f"Resource type {resource_type} not supported",
411
539
  )
412
540
 
541
+ if part_of_replacement and action == ChangeAction.Remove:
542
+ # Early return as we don't want to update internal state of the executor if this is a
543
+ # cleanup of an old resource. The new resource has already been created and the state
544
+ # updated
545
+ return event
546
+
547
+ status_from_action = EventOperationFromAction[action.value]
548
+ resolved_resource = ResolvedResource(
549
+ Properties=event.resource_model,
550
+ LogicalResourceId=logical_resource_id,
551
+ Type=resource_type,
552
+ LastUpdatedTimestamp=datetime.now(UTC),
553
+ )
413
554
  match event.status:
414
555
  case OperationStatus.SUCCESS:
415
556
  # merge the resources state with the external state
@@ -422,33 +563,31 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
422
563
  # TODO: avoid the use of setdefault (debuggability/readability)
423
564
  # TODO: review the use of merge
424
565
 
425
- status_from_action = EventOperationFromAction[action.value]
426
- physical_resource_id = (
427
- extra_resource_properties["PhysicalResourceId"]
428
- if resource_provider
429
- else MOCKED_REFERENCE
430
- )
431
- resolved_resource = ResolvedResource(
432
- Properties=event.resource_model,
433
- LogicalResourceId=logical_resource_id,
434
- Type=resource_type,
435
- LastUpdatedTimestamp=datetime.now(timezone.utc),
436
- ResourceStatus=ResourceStatus(f"{status_from_action}_COMPLETE"),
437
- PhysicalResourceId=physical_resource_id,
438
- )
439
- # TODO: do we actually need this line?
440
- resolved_resource.update(extra_resource_properties)
441
-
442
- self.resources[logical_resource_id] = resolved_resource
443
-
566
+ # Don't update the resolved resources if we have deleted that resource
567
+ if action != ChangeAction.Remove:
568
+ physical_resource_id = (
569
+ extra_resource_properties["PhysicalResourceId"]
570
+ if resource_provider
571
+ else MOCKED_REFERENCE
572
+ )
573
+ resolved_resource["PhysicalResourceId"] = physical_resource_id
574
+ resolved_resource["ResourceStatus"] = ResourceStatus(
575
+ f"{status_from_action}_COMPLETE"
576
+ )
577
+ # TODO: do we actually need this line?
578
+ resolved_resource.update(extra_resource_properties)
444
579
  case OperationStatus.FAILED:
445
580
  reason = event.message
446
581
  LOG.warning(
447
582
  "Resource provider operation failed: '%s'",
448
583
  reason,
449
584
  )
585
+ resolved_resource["ResourceStatus"] = ResourceStatus(f"{status_from_action}_FAILED")
586
+ resolved_resource["ResourceStatusReason"] = reason
450
587
  case other:
451
588
  raise NotImplementedError(f"Event status '{other}' not handled")
589
+
590
+ self.resources[logical_resource_id] = resolved_resource
452
591
  return event
453
592
 
454
593
  def create_resource_provider_payload(
@@ -456,9 +595,9 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
456
595
  action: ChangeAction,
457
596
  logical_resource_id: str,
458
597
  resource_type: str,
459
- before_properties: Optional[PreprocProperties],
460
- after_properties: Optional[PreprocProperties],
461
- ) -> Optional[ResourceProviderPayload]:
598
+ before_properties: PreprocProperties | None,
599
+ after_properties: PreprocProperties | None,
600
+ ) -> ResourceProviderPayload | None:
462
601
  # FIXME: use proper credentials
463
602
  creds: Credentials = {
464
603
  "accessKeyId": self._change_set.stack.account_id,
@@ -506,3 +645,11 @@ class ChangeSetModelExecutor(ChangeSetModelPreproc):
506
645
  },
507
646
  }
508
647
  return resource_provider_payload
648
+
649
+ def _maybe_perform_on_delta(
650
+ self, delta: PreprocEntityDelta, f: Callable[[_T], _T]
651
+ ) -> PreprocEntityDelta:
652
+ # we only care about the after state
653
+ if isinstance(delta.after, str):
654
+ delta.after = f(delta.after)
655
+ return delta