Skip to content

Commit 1d58023

Browse files
feat(layers): introduce new CDK Python constructor for Powertools Lambda Layer (#5320)
* New Python constructor for layers * Improving docs
1 parent e8d4859 commit 1d58023

12 files changed

+473
-83
lines changed

.github/workflows/quality_check.yml

-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ on:
2626
- "mypy.ini"
2727
branches:
2828
- develop
29-
- v3
3029
push:
3130
paths:
3231
- "aws_lambda_powertools/**"
@@ -37,7 +36,6 @@ on:
3736
- "mypy.ini"
3837
branches:
3938
- develop
40-
- v3
4139

4240
permissions:
4341
contents: read
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Code quality - CDK constructor
2+
3+
# PROCESS
4+
#
5+
# 1. Install all dependencies and spin off containers for all supported Python versions
6+
# 2. Run code formatters and linters (various checks) for code standard
7+
# 3. Run static typing checker for potential bugs
8+
# 4. Run tests
9+
10+
# USAGE
11+
#
12+
# Always triggered on new PRs, PR changes and PR merge.
13+
14+
15+
on:
16+
pull_request:
17+
paths:
18+
- "layer/layer_constructors/**"
19+
branches:
20+
- develop
21+
push:
22+
paths:
23+
- "layer/layer_constructors/**"
24+
branches:
25+
- develop
26+
27+
permissions:
28+
contents: read
29+
30+
jobs:
31+
quality_check:
32+
runs-on: ubuntu-latest
33+
strategy:
34+
max-parallel: 4
35+
matrix:
36+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
37+
env:
38+
PYTHON: "${{ matrix.python-version }}"
39+
permissions:
40+
contents: read # checkout code only
41+
defaults:
42+
run:
43+
working-directory: ./layer_v3/layer_constructors
44+
steps:
45+
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
46+
- name: Install poetry
47+
run: pipx install poetry
48+
- name: Set up Python ${{ matrix.python-version }}
49+
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
50+
with:
51+
python-version: ${{ matrix.python-version }}
52+
cache: "poetry"
53+
- name: Set up QEMU
54+
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.0.0
55+
with:
56+
platforms: arm64
57+
# NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM)
58+
- name: Set up Docker Buildx
59+
id: builder
60+
uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # v2.4.1
61+
with:
62+
install: true
63+
driver: docker
64+
platforms: linux/amd64,linux/arm64
65+
- name: Install dependencies
66+
run: |
67+
pip install --upgrade pip pre-commit poetry
68+
poetry install
69+
- name: Test with pytest
70+
run: poetry run pytest tests

layer_v3/__init__.py

Whitespace-only changes.

layer_v3/layer/layer_stack.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
)
1515
from aws_cdk.aws_lambda import Architecture, CfnLayerVersionPermission, Runtime
1616
from aws_cdk.aws_ssm import StringParameter
17-
from cdk_aws_lambda_powertools_layer import LambdaPowertoolsLayerPythonV3
1817
from constructs import Construct
1918

19+
from layer_v3.layer_constructors.layer_stack import LambdaPowertoolsLayerPythonV3
20+
2021

