forked from aws-powertools/powertools-lambda-layer-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlambda-powertools-layer.ts
147 lines (136 loc) · 4.82 KB
/
lambda-powertools-layer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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';
/**
* Properties for Powertools layer for python.
*/
export interface PowertoolsLayerProps {
/**
* The powertools package version from pypi repository.
*/
readonly version?: string;
/**
* 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;
/**
* the name of the layer, will be randomised if empty
*/
readonly layerVersionName?: string;
/**
* the runtime of the layer
*/
readonly runtimeFamily?: lambda.RuntimeFamily;
/**
* The compatible architectures for the layer
*/
readonly compatibleArchitectures?: lambda.Architecture[];
}
/**
* Defines a new Lambda Layer with Powertools for python library.
*/
export class LambdaPowertoolsLayer extends lambda.LayerVersion {
/**
* creates build argument for the Dockerfile.
* 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 `includeExtras=true` and `version=1.22.0` we get '[all]==1.22.0'.
*
*/
static constructBuildArgs(
runtimeFamily: lambda.RuntimeFamily,
includeExtras: boolean | undefined,
version: string | undefined,
): string {
let suffix = '';
switch (runtimeFamily) {
case lambda.RuntimeFamily.PYTHON:
if (includeExtras) {
suffix = '[all]';
}
if (version) {
suffix = `${suffix}==${version}`;
}
break;
case lambda.RuntimeFamily.NODEJS:
if (version) {
suffix = `@${version}`;
}
break;
default:
break;
}
return suffix;
}
constructor(scope: Construct, id: string, props?: PowertoolsLayerProps) {
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, {
buildArgs: {
PACKAGE_SUFFIX: LambdaPowertoolsLayer.constructBuildArgs(
runtimeFamily,
props?.includeExtras,
props?.version,
),
},
// supports cross-platform docker build
platform: getDockerPlatformNameFromArchitectures(compatibleArchitectures),
}),
layerVersionName: props?.layerVersionName ? props?.layerVersionName : undefined,
license: 'MIT-0',
compatibleRuntimes: getRuntimesFromRuntimeFamily(runtimeFamily),
compatibleArchitectures,
description: `Lambda Powertools for ${languageName} [${compatibleArchitecturesDescription}]${
props?.includeExtras ? ' with extra dependencies' : ''
} ${props?.version ? `version ${props?.version}` : 'latest version'}`.trim(),
});
}
}
function getRuntimesFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily): lambda.Runtime[] | undefined {
switch (runtimeFamily) {
case lambda.RuntimeFamily.PYTHON:
return [
lambda.Runtime.PYTHON_3_7,
lambda.Runtime.PYTHON_3_8,
lambda.Runtime.PYTHON_3_9,
];
case lambda.RuntimeFamily.NODEJS:
return [
lambda.Runtime.NODEJS_12_X,
lambda.Runtime.NODEJS_14_X,
lambda.Runtime.NODEJS_16_X,
];
default:
return [];
}
}
function getLanguageNameFromRuntimeFamily(runtimeFamily: lambda.RuntimeFamily): string {
switch (runtimeFamily) {
case lambda.RuntimeFamily.PYTHON:
return 'Python';
case lambda.RuntimeFamily.NODEJS:
return 'TypeScript';
default:
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;
}
}