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
|
@@ -168,6 +168,7 @@ from localstack.services.events.utils import (
|
|
|
168
168
|
recursive_remove_none_values_from_dict,
|
|
169
169
|
)
|
|
170
170
|
from localstack.services.plugins import ServiceLifecycleHook
|
|
171
|
+
from localstack.state import StateVisitor
|
|
171
172
|
from localstack.utils.common import truncate
|
|
172
173
|
from localstack.utils.event_matcher import matches_event
|
|
173
174
|
from localstack.utils.strings import long_uid
|
|
@@ -246,6 +247,9 @@ class EventsProvider(EventsApi, ServiceLifecycleHook):
|
|
|
246
247
|
self._connection_service_store: ConnectionServiceDict = {}
|
|
247
248
|
self._api_destination_service_store: ApiDestinationServiceDict = {}
|
|
248
249
|
|
|
250
|
+
def accept_state_visitor(self, visitor: StateVisitor):
|
|
251
|
+
visitor.visit(events_stores)
|
|
252
|
+
|
|
249
253
|
def on_before_start(self):
|
|
250
254
|
JobScheduler.start()
|
|
251
255
|
|
|
@@ -45,6 +45,7 @@ from localstack.services.events.scheduler import JobScheduler
|
|
|
45
45
|
from localstack.services.events.v1.models import EventsStore, events_stores
|
|
46
46
|
from localstack.services.moto import call_moto
|
|
47
47
|
from localstack.services.plugins import ServiceLifecycleHook
|
|
48
|
+
from localstack.state import StateVisitor
|
|
48
49
|
from localstack.utils.aws.arns import event_bus_arn, parse_arn
|
|
49
50
|
from localstack.utils.aws.client_types import ServicePrincipal
|
|
50
51
|
from localstack.utils.aws.message_forwarding import send_event_to_target
|
|
@@ -83,6 +84,14 @@ class EventsProvider(EventsApi, ServiceLifecycleHook):
|
|
|
83
84
|
def on_before_stop(self):
|
|
84
85
|
JobScheduler.shutdown()
|
|
85
86
|
|
|
87
|
+
def accept_state_visitor(self, visitor: StateVisitor):
|
|
88
|
+
from moto.events.models import events_backends
|
|
89
|
+
|
|
90
|
+
from localstack.services.events.v1.models import events_stores
|
|
91
|
+
|
|
92
|
+
visitor.visit(events_backends)
|
|
93
|
+
visitor.visit(events_stores)
|
|
94
|
+
|
|
86
95
|
@route("/_aws/events/rules/<path:rule_arn>/trigger")
|
|
87
96
|
def trigger_scheduled_rule(self, request: Request, rule_arn: str):
|
|
88
97
|
"""Developer endpoint to trigger a scheduled rule."""
|
|
@@ -94,6 +94,7 @@ from localstack.services.firehose.mappers import (
|
|
|
94
94
|
convert_source_config_to_desc,
|
|
95
95
|
)
|
|
96
96
|
from localstack.services.firehose.models import FirehoseStore, firehose_stores
|
|
97
|
+
from localstack.state import StateVisitor
|
|
97
98
|
from localstack.utils.aws.arns import (
|
|
98
99
|
extract_account_id_from_arn,
|
|
99
100
|
extract_region_from_arn,
|
|
@@ -251,8 +252,12 @@ class FirehoseProvider(FirehoseApi):
|
|
|
251
252
|
|
|
252
253
|
def __init__(self) -> None:
|
|
253
254
|
super().__init__()
|
|
255
|
+
# TODO: stop/restart the kinesis listeners when stopping the service / reset the state / restore the state
|
|
254
256
|
self.kinesis_listeners = {}
|
|
255
257
|
|
|
258
|
+
def accept_state_visitor(self, visitor: StateVisitor):
|
|
259
|
+
visitor.visit(firehose_stores)
|
|
260
|
+
|
|
256
261
|
@staticmethod
|
|
257
262
|
def get_store(account_id: str, region_name: str) -> FirehoseStore:
|
|
258
263
|
return firehose_stores[account_id][region_name]
|
|
@@ -75,6 +75,7 @@ from localstack.services.iam.resources.policy_simulator import (
|
|
|
75
75
|
)
|
|
76
76
|
from localstack.services.iam.resources.service_linked_roles import SERVICE_LINKED_ROLES
|
|
77
77
|
from localstack.services.moto import call_moto
|
|
78
|
+
from localstack.state import StateVisitor
|
|
78
79
|
from localstack.utils.aws.request_context import extract_access_key_id_from_auth_header
|
|
79
80
|
|
|
80
81
|
LOG = logging.getLogger(__name__)
|
|
@@ -110,6 +111,9 @@ class IamProvider(IamApi):
|
|
|
110
111
|
apply_iam_patches()
|
|
111
112
|
self.policy_simulator = BasicIAMPolicySimulator()
|
|
112
113
|
|
|
114
|
+
def accept_state_visitor(self, visitor: StateVisitor):
|
|
115
|
+
visitor.visit(iam_backends)
|
|
116
|
+
|
|
113
117
|
@handler("CreateRole", expand=False)
|
|
114
118
|
def create_role(
|
|
115
119
|
self, context: RequestContext, request: CreateRoleRequest
|
|
@@ -7,7 +7,7 @@ from localstack.packages import InstallTarget, Package
|
|
|
7
7
|
from localstack.packages.core import GitHubReleaseInstaller, NodePackageInstaller
|
|
8
8
|
from localstack.packages.java import JavaInstallerMixin, java_package
|
|
9
9
|
|
|
10
|
-
_KINESIS_MOCK_VERSION = os.environ.get("KINESIS_MOCK_VERSION") or "0.5.
|
|
10
|
+
_KINESIS_MOCK_VERSION = os.environ.get("KINESIS_MOCK_VERSION") or "0.5.2"
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class KinesisMockEngine(StrEnum):
|
|
@@ -20,7 +20,6 @@ from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
|
|
|
20
20
|
from cryptography.hazmat.primitives.asymmetric.padding import PSS, PKCS1v15
|
|
21
21
|
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
|
|
22
22
|
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
|
|
23
|
-
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
|
24
23
|
from cryptography.hazmat.primitives.serialization import load_der_public_key
|
|
25
24
|
|
|
26
25
|
from localstack.aws.api.kms import (
|
|
@@ -233,7 +232,10 @@ class KmsCryptoKey:
|
|
|
233
232
|
|
|
234
233
|
if key_spec.startswith("RSA"):
|
|
235
234
|
key_size = RSA_CRYPTO_KEY_LENGTHS.get(key_spec)
|
|
236
|
-
|
|
235
|
+
if key_material:
|
|
236
|
+
key = crypto_serialization.load_der_private_key(key_material, password=None)
|
|
237
|
+
else:
|
|
238
|
+
key = rsa.generate_private_key(public_exponent=65537, key_size=key_size)
|
|
237
239
|
elif key_spec.startswith("ECC"):
|
|
238
240
|
curve = ECC_CURVES.get(key_spec)
|
|
239
241
|
if key_material:
|
|
@@ -442,17 +444,15 @@ class KmsKey:
|
|
|
442
444
|
|
|
443
445
|
def derive_shared_secret(self, public_key: bytes) -> bytes:
|
|
444
446
|
key_spec = self.metadata.get("KeySpec")
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
f"{self.metadata['Arn']} key usage is {self.metadata['KeyUsage']} which is not valid for DeriveSharedSecret."
|
|
455
|
-
)
|
|
447
|
+
if key_spec not in (
|
|
448
|
+
KeySpec.ECC_NIST_P256,
|
|
449
|
+
KeySpec.ECC_SECG_P256K1,
|
|
450
|
+
KeySpec.ECC_NIST_P384,
|
|
451
|
+
KeySpec.ECC_NIST_P521,
|
|
452
|
+
):
|
|
453
|
+
raise InvalidKeyUsageException(
|
|
454
|
+
f"{self.metadata['Arn']} key usage is {self.metadata['KeyUsage']} which is not valid for DeriveSharedSecret."
|
|
455
|
+
)
|
|
456
456
|
|
|
457
457
|
# Deserialize public key from DER encoded data to EllipticCurvePublicKey.
|
|
458
458
|
try:
|
|
@@ -460,14 +460,7 @@ class KmsKey:
|
|
|
460
460
|
except (UnsupportedAlgorithm, ValueError):
|
|
461
461
|
raise ValidationException("")
|
|
462
462
|
shared_secret = self.crypto_key.key.exchange(ec.ECDH(), pub_key)
|
|
463
|
-
|
|
464
|
-
return HKDF(
|
|
465
|
-
algorithm=algorithm,
|
|
466
|
-
salt=None,
|
|
467
|
-
info=b"",
|
|
468
|
-
length=algorithm.digest_size,
|
|
469
|
-
backend=default_backend(),
|
|
470
|
-
).derive(shared_secret)
|
|
463
|
+
return shared_secret
|
|
471
464
|
|
|
472
465
|
# This method gets called when a key is replicated to another region. It's meant to populate the required metadata
|
|
473
466
|
# fields in a new replica key.
|
|
@@ -646,7 +639,8 @@ class KmsKey:
|
|
|
646
639
|
# https://docs.aws.amazon.com/kms/latest/APIReference/API_TagResource.html
|
|
647
640
|
# "To edit a tag, specify an existing tag key and a new tag value."
|
|
648
641
|
for i, tag in enumerate(tags, start=1):
|
|
649
|
-
|
|
642
|
+
if tag.get("TagKey") != TAG_KEY_CUSTOM_KEY_MATERIAL:
|
|
643
|
+
validate_tag(i, tag)
|
|
650
644
|
self.tags[tag.get("TagKey")] = tag.get("TagValue")
|
|
651
645
|
|
|
652
646
|
def schedule_key_deletion(self, pending_window_in_days: int) -> None:
|
|
@@ -138,6 +138,7 @@ from localstack.services.kms.utils import (
|
|
|
138
138
|
validate_alias_name,
|
|
139
139
|
)
|
|
140
140
|
from localstack.services.plugins import ServiceLifecycleHook
|
|
141
|
+
from localstack.state import StateVisitor
|
|
141
142
|
from localstack.utils.aws.arns import get_partition, kms_alias_arn, parse_arn
|
|
142
143
|
from localstack.utils.collections import PaginatedList
|
|
143
144
|
from localstack.utils.common import select_attributes
|
|
@@ -201,6 +202,9 @@ class KmsProvider(KmsApi, ServiceLifecycleHook):
|
|
|
201
202
|
- VerifyMac
|
|
202
203
|
"""
|
|
203
204
|
|
|
205
|
+
def accept_state_visitor(self, visitor: StateVisitor):
|
|
206
|
+
visitor.visit(kms_stores)
|
|
207
|
+
|
|
204
208
|
#
|
|
205
209
|
# Helpers
|
|
206
210
|
#
|
|
@@ -14,9 +14,10 @@ function_counter = LabeledCounter(
|
|
|
14
14
|
"status",
|
|
15
15
|
"runtime",
|
|
16
16
|
"package_type",
|
|
17
|
-
# only for operation "invoke"
|
|
18
|
-
"
|
|
17
|
+
"invocation_type", # only for operation "invoke", otherwise "n/a"
|
|
18
|
+
"initialization_type",
|
|
19
19
|
],
|
|
20
|
+
schema_version=2,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
|
|
@@ -38,6 +39,14 @@ class FunctionStatus(StrEnum):
|
|
|
38
39
|
invocation_error = "invocation_error"
|
|
39
40
|
|
|
40
41
|
|
|
42
|
+
class FunctionInitializationType(StrEnum):
|
|
43
|
+
# Maps to the Lambda environment variable AWS_LAMBDA_INITIALIZATION_TYPE
|
|
44
|
+
on_demand = "on-demand"
|
|
45
|
+
lambda_managed_instances = "lambda-managed-instances"
|
|
46
|
+
# Only applies to the operation "invoke" because provisioned concurrency is not configured on "create"
|
|
47
|
+
provisioned_concurrency = "provisioned-concurrency"
|
|
48
|
+
|
|
49
|
+
|
|
41
50
|
esm_counter = LabeledCounter(namespace=NAMESPACE, name="esm", labels=["source", "status"])
|
|
42
51
|
|
|
43
52
|
|
|
@@ -3,6 +3,8 @@ Everything related to behavior or implicit functionality goes into `lambda_utils
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import datetime
|
|
6
|
+
import hashlib
|
|
7
|
+
import json
|
|
6
8
|
import random
|
|
7
9
|
import re
|
|
8
10
|
import string
|
|
@@ -62,13 +64,14 @@ DESTINATION_ARN_PATTERN = re.compile(
|
|
|
62
64
|
r"^$|arn:(aws[a-zA-Z0-9-]*):([a-zA-Z0-9\-])+:([a-z]{2}(-gov)?-[a-z]+-\d{1})?:(\d{12})?:(.*)"
|
|
63
65
|
)
|
|
64
66
|
|
|
67
|
+
# TODO: what's the difference between AWS_FUNCTION_NAME_REGEX and FUNCTION_NAME_REGEX? Can we unify?
|
|
65
68
|
AWS_FUNCTION_NAME_REGEX = re.compile(
|
|
66
|
-
"^(arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_.]+)(:(\\$LATEST
|
|
69
|
+
"^(arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_.]+)(:(\\$LATEST(\\.PUBLISHED)?|[a-zA-Z0-9-_]+))?$"
|
|
67
70
|
)
|
|
68
71
|
|
|
69
72
|
# Pattern for extracting various attributes from a full or partial ARN or just a function name.
|
|
70
73
|
FUNCTION_NAME_REGEX = re.compile(
|
|
71
|
-
r"(arn:(aws[a-zA-Z-]*):lambda:)?((?P<region>[a-z]{2}(-gov)?-[a-z]+-\d{1}):)?(?:(?P<account>\d{12}):)?(function:)?(?P<name>[a-zA-Z0-9-_\.]+)(:(?P<qualifier>\$LATEST
|
|
74
|
+
r"(arn:(aws[a-zA-Z-]*):lambda:)?((?P<region>[a-z]{2}(-gov)?-[a-z]+-\d{1}):)?(?:(?P<account>\d{12}):)?(function:)?(?P<name>[a-zA-Z0-9-_\.]+)(:(?P<qualifier>\$LATEST(\.PUBLISHED)?|[a-zA-Z0-9-_]+))?"
|
|
72
75
|
) # also length 1-170 incl.
|
|
73
76
|
# Pattern for a lambda function handler
|
|
74
77
|
HANDLER_REGEX = re.compile(r"[^\s]+")
|
|
@@ -86,9 +89,11 @@ SIGNING_JOB_ARN_REGEX = re.compile(
|
|
|
86
89
|
SIGNING_PROFILE_VERSION_ARN_REGEX = re.compile(
|
|
87
90
|
r"arn:(aws[a-zA-Z0-9-]*):([a-zA-Z0-9\-])+:([a-z]{2}(-gov)?-[a-z]+-\d{1})?:(\d{12})?:(.*)"
|
|
88
91
|
)
|
|
89
|
-
# Combined pattern for alias and version based on AWS error using "(|[a-zA-Z0-9$
|
|
90
|
-
|
|
92
|
+
# Combined pattern for alias and version based on AWS error using "\\$(LATEST(\\.PUBLISHED)?)|[a-zA-Z0-9-_$]+"
|
|
93
|
+
# This regex is based on the snapshotted validation message, just removing the double \\ before $LATEST
|
|
94
|
+
QUALIFIER_REGEX = re.compile(r"^\$(LATEST(\\.PUBLISHED)?)|[a-zA-Z0-9-_$]+$")
|
|
91
95
|
# Pattern for a version qualifier
|
|
96
|
+
# TODO: do we need to consider $LATEST.PUBLISHED here?
|
|
92
97
|
VERSION_REGEX = re.compile(r"^[0-9]+$")
|
|
93
98
|
# Pattern for an alias qualifier
|
|
94
99
|
# Rules: https://docs.aws.amazon.com/lambda/latest/dg/API_CreateAlias.html#SSS-CreateAlias-request-Name
|
|
@@ -107,36 +112,42 @@ LAMBDA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f+0000"
|
|
|
107
112
|
# An unordered list of all Lambda CPU architectures supported by LocalStack.
|
|
108
113
|
ARCHITECTURES = [Architecture.arm64, Architecture.x86_64]
|
|
109
114
|
|
|
110
|
-
# ARN
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
ARN_NAME_PATTERN_VALIDATION_TEMPLATE = "(arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{{2}}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{{1}}:)?(\\d{{12}}:)?(function:)?([a-zA-Z0-9-_{0}]+)(:(\\$LATEST|[a-zA-Z0-9-_]+))?"
|
|
115
|
+
# ARN patterns returned in validation exception messages
|
|
116
|
+
ARN_NAME_PATTERN_GET = r"(arn:(aws[a-zA-Z-]*)?:lambda:)?((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_\.]+)(:(\$LATEST(\.PUBLISHED)?|[a-zA-Z0-9-_]+))?"
|
|
117
|
+
ARN_NAME_PATTERN_CREATE = r"(arn:(aws[a-zA-Z-]*)?:lambda:)?((eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?"
|
|
114
118
|
|
|
115
119
|
# AWS response when invalid ARNs are used in Tag operations.
|
|
116
|
-
TAGGABLE_RESOURCE_ARN_PATTERN = "arn:(aws[a-zA-Z-]*):lambda:[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:\\d{12}:(function:[a-zA-Z0-9-_]+(:(\\$LATEST|[a-zA-Z0-9-_]+))?|layer:([a-zA-Z0-9-_]+)|code-signing-config:csc-[a-z0-9]{17}|event-source-mapping:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"
|
|
120
|
+
TAGGABLE_RESOURCE_ARN_PATTERN = "arn:(aws[a-zA-Z-]*):lambda:(eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:\\d{12}:(function:[a-zA-Z0-9-_]+(:(\\$LATEST|[a-zA-Z0-9-_]+))?|layer:([a-zA-Z0-9-_]+)|code-signing-config:csc-[a-z0-9]{17}|event-source-mapping:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|capacity-provider:[a-zA-Z0-9-_]+)"
|
|
117
121
|
|
|
118
122
|
|
|
119
123
|
def validate_function_name(function_name_or_arn: str, operation_type: str):
|
|
120
124
|
function_name, *_ = function_locators_from_arn(function_name_or_arn)
|
|
121
|
-
arn_name_pattern =
|
|
125
|
+
arn_name_pattern = ARN_NAME_PATTERN_CREATE
|
|
122
126
|
max_length = 170
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
if operation_type == "GetFunction" or operation_type == "Invoke":
|
|
129
|
+
arn_name_pattern = ARN_NAME_PATTERN_GET
|
|
130
|
+
elif operation_type == "CreateFunction":
|
|
131
|
+
# https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-FunctionName
|
|
132
|
+
if function_name == function_name_or_arn: # only a function name
|
|
128
133
|
max_length = 64
|
|
129
|
-
|
|
134
|
+
else: # full or partial ARN
|
|
130
135
|
max_length = 140
|
|
136
|
+
elif operation_type == "DeleteFunction":
|
|
137
|
+
max_length = 140
|
|
138
|
+
arn_name_pattern = ARN_NAME_PATTERN_GET
|
|
131
139
|
|
|
132
140
|
validations = []
|
|
133
|
-
if
|
|
134
|
-
constraint = f"Member must
|
|
141
|
+
if not AWS_FUNCTION_NAME_REGEX.match(function_name_or_arn) or not function_name:
|
|
142
|
+
constraint = f"Member must satisfy regular expression pattern: {arn_name_pattern}"
|
|
135
143
|
validation_msg = f"Value '{function_name_or_arn}' at 'functionName' failed to satisfy constraint: {constraint}"
|
|
136
144
|
validations.append(validation_msg)
|
|
145
|
+
if not operation_type == "CreateFunction":
|
|
146
|
+
# Immediately raises rather than summarizing all validations, except for CreateFunction
|
|
147
|
+
return validations
|
|
137
148
|
|
|
138
|
-
if
|
|
139
|
-
constraint = f"Member must
|
|
149
|
+
if len(function_name_or_arn) > max_length:
|
|
150
|
+
constraint = f"Member must have length less than or equal to {max_length}"
|
|
140
151
|
validation_msg = f"Value '{function_name_or_arn}' at 'functionName' failed to satisfy constraint: {constraint}"
|
|
141
152
|
validations.append(validation_msg)
|
|
142
153
|
|
|
@@ -154,7 +165,7 @@ def validate_qualifier(qualifier: str):
|
|
|
154
165
|
validations.append(validation_msg)
|
|
155
166
|
|
|
156
167
|
if not QUALIFIER_REGEX.match(qualifier):
|
|
157
|
-
constraint = "Member must satisfy regular expression pattern: (|[a-zA-Z0-9$
|
|
168
|
+
constraint = "Member must satisfy regular expression pattern: \\$(LATEST(\\.PUBLISHED)?)|[a-zA-Z0-9-_$]+"
|
|
158
169
|
validation_msg = (
|
|
159
170
|
f"Value '{qualifier}' at 'qualifier' failed to satisfy constraint: {constraint}"
|
|
160
171
|
)
|
|
@@ -571,6 +582,12 @@ def map_config_out(
|
|
|
571
582
|
optional_kwargs["CodeSize"] = 0
|
|
572
583
|
optional_kwargs["CodeSha256"] = version.config.image.code_sha256
|
|
573
584
|
|
|
585
|
+
if version.config.CapacityProviderConfig:
|
|
586
|
+
optional_kwargs["CapacityProviderConfig"] = version.config.CapacityProviderConfig
|
|
587
|
+
data = json.dumps(version.config.CapacityProviderConfig, sort_keys=True).encode("utf-8")
|
|
588
|
+
config_sha_256 = hashlib.sha256(data).hexdigest()
|
|
589
|
+
optional_kwargs["ConfigSha256"] = config_sha_256
|
|
590
|
+
|
|
574
591
|
# output for an alias qualifier is completely the same except for the returned ARN
|
|
575
592
|
if alias_name:
|
|
576
593
|
function_arn = f"{':'.join(version.id.qualified_arn().split(':')[:-1])}:{alias_name}"
|
|
@@ -36,7 +36,7 @@ from localstack.services.lambda_.event_source_mapping.senders.sender_utils impor
|
|
|
36
36
|
)
|
|
37
37
|
from localstack.utils.aws.arns import parse_arn, s3_bucket_name
|
|
38
38
|
from localstack.utils.backoff import ExponentialBackoff
|
|
39
|
-
from localstack.utils.
|
|
39
|
+
from localstack.utils.batching import Batcher
|
|
40
40
|
from localstack.utils.strings import long_uid
|
|
41
41
|
|
|
42
42
|
LOG = logging.getLogger(__name__)
|
|
@@ -88,9 +88,12 @@ class AssignmentService(OtherServiceEndpoint):
|
|
|
88
88
|
self, version_manager_id: str, function_version: FunctionVersion
|
|
89
89
|
) -> ExecutionEnvironment:
|
|
90
90
|
LOG.debug("Starting new environment")
|
|
91
|
+
initialization_type = "on-demand"
|
|
92
|
+
if function_version.config.CapacityProviderConfig:
|
|
93
|
+
initialization_type = "lambda-managed-instances"
|
|
91
94
|
execution_environment = ExecutionEnvironment(
|
|
92
95
|
function_version=function_version,
|
|
93
|
-
initialization_type=
|
|
96
|
+
initialization_type=initialization_type,
|
|
94
97
|
on_timeout=self.on_timeout,
|
|
95
98
|
version_manager_id=version_manager_id,
|
|
96
99
|
)
|
|
@@ -13,6 +13,7 @@ from botocore.config import Config
|
|
|
13
13
|
from localstack import config
|
|
14
14
|
from localstack.aws.api.lambda_ import InvocationType, TooManyRequestsException
|
|
15
15
|
from localstack.services.lambda_.analytics import (
|
|
16
|
+
FunctionInitializationType,
|
|
16
17
|
FunctionOperation,
|
|
17
18
|
FunctionStatus,
|
|
18
19
|
function_counter,
|
|
@@ -198,22 +199,22 @@ class Poller:
|
|
|
198
199
|
def handle_message(self, message: dict) -> None:
|
|
199
200
|
failure_cause = None
|
|
200
201
|
qualifier = self.version_manager.function_version.id.qualifier
|
|
202
|
+
function_config = self.version_manager.function_version.config
|
|
201
203
|
event_invoke_config = self.version_manager.function.event_invoke_configs.get(qualifier)
|
|
202
204
|
runtime = None
|
|
203
205
|
status = None
|
|
206
|
+
# TODO: handle initialization_type provisioned-concurrency, which requires enriching invocation_result
|
|
207
|
+
initialization_type = (
|
|
208
|
+
FunctionInitializationType.lambda_managed_instances
|
|
209
|
+
if function_config.CapacityProviderConfig
|
|
210
|
+
else FunctionInitializationType.on_demand
|
|
211
|
+
)
|
|
204
212
|
try:
|
|
205
213
|
sqs_invocation = SQSInvocation.decode(message["Body"])
|
|
206
214
|
invocation = sqs_invocation.invocation
|
|
207
215
|
try:
|
|
208
216
|
invocation_result = self.version_manager.invoke(invocation=invocation)
|
|
209
|
-
|
|
210
|
-
function_counter.labels(
|
|
211
|
-
operation=FunctionOperation.invoke,
|
|
212
|
-
runtime=function_config.runtime or "n/a",
|
|
213
|
-
status=FunctionStatus.success,
|
|
214
|
-
invocation_type=InvocationType.Event,
|
|
215
|
-
package_type=function_config.package_type,
|
|
216
|
-
).increment()
|
|
217
|
+
status = FunctionStatus.success
|
|
217
218
|
except Exception as e:
|
|
218
219
|
# Reserved concurrency == 0
|
|
219
220
|
if self.version_manager.function.reserved_concurrent_executions == 0:
|
|
@@ -223,6 +224,7 @@ class Poller:
|
|
|
223
224
|
elif not has_enough_time_for_retry(sqs_invocation, event_invoke_config):
|
|
224
225
|
failure_cause = "EventAgeExceeded"
|
|
225
226
|
status = FunctionStatus.event_age_exceeded_error
|
|
227
|
+
|
|
226
228
|
if failure_cause:
|
|
227
229
|
invocation_result = InvocationResult(
|
|
228
230
|
is_error=True, request_id=invocation.request_id, payload=None, logs=None
|
|
@@ -240,14 +242,14 @@ class Poller:
|
|
|
240
242
|
sqs_client.delete_message(
|
|
241
243
|
QueueUrl=self.event_queue_url, ReceiptHandle=message["ReceiptHandle"]
|
|
242
244
|
)
|
|
243
|
-
|
|
244
|
-
package_type = self.version_manager.function_version.config.package_type
|
|
245
|
+
assert status, "status MUST be set before returning"
|
|
245
246
|
function_counter.labels(
|
|
246
247
|
operation=FunctionOperation.invoke,
|
|
247
248
|
runtime=runtime or "n/a",
|
|
248
249
|
status=status,
|
|
249
250
|
invocation_type=InvocationType.Event,
|
|
250
|
-
package_type=package_type,
|
|
251
|
+
package_type=function_config.package_type,
|
|
252
|
+
initialization_type=initialization_type,
|
|
251
253
|
).increment()
|
|
252
254
|
|
|
253
255
|
# Good summary blogpost: https://haithai91.medium.com/aws-lambdas-retry-behaviors-edff90e1cf1b
|
|
@@ -257,6 +259,8 @@ class Poller:
|
|
|
257
259
|
if event_invoke_config and event_invoke_config.maximum_retry_attempts is not None:
|
|
258
260
|
max_retry_attempts = event_invoke_config.maximum_retry_attempts
|
|
259
261
|
|
|
262
|
+
assert invocation_result, "Invocation result MUST exist if we are not returning before"
|
|
263
|
+
|
|
260
264
|
# An invocation error either leads to a terminal failure or to a scheduled retry
|
|
261
265
|
if invocation_result.is_error: # invocation error
|
|
262
266
|
failure_cause = None
|
|
@@ -8,6 +8,7 @@ from enum import Enum, auto
|
|
|
8
8
|
from threading import RLock, Timer
|
|
9
9
|
|
|
10
10
|
from localstack import config
|
|
11
|
+
from localstack.aws.api.lambda_ import LogFormat
|
|
11
12
|
from localstack.aws.connect import connect_to
|
|
12
13
|
from localstack.services.lambda_.invocation.lambda_models import (
|
|
13
14
|
Credentials,
|
|
@@ -149,6 +150,22 @@ class ExecutionEnvironment:
|
|
|
149
150
|
# LOCALSTACK_USER conditionally added below
|
|
150
151
|
}
|
|
151
152
|
# Conditionally added environment variables
|
|
153
|
+
# Lambda advanced logging controls:
|
|
154
|
+
# https://aws.amazon.com/blogs/compute/introducing-advanced-logging-controls-for-aws-lambda-functions/
|
|
155
|
+
logging_config = self.function_version.config.logging_config
|
|
156
|
+
if logging_config.get("LogFormat") == LogFormat.JSON:
|
|
157
|
+
env_vars["AWS_LAMBDA_LOG_FORMAT"] = logging_config["LogFormat"]
|
|
158
|
+
# TODO: test this (currently not implemented in LocalStack)
|
|
159
|
+
env_vars["AWS_LAMBDA_LOG_LEVEL"] = logging_config["ApplicationLogLevel"].capitalize()
|
|
160
|
+
# Lambda Managed Instances
|
|
161
|
+
if capacity_provider_config := self.function_version.config.CapacityProviderConfig:
|
|
162
|
+
# Disable dropping privileges for parity
|
|
163
|
+
# TODO: implement mixed permissions (maybe in RIE)
|
|
164
|
+
# env_vars["LOCALSTACK_USER"] = "root"
|
|
165
|
+
env_vars["AWS_LAMBDA_MAX_CONCURRENCY"] = capacity_provider_config[
|
|
166
|
+
"LambdaManagedInstancesCapacityProviderConfig"
|
|
167
|
+
]["PerExecutionEnvironmentMaxConcurrency"]
|
|
168
|
+
env_vars["TZ"] = ":/etc/localtime"
|
|
152
169
|
if not config.LAMBDA_DISABLE_AWS_ENDPOINT_URL:
|
|
153
170
|
env_vars["AWS_ENDPOINT_URL"] = (
|
|
154
171
|
f"http://{self.runtime_executor.get_endpoint_from_executor()}:{config.GATEWAY_LISTEN[0].port}"
|
|
@@ -159,8 +176,6 @@ class ExecutionEnvironment:
|
|
|
159
176
|
# Will be overridden by the runtime itself unless it is a provided runtime
|
|
160
177
|
if self.function_version.config.runtime:
|
|
161
178
|
env_vars["AWS_EXECUTION_ENV"] = "AWS_Lambda_rapid"
|
|
162
|
-
if self.function_version.config.environment:
|
|
163
|
-
env_vars.update(self.function_version.config.environment)
|
|
164
179
|
if config.LAMBDA_INIT_DEBUG:
|
|
165
180
|
# Disable dropping privileges because it breaks debugging
|
|
166
181
|
env_vars["LOCALSTACK_USER"] = "root"
|
|
@@ -175,6 +190,10 @@ class ExecutionEnvironment:
|
|
|
175
190
|
env_vars["LOCALSTACK_MAX_PAYLOAD_SIZE"] = int(
|
|
176
191
|
config.LAMBDA_LIMITS_MAX_FUNCTION_PAYLOAD_SIZE_BYTES
|
|
177
192
|
)
|
|
193
|
+
|
|
194
|
+
# Let users overwrite any environment variable at last (if they want so)
|
|
195
|
+
if self.function_version.config.environment:
|
|
196
|
+
env_vars.update(self.function_version.config.environment)
|
|
178
197
|
return env_vars
|
|
179
198
|
|
|
180
199
|
# Lifecycle methods
|
|
@@ -12,7 +12,7 @@ import threading
|
|
|
12
12
|
from abc import ABCMeta, abstractmethod
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import IO, Literal, TypedDict
|
|
15
|
+
from typing import IO, Literal, Optional, TypedDict
|
|
16
16
|
|
|
17
17
|
import boto3
|
|
18
18
|
from botocore.exceptions import ClientError
|
|
@@ -22,12 +22,20 @@ from localstack.aws.api import CommonServiceException
|
|
|
22
22
|
from localstack.aws.api.lambda_ import (
|
|
23
23
|
AllowedPublishers,
|
|
24
24
|
Architecture,
|
|
25
|
+
CapacityProviderArn,
|
|
26
|
+
CapacityProviderConfig,
|
|
27
|
+
CapacityProviderPermissionsConfig,
|
|
28
|
+
CapacityProviderScalingConfig,
|
|
29
|
+
CapacityProviderVpcConfig,
|
|
25
30
|
CodeSigningPolicies,
|
|
26
31
|
Cors,
|
|
27
32
|
DestinationConfig,
|
|
33
|
+
FunctionScalingConfig,
|
|
28
34
|
FunctionUrlAuthType,
|
|
35
|
+
InstanceRequirements,
|
|
29
36
|
InvocationType,
|
|
30
37
|
InvokeMode,
|
|
38
|
+
KMSKeyArn,
|
|
31
39
|
LastUpdateStatus,
|
|
32
40
|
LoggingConfig,
|
|
33
41
|
PackageType,
|
|
@@ -38,12 +46,14 @@ from localstack.aws.api.lambda_ import (
|
|
|
38
46
|
SnapStartResponse,
|
|
39
47
|
State,
|
|
40
48
|
StateReasonCode,
|
|
49
|
+
Timestamp,
|
|
41
50
|
TracingMode,
|
|
42
51
|
)
|
|
43
52
|
from localstack.aws.connect import connect_to
|
|
44
53
|
from localstack.constants import AWS_REGION_US_EAST_1, INTERNAL_AWS_SECRET_ACCESS_KEY
|
|
45
54
|
from localstack.services.lambda_.api_utils import qualified_lambda_arn, unqualified_lambda_arn
|
|
46
55
|
from localstack.utils.archives import unzip
|
|
56
|
+
from localstack.utils.files import chmod_r
|
|
47
57
|
from localstack.utils.strings import long_uid, short_uid
|
|
48
58
|
|
|
49
59
|
LOG = logging.getLogger(__name__)
|
|
@@ -212,6 +222,7 @@ class S3Code(ArchiveCode):
|
|
|
212
222
|
with tempfile.NamedTemporaryFile() as file:
|
|
213
223
|
self._download_archive_to_file(file)
|
|
214
224
|
unzip(file.name, str(target_path))
|
|
225
|
+
chmod_r(str(target_path), 0o755)
|
|
215
226
|
|
|
216
227
|
def destroy_cached(self) -> None:
|
|
217
228
|
"""
|
|
@@ -331,7 +342,7 @@ class VpcConfig:
|
|
|
331
342
|
@dataclasses.dataclass(frozen=True)
|
|
332
343
|
class UpdateStatus:
|
|
333
344
|
status: LastUpdateStatus | None
|
|
334
|
-
code: str | None = None
|
|
345
|
+
code: str | None = None
|
|
335
346
|
reason: str | None = None
|
|
336
347
|
|
|
337
348
|
|
|
@@ -568,6 +579,9 @@ class VersionFunctionConfiguration:
|
|
|
568
579
|
vpc_config: VpcConfig | None = None
|
|
569
580
|
|
|
570
581
|
logging_config: LoggingConfig = dataclasses.field(default_factory=dict)
|
|
582
|
+
# TODO: why does `CapacityProviderConfig | None = None` fail with on Python 3.13.9:
|
|
583
|
+
# TypeError: unsupported operand type(s) for |: 'NoneType' and 'NoneType'
|
|
584
|
+
CapacityProviderConfig: Optional[CapacityProviderConfig] = None # noqa
|
|
571
585
|
|
|
572
586
|
|
|
573
587
|
@dataclasses.dataclass(frozen=True)
|
|
@@ -580,6 +594,18 @@ class FunctionVersion:
|
|
|
580
594
|
return self.id.qualified_arn()
|
|
581
595
|
|
|
582
596
|
|
|
597
|
+
@dataclasses.dataclass
|
|
598
|
+
class CapacityProvider:
|
|
599
|
+
CapacityProviderArn: CapacityProviderArn
|
|
600
|
+
# State is determined dynamically
|
|
601
|
+
VpcConfig: CapacityProviderVpcConfig
|
|
602
|
+
PermissionsConfig: CapacityProviderPermissionsConfig
|
|
603
|
+
InstanceRequirements: InstanceRequirements
|
|
604
|
+
CapacityProviderScalingConfig: CapacityProviderScalingConfig
|
|
605
|
+
LastModified: Timestamp
|
|
606
|
+
KmsKeyArn: KMSKeyArn | None = None
|
|
607
|
+
|
|
608
|
+
|
|
583
609
|
@dataclasses.dataclass
|
|
584
610
|
class Function:
|
|
585
611
|
function_name: str
|
|
@@ -600,6 +626,9 @@ class Function:
|
|
|
600
626
|
provisioned_concurrency_configs: dict[str, ProvisionedConcurrencyConfiguration] = (
|
|
601
627
|
dataclasses.field(default_factory=dict)
|
|
602
628
|
)
|
|
629
|
+
function_scaling_configs: dict[str, FunctionScalingConfig] = dataclasses.field(
|
|
630
|
+
default_factory=dict
|
|
631
|
+
)
|
|
603
632
|
|
|
604
633
|
lock: threading.RLock = dataclasses.field(default_factory=threading.RLock)
|
|
605
634
|
next_version: int = 1
|