Skip to content

Commit

Permalink
Framework: Tokens can be converted to strings
Browse files Browse the repository at this point in the history
Tokens (such as resource attributes) can now be implicitly converted
into strings. Parameters and attributes can now be combined into larger
strings using the native string facilities of the host language.

The process will be reversed by the resolve() function during synthesis,
which will split the string up again into string literals and
CloudFormation intrinsics.

The same transformation is applied during JSON.stringify(), so that
Tokens in a complex JSON structure are preserved.

Fixes #24 and #168.
  • Loading branch information
Rico Huijbers committed Aug 7, 2018
1 parent 9f0b114 commit 3796389
Show file tree
Hide file tree
Showing 25 changed files with 3,816 additions and 221 deletions.
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-cloudwatch/lib/dashboard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Construct, Stack, Token, tokenAwareJsonify } from "@aws-cdk/cdk";
import { Construct, Stack, Token } from "@aws-cdk/cdk";
import { cloudformation } from './cloudwatch.generated';
import { Column, Row } from "./layout";
import { IWidget } from "./widget";
Expand Down Expand Up @@ -33,7 +33,7 @@ export class Dashboard extends Construct {
dashboardBody: new Token(() => {
const column = new Column(...this.rows);
column.position(0, 0);
return tokenAwareJsonify({ widgets: column.toJson() });
return JSON.stringify({ widgets: column.toJson() });
})
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"EvaluationPeriods": 3,
"MetricName": "ApproximateNumberOfMessagesVisible",
"Namespace": "AWS/SQS",
"Period": 300,
"Threshold": 100,
"Dimensions": [
{
"Name": "QueueName",
Expand All @@ -18,41 +23,55 @@
}
}
],
"EvaluationPeriods": 3,
"MetricName": "ApproximateNumberOfMessagesVisible",
"Namespace": "AWS/SQS",
"Period": 300,
"Statistic": "Average",
"Threshold": 100
"Statistic": "Average"
}
},
"DashCCD7F836": {
"Type": "AWS::CloudWatch::Dashboard",
"Properties": {
"DashboardName": "aws-cdk-cloudwatch-DashCCD7F836",
"DashboardBody": {
"Fn::Sub": [
"{\"widgets\":[{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# This is my dashboard\"}},{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":6,\"y\":0,\"properties\":{\"markdown\":\"you like?\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":2,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Messages in queue\",\"region\":\"${ref0}\",\"annotations\":{\"alarms\":[\"${ref1}\"]},\"yAxis\":{\"left\":{\"min\":0}}}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":8,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"${ref0}\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"${ref2}\",{\"yAxis\":\"left\",\"period\":300,\"stat\":\"Average\"}]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 3 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{\"left\":{\"min\":0},\"right\":{\"min\":0}}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":14,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"${ref0}\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"${ref2}\",{\"yAxis\":\"left\",\"period\":300,\"stat\":\"Average\"}]]}}]}",
{
"ref0": {
"Fn::Join": [
"",
[
"{\"widgets\":[{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# This is my dashboard\"}},{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":6,\"y\":0,\"properties\":{\"markdown\":\"you like?\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":2,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Messages in queue\",\"region\":\"",
{
"Ref": "AWS::Region"
},
"ref1": {
"\",\"annotations\":{\"alarms\":[\"",
{
"Fn::GetAtt": [
"Alarm7103F465",
"Arn"
]
},
"ref2": {
"\"]},\"yAxis\":{\"left\":{\"min\":0}}}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":8,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"",
{
"Ref": "AWS::Region"
},
"\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"",
{
"Fn::GetAtt": [
"queue",
"QueueName"
]
}
}
},
"\",{\"yAxis\":\"left\",\"period\":300,\"stat\":\"Average\"}]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 3 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{\"left\":{\"min\":0},\"right\":{\"min\":0}}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":14,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"",
{
"Ref": "AWS::Region"
},
"\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"",
{
"Fn::GetAtt": [
"queue",
"QueueName"
]
},
"\",{\"yAxis\":\"left\",\"period\":300,\"stat\":\"Average\"}]]}}]}"
]
]
}
},
"DashboardName": "aws-cdk-cloudwatch-DashCCD7F836"
}
}
}
}
}
15 changes: 6 additions & 9 deletions packages/@aws-cdk/aws-cloudwatch/test/test.dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export = {
test.done();
},

