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

BREAKING CHANGE: strongly type resource refs #627

Merged
merged 6 commits into from
Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
2 changes: 1 addition & 1 deletion packages/@aws-cdk/assets/lib/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class Asset extends cdk.Construct {
this.s3BucketName = bucketParam.value;
this.s3Prefix = new cdk.FnSelect(0, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value));
const s3Filename = new cdk.FnSelect(1, new cdk.FnSplit(cxapi.ASSET_PREFIX_SEPARATOR, keyParam.value));
this.s3ObjectKey = new cdk.FnConcat(this.s3Prefix, s3Filename);
this.s3ObjectKey = new s3.ObjectKey(new cdk.FnConcat(this.s3Prefix, s3Filename));

this.bucket = s3.BucketRef.import(parent, 'AssetBucket', {
bucketName: this.s3BucketName
Expand Down
53 changes: 30 additions & 23 deletions packages/@aws-cdk/assets/test/integ.assets.refs.lit.expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,29 +76,36 @@
},
"/",
{
"Fn::Select": [
0,
{
"Fn::Split": [
"||",
{
"Ref": "SampleAssetS3VersionKey3E106D34"
}
]
}
]
},
{
"Fn::Select": [
1,
{
"Fn::Split": [
"||",
{
"Ref": "SampleAssetS3VersionKey3E106D34"
}
]
}
"Fn::Join": [
"",
[
{
"Fn::Select": [
0,
{
"Fn::Split": [
"||",
{
"Ref": "SampleAssetS3VersionKey3E106D34"
}
]
}
]
},
{
"Fn::Select": [
1,
{
"Fn::Split": [
"||",
{
"Ref": "SampleAssetS3VersionKey3E106D34"
}
]
}
]
}
]
]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,9 @@ export = {

function mockVpc(stack: cdk.Stack) {
return ec2.VpcNetwork.import(stack, 'MyVpc', {
vpcId: new ec2.VpcNetworkId('my-vpc'),
vpcId: new ec2.VPCId('my-vpc'),
availabilityZones: [ 'az1' ],
publicSubnetIds: [ new ec2.VpcSubnetId('pub1') ],
privateSubnetIds: [ new ec2.VpcSubnetId('pri1') ],
publicSubnetIds: [ new ec2.SubnetId('pub1') ],
privateSubnetIds: [ new ec2.SubnetId('pri1') ],
});
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { Arn, Construct, Output } from "@aws-cdk/cdk";

/**
* Represents the ARN of a certificate
*/
export class CertificateArn extends Arn {
}
import { Construct, Output } from "@aws-cdk/cdk";
import { CertificateArn } from './certificatemanager.generated';

/**
* Interface for certificate-like objects
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-certificatemanager/lib/certificate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Construct } from '@aws-cdk/cdk';
import { CertificateArn, CertificateRef } from './certificate-ref';
import { cloudformation } from './certificatemanager.generated';
import { CertificateRef } from './certificate-ref';
import { CertificateArn, cloudformation } from './certificatemanager.generated';
import { apexDomain } from './util';

/**
Expand Down
6 changes: 2 additions & 4 deletions packages/@aws-cdk/aws-codebuild/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import kms = require('@aws-cdk/aws-kms');
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import { BuildArtifacts, CodePipelineBuildArtifacts, NoBuildArtifacts } from './artifacts';
import { cloudformation, ProjectArn } from './codebuild.generated';
import { cloudformation, ProjectArn, ProjectName } from './codebuild.generated';
import { BuildSource } from './source';

const CODEPIPELINE_TYPE = 'CODEPIPELINE';
Expand Down Expand Up @@ -704,6 +704,4 @@ export enum BuildEnvironmentVariableType {
* An environment variable stored in Systems Manager Parameter Store.
*/
ParameterStore = 'PARAMETER_STORE'
}

export class ProjectName extends cdk.Token { }
}
7 changes: 1 addition & 6 deletions packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ import iam = require('@aws-cdk/aws-iam');
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import util = require('@aws-cdk/util');
import { cloudformation, PipelineVersion } from './codepipeline.generated';
import { cloudformation, PipelineName, PipelineVersion } from './codepipeline.generated';
import { Stage } from './stage';

/**
* The ARN of a pipeline
*/
export class PipelineArn extends cdk.Arn { }

/**
* The name of the pipeline.
*/
export class PipelineName extends cdk.Token { }

export interface PipelineProps {
/**
* The S3 bucket used by this Pipeline to store artifacts.
Expand Down
123 changes: 1 addition & 122 deletions packages/@aws-cdk/aws-dynamodb/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,123 +1,2 @@
import { Construct, Token } from '@aws-cdk/cdk';
import { cloudformation } from './dynamodb.generated';

// AWS::DynamoDB CloudFormation Resources:
export * from './dynamodb.generated';

const HASH_KEY_TYPE = 'HASH';
const RANGE_KEY_TYPE = 'RANGE';

export interface TableProps {
/**
* The read capacity for the table. Careful if you add Global Secondary Indexes, as
* those will share the table's provisioned throughput.
* @default 5
*/
readCapacity?: number;
/**
* The write capacity for the table. Careful if you add Global Secondary Indexes, as
* those will share the table's provisioned throughput.
* @default 5
*/
writeCapacity?: number;

/**
* Enforces a particular physical table name.
* @default <generated>
*/
tableName?: string;
}

/**
* Provides a DynamoDB table.
*/
export class Table extends Construct {
private readonly table: cloudformation.TableResource;

private readonly keySchema = new Array<cloudformation.TableResource.KeySchemaProperty>();
private readonly attributeDefinitions = new Array<cloudformation.TableResource.AttributeDefinitionProperty>();

constructor(parent: Construct, name: string, props: TableProps = {}) {
super(parent, name);

const readCapacityUnits = props.readCapacity || 5;
const writeCapacityUnits = props.writeCapacity || 5;

this.table = new cloudformation.TableResource(this, 'Resource', {
tableName: props.tableName,
keySchema: this.keySchema,
attributeDefinitions: this.attributeDefinitions,
provisionedThroughput: { readCapacityUnits, writeCapacityUnits }
});

if (props.tableName) { this.addMetadata('aws:cdk:hasPhysicalName', props.tableName); }
}

public get tableArn() {
return this.table.tableArn;
}

public get tableName() {
return this.table.ref as TableName;
}

public get tableStreamArn() {
return this.table.tableStreamArn;
}

public addPartitionKey(name: string, type: KeyAttributeType): this {
this.addKey(name, type, HASH_KEY_TYPE);
return this;
}

public addSortKey(name: string, type: KeyAttributeType): this {
this.addKey(name, type, RANGE_KEY_TYPE);
return this;
}

public validate(): string[] {
const errors = new Array<string>();
if (!this.findKey(HASH_KEY_TYPE)) {
errors.push('a partition key must be specified');
}
return errors;
}

private findKey(keyType: string) {
return this.keySchema.find(prop => prop.keyType === keyType);
}

private addKey(name: string, type: KeyAttributeType, keyType: string) {
const existingProp = this.findKey(keyType);
if (existingProp) {
throw new Error(`Unable to set ${name} as a ${keyType} key, because ${existingProp.attributeName} is a ${keyType} key`);
}
this.registerAttribute(name, type);
this.keySchema.push({
attributeName: name,
keyType
});
return this;
}

private registerAttribute(name: string, type: KeyAttributeType) {
const existingDef = this.attributeDefinitions.find(def => def.attributeName === name);
if (existingDef && existingDef.attributeType !== type) {
throw new Error(`Unable to specify ${name} as ${type} because it was already defined as ${existingDef.attributeType}`);
}
if (!existingDef) {
this.attributeDefinitions.push({
attributeName: name,
attributeType: type
});
}
}
}

export class TableName extends Token {}

export enum KeyAttributeType {
Binary = 'B',
Number = 'N',
String = 'S',
}
export * from './table';
114 changes: 114 additions & 0 deletions packages/@aws-cdk/aws-dynamodb/lib/table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Construct } from '@aws-cdk/cdk';
import { cloudformation, TableArn, TableName, TableStreamArn } from './dynamodb.generated';

const HASH_KEY_TYPE = 'HASH';
const RANGE_KEY_TYPE = 'RANGE';

export interface TableProps {
/**
* The read capacity for the table. Careful if you add Global Secondary Indexes, as
* those will share the table's provisioned throughput.
* @default 5
*/
readCapacity?: number;
/**
* The write capacity for the table. Careful if you add Global Secondary Indexes, as
* those will share the table's provisioned throughput.
* @default 5
*/
writeCapacity?: number;

/**
* Enforces a particular physical table name.
* @default <generated>
*/
tableName?: string;
}

/**
* Provides a DynamoDB table.
*/
export class Table extends Construct {
public readonly tableArn: TableArn;
public readonly tableName: TableName;
public readonly tableStreamArn: TableStreamArn;

private readonly table: cloudformation.TableResource;

private readonly keySchema = new Array<cloudformation.TableResource.KeySchemaProperty>();
private readonly attributeDefinitions = new Array<cloudformation.TableResource.AttributeDefinitionProperty>();

constructor(parent: Construct, name: string, props: TableProps = {}) {
super(parent, name);

const readCapacityUnits = props.readCapacity || 5;
const writeCapacityUnits = props.writeCapacity || 5;

this.table = new cloudformation.TableResource(this, 'Resource', {
tableName: props.tableName,
keySchema: this.keySchema,
attributeDefinitions: this.attributeDefinitions,
provisionedThroughput: { readCapacityUnits, writeCapacityUnits }
});

if (props.tableName) { this.addMetadata('aws:cdk:hasPhysicalName', props.tableName); }

this.tableArn = this.table.tableArn;
this.tableName = this.table.ref;
this.tableStreamArn = this.table.tableStreamArn;
}

public addPartitionKey(name: string, type: KeyAttributeType): this {
this.addKey(name, type, HASH_KEY_TYPE);
return this;
}

public addSortKey(name: string, type: KeyAttributeType): this {
this.addKey(name, type, RANGE_KEY_TYPE);
return this;
}

public validate(): string[] {
const errors = new Array<string>();
if (!this.findKey(HASH_KEY_TYPE)) {
errors.push('a partition key must be specified');
}
return errors;
}

private findKey(keyType: string) {
return this.keySchema.find(prop => prop.keyType === keyType);
}

private addKey(name: string, type: KeyAttributeType, keyType: string) {
const existingProp = this.findKey(keyType);
if (existingProp) {
throw new Error(`Unable to set ${name} as a ${keyType} key, because ${existingProp.attributeName} is a ${keyType} key`);
}
this.registerAttribute(name, type);
this.keySchema.push({
attributeName: name,
keyType
});
return this;
}

private registerAttribute(name: string, type: KeyAttributeType) {
const existingDef = this.attributeDefinitions.find(def => def.attributeName === name);
if (existingDef && existingDef.attributeType !== type) {
throw new Error(`Unable to specify ${name} as ${type} because it was already defined as ${existingDef.attributeType}`);
}
if (!existingDef) {
this.attributeDefinitions.push({
attributeName: name,
attributeType: type
});
}
}
}

export enum KeyAttributeType {
Binary = 'B',
Number = 'N',
String = 'S',
}
4 changes: 1 addition & 3 deletions packages/@aws-cdk/aws-ec2/lib/security-group.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Construct, Output, Token } from '@aws-cdk/cdk';
import { Connections, IConnectable } from './connections';
import { cloudformation, SecurityGroupId, SecurityGroupVpcId } from './ec2.generated';
import { cloudformation, SecurityGroupId, SecurityGroupName, SecurityGroupVpcId } from './ec2.generated';
import { IPortRange, ISecurityGroupRule } from './security-group-rule';
import { slugify } from './util';
import { VpcNetworkRef } from './vpc-ref';
Expand Down Expand Up @@ -198,8 +198,6 @@ export class SecurityGroup extends SecurityGroupRef {
}
}

export class SecurityGroupName extends Token { }

export interface ConnectionRule {
/**
* The IP protocol name (tcp, udp, icmp) or number (see Protocol Numbers).
Expand Down
Loading