Skip to content

Commit fd067cb

Browse files
authored
Change AWS_EXECUTION_ENV set in the lambda init binary (#10212)
1 parent 8aeabc1 commit fd067cb

File tree

6 files changed

+177
-4
lines changed

6 files changed

+177
-4
lines changed

localstack/services/lambda_/invocation/docker_runtime_executor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,11 @@ def start(self, env_vars: dict[str, str]) -> None:
358358
self.container_name, f"{str(get_runtime_client_path())}/.", "/"
359359
)
360360
# tiny bit inefficient since we actually overwrite the init, but otherwise the path might not exist
361-
if config.LAMBDA_INIT_DEBUG:
361+
if config.LAMBDA_INIT_BIN_PATH:
362362
CONTAINER_CLIENT.copy_into_container(
363363
self.container_name, config.LAMBDA_INIT_BIN_PATH, "/var/rapid/init"
364364
)
365+
if config.LAMBDA_INIT_DEBUG:
365366
CONTAINER_CLIENT.copy_into_container(
366367
self.container_name, config.LAMBDA_INIT_DELVE_PATH, "/var/rapid/dlv"
367368
)

localstack/services/lambda_/invocation/execution_environment.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ def get_environment_variables(self) -> Dict[str, str]:
154154
# config.handler is None for image lambdas and will be populated at runtime (e.g., by RIE)
155155
if self.function_version.config.handler:
156156
env_vars["_HANDLER"] = self.function_version.config.handler
157-
# Not defined for custom runtimes (e.g., provided, provided.al2)
157+
# Will be overriden by the runtime itself unless it is a provided runtime
158158
if self.function_version.config.runtime:
159-
env_vars["AWS_EXECUTION_ENV"] = f"Aws_Lambda_{self.function_version.config.runtime}"
159+
env_vars["AWS_EXECUTION_ENV"] = "AWS_Lambda_rapid"
160160
if self.function_version.config.environment:
161161
env_vars.update(self.function_version.config.environment)
162162
if config.LAMBDA_INIT_DEBUG:
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def handler(event, context):
2+
pid = event.get("pid")
3+
with open(f"/proc/{pid}/environ", mode="rt") as f:
4+
environment = f.read()
5+
environment = environment.split("\x00")
6+
env_partition = [env.partition("=") for env in environment if env]
7+
env_dict = dict((env[0], env[2]) for env in env_partition)
8+
return {"environment": env_dict}

tests/aws/services/lambda_/test_lambda.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
TEST_LAMBDA_INVOCATION_TYPE = os.path.join(THIS_FOLDER, "functions/lambda_invocation_type.py")
111111
TEST_LAMBDA_VERSION = os.path.join(THIS_FOLDER, "functions/lambda_version.py")
112112
TEST_LAMBDA_CONTEXT_REQID = os.path.join(THIS_FOLDER, "functions/lambda_context.py")
113+
TEST_LAMBDA_PROCESS_INSPECTION = os.path.join(THIS_FOLDER, "functions/lambda_process_inspection.py")
113114

114115
TEST_EVENTS_SQS_RECEIVE_MESSAGE = os.path.join(THIS_FOLDER, "events/sqs-receive-message.json")
115116
TEST_EVENTS_APIGATEWAY_AWS_PROXY = os.path.join(THIS_FOLDER, "events/apigateway-aws-proxy.json")
@@ -695,6 +696,71 @@ def assert_events():
695696
)
696697
snapshot.match("invoke-result-read-number-after-timeout", result)
697698