'tokens in widgets are retained through FnSub'(test: Test) {
'tokens in widgets are retained'(test: Test) {
// GIVEN
const stack = new Stack();
const dashboard = new Dashboard(stack, 'Dash');
Expand All @@ -82,14 +82,11 @@ export = {

// THEN
expect(stack).to(haveResource('AWS::CloudWatch::Dashboard', {
DashboardBody: { "Fn::Sub": [
// tslint:disable-next-line:max-line-length
"{\"widgets\":[{\"type\":\"metric\",\"width\":1,\"height\":1,\"x\":0,\"y\":0,\"properties\":{\"view\":\"timeSeries\",\"region\":\"${ref0}\",\"metrics\":[],\"annotations\":{\"horizontal\":[]},\"yAxis\":{\"left\":{\"min\":0},\"right\":{\"min\":0}}}}]}",
{
ref0: { Ref: "AWS::Region" }
}
]
}
DashboardBody: { "Fn::Join": [ "", [
"{\"widgets\":[{\"type\":\"metric\",\"width\":1,\"height\":1,\"x\":0,\"y\":0,\"properties\":{\"view\":\"timeSeries\",\"region\":\"",
{ Ref: "AWS::Region" },
"\",\"metrics\":[],\"annotations\":{\"horizontal\":[]},\"yAxis\":{\"left\":{\"min\":0},\"right\":{\"min\":0}}}}]}"
]]}
}));

test.done();
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/cdk/lib/cloudformation/pseudo.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Token } from '../core/tokens';
import { HintedToken } from '../core/tokens';

export class PseudoParameter extends Token {
export class PseudoParameter extends HintedToken {
constructor(name: string) {
super(() => ({ Ref: name }));
super(name, () => ({ Ref: name }));
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/cdk/lib/cloudformation/resource.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Construct } from '../core/construct';
import { Token } from '../core/tokens';
import { HintedToken, Token } from '../core/tokens';
import { capitalizePropertyNames, ignoreEmpty } from '../core/util';
import { Condition } from './condition';
import { CreationPolicy, DeletionPolicy, UpdatePolicy } from './resource-policy';
Expand Down Expand Up @@ -82,7 +82,7 @@ export class Resource extends Referenceable {
* @param attributeName The name of the attribute.
*/
public getAtt(attributeName: string): Token {
return new Token(() => ({ 'Fn::GetAtt': [this.logicalId, attributeName] }));
return new HintedToken(`${this.logicalId}.${attributeName}`, () => ({ 'Fn::GetAtt': [this.logicalId, attributeName] }));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/cdk/lib/cloudformation/stack.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import cxapi = require('@aws-cdk/cx-api');
import { App } from '../app';
import { Construct, PATH_SEP } from '../core/construct';
import { resolve, Token } from '../core/tokens';
import { HintedToken, resolve, Token } from '../core/tokens';
import { Environment } from '../environment';
import { HashedAddressingScheme, IAddressingScheme, LogicalIDs } from './logical-id';
import { Resource } from './resource';
Expand Down Expand Up @@ -392,7 +392,7 @@ export abstract class Referenceable extends StackElement {
* Returns a token to a CloudFormation { Ref } that references this entity based on it's logical ID.
*/
public get ref() {
return new Token(() => ({ Ref: this.logicalId }));
return new HintedToken(`${this.logicalId}`, () => ({ Ref: this.logicalId }));
}
}

Expand Down
112 changes: 0 additions & 112 deletions packages/@aws-cdk/cdk/lib/cloudformation/token-aware-jsonify.ts

This file was deleted.

Loading

0 comments on commit 3796389

Please sign in to comment.