Skip to content

Commit 5160796

Browse files
authored
fix: do not skip bundling for stacks during CDK Import, otherwise fails (#33322)
### Issues #31999 #31677 Closes #31999 #31677 ### Reason for this change `cdk import` reports changes in the stack when none are present, for NodeJS Lambda functions. This results in the command failing. The only way to work around this is to use the --force flag, which replaces stack resources. This is not ideal as it overwrites existing resources that may contain data, and is just generally unnecessary. ### Description of changes I added `cdk import` to a configuration that determines which CLI commands bundle code. Before this change, `cdk import` skipped code bundling. This is fine for regular Lambda functions that don't rely on bundling. However, NodeJSFunction does. The original implementation of skipping bundling for certain CLI commands was introduced via Issue #9540. `cdk import` was introduced two years later in PR #17666. ### Describe any new or updated permissions being added No permissions changes. ### Description of how you validated changes I added an integration test in `packages/@aws-cdk-testing/framework-integ/test/aws-lambda-nodejs/test/integ.nodejs.build.images.ts`. <img width="757" alt="Screenshot 2025-02-06 at 17 10 41" src="https://github.com/user-attachments/assets/f7b3939f-240c-4021-b0ad-fd7e423e7c09" /> The test ensures that NodeJSFunction Lambdas are always bundled. I will add a canary in a follow-up PR to ensure that new CLI commands are explicitly determined to either need or not need bundling. I manually validated changes: 1. Created an S3 bucket: `iankhou-1738867338384` 2. Ran `cdk synth`, `cdk deploy` on a stack with a NodeJSFunction, and without an S3 bucket 3. Added code that initializes an S3 bucket and ran `cdk import` Output and console: <img width="745" alt="Screenshot 2025-02-06 at 13 45 52" src="https://github.com/user-attachments/assets/c5e4b9ef-ae84-46a4-9b37-a1f58532a00e" /> <img width="1015" alt="Screenshot 2025-02-06 at 13 45 08" src="https://github.com/user-attachments/assets/10298665-281c-4fed-a32b-5c4fbb917f92" /> ### Checklist - [X] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent ba485ef commit 5160796

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-lambda-nodejs/test/integ.nodejs.build.images.ts

+42-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import * as path from 'path';
2-
import { App, Stack, StackProps } from 'aws-cdk-lib';
2+
import * as fs from 'fs';
3+
import { App, Stack, StackProps, ValidationError } from 'aws-cdk-lib';
34
import { Construct } from 'constructs';
4-
import * as lambda from 'aws-cdk-lib/aws-lambda-nodejs';
5+
import * as lambda from 'aws-cdk-lib/aws-lambda';
6+
import * as lambdaNodeJs from 'aws-cdk-lib/aws-lambda-nodejs';
57
import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests-alpha';
68
import { IFunction, Runtime } from 'aws-cdk-lib/aws-lambda';
79

@@ -18,13 +20,13 @@ class TestStack extends Stack {
1820
const uniqueRuntimes: Runtime[] = runtimes.filter((value, index, array) => array.findIndex(value1 => value1.runtimeEquals(value)) === index);
1921

2022
uniqueRuntimes.forEach((runtime) => {
21-
this.lambdaFunctions.push(new lambda.NodejsFunction(this, `func-${runtime.name}`, {
23+
this.lambdaFunctions.push(new lambdaNodeJs.NodejsFunction(this, `func-${runtime.name}`, {
2224
entry: path.join(__dirname, 'integ-handlers/dependencies.ts'),
2325
runtime: runtime,
2426
bundling: {
2527
minify: true,
2628
sourceMap: true,
27-
sourceMapMode: lambda.SourceMapMode.BOTH,
29+
sourceMapMode: lambdaNodeJs.SourceMapMode.BOTH,
2830
},
2931
}));
3032
});
@@ -49,3 +51,39 @@ stack.lambdaFunctions.forEach(func=> {
4951
ExecutedVersion: '$LATEST',
5052
}));
5153
});
54+
55+
// Ensure that the code is bundled
56+
const assembly = app.synth();
57+
58+
stack.lambdaFunctions.forEach((func) => {
59+
const template = assembly.getStackArtifact(stack.artifactId).template;
60+
const resourceName = stack.getLogicalId(func.node.defaultChild as lambda.CfnFunction);
61+
const resource = template.Resources[resourceName];
62+
63+
if (!resource || resource.Type !== 'AWS::Lambda::Function') {
64+
throw new ValidationError(`Could not find Lambda function resource for ${func.functionName}`, stack);
65+
}
66+
67+
const s3Bucket = resource.Properties.Code.S3Bucket;
68+
const s3Key = resource.Properties.Code.S3Key;
69+
70+
if (!s3Bucket || !s3Key) {
71+
throw new ValidationError(`Could not find S3 location for function ${func.functionName}`, stack);
72+
}
73+
74+
const assetId = s3Key.split('.')[0]; // S3Key format is <hash>.zip"
75+
const assetDir = path.join(assembly.directory, `asset.${assetId}`);
76+
77+
try {
78+
if (!fs.existsSync(assetDir) || !fs.statSync(assetDir).isDirectory()) {
79+
throw new ValidationError(`Asset directory does not exist for function ${func.functionName}: ${assetDir}`, stack);
80+
}
81+
82+
const indexPath = path.join(assetDir, 'index.js');
83+
if (!fs.existsSync(indexPath)) {
84+
throw new ValidationError(`index.js not found in asset directory for function ${func.functionName}`, stack);
85+
}
86+
} catch (error) {
87+
throw error;
88+
}
89+
});

Diff for: packages/aws-cdk/lib/cli/user-configuration.ts

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const BUNDLING_COMMANDS = [
4141
Command.SYNTH,
4242
Command.SYNTHESIZE,
4343
Command.WATCH,
44+
Command.IMPORT,
4445
];
4546

4647
export type Arguments = {

0 commit comments

Comments
 (0)