2122
@jsii.implements(IAspect)
2223
class ApplyCondition:
@@ -46,11 +47,11 @@ def __init__(
4647
layer = LambdaPowertoolsLayerPythonV3(
4748
self,
4849
"Layer",
49-
layer_version_name=layer_version_name,
50-
version=powertools_version,
50+
layer_name=layer_version_name,
51+
powertools_version=powertools_version,
5152
python_version=python_version,
5253
include_extras=True,
53-
compatible_architectures=[architecture] if architecture else [],
54+
architecture=architecture or Architecture.X86_64,
5455
)
5556
layer.apply_removal_policy(RemovalPolicy.RETAIN)
5657

layer_v3/layer_constructors/__init__.py

Whitespace-only changes.
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from __future__ import annotations
2+
3+
4+
def construct_build_args(include_extras: bool = True, version: str | None = None) -> str:
5+
"""
6+
This function creates a suffix string for the Powertools package based on
7+
whether extra dependencies should be included and a specific version is required.
8+
9+
Params
10+
------
11+
include_extras: bool | None:
12+
If True, include all extra dependencies in Powertools package
13+
version: str | None
14+
The version of Powertools to install. Can be a version number or a git reference.
15+
16+
Returns
17+
-------
18+
str
19+
A string suffix to be appended to the Powertools package name during installation.
20+
Examples:
21+
- "" (empty string) if no extras or version specified
22+
- "[all]" if include_extras is True
23+
- "==1.2.3" if version is "1.2.3"
24+
- "[all]==1.2.3" if include_extras is True and version is "1.2.3"
25+
- " @ git+https://github.com/..." if version starts with "git"
26+
27+
Example
28+
-------
29+
>>> construct_build_args(True, "1.2.3")
30+
'[all]==1.2.3'
31+
>>> construct_build_args(False, "git+https://github.com/...")
32+
' @ git+https://github.com/...'
33+
"""
34+
35+
suffix = ""
36+
37+
if include_extras:
38+
suffix = "[all]"
39+
if version:
40+
if version.startswith("git"):
41+
suffix = f"{suffix} @ {version}"
42+
else:
43+
suffix = f"{suffix}=={version}"
44+
45+
return suffix
+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
from typing import TYPE_CHECKING
5+
6+
from aws_cdk import aws_lambda as lambda_
7+
8+
if TYPE_CHECKING:
9+
from constructs import Construct
10+
11+
from layer_v3.layer_constructors.helpers import construct_build_args
12+
13+
14+
class LambdaPowertoolsLayerPythonV3(lambda_.LayerVersion):
15+
"""
16+
A CDK Stack that creates a Lambda Layer for Powertools for AWS Lambda (Python) V3.
17+
18+
This stack creates a Lambda Layer containing the Powertools for AWS Lambda (Python) V3 library.
19+
It allows customization of the Python runtime version, inclusion of extra dependencies,
20+
architecture, Powertools version, and layer name.
21+
22+
Attributes:
23+
scope (Construct): The scope in which to define this construct.
24+
construct_id (str): The scoped construct ID. Must be unique amongst siblings in the same scope.
25+
python_version (lambda_.Runtime): The Python runtime version for the layer. Defaults to Python 3.12.
26+
include_extras (bool): Whether to include extra dependencies. Defaults to True.
27+
architecture (lambda_.Architecture): The compatible Lambda architecture. Defaults to x86_64.
28+
powertools_version (str): The version of Powertools to use. If empty, uses the latest version.
29+
layer_name (str): Custom name for the Lambda Layer. If empty, a default name will be used.
30+
31+
Example:
32+
>>> app = cdk.App()
33+
>>> LambdaPowertoolsLayerPythonV3(app, "PowertoolsLayer",
34+
... python_version=lambda_.Runtime.PYTHON_3_11,
35+
... include_extras=False,
36+
... architecture=lambda_.Architecture.ARM_64,
37+
... powertools_version="2.10.0",
38+
... layer_name="MyCustomPowertoolsLayer")
39+
40+
"""
41+
42+
def __init__(
43+
self,
44+
scope: Construct,
45+
construct_id: str,
46+
python_version: lambda_.Runtime = lambda_.Runtime.PYTHON_3_12,
47+
include_extras: bool = True,
48+
architecture: lambda_.Architecture = lambda_.Architecture.X86_64,
49+
powertools_version: str = "",
50+
layer_name: str = "",
51+
) -> None:
52+
53+
docker_file_path = str(Path(__file__).parent.parent / "docker")
54+
55+
python_normalized_version: str = python_version.to_string().replace("python", "")
56+
57+
if architecture.to_string() == "x86_64":
58+
docker_architecture: str = "linux/amd64"
59+
else:
60+
docker_architecture: str = "linux/arm64"
61+
62+
super().__init__(
63+
scope,
64+
construct_id,
65+
code=lambda_.Code.from_docker_build(
66+
docker_file_path,
67+
build_args={
68+
"PACKAGE_SUFFIX": construct_build_args(
69+
include_extras,
70+
powertools_version,
71+
),
72+
"PYTHON_VERSION": python_normalized_version,
73+
},
74+
platform=docker_architecture,
75+
),
76+
layer_version_name=layer_name,
77+
license="MIT-0",
78+
compatible_runtimes=[python_version],
79+
description=f"Powertools for AWS Lambda (Python) V3 [{architecture.to_string()} - Python {python_normalized_version}]" # noqa E501
80+
+ (" with extra dependencies" if include_extras else "")
81+
+ (f" version {powertools_version}" if powertools_version else " latest version"),
82+
compatible_architectures=[architecture] if architecture else None,
83+
)

layer_v3/layer_constructors/tests/__init__.py

Whitespace-only changes.

layer_v3/layer_constructors/tests/unit/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)