-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BREAKING CHANGE: strongly type resource refs (#627)
Annotate all CloudFormation resource types with the type of their 'Ref' (whether it returns a `Name`, `Id` or `Arn`). We generate specific classes for those types, just like we do for `{Fn::GetAtt}` attributes. This makes it easier to write construct libraries: it removes the need for every construct library to explicitly declare a custom type for the ref implicit type, and reduces chances of a `ClassCastException` in Java if they do it wrong. Generated resource classes no longer implicitly inherit from `Referenceable`, because not all resources even have the `{Ref}` operator defined. Fixes #619.
- Loading branch information
Showing
47 changed files
with
3,978 additions
and
368 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 2 additions & 7 deletions
9
packages/@aws-cdk/aws-certificatemanager/lib/certificate-ref.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.