Skip to content

Commit

Permalink
Download Python packages according to lambda runtime
Browse files Browse the repository at this point in the history
Packages should be downloaded for the Python version and platform
of the Lambda's runtime requested and not according to the Python
version and platform where e3-aws runs.
  • Loading branch information
pierretr committed Sep 21, 2023
1 parent 6fe7fc8 commit ab4f4dc
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/e3/aws/troposphere/awslambda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,17 @@ def resources(self, stack: Stack) -> list[AWSObject]:
class PyFunction(Function):
"""Lambda with a Python runtime."""

AMAZON_LINUX_2_RUNTIMES = ("3.8", "3.9", "3.10", "3.11")
RUNTIME_CONFIGS = {
f"python{version}": {
"implementation": "cp",
# AmazonLinux2 glibc version is 2.26 and we support only x86_64
# architecture for now
"platforms": ("manylinux_2_17_x86_64", "manylinux_2_24_x86_64"),
}
for version in AMAZON_LINUX_2_RUNTIMES
}

def __init__(
self,
name: str,
Expand Down Expand Up @@ -412,12 +423,21 @@ def create_data_dir(self, root_dir: str) -> None:

# Install the requirements
if self.requirement_file is not None:
assert self.runtime is not None
runtime_config = PyFunction.RUNTIME_CONFIGS[self.runtime]
p = Run(
[
sys.executable,
"-m",
"pip",
"install",
f"--python-version={self.runtime.lstrip('python')}",
*(
f"--platform={platform}"
for platform in runtime_config["platforms"]
),
f"--implementation={runtime_config['implementation']}",
"--only-binary=:all:",
f"--target={package_dir}",
"-r",
self.requirement_file,
Expand Down
39 changes: 39 additions & 0 deletions tests/tests_e3_aws/troposphere/awslambda/awslambda_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import pytest
import json
import io
from unittest.mock import patch
import sys

from flask import Flask, send_file
from troposphere.awslambda import (
Expand Down Expand Up @@ -395,6 +397,43 @@ def test_pyfunction(stack: Stack) -> None:
assert stack.export()["Resources"] == EXPECTED_PYFUNCTION_TEMPLATE


def test_pyfunction_with_requirements(tmp_path, stack: Stack) -> None:
"""Test PyFunction creation."""
stack.s3_bucket = "cfn_bucket"
stack.s3_key = "templates/"
code_dir = tmp_path

with patch("e3.aws.troposphere.awslambda.Run") as mock_run:
mock_run.return_value.status = 0
PyFunction(
name="mypylambda",
description="this is a test",
role="somearn",
runtime="python3.11",
code_dir=str(code_dir),
handler="app.main",
requirement_file="requirements.txt",
).create_data_dir("dummy")
# Ensure the right pip command is called
mock_run.assert_called_once_with(
[
sys.executable,
"-m",
"pip",
"install",
"--python-version=3.11",
"--platform=manylinux_2_17_x86_64",
"--platform=manylinux_2_24_x86_64",
"--implementation=cp",
"--only-binary=:all:",
"--target=dummy/Mypylambda/package",
"-r",
"requirements.txt",
],
output=None,
)


def test_pyfunction_policy_document(stack: Stack) -> None:
"""Test cfn_policy_document of PyFunction."""
stack.s3_bucket = "cfn_bucket"
Expand Down

0 comments on commit ab4f4dc

Please sign in to comment.