Skip to content

Commit b512a72

Browse files
authored
feat(cli): show all information from waiter errors (#33035)
Waiter errors now have an additional piece of information: the responses that were observed during the polling, and their counts. Relay this information to the user in the error message. Closes #32481. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 9e2f628 commit b512a72

File tree

6 files changed

+116
-16
lines changed

6 files changed

+116
-16
lines changed

packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,8 @@ integTest(
25472547
// THEN
25482548
const expectedSubstring = 'Resource is not in the expected state due to waiter status: TIMEOUT';
25492549
expect(deployOutput).toContain(expectedSubstring);
2550+
expect(deployOutput).toContain('Observed responses:');
2551+
expect(deployOutput).toContain('200: OK');
25502552
expect(deployOutput).not.toContain('hotswapped!');
25512553
}),
25522554
);

packages/aws-cdk/THIRD_PARTY_LICENSES

+2-2
Original file line numberDiff line numberDiff line change
@@ -16464,7 +16464,7 @@ Apache License
1646416464

1646516465
----------------
1646616466

16467-
** @smithy/[email protected].8 - https://www.npmjs.com/package/@smithy/service-error-classification/v/3.0.8 | Apache-2.0
16467+
** @smithy/[email protected].11 - https://www.npmjs.com/package/@smithy/service-error-classification/v/3.0.11 | Apache-2.0
1646816468
Apache License
1646916469
Version 2.0, January 2004
1647016470
http://www.apache.org/licenses/
@@ -20570,7 +20570,7 @@ Apache License
2057020570

2057120571
----------------
2057220572

20573-
** @smithy/[email protected].8 - https://www.npmjs.com/package/@smithy/util-retry/v/3.0.8 | Apache-2.0
20573+
** @smithy/[email protected].11 - https://www.npmjs.com/package/@smithy/util-retry/v/3.0.11 | Apache-2.0
2057420574
Apache License
2057520575
Version 2.0, January 2004
2057620576
http://www.apache.org/licenses/

