Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): misc cleanups to App-related APIs #2731

Merged
merged 20 commits into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// !cdk-integ:stack PipelineStack
eladb marked this conversation as resolved.
Show resolved Hide resolved
import codebuild = require('@aws-cdk/aws-codebuild');
import codecommit = require('@aws-cdk/aws-codecommit');
import codepipeline = require('@aws-cdk/aws-codepipeline');
Expand Down
3 changes: 2 additions & 1 deletion tools/cdk-integ-tools/bin/cdk-integ-assert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ async function main() {
throw new Error(`No such file: ${test.expectedFileName}. Run 'npm run integ'.`);
}

const stackToDeploy = await test.determineTestStack();
const expected = await test.readExpected();

const args = new Array<string>();
args.push('--no-path-metadata');
args.push('--no-asset-metadata');
args.push('--no-staging');

const actual = await test.invoke(['--json', ...args, 'synth'], { json: true, context: STATIC_TEST_CONTEXT });
const actual = await test.invoke(['--json', ...args, 'synth', stackToDeploy], { json: true, context: STATIC_TEST_CONTEXT });
eladb marked this conversation as resolved.
Show resolved Hide resolved

const diff = diffTemplate(expected, actual);

Expand Down
7 changes: 5 additions & 2 deletions tools/cdk-integ-tools/bin/cdk-integ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ async function main() {
for (const test of tests) {
console.error(`Trying to deploy ${test.name}`);

const stackToDeploy = await test.determineTestStack();
console.error(`Selected stack: ${stackToDeploy}`);

const args = new Array<string>();

// don't inject cloudformation metadata into template
Expand All @@ -37,12 +40,12 @@ async function main() {

try {
// tslint:disable-next-line:max-line-length
await test.invoke([ ...args, 'deploy', '--require-approval', 'never' ], { verbose: argv.verbose }); // Note: no context, so use default user settings!
await test.invoke([ ...args, 'deploy', '--require-approval', 'never', stackToDeploy ], { verbose: argv.verbose }); // Note: no context, so use default user settings!

console.error(`Success! Writing out reference synth.`);

// If this all worked, write the new expectation file
const actual = await test.invoke([ ...args, '--json', 'synth' ], {
const actual = await test.invoke([ ...args, '--json', 'synth', stackToDeploy ], {
json: true,
context: STATIC_TEST_CONTEXT,
verbose: argv.verbose
Expand Down
55 changes: 55 additions & 0 deletions tools/cdk-integ-tools/lib/integ-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import util = require('util');

const stat = util.promisify(fs.stat);
const readdir = util.promisify(fs.readdir);
const CDK_INTEG_STACK_PRAGMA = '/// !cdk-integ:stack';

export class IntegrationTests {
constructor(private readonly directory: string) {
}

public async fromCliArgs(tests?: string[]): Promise<IntegrationTest[]> {
let allTests = await this.discover();
const all = allTests.map(x => x.name);
let foundAll = true;

if (tests && tests.length > 0) {
// Pare down found tests to filter
Expand All @@ -22,9 +25,15 @@ export class IntegrationTests {
const selectedNames = allTests.map(t => t.name);
for (const unmatched of tests.filter(t => !selectedNames.includes(t))) {
process.stderr.write(`No such integ test: ${unmatched}\n`);
foundAll = false;
}
}

if (!foundAll) {
process.stderr.write(`Available tests: ${all.join(' ')}\n`);
return [];
}

return allTests;
}

Expand Down Expand Up @@ -62,11 +71,13 @@ export class IntegrationTest {
public readonly expectedFileName: string;
private readonly expectedFilePath: string;
private readonly cdkContextPath: string;
private readonly sourceFilePath: string;

constructor(private readonly directory: string, public readonly name: string) {
const baseName = this.name.endsWith('.js') ? this.name.substr(0, this.name.length - 3) : this.name;
this.expectedFileName = baseName + '.expected.json';
this.expectedFilePath = path.join(this.directory, this.expectedFileName);
this.sourceFilePath = path.join(this.directory, this.name);
this.cdkContextPath = path.join(this.directory, 'cdk.context.json');
}

Expand Down Expand Up @@ -95,6 +106,31 @@ export class IntegrationTest {
return fs.existsSync(this.expectedFilePath);
}

/**
* Returns the single test stack to use.
*
* If the test has a single stack, it will be chosen. Otherwise a pragma is expected within the
* test file the name of the stack:
*
* @example
*
* /// !cdk-integ:stack <stack-name>
*
*/
public async determineTestStack() {
const pragma = (await this.readStackPragma());
const availableStacks = (await this.invoke([ 'ls' ])).split('\n');
const selectedStacks = availableStacks.filter((x: any) => pragma ? x === pragma : x);
if (selectedStacks.length !== 1) {
throw new Error(`"cdk-integ" can only operate on apps with a single stack.\n\n` +
` If your app has multiple stacks, specify which stack to select by adding this to your test source:\n\n` +
` ${CDK_INTEG_STACK_PRAGMA} <stack-name>\n\n` +
` Available stacks: ${availableStacks.join(' ')}\n`);
}

return selectedStacks[0];
}

public async readExpected(): Promise<any> {
return JSON.parse((await util.promisify(fs.readFile)(this.expectedFilePath, { encoding: 'utf-8' })));
}
Expand All @@ -112,6 +148,25 @@ export class IntegrationTest {
fs.unlinkSync(this.cdkContextPath);
}
}

/**
* Reads the test source file and looks for the "!cdk-integ" pragma. If it exists, returns it's
* contents. This allows integ tests to supply custom command line arguments to "cdk deploy" and "cdk synth".
*/
private async readStackPragma(): Promise<string | undefined> {
const source = await util.promisify(fs.readFile)(this.sourceFilePath, 'utf-8');
const pragmaLine = source.split('\n').find(x => x.startsWith(CDK_INTEG_STACK_PRAGMA));
if (!pragmaLine) {
return undefined;
}

const args = pragmaLine.substring(CDK_INTEG_STACK_PRAGMA.length).trim().split(' ');
if (args.length !== 1) {
throw new Error(`Syntax of stack pragma in test code: ${CDK_INTEG_STACK_PRAGMA} <stack>`);
}

return args[0];
}
}

// Default context we run all integ tests with, so they don't depend on the
Expand Down