699+
@markers.aws.validated
700+
@markers.snapshot.skip_snapshot_verify(
701+
paths=[
702+
"$..CreateFunctionResponse.LoggingConfig",
703+
# not set directly on init in lambda, but only on runtime processes
704+
"$..Payload.environment.AWS_ACCESS_KEY_ID",
705+
"$..Payload.environment.AWS_SECRET_ACCESS_KEY",
706+
"$..Payload.environment.AWS_SESSION_TOKEN",
707+
"$..Payload.environment.AWS_XRAY_DAEMON_ADDRESS",
708+
# variables set by default in the image/docker
709+
"$..Payload.environment.HOME",
710+
"$..Payload.environment.HOSTNAME",
711+
# LocalStack specific variables
712+
"$..Payload.environment.AWS_ENDPOINT_URL",
713+
"$..Payload.environment.AWS_LAMBDA_FUNCTION_TIMEOUT",
714+
"$..Payload.environment.EDGE_PORT",
715+
"$..Payload.environment.LOCALSTACK_FUNCTION_ACCOUNT_ID",
716+
"$..Payload.environment.LOCALSTACK_HOSTNAME",
717+
"$..Payload.environment.LOCALSTACK_INIT_LOG_LEVEL",
718+
"$..Payload.environment.LOCALSTACK_RUNTIME_ENDPOINT",
719+
"$..Payload.environment.LOCALSTACK_RUNTIME_ID",
720+
"$..Payload.environment.LOCALSTACK_USER",
721+
"$..Payload.environment.LOCALSTACK_POST_INVOKE_WAIT_MS",
722+
# internal AWS lambda functionality
723+
"$..Payload.environment._AWS_XRAY_DAEMON_ADDRESS",
724+
"$..Payload.environment._LAMBDA_CONSOLE_SOCKET",
725+
"$..Payload.environment._LAMBDA_CONTROL_SOCKET",
726+
"$..Payload.environment._LAMBDA_DIRECT_INVOKE_SOCKET",
727+
"$..Payload.environment._LAMBDA_LOG_FD",
728+
"$..Payload.environment._LAMBDA_RUNTIME_LOAD_TIME",
729+
"$..Payload.environment._LAMBDA_SB_ID",
730+
"$..Payload.environment._LAMBDA_SHARED_MEM_FD",
731+
"$..Payload.environment._LAMBDA_TELEMETRY_API_PASSPHRASE",
732+
"$..Payload.environment._X_AMZN_TRACE_ID",
733+
]
734+
)
735+
def test_lambda_init_environment(
736+
self, aws_client, create_lambda_function, snapshot, monkeypatch
737+
):
738+
if not is_aws_cloud():
739+
# needed to be able to read /proc/1/environ
740+
monkeypatch.setattr(config, "LAMBDA_INIT_USER", "root")
741+
func_name = f"test_lambda_{short_uid()}"
742+
# The file descriptors might change, and might have to be added to the transformers at some point
743+
snapshot.add_transformer(
744+
[
745+
snapshot.transform.key_value(
746+
"_LAMBDA_TELEMETRY_API_PASSPHRASE", "telemetry-passphrase"
747+
),
748+
snapshot.transform.key_value("AWS_LAMBDA_LOG_STREAM_NAME", "log-stream-name"),
749+
snapshot.transform.key_value("_X_AMZN_TRACE_ID", "xray-trace-id"),
750+
snapshot.transform.key_value("_LAMBDA_RUNTIME_LOAD_TIME", "runtime-load-time"),
751+
]
752+
)
753+
create_result = create_lambda_function(
754+
func_name=func_name,
755+
handler_file=TEST_LAMBDA_PROCESS_INSPECTION,
756+
runtime=Runtime.python3_12,
757+
client=aws_client.lambda_,
758+
)
759+
snapshot.match("create-result", create_result)
760+
761+
result = aws_client.lambda_.invoke(FunctionName=func_name, Payload=json.dumps({"pid": 1}))
762+
snapshot.match("lambda-init-inspection", result)
763+
698764

