localstack-core 4.10.1.dev42__py3-none-any.whl → 4.12.1.dev18__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 (158) hide show
  1. localstack/aws/api/apigateway/__init__.py +42 -0
  2. localstack/aws/api/cloudformation/__init__.py +161 -0
  3. localstack/aws/api/ec2/__init__.py +1178 -12
  4. localstack/aws/api/iam/__init__.py +228 -0
  5. localstack/aws/api/kms/__init__.py +1 -0
  6. localstack/aws/api/lambda_/__init__.py +1034 -66
  7. localstack/aws/api/logs/__init__.py +500 -0
  8. localstack/aws/api/opensearch/__init__.py +100 -0
  9. localstack/aws/api/redshift/__init__.py +69 -0
  10. localstack/aws/api/resourcegroupstaggingapi/__init__.py +36 -0
  11. localstack/aws/api/route53/__init__.py +45 -0
  12. localstack/aws/api/route53resolver/__init__.py +1 -0
  13. localstack/aws/api/s3/__init__.py +64 -0
  14. localstack/aws/api/s3control/__init__.py +19 -0
  15. localstack/aws/api/secretsmanager/__init__.py +37 -23
  16. localstack/aws/api/stepfunctions/__init__.py +52 -10
  17. localstack/aws/api/sts/__init__.py +52 -0
  18. localstack/aws/connect.py +35 -15
  19. localstack/aws/handlers/logging.py +8 -4
  20. localstack/aws/handlers/service.py +11 -2
  21. localstack/aws/protocol/serializer.py +1 -1
  22. localstack/config.py +8 -0
  23. localstack/constants.py +3 -0
  24. localstack/deprecations.py +0 -6
  25. localstack/dev/kubernetes/__main__.py +39 -14
  26. localstack/runtime/analytics.py +11 -0
  27. localstack/services/acm/provider.py +17 -1
  28. localstack/services/apigateway/legacy/provider.py +28 -15
  29. localstack/services/cloudformation/engine/template_preparer.py +6 -2
  30. localstack/services/cloudformation/engine/v2/change_set_model.py +9 -0
  31. localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +15 -1
  32. localstack/services/cloudformation/engine/v2/change_set_resource_support_checker.py +114 -0
  33. localstack/services/cloudformation/provider.py +26 -1
  34. localstack/services/cloudformation/provider_utils.py +20 -0
  35. localstack/services/cloudformation/resource_provider.py +5 -4
  36. localstack/services/cloudformation/scaffolding/__main__.py +94 -22
  37. localstack/services/cloudformation/v2/provider.py +41 -0
  38. localstack/services/cloudwatch/provider.py +10 -3
  39. localstack/services/cloudwatch/provider_v2.py +6 -3
  40. localstack/services/configservice/provider.py +5 -1
  41. localstack/services/dynamodb/provider.py +1 -0
  42. localstack/services/dynamodb/v2/provider.py +1 -0
  43. localstack/services/dynamodbstreams/provider.py +6 -0
  44. localstack/services/dynamodbstreams/v2/provider.py +6 -0
  45. localstack/services/ec2/provider.py +6 -0
  46. localstack/services/es/provider.py +6 -0
  47. localstack/services/events/provider.py +4 -0
  48. localstack/services/events/v1/provider.py +9 -0
  49. localstack/services/firehose/provider.py +5 -0
  50. localstack/services/iam/provider.py +4 -0
  51. localstack/services/kinesis/packages.py +1 -1
  52. localstack/services/kms/models.py +16 -22
  53. localstack/services/kms/provider.py +4 -0
  54. localstack/services/lambda_/analytics.py +11 -2
  55. localstack/services/lambda_/api_utils.py +37 -20
  56. localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
  57. localstack/services/lambda_/invocation/assignment.py +4 -1
  58. localstack/services/lambda_/invocation/event_manager.py +15 -11
  59. localstack/services/lambda_/invocation/execution_environment.py +21 -2
  60. localstack/services/lambda_/invocation/lambda_models.py +31 -2
  61. localstack/services/lambda_/invocation/lambda_service.py +62 -3
  62. localstack/services/lambda_/invocation/models.py +9 -1
  63. localstack/services/lambda_/invocation/version_manager.py +18 -3
  64. localstack/services/lambda_/provider.py +307 -106
  65. localstack/services/lambda_/resource_providers/aws_lambda_function.py +33 -1
  66. localstack/services/lambda_/runtimes.py +3 -1
  67. localstack/services/logs/provider.py +9 -0
  68. localstack/services/opensearch/packages.py +34 -20
  69. localstack/services/opensearch/provider.py +53 -3
  70. localstack/services/resource_groups/provider.py +5 -1
  71. localstack/services/resourcegroupstaggingapi/provider.py +6 -1
  72. localstack/services/route53/provider.py +7 -0
  73. localstack/services/route53resolver/provider.py +5 -0
  74. localstack/services/s3/constants.py +5 -0
  75. localstack/services/s3/exceptions.py +9 -0
  76. localstack/services/s3/models.py +9 -1
  77. localstack/services/s3/provider.py +51 -43
  78. localstack/services/s3/utils.py +81 -15
  79. localstack/services/s3control/provider.py +107 -2
  80. localstack/services/s3control/validation.py +50 -0
  81. localstack/services/scheduler/provider.py +4 -2
  82. localstack/services/secretsmanager/provider.py +4 -0
  83. localstack/services/ses/provider.py +4 -0
  84. localstack/services/sns/constants.py +16 -1
  85. localstack/services/sns/provider.py +5 -0
  86. localstack/services/sns/publisher.py +15 -6
  87. localstack/services/sns/v2/models.py +9 -0
  88. localstack/services/sns/v2/provider.py +750 -19
  89. localstack/services/sns/v2/utils.py +12 -0
  90. localstack/services/sqs/constants.py +6 -0
  91. localstack/services/sqs/provider.py +9 -1
  92. localstack/services/sqs/resource_providers/aws_sqs_queue.py +61 -46
  93. localstack/services/ssm/provider.py +6 -0
  94. localstack/services/stepfunctions/asl/component/common/path/result_path.py +1 -1
  95. localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +0 -1
  96. localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +0 -1
  97. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +8 -8
  98. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/{mock_eval_utils.py → local_mock_eval_utils.py} +13 -9
  99. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +6 -6
  100. localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +1 -1
  101. localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +4 -0
  102. localstack/services/stepfunctions/asl/component/test_state/state/base_mock.py +118 -0
  103. localstack/services/stepfunctions/asl/component/test_state/state/common.py +82 -0
  104. localstack/services/stepfunctions/asl/component/test_state/state/execution.py +139 -0
  105. localstack/services/stepfunctions/asl/component/test_state/state/map.py +77 -0
  106. localstack/services/stepfunctions/asl/component/test_state/state/task.py +44 -0
  107. localstack/services/stepfunctions/asl/eval/environment.py +30 -22
  108. localstack/services/stepfunctions/asl/eval/states.py +1 -1
  109. localstack/services/stepfunctions/asl/eval/test_state/environment.py +49 -9
  110. localstack/services/stepfunctions/asl/eval/test_state/program_state.py +22 -0
  111. localstack/services/stepfunctions/asl/jsonata/jsonata.py +5 -1
  112. localstack/services/stepfunctions/asl/parse/preprocessor.py +67 -24
  113. localstack/services/stepfunctions/asl/parse/test_state/asl_parser.py +5 -4
  114. localstack/services/stepfunctions/asl/parse/test_state/preprocessor.py +222 -31
  115. localstack/services/stepfunctions/asl/static_analyser/test_state/test_state_analyser.py +256 -22
  116. localstack/services/stepfunctions/backend/execution.py +10 -11
  117. localstack/services/stepfunctions/backend/execution_worker.py +5 -5
  118. localstack/services/stepfunctions/backend/test_state/execution.py +36 -0
  119. localstack/services/stepfunctions/backend/test_state/execution_worker.py +33 -1
  120. localstack/services/stepfunctions/backend/test_state/test_state_mock.py +127 -0
  121. localstack/services/stepfunctions/local_mocking/__init__.py +9 -0
  122. localstack/services/stepfunctions/{mocking → local_mocking}/mock_config.py +24 -17
  123. localstack/services/stepfunctions/provider.py +83 -25
  124. localstack/services/stepfunctions/test_state/mock_config.py +47 -0
  125. localstack/services/sts/provider.py +7 -0
  126. localstack/services/support/provider.py +5 -1
  127. localstack/services/swf/provider.py +5 -1
  128. localstack/services/transcribe/provider.py +7 -0
  129. localstack/testing/aws/lambda_utils.py +1 -1
  130. localstack/testing/aws/util.py +2 -1
  131. localstack/testing/config.py +1 -0
  132. localstack/testing/pytest/fixtures.py +28 -0
  133. localstack/testing/snapshots/transformer_utility.py +5 -0
  134. localstack/utils/analytics/publisher.py +37 -155
  135. localstack/utils/analytics/service_request_aggregator.py +6 -4
  136. localstack/utils/aws/arns.py +7 -0
  137. localstack/utils/aws/client_types.py +2 -4
  138. localstack/utils/batching.py +258 -0
  139. localstack/utils/bootstrap.py +2 -2
  140. localstack/utils/catalog/catalog.py +3 -2
  141. localstack/utils/collections.py +23 -11
  142. localstack/utils/container_utils/container_client.py +22 -13
  143. localstack/utils/container_utils/docker_cmd_client.py +6 -6
  144. localstack/version.py +2 -2
  145. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/METADATA +7 -7
  146. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/RECORD +155 -146
  147. localstack_core-4.12.1.dev18.dist-info/plux.json +1 -0
  148. localstack/services/stepfunctions/mocking/__init__.py +0 -0
  149. localstack/utils/batch_policy.py +0 -124
  150. localstack_core-4.10.1.dev42.dist-info/plux.json +0 -1
  151. /localstack/services/stepfunctions/{mocking → local_mocking}/mock_config_file.py +0 -0
  152. {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack +0 -0
  153. {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack-supervisor +0 -0
  154. {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack.bat +0 -0
  155. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/WHEEL +0 -0
  156. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/entry_points.txt +0 -0
  157. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/licenses/LICENSE.txt +0 -0
  158. {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ import io
5
5
  import logging
6
6
  import os.path
7
7
  import random
8
+ import time
8
9
  import uuid
9
10
  from concurrent.futures import Executor, Future, ThreadPoolExecutor
10
11
  from datetime import datetime
@@ -19,6 +20,7 @@ from localstack.aws.api.lambda_ import (
19
20
  InvalidRequestContentException,
20
21
  InvocationType,
21
22
  LastUpdateStatus,
23
+ NoPublishedVersionException,
22
24
  ResourceConflictException,
23
25
  ResourceNotFoundException,
24
26
  State,
@@ -27,6 +29,7 @@ from localstack.aws.connect import connect_to
27
29
  from localstack.constants import AWS_REGION_US_EAST_1
28
30
  from localstack.services.lambda_ import hooks as lambda_hooks
29
31
  from localstack.services.lambda_.analytics import (
32
+ FunctionInitializationType,
30
33
  FunctionOperation,
31
34
  FunctionStatus,
32
35
  function_counter,
@@ -190,6 +193,9 @@ class LambdaService:
190
193
  lambda_hooks.create_function_version.run(function_version.qualified_arn)
191
194
  return self.task_executor.submit(self._start_lambda_version, version_manager)
192
195
 
196
+ def publish_version_async(self, function_version: FunctionVersion):
197
+ self.task_executor.submit(self.publish_version, function_version)
198
+
193
199
  def publish_version(self, function_version: FunctionVersion):
194
200
  """
195
201
  Synchronously create a function version (manager)
@@ -200,6 +206,14 @@ class LambdaService:
200
206
 
201
207
  :param function_version: Function Version to create
202
208
  """
209
+ # HACK: trying to match the AWS timing behavior of Lambda Managed Instances for the operation
210
+ # publish_version followed by get_function because transitioning LastUpdateStatus from InProgress to
211
+ # Successful happens too fast on LocalStack (thanks to caching in prepare_version).
212
+ # Without this hack, test_latest_published_update_config fails at get_function_response_postpublish
213
+ # and test_lifecycle_invoke is flaky, sometimes not triggering the ResourceConflictException
214
+ # Increasing this sleep too much (e.g., 10s) shouldn't cause any side effects apart from slow responsiveness
215
+ if function_version.config.CapacityProviderConfig:
216
+ time.sleep(0.1)
203
217
  with self.lambda_version_manager_lock:
204
218
  qualified_arn = function_version.id.qualified_arn()
205
219
  version_manager = self.lambda_starting_versions.get(qualified_arn)
@@ -225,7 +239,7 @@ class LambdaService:
225
239
  def invoke(
226
240
  self,
227
241
  function_name: str,
228
- qualifier: str,
242
+ qualifier: str | None,
229
243
  region: str,
230
244
  account_id: str,
231
245
  invocation_type: InvocationType | None,
@@ -258,13 +272,27 @@ class LambdaService:
258
272
  account=account_id,
259
273
  region=region,
260
274
  )
261
- qualifier = qualifier or "$LATEST"
262
275
  state = lambda_stores[account_id][region]
263
276
  function = state.functions.get(function_name)
264
277
 
265
278
  if function is None:
279
+ if not qualifier:
280
+ invoked_arn += ":$LATEST"
266
281
  raise ResourceNotFoundException(f"Function not found: {invoked_arn}", Type="User")
267
282
 
283
+ # A provided qualifier always takes precedence, but the default depends on whether $LATEST.PUBLISHED exists
284
+ version_latest_published = function.versions.get("$LATEST.PUBLISHED")
285
+ if version_latest_published:
286
+ qualifier = qualifier or "$LATEST.PUBLISHED"
287
+ invoked_arn = lambda_arn(
288
+ function_name=function_name,
289
+ qualifier=qualifier,
290
+ account=account_id,
291
+ region=region,
292
+ )
293
+ else:
294
+ qualifier = qualifier or "$LATEST"
295
+
268
296
  if qualifier_is_alias(qualifier):
269
297
  alias = function.aliases.get(qualifier)
270
298
  if not alias:
@@ -282,8 +310,27 @@ class LambdaService:
282
310
  # Need the qualified arn to exactly get the target lambda
283
311
  qualified_arn = qualified_lambda_arn(function_name, version_qualifier, account_id, region)
284
312
  version = function.versions.get(version_qualifier)
313
+ if version is None:
314
+ raise ResourceNotFoundException(f"Function not found: {invoked_arn}", Type="User")
285
315
  runtime = version.config.runtime or "n/a"
286
316
  package_type = version.config.package_type
317
+ # Not considering provisioned concurrency for such early errors
318
+ initialization_type = (
319
+ FunctionInitializationType.lambda_managed_instances
320
+ if version.config.CapacityProviderConfig
321
+ else FunctionInitializationType.on_demand
322
+ )
323
+ if version.config.CapacityProviderConfig and qualifier == "$LATEST":
324
+ if function.versions.get("$LATEST.PUBLISHED"):
325
+ raise InvalidParameterValueException(
326
+ "Functions configured with capacity provider configuration can't be invoked with $LATEST qualifier. To invoke this function, specify a published version qualifier or $LATEST.PUBLISHED.",
327
+ Type="User",
328
+ )
329
+ else:
330
+ raise NoPublishedVersionException(
331
+ "The function can't be invoked because no published version exists. For functions with capacity provider configuration, either publish a version to $LATEST.PUBLISHED, or specify a published version qualifier.",
332
+ Type="User",
333
+ )
287
334
  try:
288
335
  version_manager = self.get_lambda_version_manager(qualified_arn)
289
336
  event_manager = self.get_lambda_event_manager(qualified_arn)
@@ -315,6 +362,7 @@ class LambdaService:
315
362
  status=status,
316
363
  invocation_type=invocation_type,
317
364
  package_type=package_type,
365
+ initialization_type=initialization_type,
318
366
  ).increment()
319
367
  raise ResourceConflictException(
320
368
  f"The operation cannot be performed at this time. The function is currently in the following state: {state}"
@@ -333,6 +381,7 @@ class LambdaService:
333
381
  status=FunctionStatus.invalid_payload_error,
334
382
  invocation_type=invocation_type,
335
383
  package_type=package_type,
384
+ initialization_type=initialization_type,
336
385
  ).increment()
337
386
  # MAYBE: improve parity of detailed exception message (quite cumbersome)
338
387
  raise InvalidRequestContentException(
@@ -377,12 +426,14 @@ class LambdaService:
377
426
  if invocation_result.is_error
378
427
  else FunctionStatus.success
379
428
  )
429
+ # TODO: handle initialization_type provisioned-concurrency, requires enriching invocation_result
380
430
  function_counter.labels(
381
431
  operation=FunctionOperation.invoke,
382
432
  runtime=runtime,
383
433
  status=status,
384
434
  invocation_type=invocation_type,
385
435
  package_type=package_type,
436
+ initialization_type=initialization_type,
386
437
  ).increment()
387
438
  return invocation_result
388
439
 
@@ -393,7 +444,10 @@ class LambdaService:
393
444
 
394
445
  :param new_version: New version (with the same qualifier as an older one)
395
446
  """
396
- if new_version.qualified_arn not in self.lambda_running_versions:
447
+ if (
448
+ new_version.qualified_arn not in self.lambda_running_versions
449
+ and not new_version.config.CapacityProviderConfig
450
+ ):
397
451
  raise ValueError(
398
452
  f"Version {new_version.qualified_arn} cannot be updated if an old one is not running"
399
453
  )
@@ -437,6 +491,11 @@ class LambdaService:
437
491
  elif new_state.state == State.Failed:
438
492
  update_status = UpdateStatus(status=LastUpdateStatus.Failed)
439
493
  self.task_executor.submit(new_version_manager.stop)
494
+ elif (
495
+ new_state.state == State.ActiveNonInvocable
496
+ and function_version.config.CapacityProviderConfig
497
+ ):
498
+ update_status = UpdateStatus(status=LastUpdateStatus.Successful)
440
499
  else:
441
500
  # TODO what to do if state pending or inactive is supported?
442
501
  self.task_executor.submit(new_version_manager.stop)
@@ -1,5 +1,10 @@
1
1
  from localstack.aws.api.lambda_ import EventSourceMappingConfiguration
2
- from localstack.services.lambda_.invocation.lambda_models import CodeSigningConfig, Function, Layer
2
+ from localstack.services.lambda_.invocation.lambda_models import (
3
+ CapacityProvider,
4
+ CodeSigningConfig,
5
+ Function,
6
+ Layer,
7
+ )
3
8
  from localstack.services.stores import AccountRegionBundle, BaseStore, LocalAttribute
4
9
  from localstack.utils.tagging import TaggingService
5
10
 
@@ -17,6 +22,9 @@ class LambdaStore(BaseStore):
17
22
  # maps layer names to Layers
18
23
  layers: dict[str, Layer] = LocalAttribute(default=dict)
19
24
 
25
+ # maps capacity provider names to respective CapacityProvider
26
+ capacity_providers: dict[str, CapacityProvider] = LocalAttribute(default=dict)
27
+
20
28
  # maps resource ARNs for EventSourceMappings and CodeSigningConfiguration to tags
21
29
  TAGS = LocalAttribute(default=TaggingService)
22
30
 
@@ -100,11 +100,26 @@ class LambdaVersionManager:
100
100
 
101
101
  # code and reason not set for success scenario because only failed states provide this field:
102
102
  # https://docs.aws.amazon.com/lambda/latest/dg/API_GetFunctionConfiguration.html#SSS-GetFunctionConfiguration-response-LastUpdateStatusReasonCode
103
- self.state = VersionState(state=State.Active)
103
+ new_state = State.Active
104
+ if (
105
+ self.function_version.config.CapacityProviderConfig
106
+ and self.function_version.id.qualifier == "$LATEST"
107
+ ):
108
+ new_state = State.ActiveNonInvocable
109
+ # HACK: trying to match the AWS timing behavior of Lambda Managed Instances for the operation
110
+ # update_function_configuration followed by get_function because transitioning LastUpdateStatus from
111
+ # InProgress to Successful happens too fast on LocalStack (thanks to caching in prepare_version).
112
+ # Without this hack, test_latest_published_update_config fails at get_function_response_postupdate_latest
113
+ # TODO: this sleep has side-effects and we should be looking into alternatives
114
+ # Increasing this sleep too much (e.g., 3s) could cause the side effect that a created function is not
115
+ # ready for updates (i.e., rejected with a ResourceConflictException) and failing other tests
116
+ # time.sleep(0.1)
117
+ self.state = VersionState(state=new_state)
104
118
  LOG.debug(
105
- "Changing Lambda %s (id %s) to active",
119
+ "Changing Lambda %s (id %s) to %s",
106
120
  self.function_arn,
107
121
  self.function_version.config.internal_revision,
122
+ new_state,
108
123
  )
109
124
  except Exception as e:
110
125
  self.state = VersionState(
@@ -113,7 +128,7 @@ class LambdaVersionManager:
113
128
  reason=f"Error while creating lambda: {e}",
114
129
  )
115
130
  LOG.debug(
116
- "Changing Lambda %s (id %s) to failed. Reason: %s",
131
+ "Changing Lambda %s (id %s) to Failed. Reason: %s",
117
132
  self.function_arn,
118
133
  self.function_version.config.internal_revision,
119
134
  e,