Skip to content

Commit

Permalink
fix: always wait for creation
Browse files Browse the repository at this point in the history
  • Loading branch information
jbw committed Aug 25, 2023
1 parent e7500f0 commit b09669c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 35 deletions.
36 changes: 24 additions & 12 deletions src/cloudformation/change-set/cloud-formation-change-set.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as AWS from 'aws-sdk';
import { PromiseResult } from 'aws-sdk/lib/request';
import { AWSWaitForResp } from '../../aws-wait-for-resp';

export class CloudFormationChangeSet {
constructor(private readonly cf: AWS.CloudFormation) {}
Expand Down Expand Up @@ -29,18 +30,13 @@ export class CloudFormationChangeSet {
console.debug('Waiting for change set creation');

try {
const waitForResp = await this.cf
.waitFor('changeSetCreateComplete', {
StackName: stackName,
ChangeSetName: changeSetName,
})
.promise();
const waitForResp = await this.waitForChangeSetCreation(stackName, changeSetName);

if (waitForResp.ExecutionStatus === 'EXECUTE_COMPLETE') {
console.debug('Change set execution already complete');

return {
status: '200',
status: waitForResp.$response.httpResponse.statusCode.toString(),
stackId: waitForResp.StackId,
};
}
Expand All @@ -56,7 +52,7 @@ export class CloudFormationChangeSet {
}

return {
status: '200',
status: createChangeSetResp.$response.httpResponse.statusCode.toString(),
stackId: createChangeSetResp.StackId,
};
}
Expand Down Expand Up @@ -96,13 +92,29 @@ export class CloudFormationChangeSet {

if (waitFor) {
console.debug('Waiting for stack update to complete...');
await this.waitForStackCreation(stackName);
//await this.waitForStackUpdate(stackName);
//await this.waitForStackCreation(stackName);
}
}

private waitForStackCreation(
stackName: string,
): Promise<PromiseResult<AWS.CloudFormation.DescribeStacksOutput, AWS.AWSError>> {
private waitForStackCreation(stackName: string): Promise<AWSWaitForResp> {
return this.cf.waitFor('stackCreateComplete', { StackName: stackName }).promise();
}

private waitForStackUpdate(stackName: string): Promise<AWSWaitForResp> {
console.debug('Waiting for stack update...');
return this.cf.waitFor('stackUpdateComplete', { StackName: stackName }).promise();
}

private waitForChangeSetCreation(
stackName: string,
changeSetName: string,
): Promise<PromiseResult<AWS.CloudFormation.DescribeChangeSetOutput, AWS.AWSError>> {
return this.cf
.waitFor('changeSetCreateComplete', {
StackName: stackName,
ChangeSetName: changeSetName,
})
.promise();
}
}
27 changes: 8 additions & 19 deletions src/cloudformation/stack/cloud-formation-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,26 @@ export class CloudFormationStack {

private async update(stack: Stack): Promise<CloudFormationStackResponse> {
console.debug('Updating stack...');
const { waitFor } = this.stackOptions || {};

if (!stack) return { status: '404' };

const stackName = stack.StackName;
const changeSetName = `${stackName}-changeset`;
const input = this.buildChangeSetInput(stackName, changeSetName);
const template = this.readTemplate(this.stackOptions.template.filepath!);

await this.changeSet.create({
template: this.readTemplate(this.stackOptions.template.filepath!),
waitFor,
const resp = await this.changeSet.create({
template,
waitFor: true,
execute: true,
params: input,
});

await this.waitForChangeSetCreation(changeSetName);
return resp;
}

return {
status: '200',
stackId: stack.StackId,
};
public getChangeSet(name: string, stackName: string): Promise<AWS.CloudFormation.Types.DescribeChangeSetOutput> {
return this.cf.describeChangeSet({ ChangeSetName: name, StackName: stackName }).promise();
}

public async getStack(name: string): Promise<Stack | undefined> {
Expand Down Expand Up @@ -184,16 +183,6 @@ export class CloudFormationStack {
return this.cf.waitFor('stackCreateComplete', { StackName: this.stackOptions.name }).promise();
}

private waitForStackUpdate(): Promise<AWSWaitForResp> {
console.debug('Waiting for stack update...');
return this.cf.waitFor('stackUpdateComplete', { StackName: this.stackOptions.name }).promise();
}

private waitForChangeSetCreation(changeSetName: string): Promise<AWSWaitForResp> {
console.debug('Waiting for change set creation...');
return this.cf.waitFor('changeSetCreateComplete', { ChangeSetName: changeSetName }).promise();
}

private waitForStackExists(): Promise<AWSWaitForResp> {
console.debug('Waiting for describe stacks...');
return this.cf.waitFor('stackExists', { StackName: this.stackOptions.name }).promise();
Expand Down
67 changes: 63 additions & 4 deletions test/deploy.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dotenv/config'; import { CloudFormationStack } from '../src/cloudformation/stack/cloud-formation-stack';
import 'dotenv/config';
import { CloudFormationStack } from '../src/cloudformation/stack/cloud-formation-stack';
import { CloudFormationStackOptions } from '../src/cloudformation/stack/cloud-formation-stack-options';
import { createParameterOverrides } from '../src/createParameterOverrides';

Expand Down Expand Up @@ -47,9 +48,12 @@ describe('deploy', () => {
const resp = await stack.deploy();

// then
const stackInfo = await stack.getStack(options.stack.name);
expect(stackInfo?.StackName).toBe(stackName);
expect(stackInfo?.StackStatus).toBe('CREATE_COMPLETE');
expect(resp.stackId).toContain(stackName);
expect(resp.status).toBe('200');
});
}, 50000);

it('should deploy', async () => {
// given
Expand All @@ -60,6 +64,12 @@ describe('deploy', () => {
name: stackName,
template: { filepath: 'test/test-template.json' },
waitFor: true,
parameterOverrides: [
{
ParameterKey: 'Environment',
ParameterValue: 'dev',
},
],
},
client: {
region: 'us-east-1',
Expand All @@ -81,6 +91,7 @@ describe('deploy', () => {
expect(resp.status).toBe('200');
expect(stackInfo?.StackName).toBe(stackName);
expect(stackInfo?.StackStatus).toBe('CREATE_COMPLETE');
expect(stackInfo?.Parameters).toEqual(options.stack.parameterOverrides);
}, 500000);

it('should update', async () => {
Expand Down Expand Up @@ -122,10 +133,58 @@ describe('deploy', () => {
const updated = CloudFormationStack.createStack(options);
const resp = await updated.deploy();
const updatedStack = await updated.getStack(options.stack.name);
const changeSet = await updated.getChangeSet(updatedStack?.ChangeSetId!, options.stack.name);

// then
expect(resp.stackId).toContain(stackName);
expect(resp.status).toBe('200');
expect(updatedStack?.Parameters).toEqual(options.stack.parameterOverrides);
}, 500000);
expect(changeSet?.Parameters).toEqual(options.stack.parameterOverrides);
}, 5000000);

it.only('should update and not wait', async () => {
// given
const timestamp = new Date().getTime().toString();
const stackName = 'test-stack-2' + timestamp;
const options: CloudFormationStackOptions = {
stack: {
name: stackName,
template: { filepath: 'test/test-template.json' },
waitFor: false,
deleteFailedChangeSet: false,
parameterOverrides: [
{
ParameterKey: 'Environment',
ParameterValue: 'dev',
},
],
},
client: {
region: 'us-east-1',
endpoint: LOCALSTACK_URL,
accessKeyId: AWS_ACCESS_KEY_ID,
secretAccessKey: AWS_SECRET_ACCESS_KEY,
},
};

// when
await CloudFormationStack.createStack(options).deploy();

options.stack.template.filepath = 'test/test-template-update.json';
options.stack.parameterOverrides = [
{
ParameterKey: 'Environment',
ParameterValue: 'test',
},
];

const updated = CloudFormationStack.createStack(options);
const resp = await updated.deploy();
const updatedStack = await updated.getStack(options.stack.name);
const changeSet = await updated.getChangeSet(updatedStack?.ChangeSetId!, options.stack.name);

// then
expect(resp.stackId).toContain(stackName);
expect(resp.status).toBe('200');
expect(changeSet?.Parameters).toEqual(options.stack.parameterOverrides);
}, 5000000);
});

0 comments on commit b09669c

Please sign in to comment.