Skip to content

Commit

Permalink
chore(migrate): add integ tests with app deployment (aws#27509)
Browse files Browse the repository at this point in the history
> REPLACE THIS TEXT BLOCK
>
> Describe the reason for this change, what the solution is, and any
> important design decisions you made. 
>
> Remember to follow the [CONTRIBUTING GUIDE] and [DESIGN GUIDELINES] for any
> code you submit.
>
> [CONTRIBUTING GUIDE]: https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md
> [DESIGN GUIDELINES]: https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md

Closes #<issue number here>.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
TheRealAmazonKendra authored Oct 12, 2023
1 parent 71b9737 commit 1fc5dda
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 3 deletions.
65 changes: 63 additions & 2 deletions packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,50 @@ export function withCdkApp(
};
}

export function withCdkMigrateApp<A extends TestContext>(language: string, block: (context: TestFixture) => Promise<void>) {
return async (context: A) => {
const stackName = `cdk-migrate-${language}-integ-${context.randomString}`;
const integTestDir = path.join(os.tmpdir(), `cdk-migrate-${language}-integ-${context.randomString}`);

context.output.write(` Stack name: ${stackName}\n`);
context.output.write(` Test directory: ${integTestDir}\n`);

const awsClients = await AwsClients.default(context.output);
fs.mkdirSync(integTestDir);
const fixture = new TestFixture(
integTestDir,
stackName,
context.output,
awsClients,
context.randomString,
);

await fixture.cdkMigrate(language, stackName);

const testFixture = new TestFixture(
path.join(integTestDir, stackName),
stackName,
context.output,
awsClients,
context.randomString,
);

let success = true;
try {
await block(testFixture);
} catch (e) {
success = false;
throw e;
} finally {
if (process.env.INTEG_NO_CLEAN) {
context.log(`Left test directory in '${integTestDir}' ($INTEG_NO_CLEAN)`);
} else {
await fixture.dispose(success);
}
}
};
}

export function withMonolithicCfnIncludeCdkApp<A extends TestContext>(block: (context: TestFixture) => Promise<void>) {
return async (context: A) => {
const uberPackage = process.env.UBERPACKAGE;
Expand Down Expand Up @@ -141,6 +185,10 @@ export function withDefaultFixture(block: (context: TestFixture) => Promise<void
return withAws(withTimeout(DEFAULT_TEST_TIMEOUT_S, withCdkApp(block)));
}

export function withCDKMigrateFixture(language: string, block: (content: TestFixture) => Promise<void>) {
return withAws(withTimeout(DEFAULT_TEST_TIMEOUT_S, withCdkMigrateApp(language, block)));
}

export interface DisableBootstrapContext {
/**
* Whether to disable creating the default bootstrap
Expand Down Expand Up @@ -270,7 +318,7 @@ export class TestFixture extends ShellHelper {
this.output.write(`${s}\n`);
}

public async cdkDeploy(stackNames: string | string[], options: CdkCliOptions = {}) {
public async cdkDeploy(stackNames: string | string[], options: CdkCliOptions = {}, skipStackRename?: boolean) {
stackNames = typeof stackNames === 'string' ? [stackNames] : stackNames;

const neverRequireApproval = options.neverRequireApproval ?? true;
Expand All @@ -280,7 +328,7 @@ export class TestFixture extends ShellHelper {
...(options.options ?? []),
// use events because bar renders bad in tests
'--progress', 'events',
...this.fullStackName(stackNames)], options);
...(skipStackRename ? stackNames : this.fullStackName(stackNames))], options);
}

public async cdkSynth(options: CdkCliOptions = {}) {
Expand Down Expand Up @@ -379,6 +427,19 @@ export class TestFixture extends ShellHelper {
});
}

public async cdkMigrate(language: string, stackName: string, inputPath?: string, options?: CdkCliOptions) {
return this.cdk([
'migrate',
'--language',
language,
'--stack-name',
stackName,
'--from-path',
inputPath ?? path.join(__dirname, '..', 'resources', 'templates', 'sqs-template.json').toString(),
...(options?.options ?? []),
], options);
}

public async cdk(args: string[], options: CdkCliOptions = {}) {
const verbose = options.verbose ?? true;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Sample Template SQS_With_CloudWatch_Alarms: Sample template showing how to create an SQS queue with AWS CloudWatch alarms on queue depth.",
"Resources": {
"MyQueue": {
"Type": "AWS::SQS::Queue",
"Properties": {}
}
},
"Outputs": {
"QueueURL": {
"Description": "URL of newly created SQS Queue",
"Value": {
"Ref": "MyQueue"
}
},
"QueueARN": {
"Description": "ARN of newly created SQS Queue",
"Value": {
"Fn::GetAtt": [
"MyQueue",
"Arn"
]
}
},
"QueueName": {
"Description": "Name newly created SQS Queue",
"Value": {
"Fn::GetAtt": [
"MyQueue",
"QueueName"
]
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { promises as fs, existsSync } from 'fs';
import * as os from 'os';
import * as path from 'path';
import { integTest, cloneDirectory, shell, withDefaultFixture, retry, sleep, randomInteger, withSamIntegrationFixture, RESOURCES_DIR } from '../../lib';
import { integTest, cloneDirectory, shell, withDefaultFixture, retry, sleep, randomInteger, withSamIntegrationFixture, RESOURCES_DIR, withCDKMigrateFixture } from '../../lib';

jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime

Expand Down Expand Up @@ -571,6 +571,23 @@ integTest('deploy with role', withDefaultFixture(async (fixture) => {
}
}));

// TODO add go back in when template synths properly
['typescript', 'python', 'csharp', 'java'].forEach(language => {
integTest(`cdk migrate ${language}`, withCDKMigrateFixture(language, async (fixture) => {
if (language === 'python') {
await fixture.shell(['pip', 'install', '-r', 'requirements.txt']);
}

const stackArn = await fixture.cdkDeploy(fixture.stackNamePrefix, { neverRequireApproval: true, verbose: true, captureStderr: false }, true);
const response = await fixture.aws.cloudFormation('describeStacks', {
StackName: stackArn,
});

expect(response.Stacks?.[0].StackStatus).toEqual('CREATE_COMPLETE');
await fixture.cdkDestroy(fixture.stackNamePrefix);
}));
});

integTest('cdk diff', withDefaultFixture(async (fixture) => {
const diff1 = await fixture.cdk(['diff', fixture.fullStackName('test-1')]);
expect(diff1).toContain('AWS::SNS::Topic');
Expand Down

0 comments on commit 1fc5dda

Please sign in to comment.