Skip to content

Commit 55bca78

Browse files
authored
fix(lambda-nodejs): AWS SDK v2 is not available for node18.x runtime (#22989)
This PR set default of `externalModules` aws-sdk v3 when use greater than or equal nodejs v18 runtime, because [Lambda runtime nodejs v18 includes aws-sdk v3](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#:~:text=Node.js%2018,3.188.0). fix #22976 ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent e53352d commit 55bca78

18 files changed

+1955
-39
lines changed

packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class Bundling implements cdk.BundlingOptions {
113113
}
114114

115115
this.externals = [
116-
...props.externalModules ?? ['aws-sdk'], // Mark aws-sdk as external by default (available in the runtime)
116+
...props.externalModules ?? (isSdkV2Runtime(props.runtime) ? ['aws-sdk'] : ['@aws-sdk/*']), // Mark aws-sdk as external by default (available in the runtime)
117117
...props.nodeModules ?? [], // Mark the modules that we are going to install as externals also
118118
];
119119

@@ -367,3 +367,17 @@ function toCliArgs(esbuildArgs: { [key: string]: string | boolean }): string {
367367

368368
return args.join(' ');
369369
}
370+
371+
function isSdkV2Runtime(runtime: Runtime): boolean {
372+
const sdkV2RuntimeList = [
373+
Runtime.NODEJS,
374+
Runtime.NODEJS_4_3,
375+
Runtime.NODEJS_6_10,
376+
Runtime.NODEJS_8_10,
377+
Runtime.NODEJS_10_X,
378+
Runtime.NODEJS_12_X,
379+
Runtime.NODEJS_14_X,
380+
Runtime.NODEJS_16_X,
381+
];
382+
return sdkV2RuntimeList.includes(runtime);
383+
}

packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export interface BundlingOptions {
183183
* A list of modules that should be considered as externals (already available
184184
* in the runtime).
185185
*
186-
* @default ['aws-sdk']
186+
* @default - ['aws-sdk'] if the runtime is < Node.js 18.x, ['@aws-sdk/*'] otherwise.
187187
*/
188188
readonly externalModules?: string[];
189189

packages/@aws-cdk/aws-lambda-nodejs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"@aws-cdk/aws-ec2": "0.0.0",
7777
"@aws-cdk/cdk-build-tools": "0.0.0",
7878
"@aws-cdk/integ-runner": "0.0.0",
79+
"@aws-cdk/integ-tests": "0.0.0",
7980
"@aws-cdk/pkglint": "0.0.0",
8081
"@types/jest": "^27.5.2",
8182
"delay": "5.0.0",

packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,27 @@ test('esbuild bundling source map default', () => {
282282
});
283283
});
284284

285+
test('esbuild bundling without aws-sdk v3 when use greater than or equal Runtime.NODEJS_18_X', () => {
286+
Bundling.bundle({
287+
entry,
288+
projectRoot,
289+
depsLockFilePath,
290+
runtime: Runtime.NODEJS_18_X,
291+
architecture: Architecture.X86_64,
292+
});
293+
294+
// Correctly bundles with esbuild
295+
expect(Code.fromAsset).toHaveBeenCalledWith(path.dirname(depsLockFilePath), {
296+
assetHashType: AssetHashType.OUTPUT,
297+
bundling: expect.objectContaining({
298+
command: [
299+
'bash', '-c',
300+
'esbuild --bundle "/asset-input/lib/handler.ts" --target=node18 --platform=node --outfile="/asset-output/index.js" --external:@aws-sdk/*',
301+
],
302+
}),
303+
});
304+
});
305+
285306
test('esbuild bundling source map inline', () => {
286307
Bundling.bundle({
287308
entry,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable no-console */
2+
// @ts-ignore
3+
import { S3Client } from '@aws-sdk/client-s3'; // eslint-disable-line import/no-extraneous-dependencies, import/no-unresolved
4+
5+
const s3 = new S3Client();
6+
7+
export async function handler() {
8+
console.log(s3);
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"version": "21.0.0",
3+
"files": {
4+
"b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b": {
5+
"source": {
6+
"path": "asset.b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.bundle",
7+
"packaging": "zip"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.zip",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
},
17+
"4efc8f1a2c0b0f1f18d1cb27a1d752a4cd6b71b6676f0ee88ebdab71a7bdaffc": {
18+
"source": {
19+
"path": "LambdaDependenciesDefaultTestDeployAssert259C940B.template.json",
20+
"packaging": "file"
21+
},
22+
"destinations": {
23+
"current_account-current_region": {
24+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
25+
"objectKey": "4efc8f1a2c0b0f1f18d1cb27a1d752a4cd6b71b6676f0ee88ebdab71a7bdaffc.json",
26+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
27+
}
28+
}
29+
}
30+
},
31+
"dockerImages": {}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
{
2+
"Resources": {
3+
"LambdaInvoke5050b1f640cc49956b59f2a71febe95c": {
4+
"Type": "Custom::DeployAssert@SdkCallLambdainvoke",
5+
"Properties": {
6+
"ServiceToken": {
7+
"Fn::GetAtt": [
8+
"SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F",
9+
"Arn"
10+
]
11+
},
12+
"service": "Lambda",
13+
"api": "invoke",
14+
"expected": "{\"$ObjectLike\":{\"Payload\":\"null\"}}",
15+
"parameters": {
16+
"FunctionName": {
17+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies:ExportsOutputRefexternal068F12D12C72A375"
18+
}
19+
},
20+
"flattenResponse": "false",
21+
"salt": "1669400129606"
22+
},
23+
"UpdateReplacePolicy": "Delete",
24+
"DeletionPolicy": "Delete"
25+
},
26+
"LambdaInvoke5050b1f640cc49956b59f2a71febe95cInvokeB4FBC029": {
27+
"Type": "AWS::Lambda::Permission",
28+
"Properties": {
29+
"Action": "lambda:InvokeFunction",
30+
"FunctionName": {
31+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies:ExportsOutputRefexternal068F12D12C72A375"
32+
},
33+
"Principal": {
34+
"Fn::GetAtt": [
35+
"SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73",
36+
"Arn"
37+
]
38+
}
39+
}
40+
},
41+
"SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": {
42+
"Type": "AWS::IAM::Role",
43+
"Properties": {
44+
"AssumeRolePolicyDocument": {
45+
"Version": "2012-10-17",
46+
"Statement": [
47+
{
48+
"Action": "sts:AssumeRole",
49+
"Effect": "Allow",
50+
"Principal": {
51+
"Service": "lambda.amazonaws.com"
52+
}
53+
}
54+
]
55+
},
56+
"ManagedPolicyArns": [
57+
{
58+
"Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
59+
}
60+
],
61+
"Policies": [
62+
{
63+
"PolicyName": "Inline",
64+
"PolicyDocument": {
65+
"Version": "2012-10-17",
66+
"Statement": [
67+
{
68+
"Action": [
69+
"lambda:Invoke"
70+
],
71+
"Effect": "Allow",
72+
"Resource": [
73+
"*"
74+
]
75+
},
76+
{
77+
"Action": [
78+
"lambda:InvokeFunction"
79+
],
80+
"Effect": "Allow",
81+
"Resource": [
82+
{
83+
"Fn::Join": [
84+
"",
85+
[
86+
"arn:",
87+
{
88+
"Ref": "AWS::Partition"
89+
},
90+
":lambda:",
91+
{
92+
"Ref": "AWS::Region"
93+
},
94+
":",
95+
{
96+
"Ref": "AWS::AccountId"
97+
},
98+
":function:",
99+
{
100+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies:ExportsOutputRefexternal068F12D12C72A375"
101+
}
102+
]
103+
]
104+
}
105+
]
106+
},
107+
{
108+
"Action": [
109+
"lambda:Invoke"
110+
],
111+
"Effect": "Allow",
112+
"Resource": [
113+
"*"
114+
]
115+
},
116+
{
117+
"Action": [
118+
"lambda:InvokeFunction"
119+
],
120+
"Effect": "Allow",
121+
"Resource": [
122+
{
123+
"Fn::Join": [
124+
"",
125+
[
126+
"arn:",
127+
{
128+
"Ref": "AWS::Partition"
129+
},
130+
":lambda:",
131+
{
132+
"Ref": "AWS::Region"
133+
},
134+
":",
135+
{
136+
"Ref": "AWS::AccountId"
137+
},
138+
":function:",
139+
{
140+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies-for-sdk-v3:ExportsOutputRefexternalsdkv3B69F9D996ACDF2E7"
141+
}
142+
]
143+
]
144+
}
145+
]
146+
}
147+
]
148+
}
149+
}
150+
]
151+
}
152+
},
153+
"SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": {
154+
"Type": "AWS::Lambda::Function",
155+
"Properties": {
156+
"Runtime": "nodejs14.x",
157+
"Code": {
158+
"S3Bucket": {
159+
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
160+
},
161+
"S3Key": "b54b99043c35bd080b9d9d1afce31e3541cf15b679799ba980ed40c837dcb03b.zip"
162+
},
163+
"Timeout": 120,
164+
"Handler": "index.handler",
165+
"Role": {
166+
"Fn::GetAtt": [
167+
"SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73",
168+
"Arn"
169+
]
170+
}
171+
}
172+
},
173+
"LambdaInvoke7d0602e4b9f40ae057f935d874b5f971": {
174+
"Type": "Custom::DeployAssert@SdkCallLambdainvoke",
175+
"Properties": {
176+
"ServiceToken": {
177+
"Fn::GetAtt": [
178+
"SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F",
179+
"Arn"
180+
]
181+
},
182+
"service": "Lambda",
183+
"api": "invoke",
184+
"expected": "{\"$ObjectLike\":{\"Payload\":\"null\"}}",
185+
"parameters": {
186+
"FunctionName": {
187+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies-for-sdk-v3:ExportsOutputRefexternalsdkv3B69F9D996ACDF2E7"
188+
}
189+
},
190+
"flattenResponse": "false",
191+
"salt": "1669400129608"
192+
},
193+
"UpdateReplacePolicy": "Delete",
194+
"DeletionPolicy": "Delete"
195+
},
196+
"LambdaInvoke7d0602e4b9f40ae057f935d874b5f971Invoke970717DE": {
197+
"Type": "AWS::Lambda::Permission",
198+
"Properties": {
199+
"Action": "lambda:InvokeFunction",
200+
"FunctionName": {
201+
"Fn::ImportValue": "cdk-integ-lambda-nodejs-dependencies-for-sdk-v3:ExportsOutputRefexternalsdkv3B69F9D996ACDF2E7"
202+
},
203+
"Principal": {
204+
"Fn::GetAtt": [
205+
"SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73",
206+
"Arn"
207+
]
208+
}
209+
}
210+
}
211+
},
212+
"Outputs": {
213+
"AssertionResultsLambdaInvoke5050b1f640cc49956b59f2a71febe95c": {
214+
"Value": {
215+
"Fn::GetAtt": [
216+
"LambdaInvoke5050b1f640cc49956b59f2a71febe95c",
217+
"assertion"
218+
]
219+
}
220+
},
221+
"AssertionResultsLambdaInvoke7d0602e4b9f40ae057f935d874b5f971": {
222+
"Value": {
223+
"Fn::GetAtt": [
224+
"LambdaInvoke7d0602e4b9f40ae057f935d874b5f971",
225+
"assertion"
226+
]
227+
}
228+
}
229+
},
230+
"Parameters": {
231+
"BootstrapVersion": {
232+
"Type": "AWS::SSM::Parameter::Value<String>",
233+
"Default": "/cdk-bootstrap/hnb659fds/version",
234+
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
235+
}
236+
},
237+
"Rules": {
238+
"CheckBootstrapVersion": {
239+
"Assertions": [
240+
{
241+
"Assert": {
242+
"Fn::Not": [
243+
{
244+
"Fn::Contains": [
245+
[
246+
"1",
247+
"2",
248+
"3",
249+
"4",
250+
"5"
251+
],
252+
{
253+
"Ref": "BootstrapVersion"
254+
}
255+
]
256+
}
257+
]
258+
},
259+
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
260+
}
261+
]
262+
}
263+
}
264+
}

0 commit comments

Comments
 (0)