Skip to content

Commit 6508f78

Browse files
author
Elad Ben-Israel
authored
feat: use stringified tokens for resource attributes instead of strong types (#712)
This change removes all strong-types generated to represent CloudFormation resource attributes that return a string (such as `QueueArn`, `DeploymentGroupId`) and replaces them with `string` that contains a stringified token (via #518). This allows working with these attributes as if they were regular strings, and dramatically simplifies the type-system and unneeded wrapping when assigning values to such attributes. The ".ref" property of each resource has been replaced with a property named according to the actual semantic meaning of the intrinsic reference (such as `queueArn`), and also returns a `string`. Users can test if a string contains stringified tokens using the function `unresolved(o)`, which can be applied to either strings or objects (previously was `isToken(o)`). Fixes #695 (opened #744 to follow up on non-string attributes)
1 parent 680f0df commit 6508f78

File tree

134 files changed

+1106
-1079
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

134 files changed

+1106
-1079
lines changed

build.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ if [ ! -d node_modules ]; then
55
/bin/bash ./install.sh
66
fi
77

8+
fail() {
9+
echo "❌ Last command failed. Scroll up to see errors in log."
10+
exit 1
11+
}
12+
813
/bin/bash ./git-secrets-scan.sh
914

1015
BUILD_INDICATOR=".BUILD_COMPLETED"
@@ -19,10 +24,10 @@ trap "rm -rf $MERKLE_BUILD_CACHE" EXIT
1924

2025
echo "============================================================================================="
2126
echo "building..."
22-
time lerna exec --stream "npm run build"
27+
time lerna run --no-bail --stream build || fail
2328

2429
echo "============================================================================================="
2530
echo "testing..."
26-
lerna run --stream test
31+
lerna run --no-bail --stream test || fail
2732

2833
touch $BUILD_INDICATOR

docs/src/examples.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ The following example creates the Aurora database **MyAuroraDatabase**.
168168
new rds.DatabaseCluster(this, 'MyRdsDb', {
169169
defaultDatabaseName: 'MyAuroraDatabase',
170170
masterUser: {
171-
username: new cdk.Token('admin'),
172-
password: new cdk.Token('123456')
171+
username: 'admin',
172+
password: '123456'
173173
},
174174
engine: rds.DatabaseClusterEngine.Aurora,
175175
instanceProps: {

examples/cdk-examples-typescript/chat-app/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class MyStack extends cdk.Stack {
1313
new CognitoChatRoomPool(this, 'UserPool');
1414

1515
const bucket = s3.BucketRef.import(this, 'DougsBucket', {
16-
bucketName: new s3.BucketName('dougs-chat-app')
16+
bucketName: 'dougs-chat-app'
1717
});
1818

1919
new ChatAppFunction(this, 'StartAddBucket', {

packages/@aws-cdk/aws-cloudformation/examples/index.ts renamed to examples/cdk-examples-typescript/custom-resource/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { CustomResource } from '@aws-cdk/aws-cloudformation';
12
import lambda = require('@aws-cdk/aws-lambda');
23
import { cloudformation as s3 } from '@aws-cdk/aws-s3';
34
import cdk = require('@aws-cdk/cdk');
45
import fs = require('fs');
5-
import { CustomResource, SingletonLambda } from '../lib';
66

77
interface DemoResourceProps {
88
/**
@@ -18,24 +18,24 @@ interface DemoResourceProps {
1818

1919
class DemoResource extends cdk.Construct implements cdk.IDependable {
2020
public readonly dependencyElements: cdk.IDependable[];
21-
public readonly response: cdk.Token;
21+
public readonly response: string;
2222

2323
constructor(parent: cdk.Construct, name: string, props: DemoResourceProps) {
2424
super(parent, name);
2525

2626
const resource = new CustomResource(this, 'Resource', {
27-
lambdaProvider: new SingletonLambda(this, 'Singleton', {
27+
lambdaProvider: new lambda.SingletonFunction(this, 'Singleton', {
2828
uuid: 'f7d4f730-4ee1-11e8-9c2d-fa7ae01bbebc',
2929
// This makes the demo only work as top-level TypeScript program, but that's fine for now
30-
code: new lambda.LambdaInlineCode(fs.readFileSync('integ.trivial-lambda-provider.py', { encoding: 'utf-8' })),
30+
code: lambda.Code.inline(fs.readFileSync('provider.py', { encoding: 'utf-8' })),
3131
handler: 'index.main',
3232
timeout: 300,
33-
runtime: lambda.LambdaRuntime.Python27,
33+
runtime: lambda.Runtime.Python27,
3434
}),
3535
properties: props
3636
});
3737

38-
this.response = resource.getAtt('Response');
38+
this.response = resource.getAtt('Response').toString();
3939
this.dependencyElements = [resource];
4040
}
4141
}
@@ -101,4 +101,4 @@ new SucceedingStack(app, 'SucceedingStack');
101101
new FailCreationStack(app, 'FailCreationStack');
102102
new FailAfterCreatingStack(app, 'FailAfterCreatingStack');
103103

104-
process.stdout.write(app.run());
104+
process.stdout.write(app.run());

packages/@aws-cdk/aws-cloudformation/examples/provider.py renamed to examples/cdk-examples-typescript/custom-resource/provider.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ def main(event, context):
2323
except Exception as e:
2424
log.exception(e)
2525
# cfnresponse's error message is always "see CloudWatch"
26-
cfnresponse.send(event, context, cfnresponse.FAILED, {}, physical_id)
26+
cfnresponse.send(event, context, cfnresponse.FAILED, {}, physical_id)

examples/cdk-examples-typescript/neptune-demo/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import ec2 = require('@aws-cdk/aws-ec2');
22
import neptune = require('@aws-cdk/aws-neptune');
3-
import rds = require('@aws-cdk/aws-rds');
43
import cdk = require('@aws-cdk/cdk');
54

65
class NeptuneDemoStack extends cdk.Stack {
@@ -19,8 +18,8 @@ class NeptuneDemoStack extends cdk.Stack {
1918
masterUser: {
2019
// This would normally be imported from SSM parmeter store encrypted string,
2120
// but don't want to overcomplicate the example
22-
username: new rds.Username('admin'),
23-
password: new rds.Password('eRSDwst7lpzu'),
21+
username: 'admin',
22+
password: 'eRSDwst7lpzu',
2423
}
2524
});
2625
database.connections.allowDefaultPortFrom(new ec2.AnyIPv4(), 'Allow the world to connect');

packages/@aws-cdk/assets/lib/asset.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ export class Asset extends cdk.Construct {
4747
/**
4848
* Attribute that represents the name of the bucket this asset exists in.
4949
*/
50-
public readonly s3BucketName: s3.BucketName;
50+
public readonly s3BucketName: string;
5151

5252
/**
5353
* Attribute which represents the S3 object key of this asset.
5454
*/
55-
public readonly s3ObjectKey: s3.ObjectKey;
55+
public readonly s3ObjectKey: string;
5656

5757
/**
5858
* Attribute which represents the S3 URL of this asset.
5959
* @example https://s3.us-west-1.amazonaws.com/bucket/key
6060
*/
61-
public readonly s3Url: s3.S3Url;
61+
public readonly s3Url: string;
6262

6363
/**
6464
* Resolved full-path location of this asset.
@@ -70,7 +70,7 @@ export class Asset extends cdk.Construct {
7070
/**
7171
* The S3 prefix where all different versions of this asset are stored
7272
*/
73-
private readonly s3Prefix: cdk.Token;
73+
private readonly s3Prefix: string;
7474

7575
constructor(parent: cdk.Construct, id: string, props: GenericAssetProps) {
7676
super(parent, id);
@@ -94,10 +94,10 @@ export class Asset extends cdk.Construct {
9494
description: `S3 key for asset version "${this.path}"`
9595
});
9696

97-
this.s3BucketName = new s3.BucketName(bucketParam.value);
98-
this.s3Prefix = new cdk.FnSelect(0, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value));
99-
const s3Filename = new cdk.FnSelect(1, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value));
100-
this.s3ObjectKey = new s3.ObjectKey(new cdk.FnConcat(this.s3Prefix, s3Filename));
97+
this.s3BucketName = bucketParam.value.toString();
98+
this.s3Prefix = new cdk.FnSelect(0, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value)).toString();
99+
const s3Filename = new cdk.FnSelect(1, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value)).toString();
100+
this.s3ObjectKey = `${this.s3Prefix}${s3Filename}`;
101101

102102
this.bucket = s3.BucketRef.import(this, 'AssetBucket', {
103103
bucketName: this.s3BucketName

packages/@aws-cdk/aws-apigateway/lib/deployment.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import cdk = require('@aws-cdk/cdk');
22
import crypto = require('crypto');
3-
import { cloudformation, DeploymentId } from './apigateway.generated';
3+
import { cloudformation } from './apigateway.generated';
44
import { RestApiRef } from './restapi-ref';
55

66
export interface DeploymentProps {
@@ -55,7 +55,7 @@ export interface DeploymentProps {
5555
* automatically for the `restApi.latestDeployment` deployment.
5656
*/
5757
export class Deployment extends cdk.Construct implements cdk.IDependable {
58-
public readonly deploymentId: DeploymentId;
58+
public readonly deploymentId: string;
5959
public readonly api: RestApiRef;
6060

6161
/**
@@ -78,7 +78,7 @@ export class Deployment extends cdk.Construct implements cdk.IDependable {
7878
}
7979

8080
this.api = props.api;
81-
this.deploymentId = new DeploymentId(() => this.resource.ref);
81+
this.deploymentId = new cdk.Token(() => this.resource.deploymentId).toString();
8282
this.dependencyElements.push(this.resource);
8383
}
8484

@@ -142,13 +142,13 @@ class LatestDeploymentResource extends cloudformation.DeploymentResource {
142142
* Returns a lazy reference to this resource (evaluated only upon synthesis).
143143
*/
144144
public get ref() {
145-
return new DeploymentId(() => ({ Ref: this.lazyLogicalId }));
145+
return new cdk.Token(() => ({ Ref: this.lazyLogicalId })).toString();
146146
}
147147

148148
/**
149149
* Does nothing.
150150
*/
151-
public set ref(_v: DeploymentId) {
151+
public set ref(_v: string) {
152152
return;
153153
}
154154

packages/@aws-cdk/aws-apigateway/lib/integrations/aws.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class AwsIntegration extends Integration {
6868
super({
6969
type,
7070
integrationHttpMethod: 'POST',
71-
uri: cdk.Arn.fromComponents({
71+
uri: cdk.ArnUtils.fromComponents({
7272
service: 'apigateway',
7373
account: backend,
7474
resource: apiType,

packages/@aws-cdk/aws-apigateway/lib/method.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import cdk = require('@aws-cdk/cdk');
2-
import { AuthorizerId, cloudformation, MethodId } from './apigateway.generated';
2+
import { cloudformation } from './apigateway.generated';
33
import { Integration } from './integration';
44
import { MockIntegration } from './integrations/mock';
55
import { IRestApiResource } from './resource';
@@ -26,7 +26,7 @@ export interface MethodOptions {
2626
* NOTE: in the future this will be replaced with an `AuthorizerRef`
2727
* construct.
2828
*/
29-
authorizerId?: AuthorizerId;
29+
authorizerId?: string;
3030

3131
/**
3232
* Indicates whether the method requires clients to submit a valid API key.
@@ -65,7 +65,7 @@ export interface MethodProps {
6565
}
6666

6767
export class Method extends cdk.Construct {
68-
public readonly methodId: MethodId;
68+
public readonly methodId: string;
6969
public readonly httpMethod: string;
7070
public readonly resource: IRestApiResource;
7171
public readonly restApi: RestApi;
@@ -115,7 +115,7 @@ export class Method extends cdk.Construct {
115115
* NOTE: {stage} will refer to the `restApi.deploymentStage`, which will
116116
* automatically set if auto-deploy is enabled.
117117
*/
118-
public get methodArn(): cdk.Arn {
118+
public get methodArn(): string {
119119
if (!this.restApi.deploymentStage) {
120120
throw new Error('There is no stage associated with this restApi. Either use `autoDeploy` or explicitly assign `deploymentStage`');
121121
}
@@ -128,7 +128,7 @@ export class Method extends cdk.Construct {
128128
* Returns an execute-api ARN for this method's "test-invoke-stage" stage.
129129
* This stage is used by the AWS Console UI when testing the method.
130130
*/
131-
public get testMethodArn(): cdk.Arn {
131+
public get testMethodArn(): string {
132132
return this.restApi.executeApiArn(this.httpMethod, this.resource.resourcePath, 'test-invoke-stage');
133133
}
134134

@@ -156,7 +156,7 @@ export class Method extends cdk.Construct {
156156
credentials = options.credentialsRole.roleArn;
157157
} else if (options.credentialsPassthrough) {
158158
// arn:aws:iam::*:user/*
159-
credentials = cdk.Arn.fromComponents({ service: 'iam', region: '', account: '*', resource: 'user', sep: '/', resourceName: '*' });
159+
credentials = cdk.ArnUtils.fromComponents({ service: 'iam', region: '', account: '*', resource: 'user', sep: '/', resourceName: '*' });
160160
}
161161

162162
return {

0 commit comments

Comments
 (0)