localstack-core 4.6.1.dev60__py3-none-any.whl → 4.10.1.dev12__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 (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 +1545 -66
  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 +36 -23
  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 +44 -30
  57. localstack/constants.py +4 -29
  58. localstack/deprecations.py +5 -5
  59. localstack/dev/kubernetes/__main__.py +130 -7
  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 +289 -136
  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 +183 -0
  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 +11 -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 +33 -22
  175. localstack/services/cloudformation/v2/entities.py +103 -88
  176. localstack/services/cloudformation/v2/provider.py +872 -131
  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 +159 -18
  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 +157 -18
  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 +62 -26
  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 +39 -22
  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 +7 -5
  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 +36 -23
  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 -49
  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 +119 -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.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/METADATA +18 -13
  654. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/RECORD +663 -655
  655. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/entry_points.txt +8 -4
  656. localstack_core-4.10.1.dev12.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.dev60.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.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack +0 -0
  668. {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack-supervisor +0 -0
  669. {localstack_core-4.6.1.dev60.data → localstack_core-4.10.1.dev12.data}/scripts/localstack.bat +0 -0
  670. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/WHEEL +0 -0
  671. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/licenses/LICENSE.txt +0 -0
  672. {localstack_core-4.6.1.dev60.dist-info → localstack_core-4.10.1.dev12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,183 @@
1
+ import re
2
+ from typing import Any
3
+
4
+ from botocore.exceptions import ParamValidationError
5
+
6
+ from localstack.services.cloudformation.engine.v2.change_set_model import (
7
+ NodeIntrinsicFunction,
8
+ NodeProperty,
9
+ NodeResource,
10
+ NodeTemplate,
11
+ Nothing,
12
+ is_nothing,
13
+ )
14
+ from localstack.services.cloudformation.engine.v2.change_set_model_preproc import (
15
+ _PSEUDO_PARAMETERS,
16
+ ChangeSetModelPreproc,
17
+ PreprocEntityDelta,
18
+ PreprocResource,
19
+ )
20
+
21
+
22
+ class ChangeSetModelValidator(ChangeSetModelPreproc):
23
+ def validate(self):
24
+ self.process()
25
+
26
+ def visit_node_template(self, node_template: NodeTemplate):
27
+ self.visit(node_template.mappings)
28
+ self.visit(node_template.resources)
29
+ self.visit(node_template.parameters)
30
+
31
+ def visit_node_intrinsic_function_fn_get_att(
32
+ self, node_intrinsic_function: NodeIntrinsicFunction
33
+ ) -> PreprocEntityDelta:
34
+ try:
35
+ return super().visit_node_intrinsic_function_fn_get_att(node_intrinsic_function)
36
+ except RuntimeError:
37
+ return self.visit(node_intrinsic_function.arguments)
38
+
39
+ def visit_node_intrinsic_function_fn_sub(
40
+ self, node_intrinsic_function: NodeIntrinsicFunction
41
+ ) -> PreprocEntityDelta:
42
+ def _compute_sub(args: str | list[Any], select_before: bool) -> str:
43
+ # TODO: add further schema validation.
44
+ string_template: str
45
+ sub_parameters: dict
46
+ if isinstance(args, str):
47
+ string_template = args
48
+ sub_parameters = {}
49
+ elif (
50
+ isinstance(args, list)
51
+ and len(args) == 2
52
+ and isinstance(args[0], str)
53
+ and isinstance(args[1], dict)
54
+ ):
55
+ string_template = args[0]
56
+ sub_parameters = args[1]
57
+ else:
58
+ raise RuntimeError(
59
+ "Invalid arguments shape for Fn::Sub, expected a String "
60
+ f"or a Tuple of String and Map but got '{args}'"
61
+ )
62
+ sub_string = string_template
63
+ template_variable_names = re.findall("\\${([^}]+)}", string_template)
64
+ for template_variable_name in template_variable_names:
65
+ template_variable_value = Nothing
66
+
67
+ # Try to resolve the variable name as pseudo parameter.
68
+ if template_variable_name in _PSEUDO_PARAMETERS:
69
+ template_variable_value = self._resolve_pseudo_parameter(
70
+ pseudo_parameter_name=template_variable_name
71
+ )
72
+
73
+ # Try to resolve the variable name as an entry to the defined parameters.
74
+ elif template_variable_name in sub_parameters:
75
+ template_variable_value = sub_parameters[template_variable_name]
76
+
77
+ # Try to resolve the variable name as GetAtt.
78
+ elif "." in template_variable_name:
79
+ try:
80
+ template_variable_value = self._resolve_attribute(
81
+ arguments=template_variable_name, select_before=select_before
82
+ )
83
+ except RuntimeError:
84
+ pass
85
+
86
+ # Try to resolve the variable name as Ref.
87
+ else:
88
+ try:
89
+ resource_delta = self._resolve_reference(logical_id=template_variable_name)
90
+ template_variable_value = (
91
+ resource_delta.before if select_before else resource_delta.after
92
+ )
93
+ if isinstance(template_variable_value, PreprocResource):
94
+ template_variable_value = template_variable_value.physical_resource_id
95
+ except RuntimeError:
96
+ pass
97
+
98
+ if is_nothing(template_variable_value):
99
+ # override the base method just for this line to prevent accessing the
100
+ # resource properties since we are not deploying any resources
101
+ template_variable_value = ""
102
+
103
+ if not isinstance(template_variable_value, str):
104
+ template_variable_value = str(template_variable_value)
105
+
106
+ sub_string = sub_string.replace(
107
+ f"${{{template_variable_name}}}", template_variable_value
108
+ )
109
+
110
+ # FIXME: the following type reduction is ported from v1; however it appears as though such
111
+ # reduction is not performed by the engine, and certainly not at this depth given the
112
+ # lack of context. This section should be removed with Fn::Sub always retuning a string
113
+ # and the resource providers reviewed.
114
+ account_id = self._change_set.account_id
115
+ is_another_account_id = sub_string.isdigit() and len(sub_string) == len(account_id)
116
+ if sub_string == account_id or is_another_account_id:
117
+ result = sub_string
118
+ elif sub_string.isdigit():
119
+ result = int(sub_string)
120
+ else:
121
+ try:
122
+ result = float(sub_string)
123
+ except ValueError:
124
+ result = sub_string
125
+ return result
126
+
127
+ arguments_delta = self.visit(node_intrinsic_function.arguments)
128
+ arguments_before = arguments_delta.before
129
+ arguments_after = arguments_delta.after
130
+ before = self._before_cache.get(node_intrinsic_function.scope, Nothing)
131
+ if is_nothing(before) and not is_nothing(arguments_before):
132
+ before = _compute_sub(args=arguments_before, select_before=True)
133
+ after = self._after_cache.get(node_intrinsic_function.scope, Nothing)
134
+ if is_nothing(after) and not is_nothing(arguments_after):
135
+ after = _compute_sub(args=arguments_after, select_before=False)
136
+ return PreprocEntityDelta(before=before, after=after)
137
+
138
+ def visit_node_intrinsic_function_fn_transform(
139
+ self, node_intrinsic_function: NodeIntrinsicFunction
140
+ ):
141
+ # TODO Research this issue:
142
+ # Function is already resolved in the template reaching this point
143
+ # But transformation is still present in update model
144
+ return self.visit(node_intrinsic_function.arguments)
145
+
146
+ def visit_node_intrinsic_function_fn_split(
147
+ self, node_intrinsic_function: NodeIntrinsicFunction
148
+ ) -> PreprocEntityDelta:
149
+ try:
150
+ # If an argument is a Parameter it should be resolved, any other case, ignore it
151
+ return super().visit_node_intrinsic_function_fn_split(node_intrinsic_function)
152
+ except RuntimeError:
153
+ return self.visit(node_intrinsic_function.arguments)
154
+
155
+ def visit_node_intrinsic_function_fn_select(
156
+ self, node_intrinsic_function: NodeIntrinsicFunction
157
+ ) -> PreprocEntityDelta:
158
+ try:
159
+ # If an argument is a Parameter it should be resolved, any other case, ignore it
160
+ return super().visit_node_intrinsic_function_fn_select(node_intrinsic_function)
161
+ except RuntimeError:
162
+ return self.visit(node_intrinsic_function.arguments)
163
+
164
+ def visit_node_resource(self, node_resource: NodeResource) -> PreprocEntityDelta:
165
+ try:
166
+ if delta := super().visit_node_resource(node_resource):
167
+ return delta
168
+ return super().visit_node_properties(node_resource.properties)
169
+ except RuntimeError:
170
+ return super().visit_node_properties(node_resource.properties)
171
+
172
+ def visit_node_property(self, node_property: NodeProperty) -> PreprocEntityDelta:
173
+ try:
174
+ return super().visit_node_property(node_property)
175
+ except ParamValidationError:
176
+ return self.visit(node_property.value)
177
+
178
+ # ignore errors from dynamic replacements
179
+ def _maybe_perform_dynamic_replacements(self, delta: PreprocEntityDelta) -> PreprocEntityDelta:
180
+ try:
181
+ return super()._maybe_perform_dynamic_replacements(delta)
182
+ except Exception:
183
+ return delta
@@ -54,6 +54,7 @@ class ChangeSetModelVisitor(abc.ABC):
54
54
  # entities (parameters, mappings, conditions, etc.). Then compute the output fields; computing
55
55
  # only the output fields would only result in the deployment logic of the referenced outputs
56
56
  # being evaluated, hence enforce the visiting of all the resources first.
57
+ self.visit(node_template.conditions)
57
58
  self.visit(node_template.resources)
58
59
  self.visit(node_template.outputs)
59
60
 
@@ -177,6 +178,11 @@ class ChangeSetModelVisitor(abc.ABC):
177
178
  ):
178
179
  self.visit_children(node_intrinsic_function)
179
180
 
181
+ def visit_node_intrinsic_function_fn_import_value(
182
+ self, node_intrinsic_function: NodeIntrinsicFunction
183
+ ):
184
+ self.visit_children(node_intrinsic_function)
185
+
180
186
  def visit_node_divergence(self, node_divergence: NodeDivergence):
181
187
  self.visit_children(node_divergence)
182
188
 
@@ -0,0 +1,102 @@
1
+ import json
2
+ import logging
3
+ import re
4
+ from dataclasses import dataclass
5
+ from typing import Any
6
+
7
+ from botocore.exceptions import ClientError
8
+
9
+ from localstack.aws.connect import connect_to
10
+
11
+ LOG = logging.getLogger(__name__)
12
+
13
+ # CloudFormation allows using dynamic references in `Fn::Sub` expressions, so we must make sure
14
+ # we don't capture the parameter usage by excluding ${} characters
15
+ REGEX_DYNAMIC_REF = re.compile(r"{{resolve:([^:]+):([^${}]+)}}")
16
+
17
+
18
+ @dataclass
19
+ class DynamicReference:
20
+ service_name: str
21
+ reference_key: str
22
+
23
+
24
+ def extract_dynamic_reference(value: Any) -> DynamicReference | None:
25
+ if isinstance(value, str):
26
+ if dynamic_ref_match := REGEX_DYNAMIC_REF.search(value):
27
+ return DynamicReference(dynamic_ref_match[1], dynamic_ref_match[2])
28
+ return None
29
+
30
+
31
+ def perform_dynamic_reference_lookup(
32
+ reference: DynamicReference, account_id: str, region_name: str
33
+ ) -> str | None:
34
+ # basic dynamic reference support
35
+ # see: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html
36
+ # technically there are more restrictions for each of these services but checking each of these
37
+ # isn't really necessary for the current level of emulation
38
+
39
+ # only these 3 services are supported for dynamic references right now
40
+ if reference.service_name == "ssm":
41
+ ssm_client = connect_to(aws_access_key_id=account_id, region_name=region_name).ssm
42
+ try:
43
+ return ssm_client.get_parameter(Name=reference.reference_key)["Parameter"]["Value"]
44
+ except ClientError as e:
45
+ LOG.error("client error accessing SSM parameter '%s': %s", reference.reference_key, e)
46
+ raise
47
+ elif reference.service_name == "ssm-secure":
48
+ ssm_client = connect_to(aws_access_key_id=account_id, region_name=region_name).ssm
49
+ try:
50
+ return ssm_client.get_parameter(Name=reference.reference_key, WithDecryption=True)[
51
+ "Parameter"
52
+ ]["Value"]
53
+ except ClientError as e:
54
+ LOG.error("client error accessing SSM parameter '%s': %s", reference.reference_key, e)
55
+ raise
56
+ elif reference.service_name == "secretsmanager":
57
+ # reference key needs to be parsed further
58
+ # because {{resolve:secretsmanager:secret-id:secret-string:json-key:version-stage:version-id}}
59
+ # we match for "secret-id:secret-string:json-key:version-stage:version-id"
60
+ # where
61
+ # secret-id can either be the secret name or the full ARN of the secret
62
+ # secret-string *must* be SecretString
63
+ # all other values are optional
64
+ secret_id = reference.reference_key
65
+ [json_key, version_stage, version_id] = [None, None, None]
66
+ if "SecretString" in reference.reference_key:
67
+ parts = reference.reference_key.split(":SecretString:")
68
+ secret_id = parts[0]
69
+ # json-key, version-stage and version-id are optional.
70
+ [json_key, version_stage, version_id] = f"{parts[1]}::".split(":")[:3]
71
+
72
+ kwargs = {} # optional args for get_secret_value
73
+ if version_id:
74
+ kwargs["VersionId"] = version_id
75
+ if version_stage:
76
+ kwargs["VersionStage"] = version_stage
77
+
78
+ secretsmanager_client = connect_to(
79
+ aws_access_key_id=account_id, region_name=region_name
80
+ ).secretsmanager
81
+ try:
82
+ secret_value = secretsmanager_client.get_secret_value(SecretId=secret_id, **kwargs)[
83
+ "SecretString"
84
+ ]
85
+ except ClientError:
86
+ LOG.error("client error while trying to access key '%s': %s", secret_id)
87
+ raise
88
+
89
+ if json_key:
90
+ json_secret = json.loads(secret_value)
91
+ if json_key not in json_secret:
92
+ raise RuntimeError(
93
+ f"JSON value for {reference.service_name}.{reference.reference_key} not present"
94
+ )
95
+ return str(json_secret[json_key])
96
+ else:
97
+ return str(secret_value)
98
+
99
+ LOG.warning(
100
+ "Unsupported service for dynamic parameter: service_name=%s", reference.service_name
101
+ )
102
+ return None
@@ -1,5 +1,7 @@
1
1
  import yaml
2
2
 
3
+ from localstack.services.cloudformation.engine.validations import ValidationError
4
+
3
5
 
4
6
  def construct_raw(_, node):
5
7
  return node.value
@@ -60,5 +62,10 @@ customloader = NoDatesSafeLoader
60
62
  yaml.add_multi_constructor("!", shorthand_constructor, customloader)
61
63
 
62
64
 
63
- def parse_yaml(input_data: str):
64
- return yaml.load(input_data, customloader)
65
+ def parse_yaml(input_data: str) -> dict:
66
+ parsed = yaml.load(input_data, Loader=customloader)
67
+
68
+ if not isinstance(parsed, dict):
69
+ raise ValidationError("Template format error: unsupported structure.")
70
+
71
+ return parsed
@@ -137,6 +137,9 @@ ARN_CHANGESET_REGEX = re.compile(
137
137
  ARN_STACK_REGEX = re.compile(
138
138
  r"arn:(aws|aws-us-gov|aws-cn):cloudformation:[-a-zA-Z0-9]+:\d{12}:stack/[a-zA-Z][-a-zA-Z0-9]*/[-a-zA-Z0-9:/._+]+"
139
139
  )
140
+ ARN_STACK_SET_REGEX = re.compile(
141
+ r"arn:(aws|aws-us-gov|aws-cn):cloudformation:[-a-zA-Z0-9]+:\d{12}:stack-set/[a-zA-Z][-a-zA-Z0-9]*/[-a-zA-Z0-9:/._+]+"
142
+ )
140
143
 
141
144
 
142
145
  def clone_stack_params(stack_params):
@@ -156,7 +159,7 @@ def find_stack_instance(stack_set: StackSet, account: str, region: str):
156
159
 
157
160
  def stack_not_found_error(stack_name: str):
158
161
  # FIXME
159
- raise ValidationError("Stack with id %s does not exist" % stack_name)
162
+ raise ValidationError(f"Stack with id {stack_name} does not exist")
160
163
 
161
164
 
162
165
  def not_found_error(message: str):
@@ -302,8 +305,8 @@ class CloudformationProvider(CloudformationApi):
302
305
  deployer.deploy_stack()
303
306
  except Exception as e:
304
307
  stack.set_stack_status("CREATE_FAILED")
305
- msg = 'Unable to create stack "%s": %s' % (stack.stack_name, e)
306
- LOG.exception("%s")
308
+ msg = f'Unable to create stack "{stack.stack_name}": {e}'
309
+ LOG.error("%s", exc_info=LOG.isEnabledFor(logging.DEBUG))
307
310
  raise ValidationError(msg) from e
308
311
 
309
312
  return CreateStackOutput(StackId=stack.stack_id)
@@ -420,7 +423,7 @@ class CloudformationProvider(CloudformationApi):
420
423
  except Exception as e:
421
424
  stack.set_stack_status("UPDATE_FAILED")
422
425
  msg = f'Unable to update stack "{stack_name}": {e}'
423
- LOG.exception("%s", msg)
426
+ LOG.error("%s", msg, exc_info=LOG.isEnabledFor(logging.DEBUG))
424
427
  raise ValidationError(msg) from e
425
428
 
426
429
  return UpdateStackOutput(StackId=stack.stack_id)
@@ -602,6 +605,8 @@ class CloudformationProvider(CloudformationApi):
602
605
  req_params = request
603
606
  change_set_type = req_params.get("ChangeSetType", "UPDATE")
604
607
  stack_name = req_params.get("StackName")
608
+ if not stack_name:
609
+ raise ValidationError("Member must have length greater than or equal to 1")
605
610
  change_set_name = req_params.get("ChangeSetName")
606
611
  template_body = req_params.get("TemplateBody")
607
612
  # s3 or secretsmanager url
@@ -924,7 +929,7 @@ class CloudformationProvider(CloudformationApi):
924
929
  self, context: RequestContext, next_token: NextToken = None, **kwargs
925
930
  ) -> ListExportsOutput:
926
931
  state = get_cloudformation_store(context.account_id, context.region)
927
- return ListExportsOutput(Exports=state.exports)
932
+ return ListExportsOutput(Exports=state.exports.values())
928
933
 
929
934
  @handler("ListImports")
930
935
  def list_imports(
@@ -1049,7 +1054,7 @@ class CloudformationProvider(CloudformationApi):
1049
1054
  Description=valid_template.get("Description"), Parameters=parameters
1050
1055
  )
1051
1056
  except Exception as e:
1052
- LOG.exception("Error validating template")
1057
+ LOG.error("Error validating template", exc_info=LOG.isEnabledFor(logging.DEBUG))
1053
1058
  raise ValidationError("Template Validation Error") from e
1054
1059
 
1055
1060
  # =======================================
@@ -9,9 +9,9 @@ import builtins
9
9
  import json
10
10
  import re
11
11
  import uuid
12
+ from collections.abc import Callable
12
13
  from copy import deepcopy
13
14
  from pathlib import Path
14
- from typing import Callable, List, Optional
15
15
 
16
16
  from botocore.model import Shape, StructureShape
17
17
 
@@ -73,9 +73,12 @@ def recurse_properties(properties: dict, fn: Callable) -> dict:
73
73
  return _recurse_properties(deepcopy(properties), fn)
74
74
 
75
75
 
76
- def keys_pascalcase_to_lower_camelcase(model: dict) -> dict:
76
+ def keys_pascalcase_to_lower_camelcase(model: dict, skip_keys: set = None) -> dict:
77
77
  """Recursively change any dicts keys to lower camelcase"""
78
78
 
79
+ if skip_keys:
80
+ return _pascal_to_camel_keys_preserve_values(model, skip_keys)
81
+
79
82
  def _keys_pascalcase_to_lower_camelcase(obj):
80
83
  if isinstance(obj, dict):
81
84
  return {convert_pascalcase_to_lower_camelcase(k): v for k, v in obj.items()}
@@ -85,6 +88,33 @@ def keys_pascalcase_to_lower_camelcase(model: dict) -> dict:
85
88
  return _recurse_properties(model, _keys_pascalcase_to_lower_camelcase)
86
89
 
87
90
 
91
+ def _pascal_to_camel_keys_preserve_values(model: dict, skip_keys: set = None) -> dict:
92
+ """
93
+ Variant of keys_pascalcase_to_lower_camelcase
94
+ All VALUES of provided keys are skipped and not transformed to lower camelcase.
95
+ The keys themselves will be transformed.
96
+ The function simply stops recursion if a key matches, so make sure no lower level values are ignored.
97
+ """
98
+ skip_keys = skip_keys or set()
99
+
100
+ def _transform(obj):
101
+ if isinstance(obj, dict):
102
+ new_dict = {}
103
+ for k, v in obj.items():
104
+ new_key = convert_pascalcase_to_lower_camelcase(k)
105
+ if k in skip_keys:
106
+ new_dict[new_key] = v
107
+ else:
108
+ new_dict[new_key] = _transform(v)
109
+ return new_dict
110
+ elif isinstance(obj, list):
111
+ return [_transform(i) for i in obj]
112
+ else:
113
+ return obj
114
+
115
+ return _transform(model)
116
+
117
+
88
118
  def keys_lower_camelcase_to_pascalcase(model: dict) -> dict:
89
119
  """Recursively change any dicts keys to PascalCase"""
90
120
 
@@ -152,7 +182,7 @@ def fix_boto_parameters_based_on_report(original_params: dict, report: str) -> d
152
182
  cast_class = getattr(builtins, valid_class)
153
183
  old_value = get_nested(params, param_name)
154
184
 
155
- if cast_class == bool and str(old_value).lower() in ["true", "false"]:
185
+ if isinstance(cast_class, bool) and str(old_value).lower() in ["true", "false"]:
156
186
  new_value = str(old_value).lower() == "true"
157
187
  else:
158
188
  new_value = cast_class(old_value)
@@ -213,7 +243,7 @@ def convert_request_kwargs(parameters: dict, input_shape: StructureShape) -> dic
213
243
  return transformed_dict
214
244
 
215
245
 
216
- def convert_values_to_numbers(input_dict: dict, keys_to_skip: Optional[List[str]] = None):
246
+ def convert_values_to_numbers(input_dict: dict, keys_to_skip: list[str] | None = None):
217
247
  """
218
248
  Recursively converts all string values that represent valid integers
219
249
  in a dictionary (including nested dictionaries and lists) to integers.
@@ -5,11 +5,12 @@ import logging
5
5
  import re
6
6
  import time
7
7
  import uuid
8
+ from collections.abc import Callable
8
9
  from dataclasses import dataclass, field
9
10
  from enum import Enum, auto
10
11
  from logging import Logger
11
12
  from math import ceil
12
- from typing import TYPE_CHECKING, Any, Callable, Generic, Optional, Type, TypedDict, TypeVar
13
+ from typing import TYPE_CHECKING, Any, Generic, TypedDict, TypeVar
13
14
 
14
15
  import botocore
15
16
  from botocore.client import BaseClient
@@ -51,7 +52,7 @@ LOG = logging.getLogger(__name__)
51
52
 
52
53
  Properties = TypeVar("Properties")
53
54
 
54
- PUBLIC_REGISTRY: dict[str, Type[ResourceProvider]] = {}
55
+ PUBLIC_REGISTRY: dict[str, type[ResourceProvider]] = {}
55
56
 
56
57
  PROVIDER_DEFAULTS = {} # TODO: remove this after removing patching in -ext
57
58
 
@@ -66,12 +67,12 @@ class OperationStatus(Enum):
66
67
  @dataclass
67
68
  class ProgressEvent(Generic[Properties]):
68
69
  status: OperationStatus
69
- resource_model: Optional[Properties] = None
70
- resource_models: Optional[list[Properties]] = None
70
+ resource_model: Properties | None = None
71
+ resource_models: list[Properties] | None = None
71
72
 
72
73
  message: str = ""
73
- result: Optional[str] = None
74
- error_code: Optional[str] = None # TODO: enum
74
+ result: str | None = None
75
+ error_code: str | None = None # TODO: enum
75
76
  custom_context: dict = field(default_factory=dict)
76
77
 
77
78
 
@@ -84,7 +85,7 @@ class Credentials(TypedDict):
84
85
  class ResourceProviderPayloadRequestData(TypedDict):
85
86
  logicalResourceId: str
86
87
  resourceProperties: Properties
87
- previousResourceProperties: Optional[Properties]
88
+ previousResourceProperties: Properties | None
88
89
  callerCredentials: Credentials
89
90
  providerCredentials: Credentials
90
91
  systemTags: dict[str, str]
@@ -184,8 +185,8 @@ class ResourceRequest(Generic[Properties]):
184
185
 
185
186
  custom_context: dict = field(default_factory=dict)
186
187
 
187
- previous_state: Optional[Properties] = None
188
- previous_tags: Optional[dict[str, str]] = None
188
+ previous_state: Properties | None = None
189
+ previous_tags: dict[str, str] | None = None
189
190
  tags: dict[str, str] = field(default_factory=dict)
190
191
 
191
192
 
@@ -235,7 +236,7 @@ def get_resource_type(resource: dict) -> str:
235
236
  LOG.warning(
236
237
  "Failed to retrieve resource type %s",
237
238
  resource.get("Type"),
238
- exc_info=LOG.isEnabledFor(logging.DEBUG),
239
+ exc_info=LOG.isEnabledFor(logging.DEBUG) and config.CFN_VERBOSE_ERRORS,
239
240
  )
240
241
 
241
242
 
@@ -465,15 +466,18 @@ class ResourceProviderExecutor:
465
466
  "A ResourceProvider should always have a SCHEMA property defined."
466
467
  )
467
468
  resource_type_schema = resource_provider.SCHEMA
468
- physical_resource_id = self.extract_physical_resource_id_from_model_with_schema(
469
- event.resource_model,
470
- raw_payload["resourceType"],
471
- resource_type_schema,
472
- )
469
+ if raw_payload["action"] != "Remove":
470
+ physical_resource_id = (
471
+ self.extract_physical_resource_id_from_model_with_schema(
472
+ event.resource_model,
473
+ raw_payload["resourceType"],
474
+ resource_type_schema,
475
+ )
476
+ )
473
477
 
474
- resource["PhysicalResourceId"] = physical_resource_id
475
- resource["Properties"] = event.resource_model
476
- resource["_last_deployed_state"] = copy.deepcopy(event.resource_model)
478
+ resource["PhysicalResourceId"] = physical_resource_id
479
+ resource["Properties"] = event.resource_model
480
+ resource["_last_deployed_state"] = copy.deepcopy(event.resource_model)
477
481
  return event
478
482
  case OperationStatus.IN_PROGRESS:
479
483
  # update the shared state
@@ -514,10 +518,14 @@ class ResourceProviderExecutor:
514
518
  try:
515
519
  return resource_provider.update(request)
516
520
  except NotImplementedError:
521
+ feature_request_url = "https://github.com/localstack/localstack/issues/new?template=feature-request.yml"
517
522
  LOG.warning(
518
- 'Unable to update resource type "%s", id "%s"',
523
+ 'Unable to update resource type "%s", id "%s", '
524
+ "the update operation is not implemented for this resource. "
525
+ "Please consider submitting a feature request at this URL: %s",
519
526
  request.resource_type,
520
527
  request.logical_resource_id,
528
+ feature_request_url,
521
529
  )
522
530
  if request.previous_state is None:
523
531
  # this is an issue with our update detection. We should never be in this state.
@@ -559,6 +567,8 @@ class ResourceProviderExecutor:
559
567
  @staticmethod
560
568
  def try_load_resource_provider(resource_type: str) -> ResourceProvider | None:
561
569
  # TODO: unify namespace of plugins
570
+ if resource_type and resource_type.startswith("Custom"):
571
+ resource_type = "AWS::CloudFormation::CustomResource"
562
572
 
563
573
  # 1. try to load pro resource provider
564
574
  # prioritise pro resource providers
@@ -573,7 +583,7 @@ class ResourceProviderExecutor:
573
583
  LOG.warning(
574
584
  "Failed to load PRO resource type %s as a ResourceProvider.",
575
585
  resource_type,
576
- exc_info=LOG.isEnabledFor(logging.DEBUG),
586
+ exc_info=LOG.isEnabledFor(logging.DEBUG) and config.CFN_VERBOSE_ERRORS,
577
587
  )
578
588
 
579
589
  # 2. try to load community resource provider
@@ -588,7 +598,7 @@ class ResourceProviderExecutor:
588
598
  LOG.warning(
589
599
  "Failed to load community resource type %s as a ResourceProvider.",
590
600
  resource_type,
591
- exc_info=LOG.isEnabledFor(logging.DEBUG),
601
+ exc_info=LOG.isEnabledFor(logging.DEBUG) and config.CFN_VERBOSE_ERRORS,
592
602
  )
593
603
 
594
604
  # we could not find the resource provider
@@ -2,7 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  from pathlib import Path
5
- from typing import Optional, TypedDict
5
+ from typing import TypedDict
6
6
 
7
7
  import localstack.services.cloudformation.provider_utils as util
8
8
  from localstack.services.cloudformation.resource_provider import (
@@ -15,12 +15,12 @@ from localstack.services.cloudformation.stores import get_cloudformation_store
15
15
 
16
16
 
17
17
  class CloudFormationMacroProperties(TypedDict):
18
- FunctionName: Optional[str]
19
- Name: Optional[str]
20
- Description: Optional[str]
21
- Id: Optional[str]
22
- LogGroupName: Optional[str]
23
- LogRoleARN: Optional[str]
18
+ FunctionName: str | None
19
+ Name: str | None
20
+ Description: str | None
21
+ Id: str | None
22
+ LogGroupName: str | None
23
+ LogRoleARN: str | None
24
24
 
25
25
 
26
26
  REPEATED_INVOCATION = "repeated_invocation"
@@ -1,5 +1,3 @@
1
- from typing import Optional, Type
2
-
3
1
  from localstack.services.cloudformation.resource_provider import (
4
2
  CloudFormationResourceProviderPlugin,
5
3
  ResourceProvider,
@@ -10,7 +8,7 @@ class CloudFormationMacroProviderPlugin(CloudFormationResourceProviderPlugin):
10
8
  name = "AWS::CloudFormation::Macro"
11
9
 
12
10
  def __init__(self):
13
- self.factory: Optional[Type[ResourceProvider]] = None
11
+ self.factory: type[ResourceProvider] | None = None
14
12
 
15
13
  def load(self):
16
14
  from localstack.services.cloudformation.resource_providers.aws_cloudformation_macro import (