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.
- localstack/aws/api/apigateway/__init__.py +42 -0
- localstack/aws/api/cloudformation/__init__.py +161 -0
- localstack/aws/api/ec2/__init__.py +1178 -12
- localstack/aws/api/iam/__init__.py +228 -0
- localstack/aws/api/kms/__init__.py +1 -0
- localstack/aws/api/lambda_/__init__.py +1034 -66
- localstack/aws/api/logs/__init__.py +500 -0
- localstack/aws/api/opensearch/__init__.py +100 -0
- localstack/aws/api/redshift/__init__.py +69 -0
- localstack/aws/api/resourcegroupstaggingapi/__init__.py +36 -0
- localstack/aws/api/route53/__init__.py +45 -0
- localstack/aws/api/route53resolver/__init__.py +1 -0
- localstack/aws/api/s3/__init__.py +64 -0
- localstack/aws/api/s3control/__init__.py +19 -0
- localstack/aws/api/secretsmanager/__init__.py +37 -23
- localstack/aws/api/stepfunctions/__init__.py +52 -10
- localstack/aws/api/sts/__init__.py +52 -0
- localstack/aws/connect.py +35 -15
- localstack/aws/handlers/logging.py +8 -4
- localstack/aws/handlers/service.py +11 -2
- localstack/aws/protocol/serializer.py +1 -1
- localstack/config.py +8 -0
- localstack/constants.py +3 -0
- localstack/deprecations.py +0 -6
- localstack/dev/kubernetes/__main__.py +39 -14
- localstack/runtime/analytics.py +11 -0
- localstack/services/acm/provider.py +17 -1
- localstack/services/apigateway/legacy/provider.py +28 -15
- localstack/services/cloudformation/engine/template_preparer.py +6 -2
- localstack/services/cloudformation/engine/v2/change_set_model.py +9 -0
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +15 -1
- localstack/services/cloudformation/engine/v2/change_set_resource_support_checker.py +114 -0
- localstack/services/cloudformation/provider.py +26 -1
- localstack/services/cloudformation/provider_utils.py +20 -0
- localstack/services/cloudformation/resource_provider.py +5 -4
- localstack/services/cloudformation/scaffolding/__main__.py +94 -22
- localstack/services/cloudformation/v2/provider.py +41 -0
- localstack/services/cloudwatch/provider.py +10 -3
- localstack/services/cloudwatch/provider_v2.py +6 -3
- localstack/services/configservice/provider.py +5 -1
- localstack/services/dynamodb/provider.py +1 -0
- localstack/services/dynamodb/v2/provider.py +1 -0
- localstack/services/dynamodbstreams/provider.py +6 -0
- localstack/services/dynamodbstreams/v2/provider.py +6 -0
- localstack/services/ec2/provider.py +6 -0
- localstack/services/es/provider.py +6 -0
- localstack/services/events/provider.py +4 -0
- localstack/services/events/v1/provider.py +9 -0
- localstack/services/firehose/provider.py +5 -0
- localstack/services/iam/provider.py +4 -0
- localstack/services/kinesis/packages.py +1 -1
- localstack/services/kms/models.py +16 -22
- localstack/services/kms/provider.py +4 -0
- localstack/services/lambda_/analytics.py +11 -2
- localstack/services/lambda_/api_utils.py +37 -20
- localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
- localstack/services/lambda_/invocation/assignment.py +4 -1
- localstack/services/lambda_/invocation/event_manager.py +15 -11
- localstack/services/lambda_/invocation/execution_environment.py +21 -2
- localstack/services/lambda_/invocation/lambda_models.py +31 -2
- localstack/services/lambda_/invocation/lambda_service.py +62 -3
- localstack/services/lambda_/invocation/models.py +9 -1
- localstack/services/lambda_/invocation/version_manager.py +18 -3
- localstack/services/lambda_/provider.py +307 -106
- localstack/services/lambda_/resource_providers/aws_lambda_function.py +33 -1
- localstack/services/lambda_/runtimes.py +3 -1
- localstack/services/logs/provider.py +9 -0
- localstack/services/opensearch/packages.py +34 -20
- localstack/services/opensearch/provider.py +53 -3
- localstack/services/resource_groups/provider.py +5 -1
- localstack/services/resourcegroupstaggingapi/provider.py +6 -1
- localstack/services/route53/provider.py +7 -0
- localstack/services/route53resolver/provider.py +5 -0
- localstack/services/s3/constants.py +5 -0
- localstack/services/s3/exceptions.py +9 -0
- localstack/services/s3/models.py +9 -1
- localstack/services/s3/provider.py +51 -43
- localstack/services/s3/utils.py +81 -15
- localstack/services/s3control/provider.py +107 -2
- localstack/services/s3control/validation.py +50 -0
- localstack/services/scheduler/provider.py +4 -2
- localstack/services/secretsmanager/provider.py +4 -0
- localstack/services/ses/provider.py +4 -0
- localstack/services/sns/constants.py +16 -1
- localstack/services/sns/provider.py +5 -0
- localstack/services/sns/publisher.py +15 -6
- localstack/services/sns/v2/models.py +9 -0
- localstack/services/sns/v2/provider.py +750 -19
- localstack/services/sns/v2/utils.py +12 -0
- localstack/services/sqs/constants.py +6 -0
- localstack/services/sqs/provider.py +9 -1
- localstack/services/sqs/resource_providers/aws_sqs_queue.py +61 -46
- localstack/services/ssm/provider.py +6 -0
- localstack/services/stepfunctions/asl/component/common/path/result_path.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +0 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +0 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +8 -8
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/{mock_eval_utils.py → local_mock_eval_utils.py} +13 -9
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +6 -6
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +4 -0
- localstack/services/stepfunctions/asl/component/test_state/state/base_mock.py +118 -0
- localstack/services/stepfunctions/asl/component/test_state/state/common.py +82 -0
- localstack/services/stepfunctions/asl/component/test_state/state/execution.py +139 -0
- localstack/services/stepfunctions/asl/component/test_state/state/map.py +77 -0
- localstack/services/stepfunctions/asl/component/test_state/state/task.py +44 -0
- localstack/services/stepfunctions/asl/eval/environment.py +30 -22
- localstack/services/stepfunctions/asl/eval/states.py +1 -1
- localstack/services/stepfunctions/asl/eval/test_state/environment.py +49 -9
- localstack/services/stepfunctions/asl/eval/test_state/program_state.py +22 -0
- localstack/services/stepfunctions/asl/jsonata/jsonata.py +5 -1
- localstack/services/stepfunctions/asl/parse/preprocessor.py +67 -24
- localstack/services/stepfunctions/asl/parse/test_state/asl_parser.py +5 -4
- localstack/services/stepfunctions/asl/parse/test_state/preprocessor.py +222 -31
- localstack/services/stepfunctions/asl/static_analyser/test_state/test_state_analyser.py +256 -22
- localstack/services/stepfunctions/backend/execution.py +10 -11
- localstack/services/stepfunctions/backend/execution_worker.py +5 -5
- localstack/services/stepfunctions/backend/test_state/execution.py +36 -0
- localstack/services/stepfunctions/backend/test_state/execution_worker.py +33 -1
- localstack/services/stepfunctions/backend/test_state/test_state_mock.py +127 -0
- localstack/services/stepfunctions/local_mocking/__init__.py +9 -0
- localstack/services/stepfunctions/{mocking → local_mocking}/mock_config.py +24 -17
- localstack/services/stepfunctions/provider.py +83 -25
- localstack/services/stepfunctions/test_state/mock_config.py +47 -0
- localstack/services/sts/provider.py +7 -0
- localstack/services/support/provider.py +5 -1
- localstack/services/swf/provider.py +5 -1
- localstack/services/transcribe/provider.py +7 -0
- localstack/testing/aws/lambda_utils.py +1 -1
- localstack/testing/aws/util.py +2 -1
- localstack/testing/config.py +1 -0
- localstack/testing/pytest/fixtures.py +28 -0
- localstack/testing/snapshots/transformer_utility.py +5 -0
- localstack/utils/analytics/publisher.py +37 -155
- localstack/utils/analytics/service_request_aggregator.py +6 -4
- localstack/utils/aws/arns.py +7 -0
- localstack/utils/aws/client_types.py +2 -4
- localstack/utils/batching.py +258 -0
- localstack/utils/bootstrap.py +2 -2
- localstack/utils/catalog/catalog.py +3 -2
- localstack/utils/collections.py +23 -11
- localstack/utils/container_utils/container_client.py +22 -13
- localstack/utils/container_utils/docker_cmd_client.py +6 -6
- localstack/version.py +2 -2
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/METADATA +7 -7
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/RECORD +155 -146
- localstack_core-4.12.1.dev18.dist-info/plux.json +1 -0
- localstack/services/stepfunctions/mocking/__init__.py +0 -0
- localstack/utils/batch_policy.py +0 -124
- localstack_core-4.10.1.dev42.dist-info/plux.json +0 -1
- /localstack/services/stepfunctions/{mocking → local_mocking}/mock_config_file.py +0 -0
- {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack +0 -0
- {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.10.1.dev42.data → localstack_core-4.12.1.dev18.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/WHEEL +0 -0
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/entry_points.txt +0 -0
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/licenses/LICENSE.txt +0 -0
- {localstack_core-4.10.1.dev42.dist-info → localstack_core-4.12.1.dev18.dist-info}/top_level.txt +0 -0
|
@@ -27,6 +27,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
27
27
|
Arn,
|
|
28
28
|
Blob,
|
|
29
29
|
BlobStream,
|
|
30
|
+
CapacityProviderConfig,
|
|
30
31
|
CodeSigningConfigArn,
|
|
31
32
|
CodeSigningConfigNotFoundException,
|
|
32
33
|
CodeSigningPolicies,
|
|
@@ -39,8 +40,10 @@ from localstack.aws.api.lambda_ import (
|
|
|
39
40
|
CreateFunctionRequest,
|
|
40
41
|
CreateFunctionUrlConfigResponse,
|
|
41
42
|
DeleteCodeSigningConfigResponse,
|
|
43
|
+
DeleteFunctionResponse,
|
|
42
44
|
Description,
|
|
43
45
|
DestinationConfig,
|
|
46
|
+
DurableExecutionName,
|
|
44
47
|
EventSourceMappingConfiguration,
|
|
45
48
|
FunctionCodeLocation,
|
|
46
49
|
FunctionConfiguration,
|
|
@@ -48,6 +51,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
48
51
|
FunctionName,
|
|
49
52
|
FunctionUrlAuthType,
|
|
50
53
|
FunctionUrlQualifier,
|
|
54
|
+
FunctionVersionLatestPublished,
|
|
51
55
|
GetAccountSettingsResponse,
|
|
52
56
|
GetCodeSigningConfigResponse,
|
|
53
57
|
GetFunctionCodeSigningConfigResponse,
|
|
@@ -65,6 +69,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
65
69
|
InvokeAsyncResponse,
|
|
66
70
|
InvokeMode,
|
|
67
71
|
LambdaApi,
|
|
72
|
+
LambdaManagedInstancesCapacityProviderConfig,
|
|
68
73
|
LastUpdateStatus,
|
|
69
74
|
LayerName,
|
|
70
75
|
LayerPermissionAllowedAction,
|
|
@@ -99,6 +104,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
99
104
|
MaxProvisionedConcurrencyConfigListItems,
|
|
100
105
|
NamespacedFunctionName,
|
|
101
106
|
NamespacedStatementId,
|
|
107
|
+
NumericLatestPublishedOrAliasQualifier,
|
|
102
108
|
OnFailure,
|
|
103
109
|
OnSuccess,
|
|
104
110
|
OrganizationId,
|
|
@@ -130,6 +136,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
130
136
|
TaggableResource,
|
|
131
137
|
TagKeyList,
|
|
132
138
|
Tags,
|
|
139
|
+
TenantId,
|
|
133
140
|
TracingMode,
|
|
134
141
|
UnqualifiedFunctionName,
|
|
135
142
|
UpdateCodeSigningConfigResponse,
|
|
@@ -137,7 +144,7 @@ from localstack.aws.api.lambda_ import (
|
|
|
137
144
|
UpdateFunctionCodeRequest,
|
|
138
145
|
UpdateFunctionConfigurationRequest,
|
|
139
146
|
UpdateFunctionUrlConfigResponse,
|
|
140
|
-
|
|
147
|
+
VersionWithLatestPublished,
|
|
141
148
|
)
|
|
142
149
|
from localstack.aws.api.lambda_ import FunctionVersion as FunctionVersionApi
|
|
143
150
|
from localstack.aws.api.lambda_ import ServiceException as LambdaServiceException
|
|
@@ -151,6 +158,7 @@ from localstack.services.edge import ROUTER
|
|
|
151
158
|
from localstack.services.lambda_ import api_utils
|
|
152
159
|
from localstack.services.lambda_ import hooks as lambda_hooks
|
|
153
160
|
from localstack.services.lambda_.analytics import (
|
|
161
|
+
FunctionInitializationType,
|
|
154
162
|
FunctionOperation,
|
|
155
163
|
FunctionStatus,
|
|
156
164
|
function_counter,
|
|
@@ -209,6 +217,7 @@ from localstack.services.lambda_.invocation.lambda_service import (
|
|
|
209
217
|
store_lambda_archive,
|
|
210
218
|
store_s3_bucket_archive,
|
|
211
219
|
)
|
|
220
|
+
from localstack.services.lambda_.invocation.models import CapacityProvider as CapacityProviderModel
|
|
212
221
|
from localstack.services.lambda_.invocation.models import LambdaStore
|
|
213
222
|
from localstack.services.lambda_.invocation.runtime_executor import get_runtime_executor
|
|
214
223
|
from localstack.services.lambda_.lambda_utils import HINT_LOG
|
|
@@ -231,6 +240,7 @@ from localstack.services.plugins import ServiceLifecycleHook
|
|
|
231
240
|
from localstack.state import StateVisitor
|
|
232
241
|
from localstack.utils.aws.arns import (
|
|
233
242
|
ArnData,
|
|
243
|
+
capacity_provider_arn,
|
|
234
244
|
extract_resource_from_arn,
|
|
235
245
|
extract_service_from_arn,
|
|
236
246
|
get_partition,
|
|
@@ -239,7 +249,7 @@ from localstack.utils.aws.arns import (
|
|
|
239
249
|
)
|
|
240
250
|
from localstack.utils.aws.client_types import ServicePrincipal
|
|
241
251
|
from localstack.utils.bootstrap import is_api_enabled
|
|
242
|
-
from localstack.utils.collections import PaginatedList
|
|
252
|
+
from localstack.utils.collections import PaginatedList, merge_recursive
|
|
243
253
|
from localstack.utils.event_matcher import validate_event_pattern
|
|
244
254
|
from localstack.utils.strings import get_random_hex, short_uid, to_bytes, to_str
|
|
245
255
|
from localstack.utils.sync import poll_condition
|
|
@@ -247,6 +257,7 @@ from localstack.utils.urls import localstack_host
|
|
|
247
257
|
|
|
248
258
|
LOG = logging.getLogger(__name__)
|
|
249
259
|
|
|
260
|
+
CAPACITY_PROVIDER_ARN_NAME = "arn:aws[a-zA-Z-]*:lambda:(eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:\\d{12}:capacity-provider:[a-zA-Z0-9-_]+"
|
|
250
261
|
LAMBDA_DEFAULT_TIMEOUT = 3
|
|
251
262
|
LAMBDA_DEFAULT_MEMORY_SIZE = 128
|
|
252
263
|
|
|
@@ -296,19 +307,26 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
296
307
|
for region_name, state in account_bundle.items():
|
|
297
308
|
for fn in state.functions.values():
|
|
298
309
|
for fn_version in fn.versions.values():
|
|
299
|
-
# restore the "Pending" state for every function version and start it
|
|
300
310
|
try:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
new_config = dataclasses.replace(fn_version.config, state=new_state)
|
|
307
|
-
new_version = dataclasses.replace(fn_version, config=new_config)
|
|
308
|
-
fn.versions[fn_version.id.qualifier] = new_version
|
|
309
|
-
self.lambda_service.create_function_version(fn_version).result(
|
|
310
|
-
timeout=5
|
|
311
|
+
# $LATEST is not invokable for Lambda functions with a capacity provider
|
|
312
|
+
# and has a different State (i.e., ActiveNonInvokable)
|
|
313
|
+
is_capacity_provider_latest = (
|
|
314
|
+
fn_version.config.CapacityProviderConfig
|
|
315
|
+
and fn_version.id.qualifier == "$LATEST"
|
|
311
316
|
)
|
|
317
|
+
if not is_capacity_provider_latest:
|
|
318
|
+
# Restore the "Pending" state for the function version and start it
|
|
319
|
+
new_state = VersionState(
|
|
320
|
+
state=State.Pending,
|
|
321
|
+
code=StateReasonCode.Creating,
|
|
322
|
+
reason="The function is being created.",
|
|
323
|
+
)
|
|
324
|
+
new_config = dataclasses.replace(fn_version.config, state=new_state)
|
|
325
|
+
new_version = dataclasses.replace(fn_version, config=new_config)
|
|
326
|
+
fn.versions[fn_version.id.qualifier] = new_version
|
|
327
|
+
self.lambda_service.create_function_version(fn_version).result(
|
|
328
|
+
timeout=5
|
|
329
|
+
)
|
|
312
330
|
except Exception:
|
|
313
331
|
LOG.warning(
|
|
314
332
|
"Failed to restore function version %s",
|
|
@@ -419,6 +437,23 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
419
437
|
)
|
|
420
438
|
return esm
|
|
421
439
|
|
|
440
|
+
@staticmethod
|
|
441
|
+
def _get_capacity_provider(
|
|
442
|
+
capacity_provider_name: str,
|
|
443
|
+
account_id: str,
|
|
444
|
+
region: str,
|
|
445
|
+
error_msg_template: str = "Capacity provider not found: {}",
|
|
446
|
+
) -> CapacityProviderModel:
|
|
447
|
+
state = lambda_stores[account_id][region]
|
|
448
|
+
cp = state.capacity_providers.get(capacity_provider_name)
|
|
449
|
+
if not cp:
|
|
450
|
+
arn = capacity_provider_arn(capacity_provider_name, account_id, region)
|
|
451
|
+
raise ResourceNotFoundException(
|
|
452
|
+
error_msg_template.format(arn),
|
|
453
|
+
Type="User",
|
|
454
|
+
)
|
|
455
|
+
return cp
|
|
456
|
+
|
|
422
457
|
@staticmethod
|
|
423
458
|
def _validate_qualifier_expression(qualifier: str) -> None:
|
|
424
459
|
if error_messages := api_utils.validate_qualifier(qualifier):
|
|
@@ -489,7 +524,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
489
524
|
subnet_id = subnet_ids[0]
|
|
490
525
|
if not bool(SUBNET_ID_REGEX.match(subnet_id)):
|
|
491
526
|
raise ValidationException(
|
|
492
|
-
f"1 validation error detected: Value '[{subnet_id}]' at 'vpcConfig.subnetIds' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 1024, Member must have length greater than or equal to 0, Member must satisfy regular expression pattern:
|
|
527
|
+
f"1 validation error detected: Value '[{subnet_id}]' at 'vpcConfig.subnetIds' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 1024, Member must have length greater than or equal to 0, Member must satisfy regular expression pattern: subnet-[0-9a-z]*]"
|
|
493
528
|
)
|
|
494
529
|
|
|
495
530
|
return VpcConfig(
|
|
@@ -506,6 +541,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
506
541
|
description: str | None = None,
|
|
507
542
|
revision_id: str | None = None,
|
|
508
543
|
code_sha256: str | None = None,
|
|
544
|
+
publish_to: FunctionVersionLatestPublished | None = None,
|
|
545
|
+
is_active: bool = False,
|
|
509
546
|
) -> tuple[FunctionVersion, bool]:
|
|
510
547
|
"""
|
|
511
548
|
Release a new version to the model if all restrictions are met.
|
|
@@ -568,38 +605,57 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
568
605
|
):
|
|
569
606
|
return prev_version, False
|
|
570
607
|
# TODO check if there was a change since last version
|
|
571
|
-
|
|
572
|
-
|
|
608
|
+
if publish_to == FunctionVersionLatestPublished.LATEST_PUBLISHED:
|
|
609
|
+
qualifier = "$LATEST.PUBLISHED"
|
|
610
|
+
else:
|
|
611
|
+
qualifier = str(function.next_version)
|
|
612
|
+
function.next_version += 1
|
|
573
613
|
new_id = VersionIdentifier(
|
|
574
614
|
function_name=function_name,
|
|
575
|
-
qualifier=
|
|
615
|
+
qualifier=qualifier,
|
|
576
616
|
region=region,
|
|
577
617
|
account=account_id,
|
|
578
618
|
)
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
ApplyOn
|
|
585
|
-
|
|
619
|
+
|
|
620
|
+
if current_latest_version.config.CapacityProviderConfig:
|
|
621
|
+
# for lambda managed functions, snap start is not supported
|
|
622
|
+
snap_start = None
|
|
623
|
+
else:
|
|
624
|
+
apply_on = current_latest_version.config.snap_start["ApplyOn"]
|
|
625
|
+
optimization_status = SnapStartOptimizationStatus.Off
|
|
626
|
+
if apply_on == SnapStartApplyOn.PublishedVersions:
|
|
627
|
+
optimization_status = SnapStartOptimizationStatus.On
|
|
628
|
+
snap_start = SnapStartResponse(
|
|
629
|
+
ApplyOn=apply_on,
|
|
630
|
+
OptimizationStatus=optimization_status,
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
last_update = None
|
|
634
|
+
new_state = VersionState(
|
|
635
|
+
state=State.Pending,
|
|
636
|
+
code=StateReasonCode.Creating,
|
|
637
|
+
reason="The function is being created.",
|
|
586
638
|
)
|
|
639
|
+
if publish_to == FunctionVersionLatestPublished.LATEST_PUBLISHED:
|
|
640
|
+
last_update = UpdateStatus(
|
|
641
|
+
status=LastUpdateStatus.InProgress,
|
|
642
|
+
code="Updating",
|
|
643
|
+
reason="The function is being updated.",
|
|
644
|
+
)
|
|
645
|
+
if is_active:
|
|
646
|
+
new_state = VersionState(state=State.Active)
|
|
587
647
|
new_version = dataclasses.replace(
|
|
588
648
|
current_latest_version,
|
|
589
649
|
config=dataclasses.replace(
|
|
590
650
|
current_latest_version.config,
|
|
591
|
-
last_update=
|
|
592
|
-
state=
|
|
593
|
-
state=State.Pending,
|
|
594
|
-
code=StateReasonCode.Creating,
|
|
595
|
-
reason="The function is being created.",
|
|
596
|
-
),
|
|
651
|
+
last_update=last_update,
|
|
652
|
+
state=new_state,
|
|
597
653
|
snap_start=snap_start,
|
|
598
654
|
**changes,
|
|
599
655
|
),
|
|
600
656
|
id=new_id,
|
|
601
657
|
)
|
|
602
|
-
function.versions[
|
|
658
|
+
function.versions[qualifier] = new_version
|
|
603
659
|
return new_version, True
|
|
604
660
|
|
|
605
661
|
def _publish_version_from_existing_version(
|
|
@@ -610,6 +666,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
610
666
|
description: str | None = None,
|
|
611
667
|
revision_id: str | None = None,
|
|
612
668
|
code_sha256: str | None = None,
|
|
669
|
+
publish_to: FunctionVersionLatestPublished | None = None,
|
|
613
670
|
) -> FunctionVersion:
|
|
614
671
|
"""
|
|
615
672
|
Publish version from an existing, already initialized LATEST
|
|
@@ -622,6 +679,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
622
679
|
:param code_sha256: code sha (check if current code matches)
|
|
623
680
|
:return: new version
|
|
624
681
|
"""
|
|
682
|
+
is_active = True if publish_to == FunctionVersionLatestPublished.LATEST_PUBLISHED else False
|
|
625
683
|
new_version, changed = self._create_version_model(
|
|
626
684
|
function_name=function_name,
|
|
627
685
|
region=region,
|
|
@@ -629,18 +687,34 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
629
687
|
description=description,
|
|
630
688
|
revision_id=revision_id,
|
|
631
689
|
code_sha256=code_sha256,
|
|
690
|
+
publish_to=publish_to,
|
|
691
|
+
is_active=is_active,
|
|
632
692
|
)
|
|
633
693
|
if not changed:
|
|
634
694
|
return new_version
|
|
635
|
-
|
|
695
|
+
|
|
696
|
+
if new_version.config.CapacityProviderConfig:
|
|
697
|
+
self.lambda_service.publish_version_async(new_version)
|
|
698
|
+
else:
|
|
699
|
+
self.lambda_service.publish_version(new_version)
|
|
636
700
|
state = lambda_stores[account_id][region]
|
|
637
701
|
function = state.functions.get(function_name)
|
|
702
|
+
|
|
703
|
+
# Update revision id for $LATEST version
|
|
638
704
|
# TODO: re-evaluate data model to prevent this dirty hack just for bumping the revision id
|
|
639
705
|
latest_version = function.versions["$LATEST"]
|
|
640
706
|
function.versions["$LATEST"] = dataclasses.replace(
|
|
641
707
|
latest_version, config=dataclasses.replace(latest_version.config)
|
|
642
708
|
)
|
|
643
|
-
|
|
709
|
+
if new_version.config.CapacityProviderConfig:
|
|
710
|
+
# publish_version happens async for functions with a capacity provider.
|
|
711
|
+
# Therefore, we return the new_version with State=Pending or LastUpdateStatus=InProgress ($LATEST.PUBLISHED)
|
|
712
|
+
return new_version
|
|
713
|
+
else:
|
|
714
|
+
# Regular functions yield an Active state modified during `publish_version` (sync).
|
|
715
|
+
# Therefore, we need to get the updated version from the store.
|
|
716
|
+
updated_version = function.versions.get(new_version.id.qualifier)
|
|
717
|
+
return updated_version
|
|
644
718
|
|
|
645
719
|
def _publish_version_with_changes(
|
|
646
720
|
self,
|
|
@@ -650,6 +724,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
650
724
|
description: str | None = None,
|
|
651
725
|
revision_id: str | None = None,
|
|
652
726
|
code_sha256: str | None = None,
|
|
727
|
+
publish_to: FunctionVersionLatestPublished | None = None,
|
|
728
|
+
is_active: bool = False,
|
|
653
729
|
) -> FunctionVersion:
|
|
654
730
|
"""
|
|
655
731
|
Publish version together with a new latest version (publish on create / update)
|
|
@@ -669,6 +745,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
669
745
|
description=description,
|
|
670
746
|
revision_id=revision_id,
|
|
671
747
|
code_sha256=code_sha256,
|
|
748
|
+
publish_to=publish_to,
|
|
749
|
+
is_active=is_active,
|
|
672
750
|
)
|
|
673
751
|
if not changed:
|
|
674
752
|
return new_version
|
|
@@ -720,7 +798,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
720
798
|
if layer_version_str is None:
|
|
721
799
|
raise ValidationException(
|
|
722
800
|
f"1 validation error detected: Value '[{layer_version_arn}]'"
|
|
723
|
-
+
|
|
801
|
+
+ " at 'layers' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 2048, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: "
|
|
802
|
+
+ "(arn:(aws[a-zA-Z-]*)?:lambda:(eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:\\d{12}:layer:[a-zA-Z0-9-_]+:[0-9]+)|(arn:[a-zA-Z0-9-]+:lambda:::awslayer:[a-zA-Z0-9-_]+), Member must not be null]",
|
|
724
803
|
)
|
|
725
804
|
|
|
726
805
|
state = lambda_stores[layer_account_id][layer_region]
|
|
@@ -783,6 +862,30 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
783
862
|
)
|
|
784
863
|
visited_layers[layer_arn] = layer_version_arn
|
|
785
864
|
|
|
865
|
+
def _validate_capacity_provider_config(
|
|
866
|
+
self, capacity_provider_config: CapacityProviderConfig, context: RequestContext
|
|
867
|
+
):
|
|
868
|
+
if not capacity_provider_config.get("LambdaManagedInstancesCapacityProviderConfig"):
|
|
869
|
+
raise ValidationException(
|
|
870
|
+
"1 validation error detected: Value null at 'capacityProviderConfig.lambdaManagedInstancesCapacityProviderConfig' failed to satisfy constraint: Member must not be null"
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
capacity_provider_arn = capacity_provider_config.get(
|
|
874
|
+
"LambdaManagedInstancesCapacityProviderConfig", {}
|
|
875
|
+
).get("CapacityProviderArn")
|
|
876
|
+
if not capacity_provider_arn:
|
|
877
|
+
raise ValidationException(
|
|
878
|
+
"1 validation error detected: Value null at 'capacityProviderConfig.lambdaManagedInstancesCapacityProviderConfig.capacityProviderArn' failed to satisfy constraint: Member must not be null"
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
if not re.match(CAPACITY_PROVIDER_ARN_NAME, capacity_provider_arn):
|
|
882
|
+
raise ValidationException(
|
|
883
|
+
f"1 validation error detected: Value '{capacity_provider_arn}' at 'capacityProviderConfig.lambdaManagedInstancesCapacityProviderConfig.capacityProviderArn' failed to satisfy constraint: Member must satisfy regular expression pattern: {CAPACITY_PROVIDER_ARN_NAME}"
|
|
884
|
+
)
|
|
885
|
+
|
|
886
|
+
capacity_provider_name = capacity_provider_arn.split(":")[-1]
|
|
887
|
+
self.get_capacity_provider(context, capacity_provider_name)
|
|
888
|
+
|
|
786
889
|
@staticmethod
|
|
787
890
|
def map_layers(new_layers: list[str]) -> list[LayerVersion]:
|
|
788
891
|
layers = []
|
|
@@ -941,11 +1044,13 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
941
1044
|
account_id=context_account_id,
|
|
942
1045
|
)
|
|
943
1046
|
else:
|
|
944
|
-
raise LambdaServiceException("
|
|
1047
|
+
raise LambdaServiceException("A ZIP file or S3 bucket is required")
|
|
945
1048
|
elif package_type == PackageType.Image:
|
|
946
1049
|
image = request_code.get("ImageUri")
|
|
947
1050
|
if not image:
|
|
948
|
-
raise LambdaServiceException(
|
|
1051
|
+
raise LambdaServiceException(
|
|
1052
|
+
"An image is required when the package type is set to 'image'"
|
|
1053
|
+
)
|
|
949
1054
|
image = create_image_code(image_uri=image)
|
|
950
1055
|
|
|
951
1056
|
image_config_req = request.get("ImageConfig", {})
|
|
@@ -956,6 +1061,26 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
956
1061
|
)
|
|
957
1062
|
# Runtime management controls are not available when providing a custom image
|
|
958
1063
|
runtime_version_config = None
|
|
1064
|
+
|
|
1065
|
+
capacity_provider_config = None
|
|
1066
|
+
memory_size = request.get("MemorySize", LAMBDA_DEFAULT_MEMORY_SIZE)
|
|
1067
|
+
if "CapacityProviderConfig" in request:
|
|
1068
|
+
capacity_provider_config = request["CapacityProviderConfig"]
|
|
1069
|
+
self._validate_capacity_provider_config(capacity_provider_config, context)
|
|
1070
|
+
|
|
1071
|
+
default_config = CapacityProviderConfig(
|
|
1072
|
+
LambdaManagedInstancesCapacityProviderConfig=LambdaManagedInstancesCapacityProviderConfig(
|
|
1073
|
+
ExecutionEnvironmentMemoryGiBPerVCpu=2.0,
|
|
1074
|
+
PerExecutionEnvironmentMaxConcurrency=16,
|
|
1075
|
+
)
|
|
1076
|
+
)
|
|
1077
|
+
capacity_provider_config = merge_recursive(default_config, capacity_provider_config)
|
|
1078
|
+
memory_size = 2048
|
|
1079
|
+
if request.get("LoggingConfig", {}).get("LogFormat") == LogFormat.Text:
|
|
1080
|
+
raise InvalidParameterValueException(
|
|
1081
|
+
'LogLevel is not supported when LogFormat is set to "Text". Remove LogLevel from your request or change the LogFormat to "JSON" and try again.',
|
|
1082
|
+
Type="User",
|
|
1083
|
+
)
|
|
959
1084
|
if "LoggingConfig" in request:
|
|
960
1085
|
logging_config = request["LoggingConfig"]
|
|
961
1086
|
LOG.warning(
|
|
@@ -979,11 +1104,25 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
979
1104
|
| logging_config
|
|
980
1105
|
)
|
|
981
1106
|
|
|
1107
|
+
elif capacity_provider_config:
|
|
1108
|
+
logging_config = LoggingConfig(
|
|
1109
|
+
LogFormat=LogFormat.JSON,
|
|
1110
|
+
LogGroup=f"/aws/lambda/{function_name}",
|
|
1111
|
+
ApplicationLogLevel="INFO",
|
|
1112
|
+
SystemLogLevel="INFO",
|
|
1113
|
+
)
|
|
982
1114
|
else:
|
|
983
1115
|
logging_config = LoggingConfig(
|
|
984
1116
|
LogFormat=LogFormat.Text, LogGroup=f"/aws/lambda/{function_name}"
|
|
985
1117
|
)
|
|
986
|
-
|
|
1118
|
+
snap_start = (
|
|
1119
|
+
None
|
|
1120
|
+
if capacity_provider_config
|
|
1121
|
+
else SnapStartResponse(
|
|
1122
|
+
ApplyOn=request.get("SnapStart", {}).get("ApplyOn", SnapStartApplyOn.None_),
|
|
1123
|
+
OptimizationStatus=SnapStartOptimizationStatus.Off,
|
|
1124
|
+
)
|
|
1125
|
+
)
|
|
987
1126
|
version = FunctionVersion(
|
|
988
1127
|
id=arn,
|
|
989
1128
|
config=VersionFunctionConfiguration(
|
|
@@ -992,7 +1131,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
992
1131
|
role=request["Role"],
|
|
993
1132
|
timeout=request.get("Timeout", LAMBDA_DEFAULT_TIMEOUT),
|
|
994
1133
|
runtime=request.get("Runtime"),
|
|
995
|
-
memory_size=
|
|
1134
|
+
memory_size=memory_size,
|
|
996
1135
|
handler=request.get("Handler"),
|
|
997
1136
|
package_type=package_type,
|
|
998
1137
|
environment=env_vars,
|
|
@@ -1008,10 +1147,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1008
1147
|
ephemeral_storage=LambdaEphemeralStorage(
|
|
1009
1148
|
size=request.get("EphemeralStorage", {}).get("Size", 512)
|
|
1010
1149
|
),
|
|
1011
|
-
snap_start=
|
|
1012
|
-
ApplyOn=request.get("SnapStart", {}).get("ApplyOn", SnapStartApplyOn.None_),
|
|
1013
|
-
OptimizationStatus=SnapStartOptimizationStatus.Off,
|
|
1014
|
-
),
|
|
1150
|
+
snap_start=snap_start,
|
|
1015
1151
|
runtime_version_config=runtime_version_config,
|
|
1016
1152
|
dead_letter_arn=request.get("DeadLetterConfig", {}).get("TargetArn"),
|
|
1017
1153
|
vpc_config=self._build_vpc_config(
|
|
@@ -1023,18 +1159,40 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1023
1159
|
reason="The function is being created.",
|
|
1024
1160
|
),
|
|
1025
1161
|
logging_config=logging_config,
|
|
1162
|
+
# TODO: might need something like **optional_kwargs if None
|
|
1163
|
+
# -> Test with regular GetFunction (i.e., without a capacity provider)
|
|
1164
|
+
CapacityProviderConfig=capacity_provider_config,
|
|
1026
1165
|
),
|
|
1027
1166
|
)
|
|
1028
|
-
|
|
1167
|
+
version_post_response = None
|
|
1168
|
+
if capacity_provider_config:
|
|
1169
|
+
version_post_response = dataclasses.replace(
|
|
1170
|
+
version,
|
|
1171
|
+
config=dataclasses.replace(
|
|
1172
|
+
version.config,
|
|
1173
|
+
last_update=UpdateStatus(status=LastUpdateStatus.Successful),
|
|
1174
|
+
state=VersionState(state=State.ActiveNonInvocable),
|
|
1175
|
+
),
|
|
1176
|
+
)
|
|
1177
|
+
fn.versions["$LATEST"] = version_post_response or version
|
|
1029
1178
|
state.functions[function_name] = fn
|
|
1179
|
+
initialization_type = (
|
|
1180
|
+
FunctionInitializationType.lambda_managed_instances
|
|
1181
|
+
if capacity_provider_config
|
|
1182
|
+
else FunctionInitializationType.on_demand
|
|
1183
|
+
)
|
|
1030
1184
|
function_counter.labels(
|
|
1031
1185
|
operation=FunctionOperation.create,
|
|
1032
1186
|
runtime=runtime or "n/a",
|
|
1033
1187
|
status=FunctionStatus.success,
|
|
1034
1188
|
invocation_type="n/a",
|
|
1035
1189
|
package_type=package_type,
|
|
1190
|
+
initialization_type=initialization_type,
|
|
1036
1191
|
)
|
|
1037
|
-
|
|
1192
|
+
# TODO: consider potential other side effects of not having a function version for $LATEST
|
|
1193
|
+
# Provisioning happens upon publishing for functions using a capacity provider
|
|
1194
|
+
if not capacity_provider_config:
|
|
1195
|
+
self.lambda_service.create_function_version(version)
|
|
1038
1196
|
|
|
1039
1197
|
if tags := request.get("Tags"):
|
|
1040
1198
|
# This will check whether the function exists.
|
|
@@ -1042,7 +1200,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1042
1200
|
|
|
1043
1201
|
if request.get("Publish"):
|
|
1044
1202
|
version = self._publish_version_with_changes(
|
|
1045
|
-
function_name=function_name,
|
|
1203
|
+
function_name=function_name,
|
|
1204
|
+
region=context_region,
|
|
1205
|
+
account_id=context_account_id,
|
|
1206
|
+
publish_to=request.get("PublishTo"),
|
|
1046
1207
|
)
|
|
1047
1208
|
|
|
1048
1209
|
if config.LAMBDA_SYNCHRONOUS_CREATE:
|
|
@@ -1051,7 +1212,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1051
1212
|
lambda: get_function_version(
|
|
1052
1213
|
function_name, version.id.qualifier, version.id.account, version.id.region
|
|
1053
1214
|
).config.state.state
|
|
1054
|
-
in [State.Active, State.Failed],
|
|
1215
|
+
in [State.Active, State.ActiveNonInvocable, State.Failed],
|
|
1055
1216
|
timeout=10,
|
|
1056
1217
|
):
|
|
1057
1218
|
LOG.warning(
|
|
@@ -1242,6 +1403,19 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1242
1403
|
if new_mode:
|
|
1243
1404
|
replace_kwargs["tracing_config_mode"] = new_mode
|
|
1244
1405
|
|
|
1406
|
+
if "CapacityProviderConfig" in request:
|
|
1407
|
+
if latest_version.config.CapacityProviderConfig and not request[
|
|
1408
|
+
"CapacityProviderConfig"
|
|
1409
|
+
].get("LambdaManagedInstancesCapacityProviderConfig"):
|
|
1410
|
+
raise ValidationException(
|
|
1411
|
+
"1 validation error detected: Value null at 'capacityProviderConfig.lambdaManagedInstancesCapacityProviderConfig' failed to satisfy constraint: Member must not be null"
|
|
1412
|
+
)
|
|
1413
|
+
if not latest_version.config.CapacityProviderConfig:
|
|
1414
|
+
raise InvalidParameterValueException(
|
|
1415
|
+
"CapacityProviderConfig isn't supported for Lambda Default functions.",
|
|
1416
|
+
Type="User",
|
|
1417
|
+
)
|
|
1418
|
+
|
|
1245
1419
|
new_latest_version = dataclasses.replace(
|
|
1246
1420
|
latest_version,
|
|
1247
1421
|
config=dataclasses.replace(
|
|
@@ -1327,7 +1501,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1327
1501
|
code = None
|
|
1328
1502
|
image = create_image_code(image_uri=image)
|
|
1329
1503
|
else:
|
|
1330
|
-
raise LambdaServiceException("
|
|
1504
|
+
raise LambdaServiceException("A ZIP file, S3 bucket, or image is required")
|
|
1331
1505
|
|
|
1332
1506
|
old_function_version = function.versions.get("$LATEST")
|
|
1333
1507
|
replace_kwargs = {"code": code} if code else {"image": image}
|
|
@@ -1365,7 +1539,12 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1365
1539
|
self.lambda_service.update_version(new_version=function_version)
|
|
1366
1540
|
if request.get("Publish"):
|
|
1367
1541
|
function_version = self._publish_version_with_changes(
|
|
1368
|
-
function_name=function_name,
|
|
1542
|
+
function_name=function_name,
|
|
1543
|
+
region=region,
|
|
1544
|
+
account_id=account_id,
|
|
1545
|
+
# TODO: validations for PublishTo without Publish=True
|
|
1546
|
+
publish_to=request.get("PublishTo"),
|
|
1547
|
+
is_active=True,
|
|
1369
1548
|
)
|
|
1370
1549
|
return api_utils.map_config_out(
|
|
1371
1550
|
function_version, return_qualified_arn=bool(request.get("Publish"))
|
|
@@ -1380,10 +1559,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1380
1559
|
def delete_function(
|
|
1381
1560
|
self,
|
|
1382
1561
|
context: RequestContext,
|
|
1383
|
-
function_name:
|
|
1384
|
-
qualifier:
|
|
1562
|
+
function_name: NamespacedFunctionName,
|
|
1563
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
1385
1564
|
**kwargs,
|
|
1386
|
-
) ->
|
|
1565
|
+
) -> DeleteFunctionResponse:
|
|
1387
1566
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
1388
1567
|
function_name, qualifier = api_utils.get_name_and_qualifier(
|
|
1389
1568
|
function_name, qualifier, context
|
|
@@ -1409,10 +1588,13 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1409
1588
|
raise e
|
|
1410
1589
|
function = store.functions.get(function_name)
|
|
1411
1590
|
|
|
1591
|
+
function_has_capacity_provider = False
|
|
1412
1592
|
if qualifier:
|
|
1413
1593
|
# delete a version of the function
|
|
1414
1594
|
version = function.versions.pop(qualifier, None)
|
|
1415
1595
|
if version:
|
|
1596
|
+
if version.config.CapacityProviderConfig:
|
|
1597
|
+
function_has_capacity_provider = True
|
|
1416
1598
|
self.lambda_service.stop_version(version.id.qualified_arn())
|
|
1417
1599
|
destroy_code_if_not_used(code=version.config.code, function=function)
|
|
1418
1600
|
else:
|
|
@@ -1421,11 +1603,20 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1421
1603
|
# the old version gets cleaned up in the internal lambda service.
|
|
1422
1604
|
function = store.functions.pop(function_name)
|
|
1423
1605
|
for version in function.versions.values():
|
|
1424
|
-
|
|
1606
|
+
# Functions with a capacity provider do NOT have a version manager for $LATEST because only
|
|
1607
|
+
# published versions are invokable.
|
|
1608
|
+
if version.config.CapacityProviderConfig:
|
|
1609
|
+
function_has_capacity_provider = True
|
|
1610
|
+
if version.id.qualifier == "$LATEST":
|
|
1611
|
+
pass
|
|
1612
|
+
else:
|
|
1613
|
+
self.lambda_service.stop_version(qualified_arn=version.id.qualified_arn())
|
|
1425
1614
|
# we can safely destroy the code here
|
|
1426
1615
|
if version.config.code:
|
|
1427
1616
|
version.config.code.destroy()
|
|
1428
1617
|
|
|
1618
|
+
return DeleteFunctionResponse(StatusCode=202 if function_has_capacity_provider else 204)
|
|
1619
|
+
|
|
1429
1620
|
def list_functions(
|
|
1430
1621
|
self,
|
|
1431
1622
|
context: RequestContext,
|
|
@@ -1469,7 +1660,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1469
1660
|
self,
|
|
1470
1661
|
context: RequestContext,
|
|
1471
1662
|
function_name: NamespacedFunctionName,
|
|
1472
|
-
qualifier:
|
|
1663
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
1473
1664
|
**kwargs,
|
|
1474
1665
|
) -> GetFunctionResponse:
|
|
1475
1666
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -1540,7 +1731,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1540
1731
|
self,
|
|
1541
1732
|
context: RequestContext,
|
|
1542
1733
|
function_name: NamespacedFunctionName,
|
|
1543
|
-
qualifier:
|
|
1734
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
1544
1735
|
**kwargs,
|
|
1545
1736
|
) -> FunctionConfiguration:
|
|
1546
1737
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -1560,11 +1751,13 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1560
1751
|
self,
|
|
1561
1752
|
context: RequestContext,
|
|
1562
1753
|
function_name: NamespacedFunctionName,
|
|
1563
|
-
invocation_type: InvocationType = None,
|
|
1564
|
-
log_type: LogType = None,
|
|
1565
|
-
client_context: String = None,
|
|
1566
|
-
|
|
1567
|
-
|
|
1754
|
+
invocation_type: InvocationType | None = None,
|
|
1755
|
+
log_type: LogType | None = None,
|
|
1756
|
+
client_context: String | None = None,
|
|
1757
|
+
durable_execution_name: DurableExecutionName | None = None,
|
|
1758
|
+
payload: IO[Blob] | None = None,
|
|
1759
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
1760
|
+
tenant_id: TenantId | None = None,
|
|
1568
1761
|
**kwargs,
|
|
1569
1762
|
) -> InvocationResponse:
|
|
1570
1763
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -1634,9 +1827,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1634
1827
|
self,
|
|
1635
1828
|
context: RequestContext,
|
|
1636
1829
|
function_name: FunctionName,
|
|
1637
|
-
code_sha256: String = None,
|
|
1638
|
-
description: Description = None,
|
|
1639
|
-
revision_id: String = None,
|
|
1830
|
+
code_sha256: String | None = None,
|
|
1831
|
+
description: Description | None = None,
|
|
1832
|
+
revision_id: String | None = None,
|
|
1833
|
+
publish_to: FunctionVersionLatestPublished | None = None,
|
|
1640
1834
|
**kwargs,
|
|
1641
1835
|
) -> FunctionConfiguration:
|
|
1642
1836
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -1648,6 +1842,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1648
1842
|
region=region,
|
|
1649
1843
|
revision_id=revision_id,
|
|
1650
1844
|
code_sha256=code_sha256,
|
|
1845
|
+
publish_to=publish_to,
|
|
1651
1846
|
)
|
|
1652
1847
|
return api_utils.map_config_out(new_version, return_qualified_arn=True)
|
|
1653
1848
|
|
|
@@ -1706,7 +1901,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1706
1901
|
)
|
|
1707
1902
|
if not api_utils.qualifier_is_version(key):
|
|
1708
1903
|
raise ValidationException(
|
|
1709
|
-
f"1 validation error detected: Value '{{{key}={value}}}' at 'routingConfig.additionalVersionWeights' failed to satisfy constraint: Map keys must satisfy constraint: [Member must have length less than or equal to 1024, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: [0-9]
|
|
1904
|
+
f"1 validation error detected: Value '{{{key}={value}}}' at 'routingConfig.additionalVersionWeights' failed to satisfy constraint: Map keys must satisfy constraint: [Member must have length less than or equal to 1024, Member must have length greater than or equal to 1, Member must satisfy regular expression pattern: [0-9]+]"
|
|
1710
1905
|
)
|
|
1711
1906
|
|
|
1712
1907
|
# checking if the version in the config exists
|
|
@@ -1723,7 +1918,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1723
1918
|
context: RequestContext,
|
|
1724
1919
|
function_name: FunctionName,
|
|
1725
1920
|
name: Alias,
|
|
1726
|
-
function_version:
|
|
1921
|
+
function_version: VersionWithLatestPublished,
|
|
1727
1922
|
description: Description = None,
|
|
1728
1923
|
routing_config: AliasRoutingConfiguration = None,
|
|
1729
1924
|
**kwargs,
|
|
@@ -1774,7 +1969,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1774
1969
|
self,
|
|
1775
1970
|
context: RequestContext,
|
|
1776
1971
|
function_name: FunctionName,
|
|
1777
|
-
function_version:
|
|
1972
|
+
function_version: VersionWithLatestPublished = None,
|
|
1778
1973
|
marker: String = None,
|
|
1779
1974
|
max_items: MaxListItems = None,
|
|
1780
1975
|
**kwargs,
|
|
@@ -1842,7 +2037,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
1842
2037
|
context: RequestContext,
|
|
1843
2038
|
function_name: FunctionName,
|
|
1844
2039
|
name: Alias,
|
|
1845
|
-
function_version:
|
|
2040
|
+
function_version: VersionWithLatestPublished = None,
|
|
1846
2041
|
description: Description = None,
|
|
1847
2042
|
routing_config: AliasRoutingConfiguration = None,
|
|
1848
2043
|
revision_id: String = None,
|
|
@@ -2069,6 +2264,9 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2069
2264
|
raise Exception("unknown version") # TODO: cover via test
|
|
2070
2265
|
elif qualifier == "$LATEST":
|
|
2071
2266
|
pass
|
|
2267
|
+
elif qualifier == "$LATEST.PUBLISHED":
|
|
2268
|
+
if fn.versions.get(qualifier):
|
|
2269
|
+
pass
|
|
2072
2270
|
else:
|
|
2073
2271
|
raise Exception("invalid functionname") # TODO: cover via test
|
|
2074
2272
|
fn_arn = api_utils.qualified_lambda_arn(function_name, qualifier, account, region)
|
|
@@ -2591,7 +2789,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2591
2789
|
if revision_id != fn_revision_id:
|
|
2592
2790
|
raise PreconditionFailedException(
|
|
2593
2791
|
"The Revision Id provided does not match the latest Revision Id. "
|
|
2594
|
-
"Call the
|
|
2792
|
+
"Call the GetPolicy API to retrieve the latest Revision Id",
|
|
2595
2793
|
Type="User",
|
|
2596
2794
|
)
|
|
2597
2795
|
|
|
@@ -2649,10 +2847,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2649
2847
|
def remove_permission(
|
|
2650
2848
|
self,
|
|
2651
2849
|
context: RequestContext,
|
|
2652
|
-
function_name:
|
|
2850
|
+
function_name: NamespacedFunctionName,
|
|
2653
2851
|
statement_id: NamespacedStatementId,
|
|
2654
|
-
qualifier:
|
|
2655
|
-
revision_id: String = None,
|
|
2852
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
2853
|
+
revision_id: String | None = None,
|
|
2656
2854
|
**kwargs,
|
|
2657
2855
|
) -> None:
|
|
2658
2856
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -2716,7 +2914,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2716
2914
|
self,
|
|
2717
2915
|
context: RequestContext,
|
|
2718
2916
|
function_name: NamespacedFunctionName,
|
|
2719
|
-
qualifier:
|
|
2917
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
2720
2918
|
**kwargs,
|
|
2721
2919
|
) -> GetPolicyResponse:
|
|
2722
2920
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -2758,9 +2956,9 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2758
2956
|
self,
|
|
2759
2957
|
context: RequestContext,
|
|
2760
2958
|
allowed_publishers: AllowedPublishers,
|
|
2761
|
-
description: Description = None,
|
|
2762
|
-
code_signing_policies: CodeSigningPolicies = None,
|
|
2763
|
-
tags: Tags = None,
|
|
2959
|
+
description: Description | None = None,
|
|
2960
|
+
code_signing_policies: CodeSigningPolicies | None = None,
|
|
2961
|
+
tags: Tags | None = None,
|
|
2764
2962
|
**kwargs,
|
|
2765
2963
|
) -> CreateCodeSigningConfigResponse:
|
|
2766
2964
|
account = context.account_id
|
|
@@ -2785,7 +2983,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2785
2983
|
self,
|
|
2786
2984
|
context: RequestContext,
|
|
2787
2985
|
code_signing_config_arn: CodeSigningConfigArn,
|
|
2788
|
-
function_name:
|
|
2986
|
+
function_name: NamespacedFunctionName,
|
|
2789
2987
|
**kwargs,
|
|
2790
2988
|
) -> PutFunctionCodeSigningConfigResponse:
|
|
2791
2989
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -2852,7 +3050,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2852
3050
|
return GetCodeSigningConfigResponse(CodeSigningConfig=api_utils.map_csc(csc))
|
|
2853
3051
|
|
|
2854
3052
|
def get_function_code_signing_config(
|
|
2855
|
-
self, context: RequestContext, function_name:
|
|
3053
|
+
self, context: RequestContext, function_name: NamespacedFunctionName, **kwargs
|
|
2856
3054
|
) -> GetFunctionCodeSigningConfigResponse:
|
|
2857
3055
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
2858
3056
|
state = lambda_stores[account_id][region]
|
|
@@ -2870,7 +3068,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
2870
3068
|
return GetFunctionCodeSigningConfigResponse()
|
|
2871
3069
|
|
|
2872
3070
|
def delete_function_code_signing_config(
|
|
2873
|
-
self, context: RequestContext, function_name:
|
|
3071
|
+
self, context: RequestContext, function_name: NamespacedFunctionName, **kwargs
|
|
2874
3072
|
) -> None:
|
|
2875
3073
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
2876
3074
|
state = lambda_stores[account_id][region]
|
|
@@ -3280,7 +3478,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3280
3478
|
raise ValidationException(
|
|
3281
3479
|
"1 validation error detected: Value '"
|
|
3282
3480
|
+ destination_arn
|
|
3283
|
-
+
|
|
3481
|
+
+ "' at 'destinationConfig.onFailure.destination' failed to satisfy constraint: Member must satisfy regular expression pattern: "
|
|
3482
|
+
+ "$|kafka://([^.]([a-zA-Z0-9\\-_.]{0,248}))|arn:(aws[a-zA-Z0-9-]*):([a-zA-Z0-9\\-])+:((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1})?:(\\d{12})?:(.*)"
|
|
3284
3483
|
)
|
|
3285
3484
|
|
|
3286
3485
|
match destination_arn.split(":")[2]:
|
|
@@ -3330,7 +3529,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3330
3529
|
self,
|
|
3331
3530
|
context: RequestContext,
|
|
3332
3531
|
function_name: FunctionName,
|
|
3333
|
-
qualifier:
|
|
3532
|
+
qualifier: NumericLatestPublishedOrAliasQualifier = None,
|
|
3334
3533
|
maximum_retry_attempts: MaximumRetryAttempts = None,
|
|
3335
3534
|
maximum_event_age_in_seconds: MaximumEventAgeInSeconds = None,
|
|
3336
3535
|
destination_config: DestinationConfig = None,
|
|
@@ -3412,7 +3611,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3412
3611
|
self,
|
|
3413
3612
|
context: RequestContext,
|
|
3414
3613
|
function_name: FunctionName,
|
|
3415
|
-
qualifier:
|
|
3614
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
3416
3615
|
**kwargs,
|
|
3417
3616
|
) -> FunctionEventInvokeConfig:
|
|
3418
3617
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -3489,7 +3688,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3489
3688
|
self,
|
|
3490
3689
|
context: RequestContext,
|
|
3491
3690
|
function_name: FunctionName,
|
|
3492
|
-
qualifier:
|
|
3691
|
+
qualifier: NumericLatestPublishedOrAliasQualifier | None = None,
|
|
3493
3692
|
**kwargs,
|
|
3494
3693
|
) -> None:
|
|
3495
3694
|
account_id, region = api_utils.get_account_and_region(function_name, context)
|
|
@@ -3517,7 +3716,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3517
3716
|
self,
|
|
3518
3717
|
context: RequestContext,
|
|
3519
3718
|
function_name: FunctionName,
|
|
3520
|
-
qualifier:
|
|
3719
|
+
qualifier: NumericLatestPublishedOrAliasQualifier = None,
|
|
3521
3720
|
maximum_retry_attempts: MaximumRetryAttempts = None,
|
|
3522
3721
|
maximum_event_age_in_seconds: MaximumEventAgeInSeconds = None,
|
|
3523
3722
|
destination_config: DestinationConfig = None,
|
|
@@ -3608,10 +3807,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3608
3807
|
context: RequestContext,
|
|
3609
3808
|
layer_name: LayerName,
|
|
3610
3809
|
content: LayerVersionContentInput,
|
|
3611
|
-
description: Description = None,
|
|
3612
|
-
compatible_runtimes: CompatibleRuntimes = None,
|
|
3613
|
-
license_info: LicenseInfo = None,
|
|
3614
|
-
compatible_architectures: CompatibleArchitectures = None,
|
|
3810
|
+
description: Description | None = None,
|
|
3811
|
+
compatible_runtimes: CompatibleRuntimes | None = None,
|
|
3812
|
+
license_info: LicenseInfo | None = None,
|
|
3813
|
+
compatible_architectures: CompatibleArchitectures | None = None,
|
|
3615
3814
|
**kwargs,
|
|
3616
3815
|
) -> PublishLayerVersionResponse:
|
|
3617
3816
|
"""
|
|
@@ -3749,10 +3948,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3749
3948
|
def list_layers(
|
|
3750
3949
|
self,
|
|
3751
3950
|
context: RequestContext,
|
|
3752
|
-
compatible_runtime: Runtime = None,
|
|
3753
|
-
marker: String = None,
|
|
3754
|
-
max_items: MaxLayerListItems = None,
|
|
3755
|
-
compatible_architecture: Architecture = None,
|
|
3951
|
+
compatible_runtime: Runtime | None = None,
|
|
3952
|
+
marker: String | None = None,
|
|
3953
|
+
max_items: MaxLayerListItems | None = None,
|
|
3954
|
+
compatible_architecture: Architecture | None = None,
|
|
3756
3955
|
**kwargs,
|
|
3757
3956
|
) -> ListLayersResponse:
|
|
3758
3957
|
validation_errors = []
|
|
@@ -3804,10 +4003,10 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
3804
4003
|
self,
|
|
3805
4004
|
context: RequestContext,
|
|
3806
4005
|
layer_name: LayerName,
|
|
3807
|
-
compatible_runtime: Runtime = None,
|
|
3808
|
-
marker: String = None,
|
|
3809
|
-
max_items: MaxLayerListItems = None,
|
|
3810
|
-
compatible_architecture: Architecture = None,
|
|
4006
|
+
compatible_runtime: Runtime | None = None,
|
|
4007
|
+
marker: String | None = None,
|
|
4008
|
+
max_items: MaxLayerListItems | None = None,
|
|
4009
|
+
compatible_architecture: Architecture | None = None,
|
|
3811
4010
|
**kwargs,
|
|
3812
4011
|
) -> ListLayerVersionsResponse:
|
|
3813
4012
|
validation_errors = api_utils.validate_layer_runtimes_and_architectures(
|
|
@@ -4155,7 +4354,7 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
4155
4354
|
|
|
4156
4355
|
def fetch_lambda_store_for_tagging(self, resource: TaggableResource) -> LambdaStore:
|
|
4157
4356
|
"""
|
|
4158
|
-
Takes a resource ARN for a TaggableResource (Lambda Function, Event Source Mapping,
|
|
4357
|
+
Takes a resource ARN for a TaggableResource (Lambda Function, Event Source Mapping, Code Signing Config, or Capacity Provider) and returns a corresponding
|
|
4159
4358
|
LambdaStore for its region and account.
|
|
4160
4359
|
|
|
4161
4360
|
In addition, this function validates that the ARN is a valid TaggableResource type, and that the TaggableResource exists.
|
|
@@ -4190,9 +4389,8 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
4190
4389
|
_raise_validation_exception()
|
|
4191
4390
|
|
|
4192
4391
|
resource_type, resource_identifier, *qualifier = parts
|
|
4193
|
-
if resource_type not in {"event-source-mapping", "code-signing-config", "function"}:
|
|
4194
|
-
_raise_validation_exception()
|
|
4195
4392
|
|
|
4393
|
+
# Qualifier validation raises before checking for NotFound
|
|
4196
4394
|
if qualifier:
|
|
4197
4395
|
if resource_type == "function":
|
|
4198
4396
|
raise InvalidParameterValueException(
|
|
@@ -4201,15 +4399,18 @@ class LambdaProvider(LambdaApi, ServiceLifecycleHook):
|
|
|
4201
4399
|
)
|
|
4202
4400
|
_raise_validation_exception()
|
|
4203
4401
|
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4402
|
+
if resource_type == "event-source-mapping":
|
|
4403
|
+
self._get_esm(resource_identifier, account_id, region)
|
|
4404
|
+
elif resource_type == "code-signing-config":
|
|
4405
|
+
raise NotImplementedError("Resource tagging on CSC not yet implemented.")
|
|
4406
|
+
elif resource_type == "function":
|
|
4407
|
+
self._get_function(
|
|
4408
|
+
function_name=resource_identifier, account_id=account_id, region=region
|
|
4409
|
+
)
|
|
4410
|
+
elif resource_type == "capacity-provider":
|
|
4411
|
+
self._get_capacity_provider(resource_identifier, account_id, region)
|
|
4412
|
+
else:
|
|
4413
|
+
_raise_validation_exception()
|
|
4213
4414
|
|
|
4214
4415
|
# If no exceptions are raised, assume ARN and referenced resource is valid for tag operations
|
|
4215
4416
|
return lambda_stores[account_id][region]
|