Skip to content

Commit a073e93

Browse files
iliapolorix0rrr
authored andcommitted
fix(cli): lambda hotswap fails if lambda:GetFunctionConfiguration action is not allowed (#32301)
Closes #32219 ### Reason for this change In SDKv3, the standard `waitUntilFunctionUpdated` function invokes the `GetFunctionConfiguration` API, as opposed to SDKv2, which invoked `GetFunction`. This means that consumers of SDKv3 must allow the `lambda:GetFunctionConfiguration` action in their IAM role policy. ### Description of changes Use a different waiter function provided by the SDK, which invokes `GetFunction` instead of `GetFunctionConfiguration`, and thus restoring required IAM permissions to what they were in SDKv2. See https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdatedV2.ts#L10 > As opposed to https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-lambda/src/waiters/waitForFunctionUpdated.ts#L13 ### Description of how you validated changes Manul test. Assumed a role with the following policies: ![Screenshot 2024-11-27 at 9 34 25](https://github.com/user-attachments/assets/69415c37-6fe8-44d3-972c-1373ec55f46e) ```console ❯ cdk deploy --hotswap [09:29:11] ✨ Synthesis time: 2.72s ⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments ⚠️ They should only be used for development - never use them for your production Stacks! AwsCdkPlaygroundStack: deploying... [1/1] ✨ hotswapping resources: ✨ Lambda Function 'AwsCdkPlaygroundStack-Function76856677-7Rl7hiwwO5LQ' ❌ AwsCdkPlaygroundStack failed: TimeoutError: Resource is not in the expected state due to waiter status: TIMEOUT. Waiter has timed out. ``` Then, run the CLI from the PR. ```console ❯ /Users/epolon/dev/src/github.com/aws/aws-cdk/packages/aws-cdk/bin/cdk deploy --hotswap [10:03:00] ✨ Synthesis time: 3.46s ⚠️ The --hotswap and --hotswap-fallback flags deliberately introduce CloudFormation drift to speed up deployments ⚠️ They should only be used for development - never use them for your production Stacks! AwsCdkPlaygroundStack: deploying... [1/1] ✨ hotswapping resources: ✨ Lambda Function 'AwsCdkPlaygroundStack-Function76856677-7Rl7hiwwO5LQ' ✨ Lambda Function 'AwsCdkPlaygroundStack-Function76856677-7Rl7hiwwO5LQ' hotswapped! ✅ AwsCdkPlaygroundStack ✨ Deployment time: 12.72s Stack ARN: arn:aws:cloudformation:us-east-1:01234567890:stack/AwsCdkPlaygroundStack/22f2b380-a7cd-11ef-badd-0e08a8e0b5b1 ✨ Total time: 16.19s >>> elapsed time 23s ``` ### 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 4957967 commit a073e93

File tree

4 files changed

+15
-14
lines changed

4 files changed

+15
-14
lines changed

packages/aws-cdk/lib/api/aws-auth/sdk.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ import {
246246
UpdateFunctionConfigurationCommand,
247247
type UpdateFunctionConfigurationCommandInput,
248248
type UpdateFunctionConfigurationCommandOutput,
249-
waitUntilFunctionUpdated,
249+
waitUntilFunctionUpdatedV2,
250250
} from '@aws-sdk/client-lambda';
251251
import {
252252
GetHostedZoneCommand,
@@ -841,7 +841,7 @@ export class SDK {
841841
delaySeconds: number,
842842
input: UpdateFunctionConfigurationCommandInput,
843843
): Promise<WaiterResult> => {
844-
return waitUntilFunctionUpdated(
844+
return waitUntilFunctionUpdatedV2(
845845
{
846846
client,
847847
maxDelay: delaySeconds,

packages/aws-cdk/test/api/hotswap/hotswap-test-setup.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as cxapi from '@aws-cdk/cx-api';
22
import { ListStackResourcesCommand, StackResourceSummary, StackStatus } from '@aws-sdk/client-cloudformation';
3-
import { GetFunctionConfigurationCommand } from '@aws-sdk/client-lambda';
3+
import { GetFunctionCommand } from '@aws-sdk/client-lambda';
44
import { ICloudFormationClient, SuccessfulDeployStackResult } from '../../../lib/api';
55
import { HotswapMode, HotswapPropertyOverrides } from '../../../lib/api/hotswap/common';
66
import * as deployments from '../../../lib/api/hotswap-deployments';
@@ -109,8 +109,10 @@ export class HotswapMockSdkProvider extends MockSdkProvider {
109109
constructor(rootStackName?: string) {
110110
super();
111111

112-
mockLambdaClient.on(GetFunctionConfigurationCommand).resolves({
113-
LastUpdateStatus: 'Successful',
112+
mockLambdaClient.on(GetFunctionCommand).resolves({
113+
Configuration: {
114+
LastUpdateStatus: 'Successful',
115+
},
114116
});
115117

116118
mockCloudFormationClient.on(ListStackResourcesCommand).callsFake((input) => {

packages/aws-cdk/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { UpdateFunctionCodeCommand, waitUntilFunctionUpdated } from '@aws-sdk/client-lambda';
1+
import { UpdateFunctionCodeCommand, waitUntilFunctionUpdatedV2 } from '@aws-sdk/client-lambda';
22
import * as setup from './hotswap-test-setup';
33
import { HotswapMode } from '../../../lib/api/hotswap/common';
44
import { mockLambdaClient } from '../../util/mock-sdk';
@@ -9,7 +9,7 @@ jest.mock('@aws-sdk/client-lambda', () => {
99

1010
return {
1111
...original,
12-
waitUntilFunctionUpdated: jest.fn(),
12+
waitUntilFunctionUpdatedV2: jest.fn(),
1313
};
1414
});
1515

@@ -116,7 +116,7 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot
116116
await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
117117

118118
// THEN
119-
expect(waitUntilFunctionUpdated).toHaveBeenCalledWith(
119+
expect(waitUntilFunctionUpdatedV2).toHaveBeenCalledWith(
120120
expect.objectContaining({
121121
minDelay: 5,
122122
maxDelay: 5,

packages/aws-cdk/test/api/hotswap/lambda-functions-hotswap-deployments.test.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
UpdateFunctionCodeCommand,
33
UpdateFunctionConfigurationCommand,
4-
waitUntilFunctionUpdated,
4+
waitUntilFunctionUpdatedV2,
55
} from '@aws-sdk/client-lambda';
66
import * as setup from './hotswap-test-setup';
77
import { HotswapMode } from '../../../lib/api/hotswap/common';
@@ -10,10 +10,9 @@ import { silentTest } from '../../util/silent';
1010

1111
jest.mock('@aws-sdk/client-lambda', () => {
1212
const original = jest.requireActual('@aws-sdk/client-lambda');
13-
1413
return {
1514
...original,
16-
waitUntilFunctionUpdated: jest.fn(),
15+
waitUntilFunctionUpdatedV2: jest.fn(),
1716
};
1817
});
1918

@@ -617,7 +616,7 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot
617616

618617
// THEN
619618
expect(mockLambdaClient).toHaveReceivedCommand(UpdateFunctionCodeCommand);
620-
expect(waitUntilFunctionUpdated).toHaveBeenCalledWith(
619+
expect(waitUntilFunctionUpdatedV2).toHaveBeenCalledWith(
621620
expect.objectContaining({
622621
minDelay: 1,
623622
maxDelay: 1,
@@ -675,7 +674,7 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot
675674
await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
676675

677676
// THEN
678-
expect(waitUntilFunctionUpdated).toHaveBeenCalledWith(
677+
expect(waitUntilFunctionUpdatedV2).toHaveBeenCalledWith(
679678
expect.objectContaining({
680679
minDelay: 1,
681680
maxDelay: 1,
@@ -733,7 +732,7 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot
733732
await hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact);
734733

735734
// THEN
736-
expect(waitUntilFunctionUpdated).toHaveBeenCalledWith(
735+
expect(waitUntilFunctionUpdatedV2).toHaveBeenCalledWith(
737736
expect.objectContaining({
738737
minDelay: 5,
739738
maxDelay: 5,

0 commit comments

Comments
 (0)