Skip to content

Commit

Permalink
feat(layers): introduce new CDK Python constructor for Powertools Lam…
Browse files Browse the repository at this point in the history
…bda Layer (#5320)

* New Python constructor for layers

* Improving docs
  • Loading branch information
leandrodamascena authored Nov 8, 2024
1 parent e8d4859 commit 1d58023
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 83 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/quality_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ on:
- "mypy.ini"
branches:
- develop
- v3
push:
paths:
- "aws_lambda_powertools/**"
Expand All @@ -37,7 +36,6 @@ on:
- "mypy.ini"
branches:
- develop
- v3

permissions:
contents: read
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/quality_code_cdk_constructor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Code quality - CDK constructor

# PROCESS
#
# 1. Install all dependencies and spin off containers for all supported Python versions
# 2. Run code formatters and linters (various checks) for code standard
# 3. Run static typing checker for potential bugs
# 4. Run tests

# USAGE
#
# Always triggered on new PRs, PR changes and PR merge.


on:
pull_request:
paths:
- "layer/layer_constructors/**"
branches:
- develop
push:
paths:
- "layer/layer_constructors/**"
branches:
- develop

permissions:
contents: read

jobs:
quality_check:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
env:
PYTHON: "${{ matrix.python-version }}"
permissions:
contents: read # checkout code only
defaults:
run:
working-directory: ./layer_v3/layer_constructors
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- name: Install poetry
run: pipx install poetry
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: ${{ matrix.python-version }}
cache: "poetry"
- name: Set up QEMU
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.0.0
with:
platforms: arm64
# NOTE: we need QEMU to build Layer against a different architecture (e.g., ARM)
- name: Set up Docker Buildx
id: builder
uses: docker/setup-buildx-action@f03ac48505955848960e80bbb68046aa35c7b9e7 # v2.4.1
with:
install: true
driver: docker
platforms: linux/amd64,linux/arm64
- name: Install dependencies
run: |
pip install --upgrade pip pre-commit poetry
poetry install
- name: Test with pytest
run: poetry run pytest tests
Empty file added layer_v3/__init__.py
Empty file.
9 changes: 5 additions & 4 deletions layer_v3/layer/layer_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
)
from aws_cdk.aws_lambda import Architecture, CfnLayerVersionPermission, Runtime
from aws_cdk.aws_ssm import StringParameter
from cdk_aws_lambda_powertools_layer import LambdaPowertoolsLayerPythonV3
from constructs import Construct

from layer_v3.layer_constructors.layer_stack import LambdaPowertoolsLayerPythonV3


@jsii.implements(IAspect)
class ApplyCondition:
Expand Down Expand Up @@ -46,11 +47,11 @@ def __init__(
layer = LambdaPowertoolsLayerPythonV3(
self,
"Layer",
layer_version_name=layer_version_name,
version=powertools_version,
layer_name=layer_version_name,
powertools_version=powertools_version,
python_version=python_version,
include_extras=True,
compatible_architectures=[architecture] if architecture else [],
architecture=architecture or Architecture.X86_64,
)
layer.apply_removal_policy(RemovalPolicy.RETAIN)

Expand Down
Empty file.
45 changes: 45 additions & 0 deletions layer_v3/layer_constructors/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from __future__ import annotations


def construct_build_args(include_extras: bool = True, version: str | None = None) -> str:
"""
This function creates a suffix string for the Powertools package based on
whether extra dependencies should be included and a specific version is required.
Params
------
include_extras: bool | None:
If True, include all extra dependencies in Powertools package
version: str | None
The version of Powertools to install. Can be a version number or a git reference.
Returns
-------
str
A string suffix to be appended to the Powertools package name during installation.
Examples:
- "" (empty string) if no extras or version specified
- "[all]" if include_extras is True
- "==1.2.3" if version is "1.2.3"
- "[all]==1.2.3" if include_extras is True and version is "1.2.3"
- " @ git+https://github.com/..." if version starts with "git"
Example
-------
>>> construct_build_args(True, "1.2.3")
'[all]==1.2.3'
>>> construct_build_args(False, "git+https://github.com/...")
' @ git+https://github.com/...'
"""

suffix = ""

if include_extras:
suffix = "[all]"
if version:
if version.startswith("git"):
suffix = f"{suffix} @ {version}"
else:
suffix = f"{suffix}=={version}"

return suffix
83 changes: 83 additions & 0 deletions layer_v3/layer_constructors/layer_stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from aws_cdk import aws_lambda as lambda_

if TYPE_CHECKING:
from constructs import Construct

from layer_v3.layer_constructors.helpers import construct_build_args


class LambdaPowertoolsLayerPythonV3(lambda_.LayerVersion):
"""
A CDK Stack that creates a Lambda Layer for Powertools for AWS Lambda (Python) V3.
This stack creates a Lambda Layer containing the Powertools for AWS Lambda (Python) V3 library.
It allows customization of the Python runtime version, inclusion of extra dependencies,
architecture, Powertools version, and layer name.
Attributes:
scope (Construct): The scope in which to define this construct.
construct_id (str): The scoped construct ID. Must be unique amongst siblings in the same scope.
python_version (lambda_.Runtime): The Python runtime version for the layer. Defaults to Python 3.12.
include_extras (bool): Whether to include extra dependencies. Defaults to True.
architecture (lambda_.Architecture): The compatible Lambda architecture. Defaults to x86_64.
powertools_version (str): The version of Powertools to use. If empty, uses the latest version.
layer_name (str): Custom name for the Lambda Layer. If empty, a default name will be used.
Example:
>>> app = cdk.App()
>>> LambdaPowertoolsLayerPythonV3(app, "PowertoolsLayer",
... python_version=lambda_.Runtime.PYTHON_3_11,
... include_extras=False,
... architecture=lambda_.Architecture.ARM_64,
... powertools_version="2.10.0",
... layer_name="MyCustomPowertoolsLayer")
"""

def __init__(
self,
scope: Construct,
construct_id: str,
python_version: lambda_.Runtime = lambda_.Runtime.PYTHON_3_12,
include_extras: bool = True,
architecture: lambda_.Architecture = lambda_.Architecture.X86_64,
powertools_version: str = "",
layer_name: str = "",
) -> None:

docker_file_path = str(Path(__file__).parent.parent / "docker")

python_normalized_version: str = python_version.to_string().replace("python", "")

if architecture.to_string() == "x86_64":
docker_architecture: str = "linux/amd64"
else:
docker_architecture: str = "linux/arm64"

super().__init__(
scope,
construct_id,
code=lambda_.Code.from_docker_build(
docker_file_path,
build_args={
"PACKAGE_SUFFIX": construct_build_args(
include_extras,
powertools_version,
),
"PYTHON_VERSION": python_normalized_version,
},
platform=docker_architecture,
),
layer_version_name=layer_name,
license="MIT-0",
compatible_runtimes=[python_version],
description=f"Powertools for AWS Lambda (Python) V3 [{architecture.to_string()} - Python {python_normalized_version}]" # noqa E501
+ (" with extra dependencies" if include_extras else "")
+ (f" version {powertools_version}" if powertools_version else " latest version"),
compatible_architectures=[architecture] if architecture else None,
)
Empty file.
Empty file.
Loading

0 comments on commit 1d58023

Please sign in to comment.