Skip to content
This repository was archived by the owner on Apr 5, 2025. It is now read-only.

Commit aca4b72

Browse files
feat(python)!: add v2 layer and drop python 3.6 support (#4)
Co-authored-by: Heitor Lessa <[email protected]>
1 parent 2abc1ee commit aca4b72

9 files changed

+103
-44
lines changed

.projen/deps.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.projenrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const project = new awscdk.AwsCdkConstructLibrary({
44
authorUrl: 'https://aws.amazon.com',
55
authorOrganization: true,
66
keywords: ['aws', 'cdk', 'powertools', 'python', 'layer', 'lambda', 'devax', 'typescript', 'nodejs'],
7-
cdkVersion: '2.24.1',
7+
cdkVersion: '2.44.0',
88
defaultReleaseBranch: 'main',
99
majorVersion: 2,
1010
name: 'cdk-aws-lambda-powertools-layer',

API.md

Lines changed: 15 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

layer/Python/Dockerfile

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
FROM public.ecr.aws/lambda/python:3.8
22

3-
4-
53
ARG PACKAGE_SUFFIX=''
64

75
USER root
86
WORKDIR /tmp
97

10-
11-
# PACKAGE_SUFFIX = '[pydantic]==1.23.0'
12-
# PACKAGE_SUFFIX = '[pydantic]'
13-
# PACKAGE_SUFFIX = '=='1.23.0'
8+
# PACKAGE_SUFFIX = '[all]==2.0.0'
9+
# PACKAGE_SUFFIX = '[all]'
10+
# PACKAGE_SUFFIX = '=='2.0.0'
1411
# PACKAGE_SUFFIX = ''
1512

16-
17-
RUN yum update -y && yum install -y zip unzip wget tar gzip
18-
19-
RUN pip install -t /asset/python aws-lambda-powertools$PACKAGE_SUFFIX
13+
RUN yum update -y && yum install -y zip unzip wget tar gzip binutils
14+
15+
RUN pip install -t /asset/python aws-lambda-powertools$PACKAGE_SUFFIX
16+
17+
# Removing nonessential files
18+
RUN cd /asset && \
19+
# remove boto3 and botocore (already available in Lambda Runtime)
20+
rm -rf python/boto* && \
21+
# remove boto3 dependencies
22+
rm -rf python/s3transfer* python/*dateutil* python/urllib3* python/six* && \
23+
# remove debugging symbols
24+
find python -name '*.so' -type f -exec strip "{}" \; && \
25+
# remove tests
26+
find python -wholename "*/tests/*" -type f -delete && \
27+
# remove python bytecode
28+
find python -regex '^.*\(__pycache__\|\.py[co]\)$' -delete

package.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lambda-powertools-layer.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as path from 'path';
22
import { aws_lambda as lambda } from 'aws-cdk-lib';
3+
import { Architecture } from 'aws-cdk-lib/aws-lambda';
34
import { Construct } from 'constructs';
45

56
/**
@@ -10,8 +11,9 @@ export interface PowertoolsLayerProps {
1011
* The powertools package version from pypi repository.
1112
*/
1213
readonly version?: string;
14+
1315
/**
14-
* A flag for the pydantic extras dependency, used for parsing.
16+
* A flag for the extras dependencies (pydantic, aws-xray-sdk, etc.)
1517
* This will increase the size of the layer significantly. If you don't use parsing, ignore it.
1618
*/
1719
readonly includeExtras?: boolean;
@@ -25,6 +27,11 @@ export interface PowertoolsLayerProps {
2527
* the runtime of the layer
2628
*/
2729
readonly runtimeFamily?: lambda.RuntimeFamily;
30+
31+
/**
32+
* The compatible architectures for the layer
33+
*/
34+
readonly compatibleArchitectures?: lambda.Architecture[];
2835
}
2936

3037
/**
@@ -36,7 +43,7 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
3643
* There are multiple combinations between version and extras package that results in different suffix for the installation.
3744
* With and without version, with and without extras flag.
3845
* We construct one suffix here because it is easier to do in code than inside the Dockerfile with bash commands.
39-
* For example, if we set extras=true and version=1.22.0 we get '[pydantic]==1.22.0'.
46+
* For example, if we set `includeExtras=true` and `version=1.22.0` we get '[all]==1.22.0'.
4047
*
4148
*/
4249
static constructBuildArgs(
@@ -48,7 +55,7 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
4855
switch (runtimeFamily) {
4956
case lambda.RuntimeFamily.PYTHON:
5057
if (includeExtras) {
51-
suffix = '[pydantic]';
58+
suffix = '[all]';
5259
}
5360
if (version) {
5461
suffix = `${suffix}==${version}`;
@@ -69,6 +76,9 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
6976
const runtimeFamily = props?.runtimeFamily ?? lambda.RuntimeFamily.PYTHON;
7077
const languageName = getLanguageNameFromRuntimeFamily(runtimeFamily);
7178
const dockerFilePath = path.join(__dirname, `../layer/${languageName}`);
79+
const compatibleArchitectures = props?.compatibleArchitectures ?? [lambda.Architecture.X86_64];
80+
const compatibleArchitecturesDescription = compatibleArchitectures.map((arch) => arch.name).join(', ');
81+
7282
console.log(`path ${dockerFilePath}`);
7383
super(scope, id, {
7484
code: lambda.Code.fromDockerBuild(dockerFilePath, {
@@ -79,12 +89,15 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
7989
props?.version,
8090
),
8191
},
92+
// supports cross-platform docker build
93+
platform: getDockerPlatformNameFromArchitectures(compatibleArchitectures),
8294
}),
8395
layerVersionName: props?.layerVersionName ? props?.layerVersionName : undefined,
8496
license: 'MIT-0',
8597
compatibleRuntimes: getRuntimesFromRuntimeFamily(runtimeFamily),
86-
description: `Lambda Powertools for ${languageName}${
87-
props?.includeExtras ? ' with Pydantic' : ''
98+
compatibleArchitectures,
99+
description: `Lambda Powertools for ${languageName} [${compatibleArchitecturesDescription}]${
100+
props?.includeExtras ? ' with extra dependencies' : ''
88101
} ${props?.version ? `version ${props?.version}` : 'latest version'}`.trim(),
89102
});
90103
}
@@ -94,7 +107,6 @@ function getRuntimesFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily): lamb
94107
switch (runtimeFamily) {
95108
case lambda.RuntimeFamily.PYTHON:
96109
return [
97-
lambda.Runtime.PYTHON_3_6,
98110
lambda.Runtime.PYTHON_3_7,
99111
lambda.Runtime.PYTHON_3_8,
100112
lambda.Runtime.PYTHON_3_9,
@@ -120,3 +132,16 @@ function getLanguageNameFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily):
120132
return 'Unknown';
121133
}
122134
}
135+
136+
// Docker expects a single string for the --platform option.
137+
// getDockerPlatformNameFromArchitectures converts the Architecture enum to a string.
138+
function getDockerPlatformNameFromArchitectures(architectures: lambda.Architecture[]): string {
139+
if (architectures.length == 1) {
140+
return architectures[0].dockerPlatform;
141+
} else {
142+
// if we have multiple architectures, we default to x86_64, hoping for the
143+
// layer not to have any architecture specific code or at least contain
144+
// binary code for all architectures
145+
return Architecture.X86_64.dockerPlatform;
146+
}
147+
}

test/lambda-powertools-python-layer.test.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Stack } from 'aws-cdk-lib';
22
import { Template } from 'aws-cdk-lib/assertions';
3-
import { RuntimeFamily } from 'aws-cdk-lib/aws-lambda';
3+
import { Architecture, RuntimeFamily } from 'aws-cdk-lib/aws-lambda';
44
import { LambdaPowertoolsLayer } from '../src';
55

66

@@ -10,7 +10,7 @@ describe('with no configuration the construct', () => {
1010
const template = Template.fromStack(stack);
1111
test('synthesizes successfully', () => {
1212
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
13-
Description: 'Lambda Powertools for Python latest version',
13+
Description: 'Lambda Powertools for Python [x86_64] latest version',
1414
});
1515
});
1616

@@ -23,7 +23,6 @@ describe('with no configuration the construct', () => {
2323
test('matches the python 3.x runtimes', () => {
2424
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
2525
CompatibleRuntimes: [
26-
'python3.6',
2726
'python3.7',
2827
'python3.8',
2928
'python3.9',
@@ -32,6 +31,21 @@ describe('with no configuration the construct', () => {
3231
});
3332
});
3433

34+
describe('with arm64 architecture', () => {
35+
const stack = new Stack();
36+
new LambdaPowertoolsLayer(stack, 'PowertoolsLayer', {
37+
runtimeFamily: RuntimeFamily.PYTHON,
38+
compatibleArchitectures: [Architecture.ARM_64],
39+
});
40+
const template = Template.fromStack(stack);
41+
test('synthesizes successfully', () => {
42+
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
43+
Description: 'Lambda Powertools for Python [arm64] latest version',
44+
CompatibleArchitectures: ['arm64'],
45+
});
46+
});
47+
});
48+
3549
describe('for layerVersionName configuraiton the construct', () => {
3650
test('synthisizes to a layer with provided name', () => {
3751
const stack = new Stack();
@@ -54,7 +68,7 @@ describe('with version configuration the construct', () => {
5468

5569

5670
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
57-
Description: 'Lambda Powertools for Python version 1.21.0',
71+
Description: 'Lambda Powertools for Python [x86_64] version 1.21.0',
5872
});
5973
});
6074

@@ -73,34 +87,34 @@ describe('with version configuration the construct', () => {
7387
});
7488

7589
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
76-
Description: 'Lambda Powertools for Python with Pydantic version 1.22.0',
90+
Description: 'Lambda Powertools for Python [x86_64] with extra dependencies version 1.22.0',
7791
});
7892

7993
});
8094

81-
test('synthesizes with pyndatic and latest version', () => {
95+
test('synthesizes with extras and latest version', () => {
8296
const stack = new Stack();
8397
new LambdaPowertoolsLayer(stack, 'LayerExtrasNoVersion', {
8498
includeExtras: true,
8599
});
86100

87101
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
88-
Description: 'Lambda Powertools for Python with Pydantic latest version',
102+
Description: 'Lambda Powertools for Python [x86_64] with extra dependencies latest version',
89103
});
90104
});
91105
});
92106

93107
describe('construct build args for Dockerfile', () => {
94-
test('returns pydantic and version', () => {
108+
test('returns extras and version', () => {
95109
const args = LambdaPowertoolsLayer.constructBuildArgs(RuntimeFamily.PYTHON, true, '1.21.0');
96110

97-
expect(args).toEqual('[pydantic]==1.21.0');
111+
expect(args).toEqual('[all]==1.21.0');
98112
});
99113

100-
test('returns only pydantic when no version provided', () => {
114+
test('returns only extras when no version provided', () => {
101115
const args = LambdaPowertoolsLayer.constructBuildArgs(RuntimeFamily.PYTHON, true, undefined);
102116

103-
expect(args).toEqual('[pydantic]');
117+
expect(args).toEqual('[all]');
104118
});
105119

106120
test('returns only version when no extras flag provided', () => {

test/lambda-powertools-typescript-layer.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('with minimal configuration the construct', () => {
1212
const template = Template.fromStack(stack);
1313
test('synthesizes successfully', () => {
1414
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
15-
Description: 'Lambda Powertools for TypeScript latest version',
15+
Description: 'Lambda Powertools for TypeScript [x86_64] latest version',
1616
});
1717
});
1818

@@ -57,7 +57,7 @@ describe('with version configuration the construct', () => {
5757

5858

5959
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
60-
Description: `Lambda Powertools for TypeScript version ${version}`,
60+
Description: `Lambda Powertools for TypeScript [x86_64] version ${version}`,
6161
});
6262
});
6363

yarn.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)