Feature: In-process Lambda execution mode for use_docker: False
## Problem
Currently, moto offers two Lambda execution modes:
1. **Docker mode** (`use_docker: True`, default): Runs Lambda code inside a Docker container. Full fidelity, but requires Docker runtime.
2. **Simple mode** (`use_docker: False`): No Docker needed, but doesn't execute handler code at all — returns a canned response (`"Simple Lambda happy path OK"` or a queued result).
There is no middle ground. This creates a gap for a common use case:
**Testing event source mapping chains (e.g., S3 → SQS → Lambda) in CI environments without Docker.**
With the current simple mode, the Event Source Mapping trigger fires correctly (`_send_sqs_message` calls `invoke`), but the Lambda handler never actually runs. This means you can't verify that your handler processes the SQS event correctly without Docker.
## Use case
```python
@mock_aws(config={"lambda": {"use_docker": False}})
def test_s3_triggers_lambda_via_sqs():
# Setup S3 bucket with event notification → SQS
# Setup SQS queue with event source mapping → Lambda
# Lambda handler posts to an external webhook
s3.put_object(Bucket="my-bucket", Key="test.txt", Body=b"data")
# With current simple mode: Lambda "runs" but handler code never executes
# With in-process mode: handler code runs in the same process,
# so unittest.mock.patch works for external HTTP calls
```
The key advantage of in-process execution is that `unittest.mock.patch` works because everything runs in the same Python process. This makes it straightforward to mock external dependencies (HTTP calls, etc.) that the Lambda handler uses.
## Proposal
Add an in-process execution option when `use_docker: False`. When a Lambda function is created with a Python runtime and a ZipFile deployment, moto could:
1. Extract the zip to a temp directory
2. Import the handler module
3. Call the handler function directly with the event and a mock context
A rough sketch:
```python
# In LambdaSimpleBackend or a new LambdaInlineBackend
def invoke(self, function_name, qualifier, body, headers, response_headers):
func = self._lambdas.get_function_by_name_or_arn_with_qualifier(function_name, qualifier)
if func.code and func.run_time.startswith("python"):
module_name, handler_name = func.handler.rsplit(".", 1)
# Extract zip, importlib the module, call handler_name(event, context)
...
else:
# Fall back to current simple behavior for non-Python / non-zip
return super().invoke(...)
```
This would be opt-in (e.g., `{"lambda": {"use_docker": False, "execute_inline": True}}`) so it doesn't change existing behavior.
## Scope / Limitations
- Python runtimes only (at least initially)
- ZipFile deployments only (not S3 or ECR image)
- No sandboxing — the handler runs in the test process with full access
- No Lambda runtime API emulation — just direct function call
## Related
- #9852 — `use_docker: False` not working in server mode (different issue, same pain point)
0 条评论