diff --git a/.projen/deps.json b/.projen/deps.json
index e4c4705..fc3a24e 100644
--- a/.projen/deps.json
+++ b/.projen/deps.json
@@ -27,7 +27,7 @@
},
{
"name": "aws-cdk-lib",
- "version": "2.24.1",
+ "version": "2.44.0",
"type": "build"
},
{
@@ -107,7 +107,7 @@
},
{
"name": "aws-cdk-lib",
- "version": "^2.24.1",
+ "version": "^2.44.0",
"type": "peer"
},
{
diff --git a/.projenrc.js b/.projenrc.js
index 9606100..1a1f3a6 100644
--- a/.projenrc.js
+++ b/.projenrc.js
@@ -4,7 +4,7 @@ const project = new awscdk.AwsCdkConstructLibrary({
authorUrl: 'https://aws.amazon.com',
authorOrganization: true,
keywords: ['aws', 'cdk', 'powertools', 'python', 'layer', 'lambda', 'devax', 'typescript', 'nodejs'],
- cdkVersion: '2.24.1',
+ cdkVersion: '2.44.0',
defaultReleaseBranch: 'main',
majorVersion: 2,
name: 'cdk-aws-lambda-powertools-layer',
diff --git a/API.md b/API.md
index 503bf10..2e26260 100644
--- a/API.md
+++ b/API.md
@@ -95,13 +95,26 @@ const powertoolsLayerProps: PowertoolsLayerProps = { ... }
| **Name** | **Type** | **Description** |
| --- | --- | --- |
-| [`includeExtras`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertyincludeextras) | `boolean` | A flag for the pydantic extras dependency, used for parsing. |
+| [`compatibleArchitectures`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertycompatiblearchitectures) | [`aws-cdk-lib.aws_lambda.Architecture`](#aws-cdk-lib.aws_lambda.Architecture)[] | The compatible architectures for the layer. |
+| [`includeExtras`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertyincludeextras) | `boolean` | A flag for the extras dependencies (pydantic, aws-xray-sdk, etc.) This will increase the size of the layer significantly. If you don't use parsing, ignore it. |
| [`layerVersionName`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertylayerversionname) | `string` | the name of the layer, will be randomised if empty. |
| [`runtimeFamily`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertyruntimefamily) | [`aws-cdk-lib.aws_lambda.RuntimeFamily`](#aws-cdk-lib.aws_lambda.RuntimeFamily) | the runtime of the layer. |
| [`version`](#cdkawslambdapowertoolslayerpowertoolslayerpropspropertyversion) | `string` | The powertools package version from pypi repository. |
---
+##### `compatibleArchitectures`Optional
+
+```typescript
+public readonly compatibleArchitectures: Architecture[];
+```
+
+- *Type:* [`aws-cdk-lib.aws_lambda.Architecture`](#aws-cdk-lib.aws_lambda.Architecture)[]
+
+The compatible architectures for the layer.
+
+---
+
##### `includeExtras`Optional
```typescript
@@ -110,9 +123,7 @@ public readonly includeExtras: boolean;
- *Type:* `boolean`
-A flag for the pydantic extras dependency, used for parsing.
-
-This will increase the size of the layer significantly. If you don't use parsing, ignore it.
+A flag for the extras dependencies (pydantic, aws-xray-sdk, etc.) This will increase the size of the layer significantly. If you don't use parsing, ignore it.
---
diff --git a/layer/Python/Dockerfile b/layer/Python/Dockerfile
index f488f00..682c596 100644
--- a/layer/Python/Dockerfile
+++ b/layer/Python/Dockerfile
@@ -1,19 +1,28 @@
FROM public.ecr.aws/lambda/python:3.8
-
-
ARG PACKAGE_SUFFIX=''
USER root
WORKDIR /tmp
-
-# PACKAGE_SUFFIX = '[pydantic]==1.23.0'
-# PACKAGE_SUFFIX = '[pydantic]'
-# PACKAGE_SUFFIX = '=='1.23.0'
+# PACKAGE_SUFFIX = '[all]==2.0.0'
+# PACKAGE_SUFFIX = '[all]'
+# PACKAGE_SUFFIX = '=='2.0.0'
# PACKAGE_SUFFIX = ''
-
-RUN yum update -y && yum install -y zip unzip wget tar gzip
-
-RUN pip install -t /asset/python aws-lambda-powertools$PACKAGE_SUFFIX
\ No newline at end of file
+RUN yum update -y && yum install -y zip unzip wget tar gzip binutils
+
+RUN pip install -t /asset/python aws-lambda-powertools$PACKAGE_SUFFIX
+
+# Removing nonessential files
+RUN cd /asset && \
+ # remove boto3 and botocore (already available in Lambda Runtime)
+ rm -rf python/boto* && \
+ # remove boto3 dependencies
+ rm -rf python/s3transfer* python/*dateutil* python/urllib3* python/six* && \
+ # remove debugging symbols
+ find python -name '*.so' -type f -exec strip "{}" \; && \
+ # remove tests
+ find python -wholename "*/tests/*" -type f -delete && \
+ # remove python bytecode
+ find python -regex '^.*\(__pycache__\|\.py[co]\)$' -delete
\ No newline at end of file
diff --git a/package.json b/package.json
index b91aabc..9151d12 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,7 @@
"@types/prettier": "2.6.0",
"@typescript-eslint/eslint-plugin": "^5",
"@typescript-eslint/parser": "^5",
- "aws-cdk-lib": "2.24.1",
+ "aws-cdk-lib": "2.44.0",
"constructs": "10.0.5",
"eslint": "^8",
"eslint-import-resolver-node": "^0.3.6",
@@ -62,7 +62,7 @@
"typescript": "^4.8.2"
},
"peerDependencies": {
- "aws-cdk-lib": "^2.24.1",
+ "aws-cdk-lib": "^2.44.0",
"constructs": "^10.0.5"
},
"keywords": [
diff --git a/src/lambda-powertools-layer.ts b/src/lambda-powertools-layer.ts
index d9e362f..a7d060d 100644
--- a/src/lambda-powertools-layer.ts
+++ b/src/lambda-powertools-layer.ts
@@ -1,5 +1,6 @@
import * as path from 'path';
import { aws_lambda as lambda } from 'aws-cdk-lib';
+import { Architecture } from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
/**
@@ -10,8 +11,9 @@ export interface PowertoolsLayerProps {
* The powertools package version from pypi repository.
*/
readonly version?: string;
+
/**
- * A flag for the pydantic extras dependency, used for parsing.
+ * A flag for the extras dependencies (pydantic, aws-xray-sdk, etc.)
* This will increase the size of the layer significantly. If you don't use parsing, ignore it.
*/
readonly includeExtras?: boolean;
@@ -25,6 +27,11 @@ export interface PowertoolsLayerProps {
* the runtime of the layer
*/
readonly runtimeFamily?: lambda.RuntimeFamily;
+
+ /**
+ * The compatible architectures for the layer
+ */
+ readonly compatibleArchitectures?: lambda.Architecture[];
}
/**
@@ -36,7 +43,7 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
* There are multiple combinations between version and extras package that results in different suffix for the installation.
* With and without version, with and without extras flag.
* We construct one suffix here because it is easier to do in code than inside the Dockerfile with bash commands.
- * For example, if we set extras=true and version=1.22.0 we get '[pydantic]==1.22.0'.
+ * For example, if we set `includeExtras=true` and `version=1.22.0` we get '[all]==1.22.0'.
*
*/
static constructBuildArgs(
@@ -48,7 +55,7 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
switch (runtimeFamily) {
case lambda.RuntimeFamily.PYTHON:
if (includeExtras) {
- suffix = '[pydantic]';
+ suffix = '[all]';
}
if (version) {
suffix = `${suffix}==${version}`;
@@ -69,6 +76,9 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
const runtimeFamily = props?.runtimeFamily ?? lambda.RuntimeFamily.PYTHON;
const languageName = getLanguageNameFromRuntimeFamily(runtimeFamily);
const dockerFilePath = path.join(__dirname, `../layer/${languageName}`);
+ const compatibleArchitectures = props?.compatibleArchitectures ?? [lambda.Architecture.X86_64];
+ const compatibleArchitecturesDescription = compatibleArchitectures.map((arch) => arch.name).join(', ');
+
console.log(`path ${dockerFilePath}`);
super(scope, id, {
code: lambda.Code.fromDockerBuild(dockerFilePath, {
@@ -79,12 +89,15 @@ export class LambdaPowertoolsLayer extends lambda.LayerVersion {
props?.version,
),
},
+ // supports cross-platform docker build
+ platform: getDockerPlatformNameFromArchitectures(compatibleArchitectures),
}),
layerVersionName: props?.layerVersionName ? props?.layerVersionName : undefined,
license: 'MIT-0',
compatibleRuntimes: getRuntimesFromRuntimeFamily(runtimeFamily),
- description: `Lambda Powertools for ${languageName}${
- props?.includeExtras ? ' with Pydantic' : ''
+ compatibleArchitectures,
+ description: `Lambda Powertools for ${languageName} [${compatibleArchitecturesDescription}]${
+ props?.includeExtras ? ' with extra dependencies' : ''
} ${props?.version ? `version ${props?.version}` : 'latest version'}`.trim(),
});
}
@@ -94,7 +107,6 @@ function getRuntimesFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily): lamb
switch (runtimeFamily) {
case lambda.RuntimeFamily.PYTHON:
return [
- lambda.Runtime.PYTHON_3_6,
lambda.Runtime.PYTHON_3_7,
lambda.Runtime.PYTHON_3_8,
lambda.Runtime.PYTHON_3_9,
@@ -120,3 +132,16 @@ function getLanguageNameFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily):
return 'Unknown';
}
}
+
+// Docker expects a single string for the --platform option.
+// getDockerPlatformNameFromArchitectures converts the Architecture enum to a string.
+function getDockerPlatformNameFromArchitectures(architectures: lambda.Architecture[]): string {
+ if (architectures.length == 1) {
+ return architectures[0].dockerPlatform;
+ } else {
+ // if we have multiple architectures, we default to x86_64, hoping for the
+ // layer not to have any architecture specific code or at least contain
+ // binary code for all architectures
+ return Architecture.X86_64.dockerPlatform;
+ }
+}
\ No newline at end of file
diff --git a/test/lambda-powertools-python-layer.test.ts b/test/lambda-powertools-python-layer.test.ts
index 6ea4d04..b629098 100644
--- a/test/lambda-powertools-python-layer.test.ts
+++ b/test/lambda-powertools-python-layer.test.ts
@@ -1,6 +1,6 @@
import { Stack } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
-import { RuntimeFamily } from 'aws-cdk-lib/aws-lambda';
+import { Architecture, RuntimeFamily } from 'aws-cdk-lib/aws-lambda';
import { LambdaPowertoolsLayer } from '../src';
@@ -10,7 +10,7 @@ describe('with no configuration the construct', () => {
const template = Template.fromStack(stack);
test('synthesizes successfully', () => {
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: 'Lambda Powertools for Python latest version',
+ Description: 'Lambda Powertools for Python [x86_64] latest version',
});
});
@@ -23,7 +23,6 @@ describe('with no configuration the construct', () => {
test('matches the python 3.x runtimes', () => {
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
CompatibleRuntimes: [
- 'python3.6',
'python3.7',
'python3.8',
'python3.9',
@@ -32,6 +31,21 @@ describe('with no configuration the construct', () => {
});
});
+describe('with arm64 architecture', () => {
+ const stack = new Stack();
+ new LambdaPowertoolsLayer(stack, 'PowertoolsLayer', {
+ runtimeFamily: RuntimeFamily.PYTHON,
+ compatibleArchitectures: [Architecture.ARM_64],
+ });
+ const template = Template.fromStack(stack);
+ test('synthesizes successfully', () => {
+ template.hasResourceProperties('AWS::Lambda::LayerVersion', {
+ Description: 'Lambda Powertools for Python [arm64] latest version',
+ CompatibleArchitectures: ['arm64'],
+ });
+ });
+});
+
describe('for layerVersionName configuraiton the construct', () => {
test('synthisizes to a layer with provided name', () => {
const stack = new Stack();
@@ -54,7 +68,7 @@ describe('with version configuration the construct', () => {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: 'Lambda Powertools for Python version 1.21.0',
+ Description: 'Lambda Powertools for Python [x86_64] version 1.21.0',
});
});
@@ -73,34 +87,34 @@ describe('with version configuration the construct', () => {
});
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: 'Lambda Powertools for Python with Pydantic version 1.22.0',
+ Description: 'Lambda Powertools for Python [x86_64] with extra dependencies version 1.22.0',
});
});
- test('synthesizes with pyndatic and latest version', () => {
+ test('synthesizes with extras and latest version', () => {
const stack = new Stack();
new LambdaPowertoolsLayer(stack, 'LayerExtrasNoVersion', {
includeExtras: true,
});
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: 'Lambda Powertools for Python with Pydantic latest version',
+ Description: 'Lambda Powertools for Python [x86_64] with extra dependencies latest version',
});
});
});
describe('construct build args for Dockerfile', () => {
- test('returns pydantic and version', () => {
+ test('returns extras and version', () => {
const args = LambdaPowertoolsLayer.constructBuildArgs(RuntimeFamily.PYTHON, true, '1.21.0');
- expect(args).toEqual('[pydantic]==1.21.0');
+ expect(args).toEqual('[all]==1.21.0');
});
- test('returns only pydantic when no version provided', () => {
+ test('returns only extras when no version provided', () => {
const args = LambdaPowertoolsLayer.constructBuildArgs(RuntimeFamily.PYTHON, true, undefined);
- expect(args).toEqual('[pydantic]');
+ expect(args).toEqual('[all]');
});
test('returns only version when no extras flag provided', () => {
diff --git a/test/lambda-powertools-typescript-layer.test.ts b/test/lambda-powertools-typescript-layer.test.ts
index 7ce9c5b..1b3dfa3 100644
--- a/test/lambda-powertools-typescript-layer.test.ts
+++ b/test/lambda-powertools-typescript-layer.test.ts
@@ -12,7 +12,7 @@ describe('with minimal configuration the construct', () => {
const template = Template.fromStack(stack);
test('synthesizes successfully', () => {
template.hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: 'Lambda Powertools for TypeScript latest version',
+ Description: 'Lambda Powertools for TypeScript [x86_64] latest version',
});
});
@@ -57,7 +57,7 @@ describe('with version configuration the construct', () => {
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', {
- Description: `Lambda Powertools for TypeScript version ${version}`,
+ Description: `Lambda Powertools for TypeScript [x86_64] version ${version}`,
});
});
diff --git a/yarn.lock b/yarn.lock
index 6c775d4..4ab41d4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1220,16 +1220,16 @@ at-least-node@^1.0.0:
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
-aws-cdk-lib@2.24.1:
- version "2.24.1"
- resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.24.1.tgz#197d10216b384850c01205acc8e4818838964302"
- integrity sha512-xGeEX+9wPGppSiIUdf/JTLMmqMikGhlSi7bjijl3lwncZtySkdjX0j+W2A1fuKp0S8Yd2axkwVkltIMxzNH/gw==
+aws-cdk-lib@2.44.0:
+ version "2.44.0"
+ resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.44.0.tgz#e6157df7a72b8d1a4528f6fb9f9b0ed7aa404bcc"
+ integrity sha512-h0lCcS3t2TPF5FIpkA7OcE2t4vChtz/FGcZ5jVaORj21quiUz84eOhGk2BeRoKqfSp1Zqu2QxQUk6p6YpAOrRA==
dependencies:
"@balena/dockerignore" "^1.0.2"
case "1.6.3"
fs-extra "^9.1.0"
ignore "^5.2.0"
- jsonschema "^1.4.0"
+ jsonschema "^1.4.1"
minimatch "^3.1.2"
punycode "^2.1.1"
semver "^7.3.7"
@@ -3993,7 +3993,7 @@ jsonparse@^1.2.0, jsonparse@^1.3.1:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
-jsonschema@^1.4.0:
+jsonschema@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab"
integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==