Skip to content

Commit e68193e

Browse files
authored
chore: improve stability of tests by copying SSM Parameter Value (#830)
`{Fn::GetAtt}` on an `AWS::SSM::Parameter` is eventually consistent. If an SSM Parameter was just created in a stack deployment, the `{Fn::GetAtt}` may sometimes fail with a "Parameter not found" error. This causes ~2 canary failures per week (about 1% failure rate). We don't actually need to `{Fn::GetAtt}` the value as we know what it is (it is static, after all). Copy the same literal value into both places to reduce the canary failure rate by a little bit, and add a test to make sure the values don't accidentally drift apart. Internal reference D259904064. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license
1 parent 4d555c9 commit e68193e

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

packages/@aws-cdk/toolkit-lib/test/api/bootstrap/external-id.test.ts renamed to packages/@aws-cdk/toolkit-lib/test/api/bootstrap/bootstrap-template.test.ts

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@ import { Bootstrapper } from '../../../lib/api/bootstrap';
22
import type { IIoHost } from '../../../lib/api/io';
33
import { asIoHelper } from '../../../lib/api/io/private';
44

5-
describe('ExternalId Protection Integration Test', () => {
6-
let ioHost: IIoHost;
7-
let ioHelper: any;
5+
let ioHost: IIoHost;
6+
let ioHelper: any;
7+
let template: any;
88

9-
beforeEach(() => {
10-
ioHost = {
11-
notify: jest.fn(),
12-
requestResponse: jest.fn(),
13-
};
14-
ioHelper = asIoHelper(ioHost, 'bootstrap');
15-
});
16-
17-
test('bootstrap template denies AssumeRole with ExternalId by default', async () => {
18-
// GIVEN
19-
const bootstrapper = new Bootstrapper({ source: 'default' }, ioHelper);
9+
beforeEach(async () => {
10+
ioHost = {
11+
notify: jest.fn(),
12+
requestResponse: jest.fn(),
13+
};
14+
ioHelper = asIoHelper(ioHost, 'bootstrap');
2015

21-
// WHEN
22-
const template = await (bootstrapper as any).loadTemplate();
16+
// GIVEN
17+
const bootstrapper = new Bootstrapper({ source: 'default' }, ioHelper);
18+
// WHEN
19+
template = await (bootstrapper as any).loadTemplate();
20+
});
2321

22+
describe('bootstrap template', () => {
23+
test('denies AssumeRole with ExternalId by default', async () => {
2424
// THEN
2525
// Verify the parameter exists
2626
expect(template.Parameters.DenyExternalId).toMatchObject({
@@ -70,4 +70,8 @@ describe('ExternalId Protection Integration Test', () => {
7070
expect(stmt.Condition).toBeUndefined();
7171
}
7272
});
73+
74+
test('has the same values for BootstrapVersion Parameter and Output', async () => {
75+
expect(template.Outputs.BootstrapVersion.Value).toEqual(template.Resources.CdkBootstrapVersion.Properties.Value);
76+
});
7377
});

packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ Resources:
813813
Type: String
814814
Name:
815815
Fn::Sub: '/cdk-bootstrap/${Qualifier}/version'
816+
# Also update this value below (see comment there)
816817
Value: '29'
817818
Outputs:
818819
BucketName:
@@ -844,5 +845,8 @@ Outputs:
844845
BootstrapVersion:
845846
Description: The version of the bootstrap resources that are currently mastered
846847
in this stack
847-
Value:
848-
Fn::GetAtt: [CdkBootstrapVersion, Value]
848+
# This value is purposely duplicated here from the AWS::SSM::Parameter value we define above.
849+
# {Fn::GetAtt} on an SSM Parameter is eventually consistent, and can fail with "parameter
850+
# doesn't exist" even after just having been created. To reduce our deploy failure rate, we
851+
# duplicate the value here and use a build-time test to ensure the two values are the same.
852+
Value: '29'

0 commit comments

Comments
 (0)