packages/aws-cdk/lib/api/hotswap-deployments.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,7 @@ async function applyHotswappableChange(sdk: SDK, hotswapOperation: HotswappableC
426426
} catch (e: any) {
427427
if (e.name === 'TimeoutError' || e.name === 'AbortError') {
428428
const result: WaiterResult = JSON.parse(formatErrorMessage(e));
429-
const error = new ToolkitError([
430-
`Resource is not in the expected state due to waiter status: ${result.state}`,
431-
result.reason ? `${result.reason}.` : '',
432-
].join('. '));
429+
const error = new ToolkitError(formatWaiterErrorResult(result));
433430
error.name = e.name;
434431
throw error;
435432
}
@@ -443,6 +440,24 @@ async function applyHotswappableChange(sdk: SDK, hotswapOperation: HotswappableC
443440
sdk.removeCustomUserAgent(customUserAgent);
444441
}
445442

443+
function formatWaiterErrorResult(result: WaiterResult) {
444+
const main = [
445+
`Resource is not in the expected state due to waiter status: ${result.state}`,
446+
result.reason ? `${result.reason}.` : '',
447+
].join('. ');
448+
449+
if (result.observedResponses != null) {
450+
const observedResponses = Object
451+
.entries(result.observedResponses)
452+
.map(([msg, count]) => ` - ${msg} (${count})`)
453+
.join('\n');
454+
455+
return `${main} Observed responses:\n${observedResponses}`;
456+
}
457+
458+
return main;
459+
}
460+
446461
function logNonHotswappableChanges(nonHotswappableChanges: NonHotswappableChange[], hotswapMode: HotswapMode): void {
447462
if (nonHotswappableChanges.length === 0) {
448463
return;

packages/aws-cdk/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,9 @@
170170
"@smithy/property-provider": "^3.1.10",
171171
"@smithy/shared-ini-file-loader": "^3.1.8",
172172
"@smithy/types": "^3.5.0",
173-
"@smithy/util-retry": "^3.0.7",
174-
"@smithy/util-stream": "^3.1.9",
175-
"@smithy/util-waiter": "^3.1.6",
173+
"@smithy/util-retry": "^3.0.11",
174+
"@smithy/util-stream": "^3.3.4",
175+
"@smithy/util-waiter": "^3.2.0",
176176
"archiver": "^5.3.2",
177177
"camelcase": "^6.3.0",
178178
"cdk-assets": "^3.0.0-rc.123",

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

+65-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import { UpdateFunctionCodeCommand, waitUntilFunctionUpdatedV2 } from '@aws-sdk/client-lambda';
2-
import * as setup from './hotswap-test-setup';
3-
import { HotswapMode } from '../../../lib/api/hotswap/common';
4-
import { mockLambdaClient } from '../../util/mock-sdk';
5-
import { silentTest } from '../../util/silent';
6-
1+
let mockWaitUntilFunctionUpdatedV2: jest.Mock = jest.fn();
72
jest.mock('@aws-sdk/client-lambda', () => {
83
const original = jest.requireActual('@aws-sdk/client-lambda');
94

105
return {
116
...original,
12-
waitUntilFunctionUpdatedV2: jest.fn(),
7+
waitUntilFunctionUpdatedV2: mockWaitUntilFunctionUpdatedV2,
138
};
149
});
1510

11+
import { UpdateFunctionCodeCommand, waitUntilFunctionUpdatedV2 } from '@aws-sdk/client-lambda';
12+
import * as setup from './hotswap-test-setup';
13+
import { HotswapMode } from '../../../lib/api/hotswap/common';
14+
import { mockLambdaClient } from '../../util/mock-sdk';
15+
import { silentTest } from '../../util/silent';
16+
1617
let hotswapMockSdkProvider: setup.HotswapMockSdkProvider;
1718

1819
beforeEach(() => {
@@ -125,4 +126,61 @@ describe.each([HotswapMode.FALL_BACK, HotswapMode.HOTSWAP_ONLY])('%p mode', (hot
125126
{ FunctionName: 'my-function' },
126127
);
127128
});
129+
130+
silentTest(
131+
'throws error in case of timeout',
132+
async () => {
133+
// GIVEN
134+
mockWaitUntilFunctionUpdatedV2.mockRejectedValue({
135+
name: 'TimeoutError',
136+
message: JSON.stringify({
137+
state: 'TIMEOUT',
138+
reason: 'Function not found',
139+
observedResponses: {
140+
'404: The function with name foo cannot be found.': 5,
141+
},
142+
}),
143+
});
144+
setup.setCurrentCfnStackTemplate({
145+
Resources: {
146+
Func: {
147+
Type: 'AWS::Lambda::Function',
148+
Properties: {
149+
Code: {
150+
ImageUri: 'current-image',
151+
},
152+
FunctionName: 'my-function',
153+
},
154+
Metadata: {
155+
'aws:asset:path': 'old-path',
156+
},
157+
},
158+
},
159+
});
160+
const cdkStackArtifact = setup.cdkStackArtifactOf({
161+
template: {
162+
Resources: {
163+
Func: {
164+
Type: 'AWS::Lambda::Function',
165+
Properties: {
166+
Code: {
167+
ImageUri: 'new-image',
168+
},
169+
FunctionName: 'my-function',
170+
},
171+
Metadata: {
172+
'aws:asset:path': 'new-path',
173+
},
174+
},
175+
},
176+
},
177+
});
178+
179+
// THEN
180+
await expect(hotswapMockSdkProvider.tryHotswapDeployment(hotswapMode, cdkStackArtifact))
181+
.rejects
182+
.toThrow(`Resource is not in the expected state due to waiter status: TIMEOUT. Function not found. Observed responses:
183+
- 404: The function with name foo cannot be found. (5)`);
184+
},
185+
);
128186
});

yarn.lock

+25
Original file line numberDiff line numberDiff line change
@@ -8582,6 +8582,17 @@
85828582
"@smithy/util-base64" "^3.0.0"
85838583
tslib "^2.6.2"
85848584

8585+
"@smithy/fetch-http-handler@^4.1.3":
8586+
version "4.1.3"
8587+
resolved "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.3.tgz#fc590dea2470d32559ae298306f1277729d24aa9"
8588+
integrity sha512-6SxNltSncI8s689nvnzZQc/dPXcpHQ34KUj6gR/HBroytKOd/isMG3gJF/zBE1TBmTT18TXyzhg3O3SOOqGEhA==
8589+
dependencies:
8590+
"@smithy/protocol-http" "^4.1.8"
8591+
"@smithy/querystring-builder" "^3.0.11"
8592+
"@smithy/types" "^3.7.2"
8593+
"@smithy/util-base64" "^3.0.0"
8594+
tslib "^2.6.2"
8595+
85858596
"@smithy/fetch-http-handler@^5.0.0", "@smithy/fetch-http-handler@^5.0.1":
85868597
version "5.0.1"
85878598
resolved "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz#8463393442ca6a1644204849e42c386066f0df79"
@@ -9852,6 +9863,20 @@
98529863
"@smithy/util-utf8" "^3.0.0"
98539864
tslib "^2.6.2"
98549865

9866+
"@smithy/util-stream@^3.3.4":
9867+
version "3.3.4"
9868+
resolved "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.4.tgz#c506ac41310ebcceb0c3f0ba20755e4fe0a90b8d"
9869+
integrity sha512-SGhGBG/KupieJvJSZp/rfHHka8BFgj56eek9px4pp7lZbOF+fRiVr4U7A3y3zJD8uGhxq32C5D96HxsTC9BckQ==
9870+
dependencies:
9871+
"@smithy/fetch-http-handler" "^4.1.3"
9872+
"@smithy/node-http-handler" "^3.3.3"
9873+
"@smithy/types" "^3.7.2"
9874+
"@smithy/util-base64" "^3.0.0"
9875+
"@smithy/util-buffer-from" "^3.0.0"
9876+
"@smithy/util-hex-encoding" "^3.0.0"
9877+
"@smithy/util-utf8" "^3.0.0"
9878+
tslib "^2.6.2"
9879+
98559880
"@smithy/util-stream@^4.0.0", "@smithy/util-stream@^4.0.2":
98569881
version "4.0.2"
98579882
resolved "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz#63495d3f7fba9d78748d540921136dc4a8d4c067"

0 commit comments

Comments
 (0)