localstack-core 4.7.1.dev49__py3-none-any.whl → 4.10.1.dev12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- localstack/aws/api/cloudformation/__init__.py +18 -4
- localstack/aws/api/cloudwatch/__init__.py +41 -1
- localstack/aws/api/config/__init__.py +4 -0
- localstack/aws/api/core.py +6 -2
- localstack/aws/api/dynamodb/__init__.py +30 -0
- localstack/aws/api/ec2/__init__.py +1522 -65
- localstack/aws/api/iam/__init__.py +7 -0
- localstack/aws/api/kinesis/__init__.py +19 -0
- localstack/aws/api/kms/__init__.py +6 -0
- localstack/aws/api/lambda_/__init__.py +13 -0
- localstack/aws/api/logs/__init__.py +15 -0
- localstack/aws/api/redshift/__init__.py +9 -3
- localstack/aws/api/route53/__init__.py +5 -0
- localstack/aws/api/s3/__init__.py +12 -0
- localstack/aws/api/s3control/__init__.py +54 -0
- localstack/aws/api/ssm/__init__.py +2 -0
- localstack/aws/api/transcribe/__init__.py +17 -0
- localstack/aws/client.py +7 -2
- localstack/aws/forwarder.py +52 -5
- localstack/aws/handlers/analytics.py +1 -1
- localstack/aws/handlers/internal_requests.py +6 -1
- localstack/aws/handlers/logging.py +12 -2
- localstack/aws/handlers/metric_handler.py +41 -1
- localstack/aws/handlers/service.py +40 -20
- localstack/aws/mocking.py +2 -2
- localstack/aws/patches.py +2 -2
- localstack/aws/protocol/parser.py +459 -32
- localstack/aws/protocol/serializer.py +689 -69
- localstack/aws/protocol/service_router.py +120 -20
- localstack/aws/protocol/validate.py +1 -1
- localstack/aws/scaffold.py +1 -1
- localstack/aws/skeleton.py +4 -2
- localstack/aws/spec-patches.json +58 -0
- localstack/aws/spec.py +37 -16
- localstack/cli/exceptions.py +1 -1
- localstack/cli/localstack.py +6 -6
- localstack/cli/lpm.py +3 -4
- localstack/cli/plugins.py +1 -1
- localstack/cli/profiles.py +1 -2
- localstack/config.py +25 -18
- localstack/constants.py +4 -29
- localstack/dev/kubernetes/__main__.py +130 -7
- localstack/dev/run/configurators.py +1 -4
- localstack/dev/run/paths.py +1 -1
- localstack/dns/plugins.py +5 -1
- localstack/dns/server.py +13 -4
- localstack/logging/format.py +3 -3
- localstack/packages/api.py +9 -8
- localstack/packages/core.py +2 -2
- localstack/packages/plugins.py +0 -8
- localstack/runtime/analytics.py +3 -0
- localstack/runtime/hooks.py +1 -1
- localstack/runtime/init.py +2 -2
- localstack/runtime/main.py +5 -5
- localstack/runtime/patches.py +2 -2
- localstack/services/apigateway/helpers.py +1 -4
- localstack/services/apigateway/legacy/helpers.py +7 -8
- localstack/services/apigateway/legacy/integration.py +4 -3
- localstack/services/apigateway/legacy/invocations.py +6 -5
- localstack/services/apigateway/legacy/provider.py +148 -68
- localstack/services/apigateway/legacy/templates.py +1 -1
- localstack/services/apigateway/next_gen/execute_api/handlers/method_request.py +7 -2
- localstack/services/apigateway/next_gen/execute_api/handlers/resource_router.py +1 -2
- localstack/services/apigateway/next_gen/execute_api/integrations/aws.py +3 -0
- localstack/services/apigateway/next_gen/execute_api/integrations/http.py +3 -3
- localstack/services/apigateway/next_gen/execute_api/template_mapping.py +2 -2
- localstack/services/apigateway/next_gen/execute_api/test_invoke.py +114 -9
- localstack/services/apigateway/next_gen/provider.py +5 -0
- localstack/services/apigateway/resource_providers/aws_apigateway_resource.py +1 -1
- localstack/services/cloudformation/api_utils.py +4 -8
- localstack/services/cloudformation/cfn_utils.py +1 -1
- localstack/services/cloudformation/engine/entities.py +14 -4
- localstack/services/cloudformation/engine/template_deployer.py +6 -4
- localstack/services/cloudformation/engine/transformers.py +6 -4
- localstack/services/cloudformation/engine/v2/change_set_model.py +201 -13
- localstack/services/cloudformation/engine/v2/change_set_model_describer.py +52 -3
- localstack/services/cloudformation/engine/v2/change_set_model_executor.py +117 -76
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +205 -52
- localstack/services/cloudformation/engine/v2/change_set_model_transform.py +350 -116
- localstack/services/cloudformation/engine/v2/change_set_model_validator.py +56 -14
- localstack/services/cloudformation/engine/v2/change_set_model_visitor.py +1 -0
- localstack/services/cloudformation/engine/v2/resolving.py +7 -5
- localstack/services/cloudformation/engine/yaml_parser.py +9 -2
- localstack/services/cloudformation/provider.py +7 -5
- localstack/services/cloudformation/resource_provider.py +7 -1
- localstack/services/cloudformation/resources.py +24149 -0
- localstack/services/cloudformation/service_models.py +2 -2
- localstack/services/cloudformation/v2/entities.py +19 -9
- localstack/services/cloudformation/v2/provider.py +336 -106
- localstack/services/cloudformation/v2/types.py +13 -7
- localstack/services/cloudformation/v2/utils.py +4 -1
- localstack/services/cloudwatch/alarm_scheduler.py +4 -1
- localstack/services/cloudwatch/provider.py +18 -13
- localstack/services/cloudwatch/provider_v2.py +25 -28
- localstack/services/dynamodb/packages.py +2 -1
- localstack/services/dynamodb/provider.py +42 -0
- localstack/services/dynamodb/server.py +2 -2
- localstack/services/dynamodb/v2/provider.py +42 -0
- localstack/services/ecr/resource_providers/aws_ecr_repository.py +5 -2
- localstack/services/edge.py +1 -1
- localstack/services/es/provider.py +2 -2
- localstack/services/events/event_rule_engine.py +31 -13
- localstack/services/events/models.py +4 -5
- localstack/services/events/provider.py +17 -14
- localstack/services/events/target.py +17 -9
- localstack/services/events/v1/provider.py +5 -5
- localstack/services/firehose/provider.py +14 -4
- localstack/services/iam/provider.py +11 -116
- localstack/services/iam/resources/policy_simulator.py +133 -0
- localstack/services/kinesis/models.py +15 -2
- localstack/services/kinesis/provider.py +86 -3
- localstack/services/kms/provider.py +14 -5
- localstack/services/lambda_/api_utils.py +6 -3
- localstack/services/lambda_/invocation/docker_runtime_executor.py +1 -1
- localstack/services/lambda_/invocation/event_manager.py +1 -1
- localstack/services/lambda_/invocation/internal_sqs_queue.py +5 -9
- localstack/services/lambda_/invocation/lambda_models.py +10 -7
- localstack/services/lambda_/invocation/lambda_service.py +5 -1
- localstack/services/lambda_/packages.py +1 -1
- localstack/services/lambda_/provider.py +4 -3
- localstack/services/lambda_/provider_utils.py +1 -1
- localstack/services/logs/provider.py +36 -19
- localstack/services/moto.py +2 -1
- localstack/services/opensearch/cluster.py +15 -7
- localstack/services/opensearch/packages.py +26 -7
- localstack/services/opensearch/provider.py +8 -2
- localstack/services/opensearch/versions.py +56 -7
- localstack/services/plugins.py +11 -7
- localstack/services/providers.py +10 -2
- localstack/services/redshift/provider.py +0 -21
- localstack/services/s3/constants.py +5 -2
- localstack/services/s3/cors.py +4 -4
- localstack/services/s3/models.py +1 -1
- localstack/services/s3/notifications.py +55 -39
- localstack/services/s3/presigned_url.py +35 -54
- localstack/services/s3/provider.py +73 -15
- localstack/services/s3/utils.py +42 -22
- localstack/services/s3/validation.py +46 -32
- localstack/services/s3/website_hosting.py +4 -2
- localstack/services/ses/provider.py +18 -8
- localstack/services/sns/constants.py +7 -1
- localstack/services/sns/executor.py +9 -2
- localstack/services/sns/provider.py +8 -5
- localstack/services/sns/publisher.py +31 -16
- localstack/services/sns/v2/models.py +167 -0
- localstack/services/sns/v2/provider.py +867 -0
- localstack/services/sns/v2/utils.py +130 -0
- localstack/services/sqs/constants.py +1 -1
- localstack/services/sqs/developer_api.py +205 -0
- localstack/services/sqs/models.py +48 -5
- localstack/services/sqs/provider.py +38 -311
- localstack/services/sqs/query_api.py +6 -2
- localstack/services/sqs/utils.py +121 -2
- localstack/services/ssm/provider.py +1 -1
- localstack/services/stepfunctions/asl/component/intrinsic/member.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_choice/comparison/comparison.py +5 -11
- localstack/services/stepfunctions/asl/component/state/state_choice/state_choice.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_execution/state_parallel/state_parallel.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/state_task.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_pass/state_pass.py +2 -2
- localstack/services/stepfunctions/asl/component/state/state_succeed/state_succeed.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_wait/state_wait.py +1 -1
- localstack/services/stepfunctions/asl/eval/environment.py +1 -1
- localstack/services/stepfunctions/asl/jsonata/jsonata.py +1 -1
- localstack/services/stepfunctions/backend/execution.py +2 -1
- localstack/services/stores.py +1 -1
- localstack/services/transcribe/provider.py +6 -1
- localstack/state/codecs.py +61 -0
- localstack/state/core.py +11 -5
- localstack/state/pickle.py +10 -49
- localstack/testing/aws/cloudformation_utils.py +1 -1
- localstack/testing/pytest/cloudformation/fixtures.py +3 -3
- localstack/testing/pytest/cloudformation/transformers.py +0 -0
- localstack/testing/pytest/container.py +4 -5
- localstack/testing/pytest/fixtures.py +33 -31
- localstack/testing/pytest/in_memory_localstack.py +0 -4
- localstack/testing/pytest/marking.py +38 -11
- localstack/testing/pytest/stepfunctions/utils.py +4 -3
- localstack/testing/pytest/util.py +1 -1
- localstack/testing/pytest/validation_tracking.py +1 -2
- localstack/testing/snapshots/transformer_utility.py +6 -1
- localstack/utils/analytics/events.py +2 -2
- localstack/utils/analytics/metadata.py +6 -4
- localstack/utils/analytics/metrics/counter.py +8 -15
- localstack/utils/analytics/publisher.py +1 -2
- localstack/utils/analytics/service_providers.py +19 -0
- localstack/utils/analytics/service_request_aggregator.py +2 -2
- localstack/utils/archives.py +11 -11
- localstack/utils/asyncio.py +2 -2
- localstack/utils/aws/arns.py +24 -29
- localstack/utils/aws/aws_responses.py +8 -8
- localstack/utils/aws/aws_stack.py +2 -3
- localstack/utils/aws/dead_letter_queue.py +1 -5
- localstack/utils/aws/message_forwarding.py +1 -2
- localstack/utils/aws/request_context.py +4 -5
- localstack/utils/aws/resources.py +1 -1
- localstack/utils/aws/templating.py +1 -1
- localstack/utils/batch_policy.py +3 -3
- localstack/utils/bootstrap.py +21 -13
- localstack/utils/catalog/catalog.py +139 -0
- localstack/utils/catalog/catalog_loader.py +119 -0
- localstack/utils/catalog/common.py +58 -0
- localstack/utils/catalog/plugins.py +28 -0
- localstack/utils/cloudwatch/cloudwatch_util.py +5 -5
- localstack/utils/collections.py +7 -8
- localstack/utils/config_listener.py +1 -1
- localstack/utils/container_networking.py +2 -3
- localstack/utils/container_utils/container_client.py +135 -136
- localstack/utils/container_utils/docker_cmd_client.py +85 -69
- localstack/utils/container_utils/docker_sdk_client.py +69 -66
- localstack/utils/crypto.py +10 -10
- localstack/utils/diagnose.py +3 -4
- localstack/utils/docker_utils.py +9 -5
- localstack/utils/files.py +33 -13
- localstack/utils/functions.py +4 -3
- localstack/utils/http.py +11 -11
- localstack/utils/json.py +20 -6
- localstack/utils/kinesis/kinesis_connector.py +2 -1
- localstack/utils/net.py +15 -9
- localstack/utils/no_exit_argument_parser.py +2 -2
- localstack/utils/numbers.py +9 -2
- localstack/utils/objects.py +7 -6
- localstack/utils/patch.py +10 -3
- localstack/utils/run.py +12 -11
- localstack/utils/scheduler.py +11 -11
- localstack/utils/server/tcp_proxy.py +2 -2
- localstack/utils/serving.py +3 -4
- localstack/utils/strings.py +15 -16
- localstack/utils/sync.py +126 -1
- localstack/utils/tagging.py +8 -6
- localstack/utils/testutil.py +8 -8
- localstack/utils/threads.py +2 -2
- localstack/utils/time.py +12 -4
- localstack/utils/urls.py +1 -3
- localstack/utils/xray/traceid.py +1 -1
- localstack/version.py +16 -3
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/METADATA +18 -14
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/RECORD +248 -239
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/entry_points.txt +8 -4
- localstack_core-4.10.1.dev12.dist-info/plux.json +1 -0
- localstack/packages/terraform.py +0 -46
- localstack/services/cloudformation/deploy.html +0 -144
- localstack/services/cloudformation/deploy_ui.py +0 -47
- localstack/services/cloudformation/plugins.py +0 -12
- localstack_core-4.7.1.dev49.dist-info/plux.json +0 -1
- {localstack_core-4.7.1.dev49.data → localstack_core-4.10.1.dev12.data}/scripts/localstack +0 -0
- {localstack_core-4.7.1.dev49.data → localstack_core-4.10.1.dev12.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.7.1.dev49.data → localstack_core-4.10.1.dev12.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/WHEEL +0 -0
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/licenses/LICENSE.txt +0 -0
- {localstack_core-4.7.1.dev49.dist-info → localstack_core-4.10.1.dev12.dist-info}/top_level.txt +0 -0
localstack/config.py
CHANGED
|
@@ -10,7 +10,7 @@ import time
|
|
|
10
10
|
import warnings
|
|
11
11
|
from collections import defaultdict
|
|
12
12
|
from collections.abc import Mapping
|
|
13
|
-
from typing import Any,
|
|
13
|
+
from typing import Any, TypeVar
|
|
14
14
|
|
|
15
15
|
from localstack import constants
|
|
16
16
|
from localstack.constants import (
|
|
@@ -19,6 +19,7 @@ from localstack.constants import (
|
|
|
19
19
|
DEFAULT_VOLUME_DIR,
|
|
20
20
|
ENV_INTERNAL_TEST_COLLECT_METRIC,
|
|
21
21
|
ENV_INTERNAL_TEST_RUN,
|
|
22
|
+
ENV_INTERNAL_TEST_STORE_METRICS_IN_LOCALSTACK,
|
|
22
23
|
FALSE_STRINGS,
|
|
23
24
|
LOCALHOST,
|
|
24
25
|
LOCALHOST_IP,
|
|
@@ -208,13 +209,13 @@ class Directories:
|
|
|
208
209
|
return str(self.__dict__)
|
|
209
210
|
|
|
210
211
|
|
|
211
|
-
def eval_log_type(env_var_name: str) ->
|
|
212
|
+
def eval_log_type(env_var_name: str) -> str | bool:
|
|
212
213
|
"""Get the log type from environment variable"""
|
|
213
214
|
ls_log = os.environ.get(env_var_name, "").lower().strip()
|
|
214
215
|
return ls_log if ls_log in LOG_LEVELS else False
|
|
215
216
|
|
|
216
217
|
|
|
217
|
-
def parse_boolean_env(env_var_name: str) ->
|
|
218
|
+
def parse_boolean_env(env_var_name: str) -> bool | None:
|
|
218
219
|
"""Parse the value of the given env variable and return True/False, or None if it is not a boolean value."""
|
|
219
220
|
value = os.environ.get(env_var_name, "").lower().strip()
|
|
220
221
|
if value in TRUE_STRINGS:
|
|
@@ -286,7 +287,7 @@ def ping(host):
|
|
|
286
287
|
"""Returns True if the host responds to a ping request"""
|
|
287
288
|
is_in_windows = is_windows()
|
|
288
289
|
ping_opts = "-n 1 -w 2000" if is_in_windows else "-c 1 -W 2"
|
|
289
|
-
args = "ping
|
|
290
|
+
args = f"ping {ping_opts} {host}"
|
|
290
291
|
return (
|
|
291
292
|
subprocess.call(
|
|
292
293
|
args, shell=not is_in_windows, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
@@ -435,8 +436,8 @@ TMP_FOLDER = os.path.join(tempfile.gettempdir(), "localstack")
|
|
|
435
436
|
VOLUME_DIR = os.environ.get("LOCALSTACK_VOLUME_DIR", "").strip() or TMP_FOLDER
|
|
436
437
|
|
|
437
438
|
# fix for Mac OS, to be able to mount /var/folders in Docker
|
|
438
|
-
if TMP_FOLDER.startswith("/var/folders/") and os.path.exists("/private
|
|
439
|
-
TMP_FOLDER = "/private
|
|
439
|
+
if TMP_FOLDER.startswith("/var/folders/") and os.path.exists(f"/private{TMP_FOLDER}"):
|
|
440
|
+
TMP_FOLDER = f"/private{TMP_FOLDER}"
|
|
440
441
|
|
|
441
442
|
# whether to enable verbose debug logging ("LOG" is used when using the CLI with LOCALSTACK_LOG instead of LS_LOG)
|
|
442
443
|
LS_LOG = eval_log_type("LS_LOG") or eval_log_type("LOG")
|
|
@@ -649,7 +650,7 @@ class UniqueHostAndPortList(list[HostAndPort]):
|
|
|
649
650
|
- Identical identical hosts and ports are de-duped
|
|
650
651
|
"""
|
|
651
652
|
|
|
652
|
-
def __init__(self, iterable:
|
|
653
|
+
def __init__(self, iterable: list[HostAndPort] | None = None):
|
|
653
654
|
super().__init__(iterable or [])
|
|
654
655
|
self._ensure_unique()
|
|
655
656
|
|
|
@@ -1184,6 +1185,8 @@ elif _override_dynamodb_v2 == "v2":
|
|
|
1184
1185
|
os.environ["PROVIDER_OVERRIDE_DYNAMODBSTREAMS"] = "v2"
|
|
1185
1186
|
DDB_STREAMS_PROVIDER_V2 = True
|
|
1186
1187
|
|
|
1188
|
+
SNS_PROVIDER_V2 = os.environ.get("PROVIDER_OVERRIDE_SNS", "") == "v2"
|
|
1189
|
+
|
|
1187
1190
|
# TODO remove fallback to LAMBDA_DOCKER_NETWORK with next minor version
|
|
1188
1191
|
MAIN_DOCKER_NETWORK = os.environ.get("MAIN_DOCKER_NETWORK", "") or LAMBDA_DOCKER_NETWORK
|
|
1189
1192
|
|
|
@@ -1237,8 +1240,8 @@ def use_custom_dns():
|
|
|
1237
1240
|
|
|
1238
1241
|
|
|
1239
1242
|
# s3 virtual host name
|
|
1240
|
-
S3_VIRTUAL_HOSTNAME = "s3
|
|
1241
|
-
S3_STATIC_WEBSITE_HOSTNAME = "s3-website
|
|
1243
|
+
S3_VIRTUAL_HOSTNAME = f"s3.{LOCALSTACK_HOST.host}"
|
|
1244
|
+
S3_STATIC_WEBSITE_HOSTNAME = f"s3-website.{LOCALSTACK_HOST.host}"
|
|
1242
1245
|
|
|
1243
1246
|
BOTO_WAITER_DELAY = int(os.environ.get("BOTO_WAITER_DELAY") or "1")
|
|
1244
1247
|
BOTO_WAITER_MAX_ATTEMPTS = int(os.environ.get("BOTO_WAITER_MAX_ATTEMPTS") or "120")
|
|
@@ -1257,7 +1260,6 @@ IN_MEMORY_CLIENT = is_env_true("IN_MEMORY_CLIENT")
|
|
|
1257
1260
|
LOCALSTACK_RESPONSE_HEADER_ENABLED = is_env_not_false("LOCALSTACK_RESPONSE_HEADER_ENABLED")
|
|
1258
1261
|
|
|
1259
1262
|
# Serialization backend for the LocalStack internal state (`dill` is used by default`).
|
|
1260
|
-
# `jsonpickle` enables the new experimental backend.
|
|
1261
1263
|
STATE_SERIALIZATION_BACKEND = os.environ.get("STATE_SERIALIZATION_BACKEND", "").strip() or "dill"
|
|
1262
1264
|
|
|
1263
1265
|
# List of environment variable names used for configuration that are passed from the host into the LocalStack container.
|
|
@@ -1450,6 +1452,11 @@ def is_collect_metrics_mode() -> bool:
|
|
|
1450
1452
|
return is_env_true(ENV_INTERNAL_TEST_COLLECT_METRIC)
|
|
1451
1453
|
|
|
1452
1454
|
|
|
1455
|
+
def store_test_metrics_in_local_filesystem() -> bool:
|
|
1456
|
+
"""Returns True if test metrics should be stored in the local filesystem (instead of the system that runs pytest)."""
|
|
1457
|
+
return is_env_true(ENV_INTERNAL_TEST_STORE_METRICS_IN_LOCALSTACK)
|
|
1458
|
+
|
|
1459
|
+
|
|
1453
1460
|
def collect_config_items() -> list[tuple[str, Any]]:
|
|
1454
1461
|
"""Returns a list of key-value tuples of LocalStack configuration values."""
|
|
1455
1462
|
none = object() # sentinel object
|
|
@@ -1502,10 +1509,10 @@ def get_protocol() -> str:
|
|
|
1502
1509
|
|
|
1503
1510
|
|
|
1504
1511
|
def external_service_url(
|
|
1505
|
-
host:
|
|
1506
|
-
port:
|
|
1507
|
-
protocol:
|
|
1508
|
-
subdomains:
|
|
1512
|
+
host: str | None = None,
|
|
1513
|
+
port: int | None = None,
|
|
1514
|
+
protocol: str | None = None,
|
|
1515
|
+
subdomains: str | None = None,
|
|
1509
1516
|
) -> str:
|
|
1510
1517
|
"""Returns a service URL (e.g., SQS queue URL) to an external client (e.g., boto3) potentially running on another
|
|
1511
1518
|
machine than LocalStack. The configurations LOCALSTACK_HOST and USE_SSL can customize these returned URLs.
|
|
@@ -1522,10 +1529,10 @@ def external_service_url(
|
|
|
1522
1529
|
|
|
1523
1530
|
|
|
1524
1531
|
def internal_service_url(
|
|
1525
|
-
host:
|
|
1526
|
-
port:
|
|
1527
|
-
protocol:
|
|
1528
|
-
subdomains:
|
|
1532
|
+
host: str | None = None,
|
|
1533
|
+
port: int | None = None,
|
|
1534
|
+
protocol: str | None = None,
|
|
1535
|
+
subdomains: str | None = None,
|
|
1529
1536
|
) -> str:
|
|
1530
1537
|
"""Returns a service URL for internal use within LocalStack (i.e., same host).
|
|
1531
1538
|
The configuration USE_SSL can customize these returned URLs but LOCALSTACK_HOST has no effect.
|
localstack/constants.py
CHANGED
|
@@ -80,6 +80,10 @@ ENV_INTERNAL_TEST_RUN = "LOCALSTACK_INTERNAL_TEST_RUN"
|
|
|
80
80
|
# environment variable name to tag collect metrics during a test run
|
|
81
81
|
ENV_INTERNAL_TEST_COLLECT_METRIC = "LOCALSTACK_INTERNAL_TEST_COLLECT_METRIC"
|
|
82
82
|
|
|
83
|
+
# environment variable name to indicate that metrics should be stored within the container
|
|
84
|
+
ENV_INTERNAL_TEST_STORE_METRICS_IN_LOCALSTACK = "LOCALSTACK_INTERNAL_TEST_METRICS_IN_LOCALSTACK"
|
|
85
|
+
ENV_INTERNAL_TEST_STORE_METRICS_PATH = "LOCALSTACK_INTERNAL_TEST_STORE_METRICS_PATH"
|
|
86
|
+
|
|
83
87
|
# environment variable that flags whether pro was activated. do not use it for security purposes!
|
|
84
88
|
ENV_PRO_ACTIVATED = "PRO_ACTIVATED"
|
|
85
89
|
|
|
@@ -102,32 +106,6 @@ FALSE_STRINGS = ("0", "false", "False")
|
|
|
102
106
|
# strings with valid log levels for LS_LOG
|
|
103
107
|
LOG_LEVELS = ("trace-internal", "trace", "debug", "info", "warn", "error", "warning")
|
|
104
108
|
|
|
105
|
-
# the version of elasticsearch that is pre-seeded into the base image (sync with Dockerfile.base)
|
|
106
|
-
ELASTICSEARCH_DEFAULT_VERSION = "Elasticsearch_7.10"
|
|
107
|
-
# See https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/aes-supported-plugins.html
|
|
108
|
-
ELASTICSEARCH_PLUGIN_LIST = [
|
|
109
|
-
"analysis-icu",
|
|
110
|
-
"ingest-attachment",
|
|
111
|
-
"analysis-kuromoji",
|
|
112
|
-
"mapper-murmur3",
|
|
113
|
-
"mapper-size",
|
|
114
|
-
"analysis-phonetic",
|
|
115
|
-
"analysis-smartcn",
|
|
116
|
-
"analysis-stempel",
|
|
117
|
-
"analysis-ukrainian",
|
|
118
|
-
]
|
|
119
|
-
# Default ES modules to exclude (save apprx 66MB in the final image)
|
|
120
|
-
ELASTICSEARCH_DELETE_MODULES = ["ingest-geoip"]
|
|
121
|
-
|
|
122
|
-
# the version of opensearch which is used by default
|
|
123
|
-
OPENSEARCH_DEFAULT_VERSION = "OpenSearch_2.11"
|
|
124
|
-
|
|
125
|
-
# See https://docs.aws.amazon.com/opensearch-service/latest/developerguide/supported-plugins.html
|
|
126
|
-
OPENSEARCH_PLUGIN_LIST = [
|
|
127
|
-
"ingest-attachment",
|
|
128
|
-
"analysis-kuromoji",
|
|
129
|
-
]
|
|
130
|
-
|
|
131
109
|
# API endpoint for analytics events
|
|
132
110
|
API_ENDPOINT = os.environ.get("API_ENDPOINT") or "https://api.localstack.cloud/v1"
|
|
133
111
|
# new analytics API endpoint
|
|
@@ -171,9 +149,6 @@ DEFAULT_DEVELOP_PORT = 5678
|
|
|
171
149
|
DEFAULT_BUCKET_MARKER_LOCAL = "hot-reload"
|
|
172
150
|
LEGACY_DEFAULT_BUCKET_MARKER_LOCAL = "__local__"
|
|
173
151
|
|
|
174
|
-
# user that starts the opensearch process if the current user is root
|
|
175
|
-
OS_USER_OPENSEARCH = "localstack"
|
|
176
|
-
|
|
177
152
|
# output string that indicates that the stack is ready
|
|
178
153
|
READY_MARKER_OUTPUT = "Ready."
|
|
179
154
|
|
|
@@ -5,6 +5,12 @@ from typing import Literal
|
|
|
5
5
|
import click
|
|
6
6
|
import yaml
|
|
7
7
|
|
|
8
|
+
EDGE_SERVICE_NODE_PORT = 30066
|
|
9
|
+
NODE_PORT_START = 30010
|
|
10
|
+
SERVICE_PORT_START = 4510
|
|
11
|
+
NUMBER_OF_SERVICE_PORTS = 50
|
|
12
|
+
EDGE_SERVICE_DNS_PORT = 31053
|
|
13
|
+
|
|
8
14
|
|
|
9
15
|
@dataclasses.dataclass
|
|
10
16
|
class MountPoint:
|
|
@@ -27,7 +33,7 @@ def generate_mount_points(
|
|
|
27
33
|
|
|
28
34
|
# container paths
|
|
29
35
|
target_path = "/opt/code/localstack/"
|
|
30
|
-
venv_path = os.path.join(target_path, ".venv", "lib", "python3.
|
|
36
|
+
venv_path = os.path.join(target_path, ".venv", "lib", "python3.13", "site-packages")
|
|
31
37
|
|
|
32
38
|
# Community code
|
|
33
39
|
if pro:
|
|
@@ -139,7 +145,12 @@ def generate_mount_points(
|
|
|
139
145
|
return mount_points
|
|
140
146
|
|
|
141
147
|
|
|
142
|
-
def generate_k8s_cluster_config(
|
|
148
|
+
def generate_k8s_cluster_config(
|
|
149
|
+
mount_points: list[MountPoint],
|
|
150
|
+
port: int = 4566,
|
|
151
|
+
expose_dns: bool = False,
|
|
152
|
+
dns_port: int = 53,
|
|
153
|
+
):
|
|
143
154
|
volumes = [
|
|
144
155
|
{
|
|
145
156
|
"volume": f"{mount_point.host_path}:{mount_point.node_path}",
|
|
@@ -148,9 +159,64 @@ def generate_k8s_cluster_config(mount_points: list[MountPoint], port: int = 4566
|
|
|
148
159
|
for mount_point in mount_points
|
|
149
160
|
]
|
|
150
161
|
|
|
151
|
-
ports = [
|
|
162
|
+
ports = [
|
|
163
|
+
# main gateway port
|
|
164
|
+
{
|
|
165
|
+
"nodeFilters": [
|
|
166
|
+
"server:0",
|
|
167
|
+
],
|
|
168
|
+
"port": f"{port}:{EDGE_SERVICE_NODE_PORT}",
|
|
169
|
+
},
|
|
170
|
+
# 443 https port for main gateway
|
|
171
|
+
{
|
|
172
|
+
"nodeFilters": [
|
|
173
|
+
"server:0",
|
|
174
|
+
],
|
|
175
|
+
"port": f"443:{EDGE_SERVICE_NODE_PORT}",
|
|
176
|
+
},
|
|
177
|
+
# Node ports
|
|
178
|
+
{
|
|
179
|
+
"nodeFilters": [
|
|
180
|
+
"server:0",
|
|
181
|
+
],
|
|
182
|
+
"port": f"{SERVICE_PORT_START}-{SERVICE_PORT_START + NUMBER_OF_SERVICE_PORTS - 1}:{NODE_PORT_START}-{NODE_PORT_START + NUMBER_OF_SERVICE_PORTS - 1}",
|
|
183
|
+
},
|
|
184
|
+
]
|
|
152
185
|
|
|
153
|
-
|
|
186
|
+
if expose_dns:
|
|
187
|
+
ports.append(
|
|
188
|
+
{
|
|
189
|
+
"nodeFilters": [
|
|
190
|
+
"server:0",
|
|
191
|
+
],
|
|
192
|
+
"port": f"{dns_port}:{EDGE_SERVICE_DNS_PORT}/udp",
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
ports.append(
|
|
196
|
+
{
|
|
197
|
+
"nodeFilters": [
|
|
198
|
+
"server:0",
|
|
199
|
+
],
|
|
200
|
+
"port": f"{dns_port}:{EDGE_SERVICE_DNS_PORT}/tcp",
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
config = {
|
|
205
|
+
"apiVersion": "k3d.io/v1alpha5",
|
|
206
|
+
"kind": "Simple",
|
|
207
|
+
"volumes": volumes,
|
|
208
|
+
"ports": ports,
|
|
209
|
+
"options": {
|
|
210
|
+
"k3s": {
|
|
211
|
+
"extraArgs": [
|
|
212
|
+
{
|
|
213
|
+
"arg": "--kubelet-arg=container-log-max-size=1Gi",
|
|
214
|
+
"nodeFilters": ["server:*"],
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
}
|
|
154
220
|
|
|
155
221
|
return config
|
|
156
222
|
|
|
@@ -159,7 +225,7 @@ def snake_to_kebab_case(string: str):
|
|
|
159
225
|
return string.lower().replace("_", "-")
|
|
160
226
|
|
|
161
227
|
|
|
162
|
-
def
|
|
228
|
+
def generate_k8s_helm_overrides(
|
|
163
229
|
mount_points: list[MountPoint], pro: bool = False, env: list[str] | None = None
|
|
164
230
|
):
|
|
165
231
|
volumes = [
|
|
@@ -200,10 +266,48 @@ def generate_k8s_cluster_overrides(
|
|
|
200
266
|
"name": "CONTAINER_RUNTIME",
|
|
201
267
|
"value": "kubernetes",
|
|
202
268
|
},
|
|
269
|
+
{
|
|
270
|
+
"name": "RDS_MYSQL_DOCKER",
|
|
271
|
+
"value": "1",
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"name": "ENABLE_DMS",
|
|
275
|
+
"value": "1",
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
"name": "ENABLE_BEDROCK",
|
|
279
|
+
"value": "1",
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"name": "DOCDB_PROXY_CONTAINER",
|
|
283
|
+
"value": "1",
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"name": "GLUE_JOB_EXECUTOR_PROVIDER",
|
|
287
|
+
"value": "v2",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "CLOUDFRONT_LAMBDA_EDGE",
|
|
291
|
+
"value": "1",
|
|
292
|
+
},
|
|
203
293
|
]
|
|
204
294
|
|
|
205
295
|
image_repository = "localstack/localstack-pro" if pro else "localstack/localstack"
|
|
206
296
|
|
|
297
|
+
service = {
|
|
298
|
+
"edgeService": {
|
|
299
|
+
"nodePort": EDGE_SERVICE_NODE_PORT,
|
|
300
|
+
},
|
|
301
|
+
"externalServicePorts": {
|
|
302
|
+
"start": SERVICE_PORT_START,
|
|
303
|
+
"end": SERVICE_PORT_START + NUMBER_OF_SERVICE_PORTS,
|
|
304
|
+
"nodePortStart": NODE_PORT_START,
|
|
305
|
+
},
|
|
306
|
+
"dnsService": {
|
|
307
|
+
"enabled": True,
|
|
308
|
+
"nodePort": EDGE_SERVICE_DNS_PORT,
|
|
309
|
+
},
|
|
310
|
+
}
|
|
207
311
|
overrides = {
|
|
208
312
|
"debug": True,
|
|
209
313
|
"volumes": volumes,
|
|
@@ -211,6 +315,9 @@ def generate_k8s_cluster_overrides(
|
|
|
211
315
|
"extraEnvVars": extra_env_vars,
|
|
212
316
|
"image": {"repository": image_repository},
|
|
213
317
|
"lambda": {"executor": "kubernetes"},
|
|
318
|
+
"service": service,
|
|
319
|
+
"readinessProbe": {"initialDelaySeconds": 10},
|
|
320
|
+
"livenessProbe": {"initialDelaySeconds": 10},
|
|
214
321
|
}
|
|
215
322
|
|
|
216
323
|
return overrides
|
|
@@ -275,6 +382,18 @@ def print_file(content: dict, file_name: str):
|
|
|
275
382
|
help="Port to expose from the kubernetes node",
|
|
276
383
|
type=click.IntRange(0, 65535),
|
|
277
384
|
)
|
|
385
|
+
@click.option(
|
|
386
|
+
"--expose-dns",
|
|
387
|
+
is_flag=True,
|
|
388
|
+
default=False,
|
|
389
|
+
help="Expose DNS port from the kubernetes node.",
|
|
390
|
+
)
|
|
391
|
+
@click.option(
|
|
392
|
+
"--dns-port",
|
|
393
|
+
default=53,
|
|
394
|
+
help="DNS port to expose from the kubernetes node. It is applied only if --expose-dns is set.",
|
|
395
|
+
type=click.IntRange(0, 65535),
|
|
396
|
+
)
|
|
278
397
|
@click.argument("command", nargs=-1, required=False)
|
|
279
398
|
def run(
|
|
280
399
|
pro: bool = None,
|
|
@@ -287,15 +406,19 @@ def run(
|
|
|
287
406
|
command: str = None,
|
|
288
407
|
env: list[str] = None,
|
|
289
408
|
port: int = None,
|
|
409
|
+
expose_dns: bool = False,
|
|
410
|
+
dns_port: int = 53,
|
|
290
411
|
):
|
|
291
412
|
"""
|
|
292
413
|
A tool for localstack developers to generate the kubernetes cluster configuration file and the overrides to mount the localstack code into the cluster.
|
|
293
414
|
"""
|
|
294
415
|
mount_points = generate_mount_points(pro, mount_moto, mount_entrypoints)
|
|
295
416
|
|
|
296
|
-
config = generate_k8s_cluster_config(
|
|
417
|
+
config = generate_k8s_cluster_config(
|
|
418
|
+
mount_points, port=port, expose_dns=expose_dns, dns_port=dns_port
|
|
419
|
+
)
|
|
297
420
|
|
|
298
|
-
overrides =
|
|
421
|
+
overrides = generate_k8s_helm_overrides(mount_points, pro=pro, env=env)
|
|
299
422
|
|
|
300
423
|
output_dir = output_dir or os.getcwd()
|
|
301
424
|
overrides_file = overrides_file or "overrides.yml"
|
|
@@ -363,10 +363,7 @@ def _list_files_in_container_image(container_client: ContainerClient, image_name
|
|
|
363
363
|
try:
|
|
364
364
|
# docker export yields paths without prefixed slashes, so we add them here
|
|
365
365
|
# since the file is pretty big (~4MB for community, ~7MB for pro) we gzip it
|
|
366
|
-
cmd = "docker export
|
|
367
|
-
container_id,
|
|
368
|
-
cache_file,
|
|
369
|
-
)
|
|
366
|
+
cmd = f"docker export {container_id} | tar -t | awk '{{ print \"/\" $0 }}' | gzip > {cache_file}"
|
|
370
367
|
run(cmd, shell=True)
|
|
371
368
|
finally:
|
|
372
369
|
container_client.remove_container(container_id)
|
localstack/dev/run/paths.py
CHANGED
|
@@ -68,7 +68,7 @@ class ContainerPaths:
|
|
|
68
68
|
"""Important paths in the container"""
|
|
69
69
|
|
|
70
70
|
project_dir: str = "/opt/code/localstack"
|
|
71
|
-
site_packages_target_dir: str = "/opt/code/localstack/.venv/lib/python3.
|
|
71
|
+
site_packages_target_dir: str = "/opt/code/localstack/.venv/lib/python3.13/site-packages"
|
|
72
72
|
docker_entrypoint: str = "/usr/local/bin/docker-entrypoint.sh"
|
|
73
73
|
localstack_supervisor: str = "/usr/local/bin/localstack-supervisor"
|
|
74
74
|
localstack_source_dir: str
|
localstack/dns/plugins.py
CHANGED
|
@@ -11,8 +11,12 @@ DNS_SHUTDOWN_PRIORITY = -30
|
|
|
11
11
|
"""Make sure the DNS server is shut down after the ON_AFTER_SERVICE_SHUTDOWN_HANDLERS, which in turn is after
|
|
12
12
|
SERVICE_SHUTDOWN_PRIORITY. Currently this value needs to be less than -20"""
|
|
13
13
|
|
|
14
|
+
DNS_START_PRIORITY = 20
|
|
15
|
+
"""Make sure the DNS server is started before the pro activation, to ensure proper DNS resolution for the activate call,
|
|
16
|
+
if the resolv.conf is set to localhost from outside the container"""
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
|
|
19
|
+
@hooks.on_infra_start(priority=DNS_START_PRIORITY)
|
|
16
20
|
def start_dns_server():
|
|
17
21
|
try:
|
|
18
22
|
from localstack.dns import server
|
localstack/dns/server.py
CHANGED
|
@@ -254,7 +254,7 @@ class NonLoggingHandler(DNSHandler):
|
|
|
254
254
|
THREAD_LOCAL.client_address = self.client_address
|
|
255
255
|
THREAD_LOCAL.server = self.server
|
|
256
256
|
THREAD_LOCAL.request = self.request
|
|
257
|
-
return super(
|
|
257
|
+
return super().handle(*args, **kwargs)
|
|
258
258
|
except Exception:
|
|
259
259
|
pass
|
|
260
260
|
|
|
@@ -445,13 +445,22 @@ class Resolver(DnsServerProtocol):
|
|
|
445
445
|
return True
|
|
446
446
|
return False
|
|
447
447
|
|
|
448
|
+
def _find_matching_aliases(self, question: DNSQuestion) -> list[AliasTarget] | None:
|
|
449
|
+
"""
|
|
450
|
+
Find aliases matching the question, supporting wildcards.
|
|
451
|
+
"""
|
|
452
|
+
qlabel = DNSLabel(to_bytes(question.qname))
|
|
453
|
+
qtype = RecordType[QTYPE[question.qtype]]
|
|
454
|
+
for (label, rtype), targets in self.aliases.items():
|
|
455
|
+
if rtype == qtype and qlabel.matchWildcard(label):
|
|
456
|
+
return targets
|
|
457
|
+
return None
|
|
458
|
+
|
|
448
459
|
def _resolve_alias(
|
|
449
460
|
self, request: DNSRecord, reply: DNSRecord, client_address: ClientAddress
|
|
450
461
|
) -> bool:
|
|
451
462
|
if request.q.qtype in (QTYPE.A, QTYPE.AAAA, QTYPE.CNAME):
|
|
452
|
-
|
|
453
|
-
# check if we have aliases defined for our given qname/qtype pair
|
|
454
|
-
if aliases := self.aliases.get(key):
|
|
463
|
+
if aliases := self._find_matching_aliases(request.q):
|
|
455
464
|
for alias in aliases:
|
|
456
465
|
# if there is no health check, or the healthcheck is successful, we will consider this alias
|
|
457
466
|
# take the first alias passing this check
|
localstack/logging/format.py
CHANGED
|
@@ -32,7 +32,7 @@ class DefaultFormatter(logging.Formatter):
|
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
def __init__(self, fmt=LOG_FORMAT, datefmt=LOG_DATE_FORMAT):
|
|
35
|
-
super(
|
|
35
|
+
super().__init__(fmt=fmt, datefmt=datefmt)
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class AddFormattedAttributes(logging.Filter):
|
|
@@ -48,7 +48,7 @@ class AddFormattedAttributes(logging.Filter):
|
|
|
48
48
|
max_thread_len: int
|
|
49
49
|
|
|
50
50
|
def __init__(self, max_name_len: int = None, max_thread_len: int = None):
|
|
51
|
-
super(
|
|
51
|
+
super().__init__()
|
|
52
52
|
self.max_name_len = max_name_len if max_name_len else MAX_NAME_LEN
|
|
53
53
|
self.max_thread_len = max_thread_len if max_thread_len else MAX_THREAD_NAME_LEN
|
|
54
54
|
|
|
@@ -75,7 +75,7 @@ class MaskSensitiveInputFilter(logging.Filter):
|
|
|
75
75
|
patterns: list[tuple[re.Pattern[bytes], bytes]]
|
|
76
76
|
|
|
77
77
|
def __init__(self, sensitive_keys: list[str]):
|
|
78
|
-
super(
|
|
78
|
+
super().__init__()
|
|
79
79
|
|
|
80
80
|
self.patterns = [
|
|
81
81
|
(re.compile(to_bytes(rf'"{key}":\s*"[^"]+"')), to_bytes(f'"{key}": "******"'))
|
localstack/packages/api.py
CHANGED
|
@@ -3,10 +3,11 @@ import functools
|
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
5
|
from collections import defaultdict
|
|
6
|
+
from collections.abc import Callable
|
|
6
7
|
from enum import Enum
|
|
7
8
|
from inspect import getmodule
|
|
8
|
-
from threading import RLock
|
|
9
|
-
from typing import Any,
|
|
9
|
+
from threading import Lock, RLock
|
|
10
|
+
from typing import Any, Generic, ParamSpec, TypeVar
|
|
10
11
|
|
|
11
12
|
from plux import Plugin, PluginManager, PluginSpec # type: ignore
|
|
12
13
|
|
|
@@ -56,7 +57,7 @@ class PackageInstaller(abc.ABC):
|
|
|
56
57
|
multiple versions).
|
|
57
58
|
"""
|
|
58
59
|
|
|
59
|
-
def __init__(self, name: str, version: str, install_lock:
|
|
60
|
+
def __init__(self, name: str, version: str, install_lock: Lock | None = None):
|
|
60
61
|
"""
|
|
61
62
|
:param name: technical package name, f.e. "opensearch"
|
|
62
63
|
:param version: version of the package to install
|
|
@@ -70,7 +71,7 @@ class PackageInstaller(abc.ABC):
|
|
|
70
71
|
self.install_lock = install_lock or RLock()
|
|
71
72
|
self._setup_for_target: dict[InstallTarget, bool] = defaultdict(lambda: False)
|
|
72
73
|
|
|
73
|
-
def install(self, target:
|
|
74
|
+
def install(self, target: InstallTarget | None = None) -> None:
|
|
74
75
|
"""
|
|
75
76
|
Performs the package installation.
|
|
76
77
|
|
|
@@ -210,7 +211,7 @@ class Package(abc.ABC, Generic[T]):
|
|
|
210
211
|
"""
|
|
211
212
|
return self.get_installer(version).get_installed_dir()
|
|
212
213
|
|
|
213
|
-
def install(self, version: str | None = None, target:
|
|
214
|
+
def install(self, version: str | None = None, target: InstallTarget | None = None) -> None:
|
|
214
215
|
"""
|
|
215
216
|
Installs the package in the given version in the preferred target location.
|
|
216
217
|
:param version: version of the package to install. If None, the default version of the package will be used.
|
|
@@ -274,7 +275,7 @@ class MultiPackageInstaller(PackageInstaller):
|
|
|
274
275
|
assert len(package_installer) > 0
|
|
275
276
|
self.package_installer = package_installer
|
|
276
277
|
|
|
277
|
-
def install(self, target:
|
|
278
|
+
def install(self, target: InstallTarget | None = None) -> None:
|
|
278
279
|
"""
|
|
279
280
|
Installs the different packages this installer is composed of.
|
|
280
281
|
|
|
@@ -356,7 +357,7 @@ class PackagesPluginManager(PluginManager[PackagesPlugin]): # type: ignore[misc
|
|
|
356
357
|
)
|
|
357
358
|
|
|
358
359
|
def get_packages(
|
|
359
|
-
self, package_names: list[str], version:
|
|
360
|
+
self, package_names: list[str], version: str | None = None
|
|
360
361
|
) -> list[Package[PackageInstaller]]:
|
|
361
362
|
# Plugin names are unique, but there could be multiple packages with the same name in different scopes
|
|
362
363
|
plugin_specs_per_name = defaultdict(list)
|
|
@@ -390,7 +391,7 @@ T2 = TypeVar("T2")
|
|
|
390
391
|
def package(
|
|
391
392
|
name: str | None = None,
|
|
392
393
|
scope: str = "community",
|
|
393
|
-
should_load:
|
|
394
|
+
should_load: Callable[[], bool] | None = None,
|
|
394
395
|
) -> Callable[[Callable[[], Package[Any] | list[Package[Any]]]], PluginSpec]:
|
|
395
396
|
"""
|
|
396
397
|
Decorator for marking methods that create Package instances as a PackagePlugin.
|
localstack/packages/core.py
CHANGED
|
@@ -4,7 +4,7 @@ import re
|
|
|
4
4
|
from abc import ABC
|
|
5
5
|
from functools import lru_cache
|
|
6
6
|
from sys import version_info
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any
|
|
8
8
|
|
|
9
9
|
import requests
|
|
10
10
|
|
|
@@ -238,7 +238,7 @@ class NodePackageInstaller(ExecutableInstaller):
|
|
|
238
238
|
self,
|
|
239
239
|
package_name: str,
|
|
240
240
|
version: str,
|
|
241
|
-
package_spec:
|
|
241
|
+
package_spec: str | None = None,
|
|
242
242
|
main_module: str = "main.js",
|
|
243
243
|
):
|
|
244
244
|
"""
|
localstack/packages/plugins.py
CHANGED
|
@@ -5,14 +5,6 @@ from localstack.packages.api import Package, package
|
|
|
5
5
|
if TYPE_CHECKING:
|
|
6
6
|
from localstack.packages.ffmpeg import FfmpegPackageInstaller
|
|
7
7
|
from localstack.packages.java import JavaPackageInstaller
|
|
8
|
-
from localstack.packages.terraform import TerraformPackageInstaller
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@package(name="terraform")
|
|
12
|
-
def terraform_package() -> Package["TerraformPackageInstaller"]:
|
|
13
|
-
from .terraform import terraform_package
|
|
14
|
-
|
|
15
|
-
return terraform_package
|
|
16
8
|
|
|
17
9
|
|
|
18
10
|
@package(name="ffmpeg")
|
localstack/runtime/analytics.py
CHANGED
|
@@ -11,6 +11,7 @@ TRACKED_ENV_VAR = [
|
|
|
11
11
|
"ACTIVATE_PRO",
|
|
12
12
|
"ALLOW_NONSTANDARD_REGIONS",
|
|
13
13
|
"BEDROCK_PREWARM",
|
|
14
|
+
"CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES",
|
|
14
15
|
"CLOUDFRONT_LAMBDA_EDGE",
|
|
15
16
|
"CONTAINER_RUNTIME",
|
|
16
17
|
"DEBUG",
|
|
@@ -53,6 +54,7 @@ TRACKED_ENV_VAR = [
|
|
|
53
54
|
"LAMBDA_RUNTIME_ENVIRONMENT_TIMEOUT",
|
|
54
55
|
"LEGACY_EDGE_PROXY", # Not functional; deprecated in 1.0.0, removed in 2.0.0
|
|
55
56
|
"LS_LOG",
|
|
57
|
+
"LOCALSTACK_K8S_DEPLOYMENT_METHOD",
|
|
56
58
|
"MOCK_UNIMPLEMENTED", # Not functional; deprecated in 1.3.0, removed in 3.0.0
|
|
57
59
|
"OPENSEARCH_ENDPOINT_STRATEGY",
|
|
58
60
|
"PERSISTENCE",
|
|
@@ -78,6 +80,7 @@ PRESENCE_ENV_VAR = [
|
|
|
78
80
|
"HOSTNAME_FROM_LAMBDA",
|
|
79
81
|
"HOST_TMP_FOLDER", # Not functional; deprecated in 1.0.0, removed in 2.0.0
|
|
80
82
|
"INIT_SCRIPTS_PATH", # Not functional; deprecated in 1.1.0, removed in 2.0.0
|
|
83
|
+
"KUBERNETES_SERVICE_HOST",
|
|
81
84
|
"LAMBDA_DEBUG_MODE_CONFIG_PATH",
|
|
82
85
|
"LEGACY_DIRECTORIES", # Not functional; deprecated in 1.1.0, removed in 2.0.0
|
|
83
86
|
"LEGACY_INIT_DIR", # Not functional; deprecated in 1.1.0, removed in 2.0.0
|
localstack/runtime/hooks.py
CHANGED
localstack/runtime/init.py
CHANGED
|
@@ -89,9 +89,9 @@ class ShellScriptRunner(ScriptRunner):
|
|
|
89
89
|
suffixes = [".sh"]
|
|
90
90
|
|
|
91
91
|
def run(self, path: str) -> None:
|
|
92
|
-
exit_code = subprocess.call(args=[]
|
|
92
|
+
exit_code = subprocess.call(args=[path])
|
|
93
93
|
if exit_code != 0:
|
|
94
|
-
raise OSError("Script
|
|
94
|
+
raise OSError(f"Script {path} returned a non-zero exit code {exit_code}")
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
class PythonScriptRunner(ScriptRunner):
|
localstack/runtime/main.py
CHANGED
|
@@ -20,13 +20,13 @@ def print_runtime_information(in_docker: bool = False):
|
|
|
20
20
|
if in_docker:
|
|
21
21
|
try:
|
|
22
22
|
container_name = get_main_container_name()
|
|
23
|
-
print("LocalStack Docker container name:
|
|
23
|
+
print(f"LocalStack Docker container name: {container_name}")
|
|
24
24
|
inspect_result = DOCKER_CLIENT.inspect_container(container_name)
|
|
25
25
|
container_id = inspect_result["Id"]
|
|
26
|
-
print("LocalStack Docker container id:
|
|
26
|
+
print(f"LocalStack Docker container id: {container_id[:12]}")
|
|
27
27
|
image_details = DOCKER_CLIENT.inspect_image(inspect_result["Image"])
|
|
28
28
|
digests = image_details.get("RepoDigests") or ["Unavailable"]
|
|
29
|
-
print("LocalStack Docker image sha:
|
|
29
|
+
print(f"LocalStack Docker image sha: {digests[0]}")
|
|
30
30
|
except ContainerException:
|
|
31
31
|
print(
|
|
32
32
|
"LocalStack Docker container info: Failed to inspect the LocalStack docker container. "
|
|
@@ -44,10 +44,10 @@ def print_runtime_information(in_docker: bool = False):
|
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
if config.LOCALSTACK_BUILD_DATE:
|
|
47
|
-
print("LocalStack build date:
|
|
47
|
+
print(f"LocalStack build date: {config.LOCALSTACK_BUILD_DATE}")
|
|
48
48
|
|
|
49
49
|
if config.LOCALSTACK_BUILD_GIT_HASH:
|
|
50
|
-
print("LocalStack build git hash:
|
|
50
|
+
print(f"LocalStack build git hash: {config.LOCALSTACK_BUILD_GIT_HASH}")
|
|
51
51
|
|
|
52
52
|
print()
|
|
53
53
|
|