699765
URL_HANDLER_CODE = """
700766
def handler(event, ctx):

tests/aws/services/lambda_/test_lambda.snapshot.json

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3490,5 +3490,100 @@
34903490
}
34913491
}
34923492
}
3493+
},
3494+
"tests/aws/services/lambda_/test_lambda.py::TestLambdaBehavior::test_lambda_init_environment": {
3495+
"recorded-date": "13-02-2024, 12:42:59",
3496+
"recorded-content": {
3497+
"create-result": {
3498+
"CreateEventSourceMappingResponse": null,
3499+
"CreateFunctionResponse": {
3500+
"Architectures": [
3501+
"x86_64"
3502+
],
3503+
"CodeSha256": "code-sha256",
3504+
"CodeSize": "<code-size>",
3505+
"Description": "",
3506+
"Environment": {
3507+
"Variables": {}
3508+
},
3509+
"EphemeralStorage": {
3510+
"Size": 512
3511+
},
3512+
"FunctionArn": "arn:aws:lambda:<region>:111111111111:function:<function-name:1>",
3513+
"FunctionName": "<function-name:1>",
3514+
"Handler": "handler.handler",
3515+
"LastModified": "date",
3516+
"LoggingConfig": {
3517+
"LogFormat": "Text",
3518+
"LogGroup": "/aws/lambda/<function-name:1>"
3519+
},
3520+
"MemorySize": 128,
3521+
"PackageType": "Zip",
3522+
"RevisionId": "<uuid:1>",
3523+
"Role": "arn:aws:iam::111111111111:role/<resource:1>",
3524+
"Runtime": "python3.12",
3525+
"RuntimeVersionConfig": {
3526+
"RuntimeVersionArn": "arn:aws:lambda:<region>::runtime:<resource:2>"
3527+
},
3528+
"SnapStart": {
3529+
"ApplyOn": "None",
3530+
"OptimizationStatus": "Off"
3531+
},
3532+
"State": "Pending",
3533+
"StateReason": "The function is being created.",
3534+
"StateReasonCode": "Creating",
3535+
"Timeout": 30,
3536+
"TracingConfig": {
3537+
"Mode": "PassThrough"
3538+
},
3539+
"Version": "$LATEST",
3540+
"ResponseMetadata": {
3541+
"HTTPHeaders": {},
3542+
"HTTPStatusCode": 201
3543+
}
3544+
}
3545+
},
3546+
"lambda-init-inspection": {
3547+
"ExecutedVersion": "$LATEST",
3548+
"Payload": {
3549+
"environment": {
3550+
"PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin",
3551+
"LD_LIBRARY_PATH": "/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib",
3552+
"_LAMBDA_TELEMETRY_API_PASSPHRASE": "<telemetry-passphrase:1>",
3553+
"LANG": "en_US.UTF-8",
3554+
"TZ": ":UTC",
3555+
"_HANDLER": "handler.handler",
3556+
"_LAMBDA_DIRECT_INVOKE_SOCKET": "9",
3557+
"_LAMBDA_CONTROL_SOCKET": "11",
3558+
"_LAMBDA_CONSOLE_SOCKET": "12",
3559+
"LAMBDA_TASK_ROOT": "/var/task",
3560+
"LAMBDA_RUNTIME_DIR": "/var/runtime",
3561+
"_LAMBDA_LOG_FD": "18",
3562+
"_LAMBDA_SB_ID": "0",
3563+
"_LAMBDA_SHARED_MEM_FD": "8",
3564+
"AWS_REGION": "<region>",
3565+
"AWS_DEFAULT_REGION": "<region>",
3566+
"AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/<function-name:1>",
3567+
"AWS_LAMBDA_LOG_STREAM_NAME": "<log-stream-name:1>",
3568+
"AWS_LAMBDA_FUNCTION_NAME": "<function-name:1>",
3569+
"AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128",
3570+
"AWS_LAMBDA_FUNCTION_VERSION": "$LATEST",
3571+
"_AWS_XRAY_DAEMON_ADDRESS": "169.254.79.129",
3572+
"_AWS_XRAY_DAEMON_PORT": "2000",
3573+
"AWS_XRAY_DAEMON_ADDRESS": "169.254.79.129:2000",
3574+
"AWS_XRAY_CONTEXT_MISSING": "LOG_ERROR",
3575+
"_X_AMZN_TRACE_ID": "<xray-trace-id:1>",
3576+
"AWS_EXECUTION_ENV": "AWS_Lambda_rapid",
3577+
"AWS_LAMBDA_INITIALIZATION_TYPE": "on-demand",
3578+
"_LAMBDA_RUNTIME_LOAD_TIME": "<runtime-load-time:1>"
3579+
}
3580+
},
3581+
"StatusCode": 200,
3582+
"ResponseMetadata": {
3583+
"HTTPHeaders": {},
3584+
"HTTPStatusCode": 200
3585+
}
3586+
}
3587+
}
34933588
}
34943589
}

tests/aws/services/lambda_/test_lambda.validation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
"tests/aws/services/lambda_/test_lambda.py::TestLambdaBehavior::test_lambda_cache_local[python]": {
2727
"last_validated_date": "2023-11-20T21:57:14+00:00"
2828
},
29+
"tests/aws/services/lambda_/test_lambda.py::TestLambdaBehavior::test_lambda_init_environment": {
30+
"last_validated_date": "2024-02-13T12:42:58+00:00"
31+
},
2932
"tests/aws/services/lambda_/test_lambda.py::TestLambdaBehavior::test_lambda_invoke_no_timeout": {
3033
"last_validated_date": "2023-11-20T21:04:53+00:00"
3134
},
@@ -185,4 +188,4 @@
185188
"tests/aws/services/lambda_/test_lambda.py::TestRequestIdHandling::test_request_id_invoke_url": {
186189
"last_validated_date": "2023-11-20T21:08:49+00:00"
187190
}
188-
}
191+
}

0 commit comments

Comments
 (0)