Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds lambda_ephemeral_storage option for configuring the ephemeral storage. #2069

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions chalice/awsclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ def create_function(
xray: Optional[bool] = None,
timeout: OptInt = None,
memory_size: OptInt = None,
ephemeral_storage: OptInt = None,
security_group_ids: OptStrList = None,
subnet_ids: OptStrList = None,
layers: OptStrList = None,
Expand All @@ -419,6 +420,8 @@ def create_function(
kwargs['Timeout'] = timeout
if memory_size is not None:
kwargs['MemorySize'] = memory_size
if ephemeral_storage is not None:
kwargs['EphemeralStorage'] = {'Size': ephemeral_storage}
if security_group_ids is not None and subnet_ids is not None:
kwargs['VpcConfig'] = self._create_vpc_config(
security_group_ids=security_group_ids,
Expand Down Expand Up @@ -902,6 +905,7 @@ def update_function(
xray: Optional[bool] = None,
timeout: OptInt = None,
memory_size: OptInt = None,
ephemeral_storage: OptInt = None,
role_arn: OptStr = None,
subnet_ids: OptStrList = None,
security_group_ids: OptStrList = None,
Expand All @@ -921,6 +925,7 @@ def update_function(
runtime=runtime,
timeout=timeout,
memory_size=memory_size,
ephemeral_storage=ephemeral_storage,
role_arn=role_arn,
xray=xray,
subnet_ids=subnet_ids,
Expand Down Expand Up @@ -967,19 +972,19 @@ def delete_function_concurrency(self, function_name: str) -> None:
lambda_client = self._client('lambda')
lambda_client.delete_function_concurrency(FunctionName=function_name)

def _update_function_config(
def _assemble_update_function_config_kwargs(
self,
environment_variables: StrMap,
runtime: OptStr,
timeout: OptInt,
memory_size: OptInt,
ephemeral_storage: OptInt,
role_arn: OptStr,
subnet_ids: OptStrList,
security_group_ids: OptStrList,
function_name: str,
layers: OptStrList,
xray: Optional[bool],
) -> None:
) -> Dict[str, Any]:
kwargs: Dict[str, Any] = {}
if environment_variables is not None:
kwargs['Environment'] = {'Variables': environment_variables}
Expand All @@ -989,6 +994,8 @@ def _update_function_config(
kwargs['Timeout'] = timeout
if memory_size is not None:
kwargs['MemorySize'] = memory_size
if ephemeral_storage is not None:
kwargs['EphemeralStorage'] = {'Size': ephemeral_storage}
if role_arn is not None:
kwargs['Role'] = role_arn
if xray:
Expand All @@ -999,6 +1006,34 @@ def _update_function_config(
)
if layers is not None:
kwargs['Layers'] = layers
return kwargs

def _update_function_config(
self,
environment_variables: StrMap,
runtime: OptStr,
timeout: OptInt,
memory_size: OptInt,
ephemeral_storage: OptInt,
role_arn: OptStr,
subnet_ids: OptStrList,
security_group_ids: OptStrList,
function_name: str,
layers: OptStrList,
xray: Optional[bool],
) -> None:
kwargs = self._assemble_update_function_config_kwargs(
environment_variables,
runtime,
timeout,
memory_size,
ephemeral_storage,
role_arn,
subnet_ids,
security_group_ids,
layers,
xray,
)
if kwargs:
self._do_update_function_config(function_name, kwargs)

Expand Down
6 changes: 6 additions & 0 deletions chalice/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@ def lambda_memory_size(self) -> int:
varies_per_chalice_stage=True,
varies_per_function=True)

@property
def lambda_ephemeral_storage(self) -> int:
return self._chain_lookup('lambda_ephemeral_storage',
varies_per_chalice_stage=True,
varies_per_function=True)

@property
def lambda_timeout(self) -> int:
return self._chain_lookup('lambda_timeout',
Expand Down
1 change: 1 addition & 0 deletions chalice/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def index():

DEFAULT_LAMBDA_TIMEOUT = 60
DEFAULT_LAMBDA_MEMORY_SIZE = 128
DEFAULT_LAMBDA_EPHEMERAL_STORAGE = 512
MAX_LAMBDA_DEPLOYMENT_SIZE = 50 * (1024 ** 2)
# This is the name of the main handler used to
# handle API gateway requests. This is used as a key
Expand Down
1 change: 1 addition & 0 deletions chalice/deploy/appgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ def _build_lambda_function(
tags=config.tags,
timeout=config.lambda_timeout,
memory_size=config.lambda_memory_size,
ephemeral_storage=config.lambda_ephemeral_storage,
deployment_package=deployment,
role=role,
security_group_ids=security_group_ids,
Expand Down
7 changes: 6 additions & 1 deletion chalice/deploy/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
from chalice.constants import VPC_ATTACH_POLICY
from chalice.constants import DEFAULT_LAMBDA_TIMEOUT
from chalice.constants import DEFAULT_LAMBDA_MEMORY_SIZE
from chalice.constants import DEFAULT_LAMBDA_EPHEMERAL_STORAGE
from chalice.constants import DEFAULT_TLS_VERSION
from chalice.constants import SQS_EVENT_SOURCE_POLICY
from chalice.constants import KINESIS_EVENT_SOURCE_POLICY
Expand Down Expand Up @@ -422,10 +423,12 @@ def handle(self, config, resource):
class InjectDefaults(BaseDeployStep):
def __init__(self, lambda_timeout=DEFAULT_LAMBDA_TIMEOUT,
lambda_memory_size=DEFAULT_LAMBDA_MEMORY_SIZE,
lambda_ephemeral_storage=DEFAULT_LAMBDA_EPHEMERAL_STORAGE,
tls_version=DEFAULT_TLS_VERSION):
# type: (int, int, str) -> None
# type: (int, int, int, str) -> None
self._lambda_timeout = lambda_timeout
self._lambda_memory_size = lambda_memory_size
self._lambda_ephemeral_storage = lambda_ephemeral_storage
self._tls_version = DEFAULT_TLS_VERSION

def handle_lambdafunction(self, config, resource):
Expand All @@ -434,6 +437,8 @@ def handle_lambdafunction(self, config, resource):
resource.timeout = self._lambda_timeout
if resource.memory_size is None:
resource.memory_size = self._lambda_memory_size
if resource.ephemeral_storage is None:
resource.ephemeral_storage = self._lambda_ephemeral_storage

def handle_domainname(self, config, resource):
# type: (Config, models.DomainName) -> None
Expand Down
1 change: 1 addition & 0 deletions chalice/deploy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class LambdaFunction(ManagedModel):
tags: StrMap
timeout: int
memory_size: int
ephemeral_storage: int
role: IAMRole
security_group_ids: List[str]
subnet_ids: List[str]
Expand Down
2 changes: 2 additions & 0 deletions chalice/deploy/planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ def _plan_lambdafunction(self, resource):
'tags': resource.tags,
'timeout': resource.timeout,
'memory_size': resource.memory_size,
'ephemeral_storage': resource.ephemeral_storage,
'security_group_ids': resource.security_group_ids,
'subnet_ids': resource.subnet_ids,
'layers': layers
Expand Down Expand Up @@ -521,6 +522,7 @@ def _plan_lambdafunction(self, resource):
'tags': resource.tags,
'timeout': resource.timeout,
'memory_size': resource.memory_size,
'ephemeral_storage': resource.ephemeral_storage,
'security_group_ids': resource.security_group_ids,
'subnet_ids': resource.subnet_ids,
'layers': layers
Expand Down
2 changes: 2 additions & 0 deletions chalice/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ def _generate_lambdafunction(self, resource, template):
'Tracing': resource.xray and 'Active' or 'PassThrough',
'Timeout': resource.timeout,
'MemorySize': resource.memory_size,
'EphemeralStorage': {'Size': resource.ephemeral_storage},
},
} # type: Dict[str, Any]

Expand Down Expand Up @@ -1243,6 +1244,7 @@ def _generate_lambdafunction(self, resource, template):
'runtime': resource.runtime,
'handler': resource.handler,
'memory_size': resource.memory_size,
'ephemeral_storage': resource.ephemeral_storage,
'tags': resource.tags,
'timeout': resource.timeout,
'source_code_hash': '${filebase64sha256("%s")}' % (
Expand Down
33 changes: 33 additions & 0 deletions docs/source/topics/configfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ your function. The default ``lambda_memory_size`` value is ``128``. The value
must be a multiple of 64 MB.


``lambda_ephemeral_storage``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An integer representing the amount of ephemeral storage, in MB, your Lambda
function is given. The default ``lambda_ephemeral_storage`` value is ``512``.
The maximum value is ``10240``.


``lambda_timeout``
~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -387,6 +395,7 @@ that can be applied per function:
* ``iam_role_arn``
* ``lambda_memory_size``
* ``lambda_timeout``
* ``lambda_ephemeral_storage``
* ``layers``
* ``manage_iam_role``
* ``reserved_concurrency``
Expand Down Expand Up @@ -600,6 +609,30 @@ The ``prod`` stage will have these environment variables set::
}


.. _ephemeral-storage-examples:

Ephemeral Storage
~~~~~~~~~~~~~~~~~

In the following example, the ephemeral storage for the
"foo" function will be set to 1024 MB. In the dev stage
that value will be overridden and set to 2048 MB::

{
"version": "2.0",
"app_name": "app",
"lambda_functions": {
"foo": {
"lambda_ephemeral_storage": 1024
}
"dev": {
"lambda_functions": {
"foo": {
"lambda_ephemeral_storage": 2048
}
}


Per Lambda Examples
~~~~~~~~~~~~~~~~~~~

Expand Down
6 changes: 3 additions & 3 deletions docs/source/topics/middleware.rst
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,15 @@ Integrating with AWS Lambda Powertools
--------------------------------------

`AWS Lambda Powertools
<https://awslabs.github.io/aws-lambda-powertools-python/latest/>`__ is a suite of
<https://docs.powertools.aws.dev/lambda/python/latest/>`__ is a suite of
utilities for AWS Lambda functions that makes tracing with AWS X-Ray,
structured logging and creating custom metrics asynchronously easier.

You can use Chalice middleware to easily integrate Lambda Powertools with
your Chalice apps. In this example, we'll use the
`Logger
<https://awslabs.github.io/aws-lambda-powertools-python/latest/core/logger/>`__
and `Tracer <https://awslabs.github.io/aws-lambda-powertools-python/latest/core/tracer/>`__
<https://docs.powertools.aws.dev/lambda/python/latest/core/logger/>`__
and `Tracer <https://docs.powertools.aws.dev/lambda/python/latest/core/tracer/>`__
and convert them to Chalice middleware so they will be automatically applied
to all Lambda functions in our application.

Expand Down
28 changes: 28 additions & 0 deletions tests/functional/test_awsclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -1828,6 +1828,22 @@ def test_create_function_with_memory_size(self, stubbed_session):
memory_size=256) == 'arn:12345:name'
stubbed_session.verify_stubs()

def test_create_function_with_ephemeral_storage(self, stubbed_session):
stubbed_session.stub('lambda').create_function(
FunctionName='name',
Runtime='python2.7',
Code={'ZipFile': b'foo'},
Handler='app.app',
Role='myarn',
EphemeralStorage={'Size': 1024},
).returns(self.SUCCESS_RESPONSE)
stubbed_session.activate_stubs()
awsclient = TypedAWSClient(stubbed_session)
assert awsclient.create_function(
'name', 'myarn', b'foo', 'python2.7', 'app.app',
ephemeral_storage=1024) == 'arn:12345:name'
stubbed_session.verify_stubs()

def test_create_function_with_vpc_config(self, stubbed_session):
stubbed_session.stub('lambda').create_function(
FunctionName='name',
Expand Down Expand Up @@ -2186,6 +2202,18 @@ def test_update_function_code_with_memory(self, stubbed_session):
awsclient.update_function('name', b'foo', memory_size=256)
stubbed_session.verify_stubs()

def test_update_function_code_with_ephemeral(self, stubbed_session):
lambda_client = stubbed_session.stub('lambda')
lambda_client.update_function_code(
FunctionName='name', ZipFile=b'foo').returns(self.SUCCESS_RESPONSE)
lambda_client.update_function_configuration(
FunctionName='name',
EphemeralStorage={'Size': 1024}).returns(self.SUCCESS_RESPONSE)
stubbed_session.activate_stubs()
awsclient = TypedAWSClient(stubbed_session)
awsclient.update_function('name', b'foo', ephemeral_storage=1024)
stubbed_session.verify_stubs()

def test_update_function_with_vpc_config(self, stubbed_session):
lambda_client = stubbed_session.stub('lambda')
lambda_client.update_function_code(
Expand Down
1 change: 1 addition & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ def lambda_function():
tags={},
timeout=None,
memory_size=None,
ephemeral_storage=None,
role=models.PreCreatedIAMRole(role_arn='foobar'),
security_group_ids=[],
subnet_ids=[],
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/deploy/test_appgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def test_can_build_single_lambda_function_app(self,
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down Expand Up @@ -159,6 +160,7 @@ def test_can_build_single_lambda_function_app_with_log_retention(
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down Expand Up @@ -195,6 +197,7 @@ def test_can_build_single_lambda_function_app_with_managed_layer(
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down Expand Up @@ -251,6 +254,7 @@ def test_can_build_lambda_function_with_layers(self,
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down Expand Up @@ -310,6 +314,7 @@ def foo(event, context):
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down Expand Up @@ -372,6 +377,7 @@ def test_can_build_lambda_function_app_with_reserved_concurrency(
tags=config.tags,
timeout=None,
memory_size=None,
ephemeral_storage=None,
deployment_package=models.DeploymentPackage(
models.Placeholder.BUILD_STAGE),
role=models.PreCreatedIAMRole('role:arn'),
Expand Down
Loading