Skip to content

Commit

Permalink
test(toolkit): more deploy tests (#33000)
Browse files Browse the repository at this point in the history
These are tests

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
kaizencc authored Jan 17, 2025
1 parent 4a76fee commit 8c1be1e
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 13 deletions.
2 changes: 1 addition & 1 deletion packages/@aws-cdk/toolkit/lib/toolkit/toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ export class Toolkit extends CloudAssemblySourceBuilder implements AsyncDisposab
if (!confirmed) { throw new ToolkitError('Aborted by user'); }
}

// Go around through the 'while' loop again but switch rollback to false.
// Go around through the 'while' loop again but switch rollback to true.
rollback = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import * as core from 'aws-cdk-lib/core';

export default async() => {
const app = new core.App();
new core.Stack(app, 'Stack1', {
notificationArns: [
'arn:aws:sns:us-east-1:1111111111:resource',
'arn:aws:sns:us-east-1:1111111111:other-resource',
],
});
return app.synth() as any;
};
162 changes: 150 additions & 12 deletions packages/@aws-cdk/toolkit/test/actions/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { RequireApproval } from '../../lib';
import { RequireApproval, StackParameters } from '../../lib';
import { Toolkit } from '../../lib/toolkit';
import { builderFixture, TestIoHost } from '../_helpers';

const ioHost = new TestIoHost();
const toolkit = new Toolkit({ ioHost });
jest.spyOn(toolkit, 'rollback').mockResolvedValue();

let mockDeployStack = jest.fn().mockResolvedValue({
type: 'did-deploy-stack',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
});

jest.mock('../../lib/api/aws-cdk', () => {
return {
...jest.requireActual('../../lib/api/aws-cdk'),
Deployments: jest.fn().mockImplementation(() => ({
deployStack: jest.fn().mockResolvedValue({
type: 'did-deploy-stack',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
}),
deployStack: mockDeployStack,
resolveEnvironment: jest.fn().mockResolvedValue({}),
isSingleAssetPublished: jest.fn().mockResolvedValue(true),
readCurrentTemplate: jest.fn().mockResolvedValue({ Resources: {} }),
Expand All @@ -35,11 +38,7 @@ describe('deploy', () => {
await toolkit.deploy(cx);

// THEN
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'deploy',
level: 'info',
message: expect.stringContaining('Deployment time:'),
}));
successfulDeployment();
});

test('request response when require approval is set', async () => {
Expand Down Expand Up @@ -73,4 +72,143 @@ describe('deploy', () => {
message: expect.stringContaining('Do you wish to deploy these changes'),
}));
});

describe('deployment options', () => {
test('parameters are passed in', async () => {
// WHEN
const cx = await builderFixture(toolkit, 'stack-with-role');
await toolkit.deploy(cx, {
parameters: StackParameters.exactly({
'my-param': 'my-value',
}),
});

// passed through correctly to Deployments
expect(mockDeployStack).toHaveBeenCalledWith(expect.objectContaining({
parameters: { 'my-param': 'my-value' },
}));

successfulDeployment();
});

test('notification arns are passed in', async () => {
// WHEN
const arn = 'arn:aws:sns:us-east-1:1111111111:resource';
const cx = await builderFixture(toolkit, 'stack-with-role');
await toolkit.deploy(cx, {
notificationArns: [arn],
});

// passed through correctly to Deployments
expect(mockDeployStack).toHaveBeenCalledWith(expect.objectContaining({
notificationArns: [arn],
}));

successfulDeployment();
});

test('notification arns from stack are passed in', async () => {
// WHEN
const arn = 'arn:aws:sns:us-east-1:222222222222:resource';
const cx = await builderFixture(toolkit, 'stack-with-notification-arns');
await toolkit.deploy(cx, {
notificationArns: [arn],
});

// passed through correctly to Deployments
expect(mockDeployStack).toHaveBeenCalledWith(expect.objectContaining({
notificationArns: [
arn,
'arn:aws:sns:us-east-1:1111111111:resource',
'arn:aws:sns:us-east-1:1111111111:other-resource',
],
}));

successfulDeployment();
});

test('non sns notification arn results in error', async () => {
// WHEN
const arn = 'arn:aws:sqs:us-east-1:1111111111:resource';
const cx = await builderFixture(toolkit, 'stack-with-role');
await expect(async () => toolkit.deploy(cx, {
notificationArns: [arn],
})).rejects.toThrow(/Notification arn arn:aws:sqs:us-east-1:1111111111:resource is not a valid arn for an SNS topic/);
});
});

describe('deployment results', () => {
test('did-deploy-result', async () => {
// WHEN
const cx = await builderFixture(toolkit, 'stack-with-role');
await toolkit.deploy(cx);

// THEN
successfulDeployment();
});

test('failpaused-need-rollback-first', async () => {
// GIVEN
mockDeployStack.mockImplementation((params) => {
if (params.rollback === true) {
return {
type: 'did-deploy-stack',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
};
} else {
return {
type: 'failpaused-need-rollback-first',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
};
}
});

// WHEN
const cx = await builderFixture(toolkit, 'stack-with-role');
await toolkit.deploy(cx);

// THEN
successfulDeployment();
});

test('replacement-requires-rollback', async () => {
// GIVEN
mockDeployStack.mockImplementation((params) => {
if (params.rollback === true) {
return {
type: 'did-deploy-stack',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
};
} else {
return {
type: 'replacement-requires-rollback',
stackArn: 'arn:aws:cloudformation:region:account:stack/test-stack',
outputs: {},
noOp: false,
};
}
});

// WHEN
const cx = await builderFixture(toolkit, 'stack-with-role');
await toolkit.deploy(cx);

// THEN
successfulDeployment();
});
});
});

function successfulDeployment() {
expect(ioHost.notifySpy).toHaveBeenCalledWith(expect.objectContaining({
action: 'deploy',
level: 'info',
message: expect.stringContaining('Deployment time:'),
}));
}

0 comments on commit 8c1be1e

Please sign in to comment.