Skip to content

Commit

Permalink
feat(aws-cdk): add CDK app version negotiation (#988)
Browse files Browse the repository at this point in the history
Tag the CDK app output with a version, so that the Toolkit can
compare the sent and expected versions and complain if there's
a mismatch.

Fixes #891.
  • Loading branch information
rix0rrr authored Oct 25, 2018
1 parent a83ac5f commit db4e718
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/cdk/lib/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class App extends Root {
}

const result: cxapi.SynthesizeResponse = {
version: cxapi.PROTO_RESPONSE_VERSION,
stacks: this.synthesizeStacks(Object.keys(this.stacks)),
runtime: this.collectRuntimeInformation()
};
Expand Down
4 changes: 3 additions & 1 deletion packages/@aws-cdk/cdk/test/test.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ export = {
response.stacks.forEach(s => delete s.metadata);
delete response.runtime;

test.deepEqual(response, { stacks:
test.deepEqual(response, {
version: '0.14.0',
stacks:
[ { name: 'stack1',
environment:
{ name: '12345/us-east-1',
Expand Down
22 changes: 22 additions & 0 deletions packages/@aws-cdk/cx-api/lib/cxapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@

import { Environment } from './environment';

/**
* Bump this to the library version if and only if the CX protocol changes.
*
* We could also have used 1, 2, 3, ... here to indicate protocol versions, but
* those then still need to be mapped to software versions to be useful. So we
* might as well use the software version as protocol version and immediately
* generate a useful error message from this.
*
* Note the following:
*
* - The versions are not compared in a semver way, they are used as
* opaque ordered tokens.
* - The version needs to be set to the NEXT releasable version when it's
* updated (as the current verison in package.json has already been released!)
* - The request does not have versioning yet, only the response.
*/
export const PROTO_RESPONSE_VERSION = '0.14.0';

export const OUTFILE_NAME = 'cdk.out';
export const OUTDIR_ENV = 'CDK_OUTDIR';
export const CONTEXT_ENV = 'CDK_CONTEXT_JSON';
Expand All @@ -21,6 +39,10 @@ export interface MissingContext {
}

export interface SynthesizeResponse {
/**
* Protocol version
*/
version: string;
stacks: SynthesizedStack[];
runtime?: AppRuntime;
}
Expand Down
33 changes: 32 additions & 1 deletion packages/aws-cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import YAML = require('js-yaml');
import minimatch = require('minimatch');
import os = require('os');
import path = require('path');
import semver = require('semver');
import util = require('util');
import yargs = require('yargs');
import cdkUtil = require('../lib/util');
Expand Down Expand Up @@ -469,7 +470,7 @@ async function initCommandLine() {

const response = await fs.readJson(outfile);
debug(response);
return response;
return versionCheckResponse(response);
} finally {
debug('Removing outdir', outdir);
await fs.remove(outdir);
Expand Down Expand Up @@ -508,7 +509,37 @@ async function initCommandLine() {
});
}
}
}

/**
* Look at the type of response we get and upgrade it to the latest expected version
*/
function versionCheckResponse(response: cxapi.SynthesizeResponse): cxapi.SynthesizeResponse {
if (!response.version) {
// tslint:disable-next-line:max-line-length
throw new Error(`CDK Framework >= ${cxapi.PROTO_RESPONSE_VERSION} is required in order to interact with this version of the Toolkit.`);
}

const frameworkVersion = semver.coerce(response.version);
const toolkitVersion = semver.coerce(cxapi.PROTO_RESPONSE_VERSION);

// Should not happen, but I don't trust this library 100% either, so let's check for it to be safe
if (!frameworkVersion || !toolkitVersion) { throw new Error('SemVer library could not parse versions'); }

if (semver.gt(frameworkVersion, toolkitVersion)) {
throw new Error(`CDK Toolkit >= ${response.version} is required in order to interact with this program.`);
}

if (semver.lt(frameworkVersion, toolkitVersion)) {
// Toolkit protocol is newer than the framework version, and we KNOW the
// version. This is a scenario in which we could potentially do some
// upgrading of the response in the future.
//
// For now though, we simply reject old responses.
throw new Error(`CDK Framework >= ${cxapi.PROTO_RESPONSE_VERSION} is required in order to interact with this version of the Toolkit.`);
}

return response;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-cdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@types/request": "^2.47.1",
"@types/uuid": "^3.4.3",
"@types/yargs": "^8.0.3",
"@types/semver": "^5.5.0",
"cdk-build-tools": "^0.13.0",
"mockery": "^2.1.0",
"pkglint": "^0.13.0"
Expand All @@ -58,6 +59,7 @@
"promptly": "^0.2.0",
"proxy-agent": "^3.0.1",
"request": "^2.83.0",
"semver": "^5.5.0",
"source-map-support": "^0.5.6",
"yargs": "^9.0.1"
},
Expand Down

0 comments on commit db4e718

Please sign in to comment.