From 50b9d349f1c06cb2e329c81845280d1eb8108524 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Tue, 3 Dec 2024 13:49:13 -0800 Subject: [PATCH 01/22] WIP feat(ec2-alpha): transit gateway L2 --- .../lib/transit-gateway-attachment.ts | 6 ++ ...transit-gateway-route-table-association.ts | 0 ...transit-gateway-route-table-propagation.ts | 0 .../lib/transit-gateway-route-table.ts | 0 .../lib/transit-gateway-route.ts | 0 .../aws-ec2-alpha/lib/transit-gateway.ts | 69 +++++++++++++++++++ 6 files changed, 75 insertions(+) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts new file mode 100644 index 0000000000000..e3c2cc001929e --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -0,0 +1,6 @@ +import { ITransitGateway } from "./transit-gateway"; + +export interface ITransitGatewayAttachment { + readonly transitGatewayAttachmentId: string; + readonly transitGatewayId: string; +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts new file mode 100644 index 0000000000000..a031f5dae41cd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -0,0 +1,69 @@ +import { CfnVPC, CfnVPCCidrBlock, CfnTransitGateway, DefaultInstanceTenancy, ISubnet, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { Arn, CfnResource, Lazy, Names, Resource, Tag } from 'aws-cdk-lib/core'; +import { Construct, DependencyGroup, IDependable } from 'constructs'; + +export enum TransitGatewayFeatureStatus { + ENABLE = 'enable', + DISABLE = 'disable', + } + +export interface ITransitGateway { + readonly transitGatewayId: string; + readonly transitGatewayArn: string; +} + +abstract class TransitGatewayBase extends Resource implements ITransitGateway { + public abstract readonly transitGatewayId: string; + + public abstract readonly transitGatewayArn: string; + +// addRouteTable(id: string, tags: Tag[]): TransitGatewayRouteTable { +// return new TransitGatewayRouteTable(this, id, props); +// } + +// attachVpc(id: string, vpc: IVpc, subnets: ISubnet[]): TransitGatewayAttachment { +// return new TransitGatewayAttachment(this, id, props); +// } +} + +export interface TransitGatewayProps { + readonly amazonSideAsn?: number; + readonly autoAcceptSharedAttachments?: string; + + // TODO: check if any other values will be supported besides ENABLED/DISABLED + readonly defaultRouteTableAssociation?: boolean; + readonly defaultRouteTablePropagation?: boolean; + readonly description?: string; + readonly dnsSupport?: boolean; + readonly multicastSupport?: boolean; + readonly vpnEcmpSupport?: boolean; + readonly tags?: Tag[]; +} + +export class TransitGateway extends TransitGatewayBase { + public readonly transitGatewayId: string; + public readonly transitGatewayArn: string; + + constructor(scope: Construct, id: string, props: TransitGatewayProps) { + super(scope, id); + + const resource = new CfnTransitGateway(this, id, { + amazonSideAsn: props.amazonSideAsn, + autoAcceptSharedAttachments: props.autoAcceptSharedAttachments, + defaultRouteTableAssociation: props.defaultRouteTableAssociation ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + defaultRouteTablePropagation: props.defaultRouteTablePropagation ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + description: props.description, + dnsSupport: props.dnsSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + multicastSupport: props.multicastSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + vpnEcmpSupport: props.vpnEcmpSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + tags: props.tags, + }); + + this.transitGatewayId = resource.ref; + this.transitGatewayArn = this.getResourceArnAttribute(resource.ref, { + service: 'ec2', + resource: 'transit-gateway', + resourceName: this.physicalName, + }); + } +} From d2af8a5fd73d421abfb523a857f721cce1846240 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Thu, 9 Jan 2025 11:43:51 -0800 Subject: [PATCH 02/22] skeleton --- .../lib/transit-gateway-attachment.ts | 104 ++++++++++- ...transit-gateway-route-table-association.ts | 49 +++++ ...transit-gateway-route-table-propagation.ts | 50 ++++++ .../lib/transit-gateway-route-table.ts | 59 ++++++ .../lib/transit-gateway-route.ts | 62 +++++++ .../aws-ec2-alpha/lib/transit-gateway.ts | 169 +++++++++++++----- 6 files changed, 442 insertions(+), 51 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index e3c2cc001929e..d6baa79580e47 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -1,6 +1,104 @@ -import { ITransitGateway } from "./transit-gateway"; +import { IResource, Resource, Tag } from 'aws-cdk-lib/core'; +import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; +import { CfnTransitGatewayAttachment, IVpc, SubnetSelection } from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; -export interface ITransitGatewayAttachment { +export interface ITransitGatewayAttachment extends IResource { + /** + * The ID of the transit gateway attachment. + * @attribute + */ readonly transitGatewayAttachmentId: string; - readonly transitGatewayId: string; +} + +interface ITransitGatewayAttachmentOptions { + /** + * Enable or disable appliance mode support. + * + * @default - disable (false) + */ + readonly applianceModeSupport?: boolean; + + /** + * Enable or disable DNS support. + * + * @default - disable (false) + */ + readonly dnsSupport?: boolean; + + /** + * Enable or disable IPv6 support. + * + * @default - disable (false) + */ + readonly ipv6Support?: boolean; + + /** + * Enables you to reference a security group across VPCs attached to a transit gateway. + * + * @default - disable (false) + */ + readonly securityGroupReferencingSupport?: boolean; +} + +export interface TransitGatewayAttachmentProps { + /** + * A list of one or more subnets to place the attachment in. + * It is recommended to specify more subnets for better availability. + */ + readonly subnets: SubnetSelection; + // Note: SubnetSelection[] is same as Subnet[] but allows for optional filtering + + /** + * The transit gateway this attachment gets assigned to. + */ + readonly transitGateway: ITransitGateway; + + /** + * A VPC attachment(s) will get assigned to. + */ + readonly vpc: IVpc; + + /** + * The VPC attachment options. + */ + readonly transitGatewayAttachmentOptions?: ITransitGatewayAttachmentOptions; + + /** + * The tags for the transit gateway attachment. + * + * @default - none + */ + readonly tags?: Tag[]; +} + +abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { + public abstract readonly transitGatewayAttachmentId: string; +} + +export class TransitGatewayAttachment extends TransitGatewayAttachmentBase { + public readonly transitGatewayAttachmentId: string; + + constructor(scope: Construct, id: string, props: TransitGatewayAttachmentProps) { + super(scope, id); + + const resource = new CfnTransitGatewayAttachment(this, 'TransitGatewayAttachment', { + subnetIds: props.vpc.selectSubnets(props.subnets).subnetIds, + transitGatewayId: props.transitGateway.transitGatewayId, + vpcId: props.vpc.vpcId, + options: { + applianceModeSupport: (props.transitGatewayAttachmentOptions?.applianceModeSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + dnsSupport: (props.transitGatewayAttachmentOptions?.dnsSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + ipv6Support: (props.transitGatewayAttachmentOptions?.ipv6Support ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + securityGroupReferencingSupport: (props.transitGatewayAttachmentOptions?.securityGroupReferencingSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + }, + tags: props.tags, + }); + + this.transitGatewayAttachmentId = resource.ref; + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index e69de29bb2d1d..42c2e64c1e421 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -0,0 +1,49 @@ +import { IResource, Resource } from 'aws-cdk-lib/core'; +import { ITransitGatewayAttachment } from './transit-gateway-attachment'; +import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; +import { CfnTransitGatewayRouteTableAssociation } from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; + +export interface ITransitGatewayRouteTableAssociation extends IResource { + /** + * The ID of the transit gateway route table association. + */ + readonly transitGatewayRouteTableAssociationId: string; +} + +export interface TransitGatewayRouteTableAssociationProps { + /** + * The ID of the transit gateway route table association. + */ + readonly transitGatewayAttachment: ITransitGatewayAttachment; + + /** + * The ID of the transit gateway route table association. + */ + readonly transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +abstract class TransitGatewayRouteTableAssociationBase extends Resource implements ITransitGatewayRouteTableAssociation { + /** + * The ID of the transit gateway route table association. + */ + public abstract readonly transitGatewayRouteTableAssociationId: string; +} + +export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTableAssociationBase { + /** + * The ID of the transit gateway route table association. + */ + public readonly transitGatewayRouteTableAssociationId: string; + + constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) { + super(scope, id); + + const resource = new CfnTransitGatewayRouteTableAssociation(this, 'TransitGatewayRouteTableAssociation', { + transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, + transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, + }); + + this.transitGatewayRouteTableAssociationId = resource.ref; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index e69de29bb2d1d..ec1a7e5f8fad4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -0,0 +1,50 @@ +import { IResource, Resource } from 'aws-cdk-lib/core'; +import { CfnTransitGatewayRouteTablePropagation } from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; +import { ITransitGatewayAttachment } from './transit-gateway-attachment'; +import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; + +export interface ITransitGatewayRouteTablePropagation extends IResource { + /** + * The ID of the transit gateway route table propagation. + * @attribute + */ + readonly transitGatewayRouteTablePropagationId: string; +} + +export interface TransitGatewayRouteTablePropagationProps { + /** + * The ID of the transit gateway route table propagation. + */ + readonly transitGatewayAttachment: ITransitGatewayAttachment; + + /** + * The ID of the transit gateway route table propagation. + */ + readonly transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +abstract class TransitGatewayRouteTablePropagationBase extends Resource implements ITransitGatewayRouteTablePropagation { + /** + * The ID of the transit gateway route table propagation. + */ + public abstract readonly transitGatewayRouteTablePropagationId: string; +} + +export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTablePropagationBase { + /** + * The ID of the transit gateway route table propagation. + */ + public readonly transitGatewayRouteTablePropagationId: string; + + constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { + super(scope, id); + + const resource = new CfnTransitGatewayRouteTablePropagation(this, 'TransitGatewayRouteTablePropagation', { + transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, + transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, + }); + + this.transitGatewayRouteTablePropagationId = resource.ref; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index e69de29bb2d1d..5af2a9433e481 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -0,0 +1,59 @@ +import { IResource, Resource, Tag, TagManager } from 'aws-cdk-lib/core'; +import { ITransitGateway } from './transit-gateway'; +import { Construct } from 'constructs'; +import { CfnTransitGatewayRouteTable } from 'aws-cdk-lib/aws-ec2'; + +export interface ITransitGatewayRouteTable extends IResource { + /** + * The ID of the transit gateway route table + * @attribute + */ + readonly transitGatewayRouteTableId: string; +} + +export interface TransitGatewayRouteTableProps { + /** + * The ID of the transit gateway + */ + readonly transitGateway: ITransitGateway; + + /** + * The tags for the transit gateway route table. + * + * @default - none + */ + readonly tags?: Tag[]; +} + +abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable { + + public abstract readonly transitGatewayRouteTableId: string; + + addRoute(id: string, props: any): void { + return; + } + + addRoutes(id: string, props: any): void { + return; + } +} + +/** + * An AWS Transit Gateway route table + * + * @resource AWS::EC2::TransitGatewayRouteTable + */ +export class TransitGatewayRouteTable extends TransitGatewayRouteTableBase { + public readonly transitGatewayRouteTableId: string; + + constructor(scope: Construct, id: string, props: TransitGatewayRouteTableProps) { + super(scope, id); + + const resource = new CfnTransitGatewayRouteTable(this, id, { + transitGatewayId: props.transitGateway.transitGatewayId, + tags: props.tags, + }); + + this.transitGatewayRouteTableId = resource.ref; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index e69de29bb2d1d..1fa8b78b8f518 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -0,0 +1,62 @@ +import { IResource, Resource, Tag, TagManager } from 'aws-cdk-lib/core'; +import { ITransitGateway } from './transit-gateway'; +import { Construct } from 'constructs'; +import { CfnTransitGatewayRoute } from 'aws-cdk-lib/aws-ec2'; +import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; +import { ITransitGatewayAttachment } from './transit-gateway-attachment'; + +export interface ITransitGatewayRoute extends IResource { + /** + * The destination CIDR block for this route. + */ + readonly destinationCidrBlock: string; + + /** + * The transit gateway route table this route belongs to. + */ + readonly transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +export interface TransitGatewayRouteProps { + /** + * The transit gateway attachment to route the traffic to. + * + * @default - if no attachment is specified, the traffic matching the destination CIDR will be dropped (blackhole). + */ + readonly transitGatewayAttachment?: ITransitGatewayAttachment; + + /** + * The CIDR block used for destination matches. + */ + readonly destinationCidrBlock: string; + + /** + * The transit gateway route table you want to install this route into. + */ + readonly transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +abstract class TransitGatewayRouteBase extends Resource implements ITransitGatewayRoute { + public abstract destinationCidrBlock: string; + public abstract transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +export class TransitGatewayRoute extends TransitGatewayRouteBase { + public transitGatewayRouteTable: ITransitGatewayRouteTable; + public readonly destinationCidrBlock: string; + public readonly routeTableId: string; + + constructor(scope: Construct, id: string, props: TransitGatewayRouteProps) { + super(scope, id); + + const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { + destinationCidrBlock: props.destinationCidrBlock, + transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, + blackhole: props.transitGatewayAttachment?.transitGatewayAttachmentId ? false : true, + transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayAttachmentId, + }); + + this.destinationCidrBlock = resource.destinationCidrBlock; + this.routeTableId = resource.transitGatewayRouteTableId; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index a031f5dae41cd..8d314cd9b778e 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -1,25 +1,25 @@ -import { CfnVPC, CfnVPCCidrBlock, CfnTransitGateway, DefaultInstanceTenancy, ISubnet, SubnetType } from 'aws-cdk-lib/aws-ec2'; -import { Arn, CfnResource, Lazy, Names, Resource, Tag } from 'aws-cdk-lib/core'; -import { Construct, DependencyGroup, IDependable } from 'constructs'; +import { CfnTransitGateway, CfnTransitGatewayRouteTable } from 'aws-cdk-lib/aws-ec2'; +import { Resource, Tag } from 'aws-cdk-lib/core'; +import { Construct } from 'constructs'; export enum TransitGatewayFeatureStatus { - ENABLE = 'enable', - DISABLE = 'disable', - } + ENABLE = 'enable', + DISABLE = 'disable', +} export interface ITransitGateway { - readonly transitGatewayId: string; - readonly transitGatewayArn: string; -} + readonly transitGatewayId: string; + readonly transitGatewayArn: string; +} abstract class TransitGatewayBase extends Resource implements ITransitGateway { public abstract readonly transitGatewayId: string; public abstract readonly transitGatewayArn: string; -// addRouteTable(id: string, tags: Tag[]): TransitGatewayRouteTable { -// return new TransitGatewayRouteTable(this, id, props); -// } + // addRouteTable(id: string, tags: Tag[]): TransitGatewayRouteTable { + // return new TransitGatewayRouteTable(this, id, props); + // } // attachVpc(id: string, vpc: IVpc, subnets: ISubnet[]): TransitGatewayAttachment { // return new TransitGatewayAttachment(this, id, props); @@ -27,43 +27,116 @@ abstract class TransitGatewayBase extends Resource implements ITransitGateway { } export interface TransitGatewayProps { - readonly amazonSideAsn?: number; - readonly autoAcceptSharedAttachments?: string; - - // TODO: check if any other values will be supported besides ENABLED/DISABLED - readonly defaultRouteTableAssociation?: boolean; - readonly defaultRouteTablePropagation?: boolean; - readonly description?: string; - readonly dnsSupport?: boolean; - readonly multicastSupport?: boolean; - readonly vpnEcmpSupport?: boolean; - readonly tags?: Tag[]; + /** + * A private Autonomous System Number (ASN) for the Amazon side of a BGP session. The range is 64512 to 65534 for 16-bit ASNs. + * + * @default - 64512 + */ + readonly amazonSideAsn?: number; + + /** + * Enable or disable automatic acceptance of attachment requests. + * + * @default - disable (false) + */ + readonly autoAcceptSharedAttachments?: boolean; + + /** + * Enable or disable automatic association with the default association route table. + * + * @default - disable, a default route table will be created by the CDK instead of by CFN. + */ + readonly defaultRouteTableAssociation?: boolean; + + /** + * Enable or disable automatic propagation of routes to the default propagation route table. + * + * @default - disable, a default route table will be created by the CDK instead of by CFN. + */ + readonly defaultRouteTablePropagation?: boolean; + + /** + * The description of the transit gateway. + */ + readonly description?: string; + + /** + * Enable or disable DNS support + * + * @default - enable (true) + */ + readonly dnsSupport?: boolean; + + /** + * Indicates whether multicast is enabled on the transit gateway + * + * @default - disable (false) + */ + readonly multicastSupport?: boolean; + + /** + * Enable or disablesecurity group referencing support + * + * @default - disable (false) + */ + readonly securityGroupReferencingSupport?: boolean; + + /** + * The tags for the transit gateway. + * + * @default - none + */ + readonly tags?: Tag[]; + + /** + * The transit gateway CIDR blocks. + */ + readonly transitGatewayCidrBlocks?: string[]; + + /** + * Enable or disable Equal Cost Multipath Protocol support + * + * @default - enable (true) + */ + readonly vpnEcmpSupport?: boolean; } export class TransitGateway extends TransitGatewayBase { - public readonly transitGatewayId: string; - public readonly transitGatewayArn: string; - - constructor(scope: Construct, id: string, props: TransitGatewayProps) { - super(scope, id); - - const resource = new CfnTransitGateway(this, id, { - amazonSideAsn: props.amazonSideAsn, - autoAcceptSharedAttachments: props.autoAcceptSharedAttachments, - defaultRouteTableAssociation: props.defaultRouteTableAssociation ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - defaultRouteTablePropagation: props.defaultRouteTablePropagation ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - description: props.description, - dnsSupport: props.dnsSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - multicastSupport: props.multicastSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - vpnEcmpSupport: props.vpnEcmpSupport ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - tags: props.tags, - }); - - this.transitGatewayId = resource.ref; - this.transitGatewayArn = this.getResourceArnAttribute(resource.ref, { - service: 'ec2', - resource: 'transit-gateway', - resourceName: this.physicalName, - }); - } + public readonly transitGatewayId: string; + public readonly transitGatewayArn: string; + public readonly defaultRouteTable: CfnTransitGatewayRouteTable; + + constructor(scope: Construct, id: string, props: TransitGatewayProps) { + super(scope, id); + + const resource = new CfnTransitGateway(this, id, { + amazonSideAsn: props.amazonSideAsn ?? 64512, + autoAcceptSharedAttachments: (props.autoAcceptSharedAttachments ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + defaultRouteTableAssociation: (props.defaultRouteTableAssociation ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + defaultRouteTablePropagation: (props.defaultRouteTablePropagation ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + description: props.description, + dnsSupport: (props.dnsSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + multicastSupport: (props.multicastSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + vpnEcmpSupport: (props.vpnEcmpSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + tags: props.tags, + }); + + this.transitGatewayId = resource.ref; + this.transitGatewayArn = this.getResourceArnAttribute(resource.ref, { + service: 'ec2', + resource: 'transit-gateway', + resourceName: this.physicalName, + }); + + // Create the route table we'll use as default + this.defaultRouteTable = new CfnTransitGatewayRouteTable(this, 'DefaultRouteTable', { + transitGatewayId: this.transitGatewayId, + tags: [ + { key: 'Name', value: 'Default' }, + ], + }); + } } From a76835ca7ed3f44226c6eeef9326fc4dcfd69830 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 15 Jan 2025 13:37:17 -0800 Subject: [PATCH 03/22] updated classes --- .../lib/transit-gateway-attachment.ts | 67 ++- ...transit-gateway-route-table-association.ts | 4 +- ...transit-gateway-route-table-propagation.ts | 26 +- .../lib/transit-gateway-route-table.ts | 69 ++- .../lib/transit-gateway-route.ts | 62 ++- .../aws-ec2-alpha/lib/transit-gateway.ts | 115 +++-- ...way-disable-automatic-settings.assets.json | 19 + ...y-disable-automatic-settings.template.json | 206 ++++++++ .../integ.transit-gateway.js.snapshot/cdk.out | 1 + .../integ.json | 12 + ...efaultTestDeployAssertCF40BD53.assets.json | 19 + ...aultTestDeployAssertCF40BD53.template.json | 36 ++ .../manifest.json | 179 +++++++ .../tree.json | 470 ++++++++++++++++++ .../test/integ.transit-gateway.ts | 52 ++ 15 files changed, 1216 insertions(+), 121 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index d6baa79580e47..522d94ff85655 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -1,7 +1,9 @@ -import { IResource, Resource, Tag } from 'aws-cdk-lib/core'; +import { IResource, Resource } from 'aws-cdk-lib/core'; import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; -import { CfnTransitGatewayAttachment, IVpc, SubnetSelection } from 'aws-cdk-lib/aws-ec2'; +import { CfnTransitGatewayVpcAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; +import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; +import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; export interface ITransitGatewayAttachment extends IResource { /** @@ -11,7 +13,7 @@ export interface ITransitGatewayAttachment extends IResource { readonly transitGatewayAttachmentId: string; } -interface ITransitGatewayAttachmentOptions { +export interface ITransitGatewayAttachmentOptions { /** * Enable or disable appliance mode support. * @@ -46,9 +48,22 @@ export interface TransitGatewayAttachmentProps { * A list of one or more subnets to place the attachment in. * It is recommended to specify more subnets for better availability. */ - readonly subnets: SubnetSelection; - // Note: SubnetSelection[] is same as Subnet[] but allows for optional filtering + readonly subnets: ISubnet[]; + // WIP - probably will not expose these properties but will need to set them for the L1 behind the scenes + // /** + // * A list of one or more subnets to add. + // * You can specify at most one subnet per Availability Zone. + // * It is recommended to specify more subnets for better availability. + // */ + // readonly addSubnets?: ISubnet[]; + + // /** + // * A list of one or more subnets to place the attachment in. + // * It is recommended to specify more subnets for better availability. + // */ + + // readonly removeSubnets?: ISubnet[]; /** * The transit gateway this attachment gets assigned to. */ @@ -63,30 +78,31 @@ export interface TransitGatewayAttachmentProps { * The VPC attachment options. */ readonly transitGatewayAttachmentOptions?: ITransitGatewayAttachmentOptions; - - /** - * The tags for the transit gateway attachment. - * - * @default - none - */ - readonly tags?: Tag[]; } abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { public abstract readonly transitGatewayAttachmentId: string; + + // addSubnets(subnets: ISubnet[]): void { + // return; + // } + + // removeSubnets(subnets: ISubnet[]): void { + // return; + // } } -export class TransitGatewayAttachment extends TransitGatewayAttachmentBase { +export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { public readonly transitGatewayAttachmentId: string; constructor(scope: Construct, id: string, props: TransitGatewayAttachmentProps) { super(scope, id); - const resource = new CfnTransitGatewayAttachment(this, 'TransitGatewayAttachment', { - subnetIds: props.vpc.selectSubnets(props.subnets).subnetIds, + const resource = new CfnTransitGatewayVpcAttachment(this, 'TransitGatewayAttachment', { + subnetIds: props.subnets.map((subnet) => subnet.subnetId), transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, - options: { + options: props.transitGatewayAttachmentOptions ? { applianceModeSupport: (props.transitGatewayAttachmentOptions?.applianceModeSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, dnsSupport: (props.transitGatewayAttachmentOptions?.dnsSupport ?? false) @@ -95,10 +111,23 @@ export class TransitGatewayAttachment extends TransitGatewayAttachmentBase { ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, securityGroupReferencingSupport: (props.transitGatewayAttachmentOptions?.securityGroupReferencingSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - }, - tags: props.tags, + } : undefined, }); this.transitGatewayAttachmentId = resource.ref; + + if (props.transitGateway.defaultRouteTableAssociation) { + new TransitGatewayRouteTableAssociation(this, id, { + transitGatewayAttachment: this, + transitGatewayRouteTable: props.transitGateway.defaultRouteTable, + }); + } + + if (props.transitGateway.defaultRouteTablePropagation) { + new TransitGatewayRouteTablePropagation(this, id + 'Propagation', { + transitGatewayAttachment: this, + transitGatewayRouteTable: props.transitGateway.defaultRouteTable, + }); + } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index 42c2e64c1e421..9b6fe3cb23c78 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -41,9 +41,9 @@ export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTabl const resource = new CfnTransitGatewayRouteTableAssociation(this, 'TransitGatewayRouteTableAssociation', { transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, - transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, + transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); this.transitGatewayRouteTableAssociationId = resource.ref; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index ec1a7e5f8fad4..b92efd74d20f8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -6,35 +6,35 @@ import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; export interface ITransitGatewayRouteTablePropagation extends IResource { /** - * The ID of the transit gateway route table propagation. - * @attribute - */ + * The ID of the transit gateway route table propagation. + * @attribute + */ readonly transitGatewayRouteTablePropagationId: string; } export interface TransitGatewayRouteTablePropagationProps { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ readonly transitGatewayAttachment: ITransitGatewayAttachment; /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; } abstract class TransitGatewayRouteTablePropagationBase extends Resource implements ITransitGatewayRouteTablePropagation { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ public abstract readonly transitGatewayRouteTablePropagationId: string; } export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTablePropagationBase { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ public readonly transitGatewayRouteTablePropagationId: string; constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { @@ -42,9 +42,9 @@ export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTabl const resource = new CfnTransitGatewayRouteTablePropagation(this, 'TransitGatewayRouteTablePropagation', { transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, - transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, + transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); this.transitGatewayRouteTablePropagationId = resource.ref; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index 5af2a9433e481..f4210653d465b 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -1,40 +1,58 @@ -import { IResource, Resource, Tag, TagManager } from 'aws-cdk-lib/core'; +import { IResource, Resource } from 'aws-cdk-lib/core'; import { ITransitGateway } from './transit-gateway'; import { Construct } from 'constructs'; -import { CfnTransitGatewayRouteTable } from 'aws-cdk-lib/aws-ec2'; +import { CfnTransitGatewayRouteTable, IRouteTable } from 'aws-cdk-lib/aws-ec2'; +import { ITransitGatewayAttachment } from './transit-gateway-attachment'; +import { TransitGatewayActiveRoute, TransitGatewayBlackholeRoute } from './transit-gateway-route'; +import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; +import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; export interface ITransitGatewayRouteTable extends IResource { /** - * The ID of the transit gateway route table - * @attribute - */ - readonly transitGatewayRouteTableId: string; + * The ID of the transit gateway route table + * @attribute + */ + readonly routeTableId: string; } export interface TransitGatewayRouteTableProps { /** - * The ID of the transit gateway - */ + * The ID of the transit gateway + */ readonly transitGateway: ITransitGateway; - - /** - * The tags for the transit gateway route table. - * - * @default - none - */ - readonly tags?: Tag[]; } -abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable { +abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable, IRouteTable { + public abstract readonly routeTableId: string; + public abstract readonly transitGateway: ITransitGateway; - public abstract readonly transitGatewayRouteTableId: string; + addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayActiveRoute { + return new TransitGatewayActiveRoute(this, id, { + transitGatewayRouteTable: this, + transitGatewayAttachment, + destinationCidrBlock: destinationCidr, + }); + }; - addRoute(id: string, props: any): void { - return; + addBlackholeRoute(id: string, destinationCidr: string): TransitGatewayBlackholeRoute { + return new TransitGatewayBlackholeRoute(this, id, { + transitGatewayRouteTable: this, + destinationCidrBlock: destinationCidr, + }); } - addRoutes(id: string, props: any): void { - return; + addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTableAssociation { + return new TransitGatewayRouteTableAssociation(this, id, { + transitGatewayAttachment: transitGatewayAttachment, + transitGatewayRouteTable: this, + }); + } + + enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTablePropagation { + return new TransitGatewayRouteTablePropagation(this, id, { + transitGatewayAttachment: transitGatewayAttachment, + transitGatewayRouteTable: this, + }); } } @@ -44,16 +62,17 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit * @resource AWS::EC2::TransitGatewayRouteTable */ export class TransitGatewayRouteTable extends TransitGatewayRouteTableBase { - public readonly transitGatewayRouteTableId: string; + public readonly routeTableId: string; + public readonly transitGateway: ITransitGateway; constructor(scope: Construct, id: string, props: TransitGatewayRouteTableProps) { super(scope, id); const resource = new CfnTransitGatewayRouteTable(this, id, { transitGatewayId: props.transitGateway.transitGatewayId, - tags: props.tags, }); - this.transitGatewayRouteTableId = resource.ref; + this.routeTableId = resource.ref; + this.transitGateway = props.transitGateway; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index 1fa8b78b8f518..a733feb51bb08 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -1,5 +1,4 @@ -import { IResource, Resource, Tag, TagManager } from 'aws-cdk-lib/core'; -import { ITransitGateway } from './transit-gateway'; +import { IResource, Resource } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { CfnTransitGatewayRoute } from 'aws-cdk-lib/aws-ec2'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; @@ -14,17 +13,27 @@ export interface ITransitGatewayRoute extends IResource { /** * The transit gateway route table this route belongs to. */ - readonly transitGatewayRouteTable: ITransitGatewayRouteTable; + readonly routeTable: ITransitGatewayRouteTable; } -export interface TransitGatewayRouteProps { +export interface TransitGatewayActiveRouteProps { /** - * The transit gateway attachment to route the traffic to. - * - * @default - if no attachment is specified, the traffic matching the destination CIDR will be dropped (blackhole). - */ - readonly transitGatewayAttachment?: ITransitGatewayAttachment; + * The transit gateway attachment to route the traffic to. + */ + readonly transitGatewayAttachment: ITransitGatewayAttachment; + + /** + * The CIDR block used for destination matches. + */ + readonly destinationCidrBlock: string; + /** + * The transit gateway route table you want to install this route into. + */ + readonly transitGatewayRouteTable: ITransitGatewayRouteTable; +} + +export interface TransitGatewayBlackholeRouteProps { /** * The CIDR block used for destination matches. */ @@ -37,26 +46,43 @@ export interface TransitGatewayRouteProps { } abstract class TransitGatewayRouteBase extends Resource implements ITransitGatewayRoute { + public abstract routeTable: ITransitGatewayRouteTable; public abstract destinationCidrBlock: string; - public abstract transitGatewayRouteTable: ITransitGatewayRouteTable; } -export class TransitGatewayRoute extends TransitGatewayRouteBase { - public transitGatewayRouteTable: ITransitGatewayRouteTable; +export class TransitGatewayActiveRoute extends TransitGatewayRouteBase { + public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; - public readonly routeTableId: string; - constructor(scope: Construct, id: string, props: TransitGatewayRouteProps) { + constructor(scope: Construct, id: string, props: TransitGatewayActiveRouteProps) { super(scope, id); const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { + blackhole: false, destinationCidrBlock: props.destinationCidrBlock, - transitGatewayRouteTableId: props.transitGatewayRouteTable.transitGatewayRouteTableId, - blackhole: props.transitGatewayAttachment?.transitGatewayAttachmentId ? false : true, + transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayAttachmentId, }); this.destinationCidrBlock = resource.destinationCidrBlock; - this.routeTableId = resource.transitGatewayRouteTableId; + this.routeTable = props.transitGatewayRouteTable; + } +} + +export class TransitGatewayBlackholeRoute extends TransitGatewayRouteBase { + public readonly routeTable: ITransitGatewayRouteTable; + public readonly destinationCidrBlock: string; + + constructor(scope: Construct, id: string, props: TransitGatewayBlackholeRouteProps) { + super(scope, id); + + const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { + blackhole: true, + destinationCidrBlock: props.destinationCidrBlock, + transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, + }); + + this.destinationCidrBlock = resource.destinationCidrBlock; + this.routeTable = props.transitGatewayRouteTable; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 8d314cd9b778e..70b8a8c1f2d08 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -1,6 +1,9 @@ -import { CfnTransitGateway, CfnTransitGatewayRouteTable } from 'aws-cdk-lib/aws-ec2'; -import { Resource, Tag } from 'aws-cdk-lib/core'; +import { CfnTransitGateway, ISubnet, IVpc, RouterType } from 'aws-cdk-lib/aws-ec2'; +import { Resource } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; +import { ITransitGatewayRouteTable, TransitGatewayRouteTable } from './transit-gateway-route-table'; +import { TransitGatewayVpcAttachment, ITransitGatewayAttachmentOptions } from './transit-gateway-attachment'; +import { IRouteTarget } from './route'; export enum TransitGatewayFeatureStatus { ENABLE = 'enable', @@ -10,32 +13,21 @@ export enum TransitGatewayFeatureStatus { export interface ITransitGateway { readonly transitGatewayId: string; readonly transitGatewayArn: string; -} - -abstract class TransitGatewayBase extends Resource implements ITransitGateway { - public abstract readonly transitGatewayId: string; - - public abstract readonly transitGatewayArn: string; - - // addRouteTable(id: string, tags: Tag[]): TransitGatewayRouteTable { - // return new TransitGatewayRouteTable(this, id, props); - // } - -// attachVpc(id: string, vpc: IVpc, subnets: ISubnet[]): TransitGatewayAttachment { -// return new TransitGatewayAttachment(this, id, props); -// } + readonly defaultRouteTable: ITransitGatewayRouteTable; + readonly defaultRouteTableAssociation: boolean; + readonly defaultRouteTablePropagation: boolean; } export interface TransitGatewayProps { /** * A private Autonomous System Number (ASN) for the Amazon side of a BGP session. The range is 64512 to 65534 for 16-bit ASNs. * - * @default - 64512 + * @default - undefined */ readonly amazonSideAsn?: number; /** - * Enable or disable automatic acceptance of attachment requests. + * Enable or disable automatic acceptance of cross-account attachment requests. * * @default - disable (false) */ @@ -44,17 +36,24 @@ export interface TransitGatewayProps { /** * Enable or disable automatic association with the default association route table. * - * @default - disable, a default route table will be created by the CDK instead of by CFN. + * @default - enable */ readonly defaultRouteTableAssociation?: boolean; /** * Enable or disable automatic propagation of routes to the default propagation route table. * - * @default - disable, a default route table will be created by the CDK instead of by CFN. + * @default - enable */ readonly defaultRouteTablePropagation?: boolean; + /** + * A route table to be used in place of the default route table. + * + * @default - if not specified, a default route table will be created by the CDK instead of by EC2. + */ + readonly customDefaultRouteTable?: ITransitGatewayRouteTable; + /** * The description of the transit gateway. */ @@ -81,13 +80,6 @@ export interface TransitGatewayProps { */ readonly securityGroupReferencingSupport?: boolean; - /** - * The tags for the transit gateway. - * - * @default - none - */ - readonly tags?: Tag[]; - /** * The transit gateway CIDR blocks. */ @@ -101,42 +93,77 @@ export interface TransitGatewayProps { readonly vpnEcmpSupport?: boolean; } +abstract class TransitGatewayBase extends Resource implements ITransitGateway, IRouteTarget { + public abstract readonly routerType: RouterType; + public abstract readonly routerTargetId: string; + public abstract readonly transitGatewayId: string; + public abstract readonly transitGatewayArn: string; + public abstract readonly defaultRouteTable: TransitGatewayRouteTable; + public abstract readonly defaultRouteTableAssociation: boolean; + public abstract readonly defaultRouteTablePropagation: boolean; + + addRouteTable(id: string): TransitGatewayRouteTable { + return new TransitGatewayRouteTable(this, id, { + transitGateway: this, + }); + } + + attachVpc( + id: string, vpc: IVpc, + subnets: ISubnet[], + transitGatewayAttachmentOptions?: ITransitGatewayAttachmentOptions, + ): TransitGatewayVpcAttachment { + return new TransitGatewayVpcAttachment(this, id, { + transitGateway: this, + vpc: vpc, + subnets: subnets, + transitGatewayAttachmentOptions: transitGatewayAttachmentOptions ?? undefined, + }); + } +} + export class TransitGateway extends TransitGatewayBase { + public readonly routerType: RouterType; + public readonly routerTargetId: string; public readonly transitGatewayId: string; public readonly transitGatewayArn: string; - public readonly defaultRouteTable: CfnTransitGatewayRouteTable; + public readonly defaultRouteTable: TransitGatewayRouteTable; + public readonly defaultRouteTableAssociation: boolean; + public readonly defaultRouteTablePropagation: boolean; - constructor(scope: Construct, id: string, props: TransitGatewayProps) { + constructor(scope: Construct, id: string, props?: TransitGatewayProps) { super(scope, id); const resource = new CfnTransitGateway(this, id, { - amazonSideAsn: props.amazonSideAsn ?? 64512, - autoAcceptSharedAttachments: (props.autoAcceptSharedAttachments ?? false) + amazonSideAsn: props?.amazonSideAsn ?? undefined, + autoAcceptSharedAttachments: (props?.autoAcceptSharedAttachments ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - defaultRouteTableAssociation: (props.defaultRouteTableAssociation ?? false) + // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. + // Instead, CDK will create a custom default route table and use the properties to mimic the automatic assocation/propagation behaviour. + defaultRouteTableAssociation: (props?.defaultRouteTableAssociation ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - defaultRouteTablePropagation: (props.defaultRouteTablePropagation ?? false) + defaultRouteTablePropagation: (props?.defaultRouteTablePropagation ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - description: props.description, - dnsSupport: (props.dnsSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - multicastSupport: (props.multicastSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - vpnEcmpSupport: (props.vpnEcmpSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - tags: props.tags, + description: props?.description, + dnsSupport: (props?.dnsSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + multicastSupport: (props?.multicastSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + vpnEcmpSupport: (props?.vpnEcmpSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, }); this.transitGatewayId = resource.ref; + this.routerTargetId = resource.ref; + this.routerType = RouterType.TRANSIT_GATEWAY; this.transitGatewayArn = this.getResourceArnAttribute(resource.ref, { service: 'ec2', resource: 'transit-gateway', resourceName: this.physicalName, }); - // Create the route table we'll use as default - this.defaultRouteTable = new CfnTransitGatewayRouteTable(this, 'DefaultRouteTable', { - transitGatewayId: this.transitGatewayId, - tags: [ - { key: 'Name', value: 'Default' }, - ], + this.defaultRouteTable = (props?.customDefaultRouteTable as TransitGatewayRouteTable) ?? new TransitGatewayRouteTable(this, 'DefaultRouteTable', { + transitGateway: this, }); + + this.defaultRouteTableAssociation = props?.defaultRouteTableAssociation ?? true; + this.defaultRouteTablePropagation = props?.defaultRouteTablePropagation ?? true; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json new file mode 100644 index 0000000000000..151770ec5d5fd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "files": { + "167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664": { + "source": { + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json new file mode 100644 index 0000000000000..7dd9b7d5cbb97 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -0,0 +1,206 @@ +{ + "Resources": { + "SubnetTest3296A161": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.1.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest" + } + ] + } + }, + "SubnetTestSecondaryTest2AB12223": { + "Type": "AWS::EC2::VPCCidrBlock", + "Properties": { + "AmazonProvidedIpv6CidrBlock": true, + "VpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + } + }, + "testSubnet1Subnet72087287": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AssignIpv6AddressOnCreation": false, + "AvailabilityZone": "us-east-1a", + "CidrBlock": "10.1.0.0/20", + "VpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + }, + "DependsOn": [ + "SubnetTestSecondaryTest2AB12223" + ] + }, + "testSubnet1RouteTableB5FDDF81": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "DefaultCDKRouteTable" + } + ], + "VpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + }, + "DependsOn": [ + "SubnetTestSecondaryTest2AB12223" + ] + }, + "testSubnet1RouteTableAssociation1DA9E185": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Fn::GetAtt": [ + "testSubnet1RouteTableB5FDDF81", + "RouteTableId" + ] + }, + "SubnetId": { + "Ref": "testSubnet1Subnet72087287" + } + }, + "DependsOn": [ + "SubnetTestSecondaryTest2AB12223" + ] + }, + "TransitGateway11B93D57": { + "Type": "AWS::EC2::TransitGateway", + "Properties": { + "AutoAcceptSharedAttachments": "disable", + "DefaultRouteTableAssociation": "disable", + "DefaultRouteTablePropagation": "disable", + "DnsSupport": "enable", + "MulticastSupport": "disable", + "VpnEcmpSupport": "enable" + } + }, + "TransitGatewayDefaultRouteTable608EC117": { + "Type": "AWS::EC2::TransitGatewayRouteTable", + "Properties": { + "TransitGatewayId": { + "Ref": "TransitGateway11B93D57" + } + } + }, + "TransitGatewayDefaultRouteTabledefaultRTBRouteTransitGatewayRouteAB7CA8FF": { + "Type": "AWS::EC2::TransitGatewayRoute", + "Properties": { + "Blackhole": false, + "DestinationCidrBlock": "0.0.0.0/0", + "TransitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "TransitGatewayRouteTableId": { + "Ref": "TransitGatewayDefaultRouteTable608EC117" + } + } + }, + "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709": { + "Type": "AWS::EC2::TransitGatewayVpcAttachment", + "Properties": { + "AddSubnetIds": [], + "RemoveSubnetIds": [], + "SubnetIds": [ + { + "Ref": "testSubnet1Subnet72087287" + } + ], + "TransitGatewayId": { + "Ref": "TransitGateway11B93D57" + }, + "VpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + }, + "DependsOn": [ + "SubnetTest3296A161", + "SubnetTestSecondaryTest2AB12223" + ] + }, + "TransitGatewayRouteTable2047E2A04": { + "Type": "AWS::EC2::TransitGatewayRouteTable", + "Properties": { + "TransitGatewayId": { + "Ref": "TransitGateway11B93D57" + } + } + }, + "TransitGatewayRouteTable2customRtbAssociationTransitGatewayRouteTableAssociation9ADF3D3E": { + "Type": "AWS::EC2::TransitGatewayRouteTableAssociation", + "Properties": { + "TransitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "TransitGatewayRouteTableId": { + "Ref": "TransitGatewayRouteTable2047E2A04" + } + } + }, + "TransitGatewayRouteTable2customRtbPropagationTransitGatewayRouteTablePropagationFAE55BBD": { + "Type": "AWS::EC2::TransitGatewayRouteTablePropagation", + "Properties": { + "TransitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "TransitGatewayRouteTableId": { + "Ref": "TransitGatewayRouteTable2047E2A04" + } + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/cdk.out new file mode 100644 index 0000000000000..91e1a8b9901d5 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"39.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integ.json new file mode 100644 index 0000000000000..5365b390e3274 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "39.0.0", + "testCases": { + "integtest-model/DefaultTest": { + "stacks": [ + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings" + ], + "assertionStack": "integtest-model/DefaultTest/DeployAssert", + "assertionStackName": "integtestmodelDefaultTestDeployAssertCF40BD53" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json new file mode 100644 index 0000000000000..928ed61bb88d0 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.assets.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integtestmodelDefaultTestDeployAssertCF40BD53.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/integtestmodelDefaultTestDeployAssertCF40BD53.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json new file mode 100644 index 0000000000000..45a6f02e329a9 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -0,0 +1,179 @@ +{ + "version": "39.0.0", + "artifacts": { + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets" + ], + "metadata": { + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "SubnetTest3296A161" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest/SecondaryTest/SecondaryTest": [ + { + "type": "aws:cdk:logicalId", + "data": "SubnetTestSecondaryTest2AB12223" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "testSubnet1Subnet72087287" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/RouteTable/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "testSubnet1RouteTableB5FDDF81" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "testSubnet1RouteTableAssociation1DA9E185" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/TransitGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGateway11B93D57" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable/DefaultRouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayDefaultRouteTable608EC117" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable/defaultRTBRoute/TransitGatewayRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayDefaultRouteTabledefaultRTBRouteTransitGatewayRouteAB7CA8FF" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/TransitGatewayAttachment": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/RouteTable2": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayRouteTable2047E2A04" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/TransitGatewayRouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayRouteTable2customRtbAssociationTransitGatewayRouteTableAssociation9ADF3D3E" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/TransitGatewayRouteTablePropagation": [ + { + "type": "aws:cdk:logicalId", + "data": "TransitGatewayRouteTable2customRtbPropagationTransitGatewayRouteTablePropagationFAE55BBD" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings" + }, + "integtestmodelDefaultTestDeployAssertCF40BD53.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integtestmodelDefaultTestDeployAssertCF40BD53.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integtestmodelDefaultTestDeployAssertCF40BD53": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integtestmodelDefaultTestDeployAssertCF40BD53.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integtestmodelDefaultTestDeployAssertCF40BD53.assets" + ], + "metadata": { + "/integtest-model/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integtest-model/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integtest-model/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json new file mode 100644 index 0000000000000..903c7983f53d4 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -0,0 +1,470 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings": { + "id": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings", + "children": { + "SubnetTest": { + "id": "SubnetTest", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.1.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPC", + "version": "0.0.0" + } + }, + "SecondaryTest": { + "id": "SecondaryTest", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest/SecondaryTest", + "children": { + "SecondaryTest": { + "id": "SecondaryTest", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/SubnetTest/SecondaryTest/SecondaryTest", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCCidrBlock", + "aws:cdk:cloudformation:props": { + "amazonProvidedIpv6CidrBlock": true, + "vpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnVPCCidrBlock", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.VpcV2", + "version": "0.0.0" + } + }, + "testSubnet1": { + "id": "testSubnet1", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "assignIpv6AddressOnCreation": false, + "availabilityZone": "us-east-1a", + "cidrBlock": "10.1.0.0/20", + "vpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/Acl", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/RouteTable", + "children": { + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/RouteTable/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "DefaultCDKRouteTable" + } + ], + "vpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnRouteTable", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.RouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/testSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Fn::GetAtt": [ + "testSubnet1RouteTableB5FDDF81", + "RouteTableId" + ] + }, + "subnetId": { + "Ref": "testSubnet1Subnet72087287" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2-alpha.SubnetV2", + "version": "0.0.0" + } + }, + "TransitGateway": { + "id": "TransitGateway", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway", + "children": { + "TransitGateway": { + "id": "TransitGateway", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/TransitGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGateway", + "aws:cdk:cloudformation:props": { + "autoAcceptSharedAttachments": "disable", + "defaultRouteTableAssociation": "disable", + "defaultRouteTablePropagation": "disable", + "dnsSupport": "enable", + "multicastSupport": "disable", + "vpnEcmpSupport": "enable" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGateway", + "version": "0.0.0" + } + }, + "DefaultRouteTable": { + "id": "DefaultRouteTable", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable", + "children": { + "DefaultRouteTable": { + "id": "DefaultRouteTable", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable/DefaultRouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTable", + "aws:cdk:cloudformation:props": { + "transitGatewayId": { + "Ref": "TransitGateway11B93D57" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayRouteTable", + "version": "0.0.0" + } + }, + "defaultRTBRoute": { + "id": "defaultRTBRoute", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable/defaultRTBRoute", + "children": { + "TransitGatewayRoute": { + "id": "TransitGatewayRoute", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRouteTable/defaultRTBRoute/TransitGatewayRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRoute", + "aws:cdk:cloudformation:props": { + "blackhole": false, + "destinationCidrBlock": "0.0.0.0/0", + "transitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "transitGatewayRouteTableId": { + "Ref": "TransitGatewayDefaultRouteTable608EC117" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "DefaultRtbAttachment": { + "id": "DefaultRtbAttachment", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment", + "children": { + "TransitGatewayAttachment": { + "id": "TransitGatewayAttachment", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/TransitGatewayAttachment", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayVpcAttachment", + "aws:cdk:cloudformation:props": { + "addSubnetIds": [], + "removeSubnetIds": [], + "subnetIds": [ + { + "Ref": "testSubnet1Subnet72087287" + } + ], + "transitGatewayId": { + "Ref": "TransitGateway11B93D57" + }, + "vpcId": { + "Fn::GetAtt": [ + "SubnetTest3296A161", + "VpcId" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayVpcAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "RouteTable2": { + "id": "RouteTable2", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2", + "children": { + "RouteTable2": { + "id": "RouteTable2", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/RouteTable2", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTable", + "aws:cdk:cloudformation:props": { + "transitGatewayId": { + "Ref": "TransitGateway11B93D57" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayRouteTable", + "version": "0.0.0" + } + }, + "customRtbAssociation": { + "id": "customRtbAssociation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation", + "children": { + "TransitGatewayRouteTableAssociation": { + "id": "TransitGatewayRouteTableAssociation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/TransitGatewayRouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "transitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "transitGatewayRouteTableId": { + "Ref": "TransitGatewayRouteTable2047E2A04" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayRouteTableAssociation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "customRtbPropagation": { + "id": "customRtbPropagation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation", + "children": { + "TransitGatewayRouteTablePropagation": { + "id": "TransitGatewayRouteTablePropagation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/TransitGatewayRouteTablePropagation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTablePropagation", + "aws:cdk:cloudformation:props": { + "transitGatewayAttachmentId": { + "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + }, + "transitGatewayRouteTableId": { + "Ref": "TransitGatewayRouteTable2047E2A04" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayRouteTablePropagation", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integtest-model": { + "id": "integtest-model", + "path": "integtest-model", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integtest-model/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integtest-model/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integtest-model/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integtest-model/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integtest-model/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts new file mode 100644 index 0000000000000..1de4e8c429c31 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts @@ -0,0 +1,52 @@ +import * as vpc_v2 from '../lib/vpc-v2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { TransitGateway } from '../lib/transit-gateway'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { IpCidr, SubnetV2 } from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings'); + +const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6( { + cidrBlockName: 'SecondaryTest', + })], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +/** + * Since source for IPAM IPv6 is set to amazonProvided, + * can assign IPv6 address only after the allocation + * uncomment ipv6CidrBlock and provide valid IPv6 range + */ +const subnet1 = new SubnetV2(stack, 'testSubnet1', { +// new SubnetV2(stack, 'testSubnet1', { + vpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new IpCidr('10.1.0.0/20'), + //defined on the basis of allocation done in IPAM console + //ipv6CidrBlock: new Ipv6Cidr('2a05:d02c:25:4000::/60'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +const tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, +}); + +const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet1]); +attachment.node.addDependency(vpc); +const customRtb = tgw.addRouteTable('RouteTable2'); + +tgw.defaultRouteTable.addRoute('defaultRTBRoute', attachment, '0.0.0.0/0'); +customRtb.addAssociation('customRtbAssociation', attachment); +customRtb.enablePropagation('customRtbPropagation', attachment); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + From 9c0bf44833792c5ac840237866e27bbde2b1773e Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 15 Jan 2025 14:03:19 -0800 Subject: [PATCH 04/22] remove add/removeSubnetIds property + implement methods --- .../lib/transit-gateway-attachment.ts | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index 522d94ff85655..0aee58db56d07 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -47,23 +47,12 @@ export interface TransitGatewayAttachmentProps { /** * A list of one or more subnets to place the attachment in. * It is recommended to specify more subnets for better availability. + * + * To add/remove subnetIds, use the addSubnets and removeSubnets methods. + * Directly modifying this property will cause the attachment to be replaced. */ readonly subnets: ISubnet[]; - // WIP - probably will not expose these properties but will need to set them for the L1 behind the scenes - // /** - // * A list of one or more subnets to add. - // * You can specify at most one subnet per Availability Zone. - // * It is recommended to specify more subnets for better availability. - // */ - // readonly addSubnets?: ISubnet[]; - - // /** - // * A list of one or more subnets to place the attachment in. - // * It is recommended to specify more subnets for better availability. - // */ - - // readonly removeSubnets?: ISubnet[]; /** * The transit gateway this attachment gets assigned to. */ @@ -82,18 +71,11 @@ export interface TransitGatewayAttachmentProps { abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { public abstract readonly transitGatewayAttachmentId: string; - - // addSubnets(subnets: ISubnet[]): void { - // return; - // } - - // removeSubnets(subnets: ISubnet[]): void { - // return; - // } } export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { public readonly transitGatewayAttachmentId: string; + private transitGatewayAttachment: CfnTransitGatewayVpcAttachment; constructor(scope: Construct, id: string, props: TransitGatewayAttachmentProps) { super(scope, id); @@ -114,6 +96,7 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { } : undefined, }); + this.transitGatewayAttachment = resource; this.transitGatewayAttachmentId = resource.ref; if (props.transitGateway.defaultRouteTableAssociation) { @@ -130,4 +113,12 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { }); } } + + addSubnets(subnets: ISubnet[]): void { + this.transitGatewayAttachment.addSubnetIds = this.transitGatewayAttachment.addSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + } + + removeSubnets(subnets: ISubnet[]): void { + this.transitGatewayAttachment.removeSubnetIds = this.transitGatewayAttachment.removeSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + } } From 353ca25d0167073adc1ebad7bfc89acf34eda704 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 22 Jan 2025 10:21:08 -0800 Subject: [PATCH 05/22] some unit tests + class updates --- .../lib/transit-gateway-attachment.ts | 117 +---- ...transit-gateway-route-table-association.ts | 6 +- ...transit-gateway-route-table-propagation.ts | 6 +- .../lib/transit-gateway-route-table.ts | 4 +- .../lib/transit-gateway-route.ts | 7 +- .../lib/transit-gateway-vpc-attachment.ts | 116 ++++ .../aws-ec2-alpha/lib/transit-gateway.ts | 45 +- .../test/transit-gateway-route-table.test.ts | 152 ++++++ .../test/transit-gateway-route.test.ts | 116 ++++ .../test/transit-gateway.test.ts | 496 ++++++++++++++++++ 10 files changed, 929 insertions(+), 136 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index 0aee58db56d07..aa1084d27818d 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -1,124 +1,13 @@ import { IResource, Resource } from 'aws-cdk-lib/core'; -import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; -import { CfnTransitGatewayVpcAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; -import { Construct } from 'constructs'; -import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; -import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; export interface ITransitGatewayAttachment extends IResource { /** * The ID of the transit gateway attachment. * @attribute */ - readonly transitGatewayAttachmentId: string; + readonly transitGatewayVpcAttachmentId: string; } -export interface ITransitGatewayAttachmentOptions { - /** - * Enable or disable appliance mode support. - * - * @default - disable (false) - */ - readonly applianceModeSupport?: boolean; - - /** - * Enable or disable DNS support. - * - * @default - disable (false) - */ - readonly dnsSupport?: boolean; - - /** - * Enable or disable IPv6 support. - * - * @default - disable (false) - */ - readonly ipv6Support?: boolean; - - /** - * Enables you to reference a security group across VPCs attached to a transit gateway. - * - * @default - disable (false) - */ - readonly securityGroupReferencingSupport?: boolean; -} - -export interface TransitGatewayAttachmentProps { - /** - * A list of one or more subnets to place the attachment in. - * It is recommended to specify more subnets for better availability. - * - * To add/remove subnetIds, use the addSubnets and removeSubnets methods. - * Directly modifying this property will cause the attachment to be replaced. - */ - readonly subnets: ISubnet[]; - - /** - * The transit gateway this attachment gets assigned to. - */ - readonly transitGateway: ITransitGateway; - - /** - * A VPC attachment(s) will get assigned to. - */ - readonly vpc: IVpc; - - /** - * The VPC attachment options. - */ - readonly transitGatewayAttachmentOptions?: ITransitGatewayAttachmentOptions; -} - -abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { - public abstract readonly transitGatewayAttachmentId: string; -} - -export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { - public readonly transitGatewayAttachmentId: string; - private transitGatewayAttachment: CfnTransitGatewayVpcAttachment; - - constructor(scope: Construct, id: string, props: TransitGatewayAttachmentProps) { - super(scope, id); - - const resource = new CfnTransitGatewayVpcAttachment(this, 'TransitGatewayAttachment', { - subnetIds: props.subnets.map((subnet) => subnet.subnetId), - transitGatewayId: props.transitGateway.transitGatewayId, - vpcId: props.vpc.vpcId, - options: props.transitGatewayAttachmentOptions ? { - applianceModeSupport: (props.transitGatewayAttachmentOptions?.applianceModeSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - dnsSupport: (props.transitGatewayAttachmentOptions?.dnsSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - ipv6Support: (props.transitGatewayAttachmentOptions?.ipv6Support ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - securityGroupReferencingSupport: (props.transitGatewayAttachmentOptions?.securityGroupReferencingSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - } : undefined, - }); - - this.transitGatewayAttachment = resource; - this.transitGatewayAttachmentId = resource.ref; - - if (props.transitGateway.defaultRouteTableAssociation) { - new TransitGatewayRouteTableAssociation(this, id, { - transitGatewayAttachment: this, - transitGatewayRouteTable: props.transitGateway.defaultRouteTable, - }); - } - - if (props.transitGateway.defaultRouteTablePropagation) { - new TransitGatewayRouteTablePropagation(this, id + 'Propagation', { - transitGatewayAttachment: this, - transitGatewayRouteTable: props.transitGateway.defaultRouteTable, - }); - } - } - - addSubnets(subnets: ISubnet[]): void { - this.transitGatewayAttachment.addSubnetIds = this.transitGatewayAttachment.addSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); - } - - removeSubnets(subnets: ISubnet[]): void { - this.transitGatewayAttachment.removeSubnetIds = this.transitGatewayAttachment.removeSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); - } +export abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { + public abstract readonly transitGatewayVpcAttachmentId: string; } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index 9b6fe3cb23c78..c3a2b404633e8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -15,7 +15,7 @@ export interface TransitGatewayRouteTableAssociationProps { /** * The ID of the transit gateway route table association. */ - readonly transitGatewayAttachment: ITransitGatewayAttachment; + readonly transitGatewayVpcAttachment: ITransitGatewayAttachment; /** * The ID of the transit gateway route table association. @@ -39,8 +39,8 @@ export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTabl constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) { super(scope, id); - const resource = new CfnTransitGatewayRouteTableAssociation(this, 'TransitGatewayRouteTableAssociation', { - transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, + const resource = new CfnTransitGatewayRouteTableAssociation(this, id, { + transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayVpcAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index b92efd74d20f8..bb29869f49104 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -16,7 +16,7 @@ export interface TransitGatewayRouteTablePropagationProps { /** * The ID of the transit gateway route table propagation. */ - readonly transitGatewayAttachment: ITransitGatewayAttachment; + readonly transitGatewayVpcAttachment: ITransitGatewayAttachment; /** * The ID of the transit gateway route table propagation. @@ -40,8 +40,8 @@ export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTabl constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { super(scope, id); - const resource = new CfnTransitGatewayRouteTablePropagation(this, 'TransitGatewayRouteTablePropagation', { - transitGatewayAttachmentId: props.transitGatewayAttachment.transitGatewayAttachmentId, + const resource = new CfnTransitGatewayRouteTablePropagation(this, id, { + transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayVpcAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index f4210653d465b..4652587e856af 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -43,14 +43,14 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTableAssociation { return new TransitGatewayRouteTableAssociation(this, id, { - transitGatewayAttachment: transitGatewayAttachment, + transitGatewayVpcAttachment: transitGatewayAttachment, transitGatewayRouteTable: this, }); } enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTablePropagation { return new TransitGatewayRouteTablePropagation(this, id, { - transitGatewayAttachment: transitGatewayAttachment, + transitGatewayVpcAttachment: transitGatewayAttachment, transitGatewayRouteTable: this, }); } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index a733feb51bb08..850abdc7a1f7f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -7,6 +7,9 @@ import { ITransitGatewayAttachment } from './transit-gateway-attachment'; export interface ITransitGatewayRoute extends IResource { /** * The destination CIDR block for this route. + * + * Destination Cidr cannot overlap for static routes but is allowed for propagated routes. + * When overlapping occurs, static routes take precedence over propagated routes. */ readonly destinationCidrBlock: string; @@ -61,7 +64,7 @@ export class TransitGatewayActiveRoute extends TransitGatewayRouteBase { blackhole: false, destinationCidrBlock: props.destinationCidrBlock, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, - transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayAttachmentId, + transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayVpcAttachmentId, }); this.destinationCidrBlock = resource.destinationCidrBlock; @@ -76,7 +79,7 @@ export class TransitGatewayBlackholeRoute extends TransitGatewayRouteBase { constructor(scope: Construct, id: string, props: TransitGatewayBlackholeRouteProps) { super(scope, id); - const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { + const resource = new CfnTransitGatewayRoute(this, id, { blackhole: true, destinationCidrBlock: props.destinationCidrBlock, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts new file mode 100644 index 0000000000000..771730b76388f --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -0,0 +1,116 @@ +import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; +import { CfnTransitGatewayVpcAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; +import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; +import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; +import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; + +export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment {} + +export interface ITransitGatewayVpcAttachmentOptions { + /** + * Enable or disable appliance mode support. + * + * @default - disable (false) + */ + readonly applianceModeSupport?: boolean; + + /** + * Enable or disable DNS support. + * + * @default - disable (false) + */ + readonly dnsSupport?: boolean; + + /** + * Enable or disable IPv6 support. + * + * @default - disable (false) + */ + readonly ipv6Support?: boolean; + + /** + * Enables you to reference a security group across VPCs attached to a transit gateway. + * + * @default - disable (false) + */ + readonly securityGroupReferencingSupport?: boolean; +} + +export interface TransitGatewayVpcAttachmentProps { + /** + * A list of one or more subnets to place the attachment in. + * It is recommended to specify more subnets for better availability. + * + * To add/remove subnetIds, use the addSubnets and removeSubnets methods. + * Directly modifying this property will cause the attachment to be replaced. + */ + readonly subnets: ISubnet[]; + + /** + * The transit gateway this attachment gets assigned to. + */ + readonly transitGateway: ITransitGateway; + + /** + * A VPC attachment(s) will get assigned to. + */ + readonly vpc: IVpc; + + /** + * The VPC attachment options. + */ + readonly transitGatewayVpcAttachmentOptions?: ITransitGatewayVpcAttachmentOptions; +} + +export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { + public readonly transitGatewayVpcAttachmentId: string; + private transitGatewayVpcAttachment: CfnTransitGatewayVpcAttachment; + + constructor(scope: Construct, id: string, props: TransitGatewayVpcAttachmentProps) { + super(scope, id); + + const resource = new CfnTransitGatewayVpcAttachment(this, id, { + subnetIds: props.subnets.map((subnet) => subnet.subnetId), + transitGatewayId: props.transitGateway.transitGatewayId, + vpcId: props.vpc.vpcId, + options: props.transitGatewayVpcAttachmentOptions ? { + applianceModeSupport: (props.transitGatewayVpcAttachmentOptions?.applianceModeSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + dnsSupport: (props.transitGatewayVpcAttachmentOptions?.dnsSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + ipv6Support: (props.transitGatewayVpcAttachmentOptions?.ipv6Support ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + securityGroupReferencingSupport: (props.transitGatewayVpcAttachmentOptions?.securityGroupReferencingSupport ?? false) + ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + } : undefined, + }); + + this.transitGatewayVpcAttachment = resource; + this.transitGatewayVpcAttachmentId = resource.ref; + + if (props.transitGateway.defaultRouteTableAssociation) { + new TransitGatewayRouteTableAssociation(this, id + 'Association', { + transitGatewayVpcAttachment: this, + transitGatewayRouteTable: props.transitGateway.defaultRouteTable, + }); + } + + if (props.transitGateway.defaultRouteTablePropagation) { + new TransitGatewayRouteTablePropagation(this, id + 'Propagation', { + transitGatewayVpcAttachment: this, + transitGatewayRouteTable: props.transitGateway.defaultRouteTable, + }); + } + } + + addSubnets(subnets: ISubnet[]): void { + this.transitGatewayVpcAttachment.addSubnetIds = + this.transitGatewayVpcAttachment.addSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + } + + removeSubnets(subnets: ISubnet[]): void { + this.transitGatewayVpcAttachment.removeSubnetIds = + this.transitGatewayVpcAttachment.removeSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + } +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 70b8a8c1f2d08..69bead5439525 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -2,8 +2,10 @@ import { CfnTransitGateway, ISubnet, IVpc, RouterType } from 'aws-cdk-lib/aws-ec import { Resource } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { ITransitGatewayRouteTable, TransitGatewayRouteTable } from './transit-gateway-route-table'; -import { TransitGatewayVpcAttachment, ITransitGatewayAttachmentOptions } from './transit-gateway-attachment'; +import { TransitGatewayVpcAttachment, ITransitGatewayVpcAttachmentOptions } from './transit-gateway-vpc-attachment'; import { IRouteTarget } from './route'; +import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; +import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; export enum TransitGatewayFeatureStatus { ENABLE = 'enable', @@ -47,13 +49,6 @@ export interface TransitGatewayProps { */ readonly defaultRouteTablePropagation?: boolean; - /** - * A route table to be used in place of the default route table. - * - * @default - if not specified, a default route table will be created by the CDK instead of by EC2. - */ - readonly customDefaultRouteTable?: ITransitGatewayRouteTable; - /** * The description of the transit gateway. */ @@ -111,14 +106,40 @@ abstract class TransitGatewayBase extends Resource implements ITransitGateway, I attachVpc( id: string, vpc: IVpc, subnets: ISubnet[], - transitGatewayAttachmentOptions?: ITransitGatewayAttachmentOptions, + transitGatewayAttachmentOptions?: ITransitGatewayVpcAttachmentOptions, + associationRouteTable?: ITransitGatewayRouteTable, + propagationRouteTables?: ITransitGatewayRouteTable[], ): TransitGatewayVpcAttachment { - return new TransitGatewayVpcAttachment(this, id, { + const attachment = new TransitGatewayVpcAttachment(this, id, { transitGateway: this, vpc: vpc, subnets: subnets, - transitGatewayAttachmentOptions: transitGatewayAttachmentOptions ?? undefined, + transitGatewayVpcAttachmentOptions: transitGatewayAttachmentOptions ?? undefined, }); + + // If `associationRouteTable` is provided, skip creating the Association only if `associationRouteTable` is the default route table and + // automatic association (`defaultRouteTableAssociation`) is enabled, as the TransitGatewayRouteTableAttachment's constructor will handle it in that case. + if (associationRouteTable && !(this.defaultRouteTable === associationRouteTable && this.defaultRouteTableAssociation)) { + new TransitGatewayRouteTableAssociation(this, `${id}-Assoc-${this.node.addr}`, { + transitGatewayVpcAttachment: attachment, + transitGatewayRouteTable: associationRouteTable, + }); + } + + if (propagationRouteTables) { + propagationRouteTables.forEach((propagationRouteTable, index) => { + // If `propagationRouteTable` is provided, skip creating the Propagation only if `propagationRouteTable` is the default route table and + // automatic propagation (`defaultRouteTablePropagation`) is enabled, as the TransitGatewayRouteTableAttachment's constructor will handle it in that case. + if (!(this.defaultRouteTable === propagationRouteTable && this.defaultRouteTablePropagation)) { + new TransitGatewayRouteTablePropagation(this, `${id}-Propagation-${index}`, { + transitGatewayVpcAttachment: attachment, + transitGatewayRouteTable: propagationRouteTable, + }); + } + }); + } + + return attachment; } } @@ -159,7 +180,7 @@ export class TransitGateway extends TransitGatewayBase { resourceName: this.physicalName, }); - this.defaultRouteTable = (props?.customDefaultRouteTable as TransitGatewayRouteTable) ?? new TransitGatewayRouteTable(this, 'DefaultRouteTable', { + this.defaultRouteTable = new TransitGatewayRouteTable(this, 'DefaultRouteTable', { transitGateway: this, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts new file mode 100644 index 0000000000000..073b149721f48 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -0,0 +1,152 @@ +import * as cdk from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import { TransitGateway } from '../lib/transit-gateway'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; + +describe('Transit Gateway Route Table', () => { + + let stack: cdk.Stack; + let tgw: TransitGateway; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + let attachment: TransitGatewayVpcAttachment; + // let rtb1: TransitGatewayRouteTable; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + + stack = new cdk.Stack(app, 'TransitGatewayRouteTableStack', { + env: { + region: 'us-east-1', + }, + }); + + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + + attachment = new TransitGatewayVpcAttachment(stack, 'TransitGatewayVpcAttachment', { + vpc: myVpc, + transitGateway: tgw, + subnets: [mySubnet], + }); + + new TransitGatewayRouteTable(stack, 'TransitGatewayRouteTable', { + transitGateway: tgw, + }); + }); + + test('creates a transit gateway route table', () => { + Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTable', { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, 2); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + TransitGatewayRouteTableD2EDBDC1: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('addRoute method creates a transit gateway active route and adds it to the transit gateway route table', () => { + tgw.defaultRouteTable.addRoute('TransitGatewayRoute', attachment, '10.0.0.0/16'); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { + Blackhole: false, + DestinationCidrBlock: '10.0.0.0/16', + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment0B27B76B', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); + + test('addBlackholeRoute method creates a transit gateway blackhole route and adds it to the transit gateway route table', () => { + tgw.defaultRouteTable.addBlackholeRoute('TransitGatewayRoute', '10.0.0.0/16'); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { + Blackhole: true, + DestinationCidrBlock: '10.0.0.0/16', + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); + + test('addAssociation method creates a transit gateway route table association', () => { + tgw.defaultRouteTable.addAssociation('TransitGatewayRoute', attachment); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment0B27B76B', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); + + test('enablePropagation method creates a transit gateway route table propagation', () => { + tgw.defaultRouteTable.enablePropagation('TransitGatewayRoute', attachment); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment0B27B76B', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts new file mode 100644 index 0000000000000..77e094fb618af --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts @@ -0,0 +1,116 @@ +import * as cdk from 'aws-cdk-lib'; +import { Match, Template } from 'aws-cdk-lib/assertions'; +import { TransitGateway } from '../lib/transit-gateway'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; +import { TransitGatewayActiveRoute, TransitGatewayBlackholeRoute } from '../lib/transit-gateway-route'; + +describe('Transit Gateway Route', () => { + let stack: cdk.Stack; + let tgw: TransitGateway; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + let attachment: TransitGatewayVpcAttachment; + let routeTable: TransitGatewayRouteTable; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + + stack = new cdk.Stack(app, 'TransitGatewayRouteTableStack', { + env: { + region: 'us-east-1', + }, + }); + + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + + attachment = new TransitGatewayVpcAttachment(stack, 'TransitGatewayVpcAttachment', { + vpc: myVpc, + transitGateway: tgw, + subnets: [mySubnet], + }); + + routeTable = new TransitGatewayRouteTable(stack, 'TransitGatewayRouteTable', { + transitGateway: tgw, + }); + }); + + describe('TransitGatewayActiveRoute', () => { + test('creates a route with the correct properties', () => { + // WHEN + new TransitGatewayActiveRoute(stack, 'ActiveRoute', { + transitGatewayAttachment: attachment, + destinationCidrBlock: '10.1.0.0/16', + transitGatewayRouteTable: routeTable, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { + Blackhole: false, + DestinationCidrBlock: '10.1.0.0/16', + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayRouteTableD2EDBDC1', + }, + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment0B27B76B', + }, + }); + }); + }); + + describe('TransitGatewayBlackholeRoute', () => { + test('creates a blackhole route with the correct properties', () => { + // WHEN + new TransitGatewayBlackholeRoute(stack, 'BlackholeRoute', { + destinationCidrBlock: '10.2.0.0/16', + transitGatewayRouteTable: routeTable, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { + Blackhole: true, + DestinationCidrBlock: '10.2.0.0/16', + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayRouteTableD2EDBDC1', + }, + }); + }); + + test('does not include TransitGatewayAttachmentId', () => { + // WHEN + new TransitGatewayBlackholeRoute(stack, 'BlackholeRoute', { + destinationCidrBlock: '10.2.0.0/16', + transitGatewayRouteTable: routeTable, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { + Blackhole: true, + DestinationCidrBlock: '10.2.0.0/16', + TransitGatewayAttachmentId: Match.absent(), + }); + }); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts new file mode 100644 index 0000000000000..4e18f4dab0cde --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -0,0 +1,496 @@ +import * as cdk from 'aws-cdk-lib'; +import { Template } from 'aws-cdk-lib/assertions'; +import { TransitGateway } from '../lib/transit-gateway'; +import * as vpc from '../lib/vpc-v2'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +describe('Transit Gateway with default settings', () => { + + let stack: cdk.Stack; + let tgw: TransitGateway; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + + stack = new cdk.Stack(app, 'TransitGatewayStack', { + env: { + region: 'us-east-1', + }, + }); + + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + tgw = new TransitGateway(stack, 'TransitGateway'); + }); + + test('Creates a transit gateway with all default settings and default route table', () => { + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::EC2::TransitGateway', { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('add route table method should create a second transit gateway route table tha references the transit gateway', () => { + tgw.addRouteTable('RouteTable2'); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + TransitGatewayRouteTable2047E2A04: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('attach vpc method should create an attachment, association and propagation when default association/propagation are enabled', () => { + + tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + SubnetIds: [ + { + Ref: 'TestSubnet2A4BE4CA', + }, + ], + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + VpcId: { + 'Fn::GetAtt': [ + 'VpcAAD85CA4C', + 'VpcId', + ], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment3EC29F61', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment3EC29F61', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); +}); + +describe('Transit Gateway with default route table association and propagation disabled', () => { + + let stack: cdk.Stack; + let tgw: TransitGateway; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + + stack = new cdk.Stack(app, 'TransitGatewayStack', { + env: { + region: 'us-east-1', + }, + }); + + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + }); + + test('should create a transit gateway with all default settings and default route table', () => { + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::EC2::TransitGateway', { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('add route table method should create a second transit gateway route table tha references the transit gateway', () => { + tgw.addRouteTable('RouteTable2'); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + TransitGatewayRouteTable2047E2A04: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('attach vpc method should create an attachment and not create an association or propagation when default association/propagation are disabled', () => { + + tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + SubnetIds: [ + { + Ref: 'TestSubnet2A4BE4CA', + }, + ], + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + VpcId: { + 'Fn::GetAtt': [ + 'VpcAAD85CA4C', + 'VpcId', + ], + }, + }); + + Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayVpcAttachmentId: { + Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }, 0); + + Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayVpcAttachmentId: { + Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }, 0); + }); +}); + +describe('Transit Gateway with default route table association and propagation disabled', () => { + + let stack: cdk.Stack; + let tgw: TransitGateway; + let myVpc: vpc.VpcV2; + let mySubnet: subnet.SubnetV2; + + beforeEach(() => { + const app = new cdk.App({ + context: { + '@aws-cdk/core:newStyleStackSynthesis': false, + }, + }); + + stack = new cdk.Stack(app, 'TransitGatewayStack', { + env: { + region: 'us-east-1', + }, + }); + + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + }); + + test('should create a transit gateway with all default settings and default route table', () => { + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::EC2::TransitGateway', { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('add route table method should create a second transit gateway route table tha references the transit gateway', () => { + tgw.addRouteTable('RouteTable2'); + + Template.fromStack(stack).templateMatches({ + Resources: { + TransitGateway11B93D57: { + Type: 'AWS::EC2::TransitGateway', + Properties: { + AutoAcceptSharedAttachments: 'disable', + DefaultRouteTableAssociation: 'disable', + DefaultRouteTablePropagation: 'disable', + DnsSupport: 'enable', + MulticastSupport: 'disable', + VpnEcmpSupport: 'enable', + }, + }, + TransitGatewayDefaultRouteTable608EC117: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + TransitGatewayRouteTable2047E2A04: { + Type: 'AWS::EC2::TransitGatewayRouteTable', + Properties: { + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + }, + }, + }, + }); + }); + + test('attach vpc method should create an attachment and not create an association or propagation', () => { + + tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + SubnetIds: [ + { + Ref: 'TestSubnet2A4BE4CA', + }, + ], + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + VpcId: { + 'Fn::GetAtt': [ + 'VpcAAD85CA4C', + 'VpcId', + ], + }, + }); + + Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }, 0); + + Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }, 0); + }); + + test('attach vpc method should create an attachment, association and propagation when route tables are passed to the method', () => { + + tgw.attachVpc('VpcAttachment', myVpc, [mySubnet], undefined, tgw.defaultRouteTable, [tgw.defaultRouteTable]); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + SubnetIds: [ + { + Ref: 'TestSubnet2A4BE4CA', + }, + ], + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + VpcId: { + 'Fn::GetAtt': [ + 'VpcAAD85CA4C', + 'VpcId', + ], + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment3EC29F61', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayAttachmentId: { + Ref: 'TransitGatewayVpcAttachment3EC29F61', + }, + TransitGatewayRouteTableId: { + Ref: 'TransitGatewayDefaultRouteTable608EC117', + }, + }); + }); +}); From 5f0c30b0ddbaad359876f56026bbed015ea35aa0 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 22 Jan 2025 15:53:42 -0800 Subject: [PATCH 06/22] update vpc attachment resource + unit tests --- .../lib/transit-gateway-vpc-attachment.ts | 32 ++-- .../test/integ.transit-gateway-route-table.ts | 51 ++++++ ...it-gateway-route-table-association.test.ts | 61 ++++++++ ...it-gateway-route-table-propagation.test.ts | 61 ++++++++ .../transit-gateway-vpc-attachment.test.ts | 148 ++++++++++++++++++ .../test/transit-gateway.test.ts | 8 +- 6 files changed, 346 insertions(+), 15 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 771730b76388f..3d206d42cc886 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -1,5 +1,5 @@ import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; -import { CfnTransitGatewayVpcAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; +import { CfnTransitGatewayAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; @@ -41,9 +41,6 @@ export interface TransitGatewayVpcAttachmentProps { /** * A list of one or more subnets to place the attachment in. * It is recommended to specify more subnets for better availability. - * - * To add/remove subnetIds, use the addSubnets and removeSubnets methods. - * Directly modifying this property will cause the attachment to be replaced. */ readonly subnets: ISubnet[]; @@ -65,12 +62,13 @@ export interface TransitGatewayVpcAttachmentProps { export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { public readonly transitGatewayVpcAttachmentId: string; - private transitGatewayVpcAttachment: CfnTransitGatewayVpcAttachment; + private readonly subnets: ISubnet[] = []; + private transitGatewayVpcAttachment: CfnTransitGatewayAttachment; constructor(scope: Construct, id: string, props: TransitGatewayVpcAttachmentProps) { super(scope, id); - const resource = new CfnTransitGatewayVpcAttachment(this, id, { + const resource = new CfnTransitGatewayAttachment(this, id, { subnetIds: props.subnets.map((subnet) => subnet.subnetId), transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, @@ -88,6 +86,7 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { this.transitGatewayVpcAttachment = resource; this.transitGatewayVpcAttachmentId = resource.ref; + this.subnets = props.subnets; if (props.transitGateway.defaultRouteTableAssociation) { new TransitGatewayRouteTableAssociation(this, id + 'Association', { @@ -103,14 +102,25 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { }); } } - + addSubnets(subnets: ISubnet[]): void { - this.transitGatewayVpcAttachment.addSubnetIds = - this.transitGatewayVpcAttachment.addSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + for (const subnet of subnets) { + if (this.subnets.some(existing => existing.subnetId === subnet.subnetId)) { + throw new Error(`Subnet with ID ${subnet.subnetId} is already added to the Attachment ${this.transitGatewayVpcAttachmentId}.`); + } + this.subnets.push(subnet); + } + this.transitGatewayVpcAttachment.subnetIds = this.subnets.map(subnet => subnet.subnetId); } removeSubnets(subnets: ISubnet[]): void { - this.transitGatewayVpcAttachment.removeSubnetIds = - this.transitGatewayVpcAttachment.removeSubnetIds?.concat(subnets.map((subnet) => subnet.subnetId)); + for (const subnet of subnets) { + const index = this.subnets.findIndex(existing => existing.subnetId === subnet.subnetId); + if (index === -1) { + throw new Error(`Subnet with ID ${subnet.subnetId} does not exist in the Attachment ${this.transitGatewayVpcAttachmentId}.`); + } + this.subnets.splice(index, 1); + } + this.transitGatewayVpcAttachment.subnetIds = this.subnets.map(subnet => subnet.subnetId); } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts new file mode 100644 index 0000000000000..0fa2417abf694 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts @@ -0,0 +1,51 @@ +import * as vpc_v2 from '../lib/vpc-v2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { TransitGateway } from '../lib/transit-gateway'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { IpCidr, SubnetV2 } from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings'); + +const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6( { + cidrBlockName: 'SecondaryTest', + })], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +/** + * Since source for IPAM IPv6 is set to amazonProvided, + * can assign IPv6 address only after the allocation + * uncomment ipv6CidrBlock and provide valid IPv6 range + */ +const subnet1 = new SubnetV2(stack, 'testSubnet1', { + vpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new IpCidr('10.1.0.0/20'), + //defined on the basis of allocation done in IPAM console + //ipv6CidrBlock: new Ipv6Cidr('2a05:d02c:25:4000::/60'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +const tgw = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, +}); + +const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet1]); +attachment.node.addDependency(vpc); + +tgw.defaultRouteTable.addRoute('defaultRTBRoute', attachment, '0.0.0.0/0'); +tgw.defaultRouteTable.addBlackholeRoute('defaultRTBRoute2', '10.1.0.0/16'); +tgw.defaultRouteTable.addAssociation('customRtbAssociation', attachment); +tgw.defaultRouteTable.enablePropagation('customRtbPropagation', attachment); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts new file mode 100644 index 0000000000000..0332aab98dd81 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts @@ -0,0 +1,61 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import { Stack } from 'aws-cdk-lib/core'; +import * as vpc from '../lib'; +import { TransitGateway } from '../lib/transit-gateway'; +import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; +import { TransitGatewayRouteTableAssociation } from '../lib/transit-gateway-route-table-association'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +describe('TransitGatewayRouteTableAssociation', () => { + let stack: Stack; + let myVpc: vpc.VpcV2; + let transitGateway: TransitGateway; + let routeTable: TransitGatewayRouteTable; + let attachment: TransitGatewayVpcAttachment; + let mySubnet: vpc.SubnetV2; + + beforeEach(() => { + stack = new Stack(); + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + transitGateway = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + + routeTable = transitGateway.addRouteTable('RouteTable'); + + attachment = new TransitGatewayVpcAttachment(stack, 'TransitGatewayVpcAttachment', { + vpc: myVpc, + transitGateway: transitGateway, + subnets: [mySubnet], + }); + + }); + + test('creates association with required properties', () => { + // WHEN + new TransitGatewayRouteTableAssociation(stack, 'TransitGatewayRouteTableAssociation', { + transitGatewayRouteTable: routeTable, + transitGatewayVpcAttachment: attachment, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { + TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayVpcAttachmentId), + TransitGatewayRouteTableId: stack.resolve(routeTable.routeTableId), + }); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts new file mode 100644 index 0000000000000..1b6a68332e454 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts @@ -0,0 +1,61 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import { Stack } from 'aws-cdk-lib/core'; +import * as vpc from '../lib'; +import { TransitGateway } from '../lib/transit-gateway'; +import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; +import { TransitGatewayRouteTablePropagation } from '../lib/transit-gateway-route-table-propagation'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +describe('TransitGatewayRouteTablePropagation', () => { + let stack: Stack; + let myVpc: vpc.VpcV2; + let transitGateway: TransitGateway; + let routeTable: TransitGatewayRouteTable; + let attachment: TransitGatewayVpcAttachment; + let mySubnet: vpc.SubnetV2; + + beforeEach(() => { + stack = new Stack(); + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + transitGateway = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + + routeTable = transitGateway.addRouteTable('RouteTable'); + + attachment = new TransitGatewayVpcAttachment(stack, 'TransitGatewayVpcAttachment', { + vpc: myVpc, + transitGateway: transitGateway, + subnets: [mySubnet], + }); + + }); + + test('creates propagation with required properties', () => { + // WHEN + new TransitGatewayRouteTablePropagation(stack, 'TransitGatewayRouteTablePropagation', { + transitGatewayRouteTable: routeTable, + transitGatewayVpcAttachment: attachment, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { + TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayVpcAttachmentId), + TransitGatewayRouteTableId: stack.resolve(routeTable.routeTableId), + }); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts new file mode 100644 index 0000000000000..ad4286d17db75 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -0,0 +1,148 @@ +import { Template } from 'aws-cdk-lib/assertions'; +import { Stack } from 'aws-cdk-lib/core'; +import * as vpc from '../lib'; +import { TransitGateway } from '../lib/transit-gateway'; +import * as subnet from '../lib/subnet-v2'; +import { SubnetType } from 'aws-cdk-lib/aws-ec2'; + +describe('TransitGatewayVpcAttachment', () => { + let stack: Stack; + let myVpc: vpc.VpcV2; + let transitGateway: TransitGateway; + let mySubnet: vpc.SubnetV2; + + beforeEach(() => { + stack = new Stack(); + myVpc = new vpc.VpcV2(stack, 'VpcA', { + primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), + secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], + }); + + mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + transitGateway = new TransitGateway(stack, 'TransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, + }); + }); + + test('creates vpc attachment with required properties', () => { + // WHEN + transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { + SubnetIds: [ + { + Ref: 'TestSubnet2A4BE4CA', + }, + ], + TransitGatewayId: { + Ref: 'TransitGateway11B93D57', + }, + VpcId: { + 'Fn::GetAtt': [ + 'VpcAAD85CA4C', + 'VpcId', + ], + }, + }); + }); + + test('creates vpc attachment with optional properties', () => { + // WHEN + transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet], { + dnsSupport: true, + ipv6Support: true, + applianceModeSupport: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { + VpcId: stack.resolve(myVpc.vpcId), + TransitGatewayId: stack.resolve(transitGateway.transitGatewayId), + SubnetIds: [stack.resolve(mySubnet.subnetId)], + Options: { + dnsSupport: 'enable', + ipv6Support: 'enable', + applianceModeSupport: 'enable', + securityGroupReferencingSupport: 'disable', + }, + }); + }); + + test('can add subnets', () => { + // GIVEN + const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + const additionalSubnet = new subnet.SubnetV2(stack, 'AdditionalSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1b', + ipv4CidrBlock: new subnet.IpCidr('10.0.1.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + // WHEN + attachment.addSubnets([additionalSubnet]); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { + SubnetIds: [ + { Ref: 'TestSubnet2A4BE4CA' }, + { Ref: 'AdditionalSubnetD5F4E6FA' } + ], + }); + }); + + test('can remove subnets', () => { + // GIVEN + const additionalSubnet = new subnet.SubnetV2(stack, 'AdditionalSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1b', + ipv4CidrBlock: new subnet.IpCidr('10.0.1.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet, additionalSubnet]); + + // WHEN + attachment.removeSubnets([additionalSubnet]); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { + SubnetIds: [{ Ref: 'TestSubnet2A4BE4CA' }], + }); + }); + + test('throws error when adding duplicate subnet', () => { + // GIVEN + const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + // THEN + expect(() => attachment.addSubnets([mySubnet])).toThrow( + `Subnet with ID ${mySubnet.subnetId} is already added to the Attachment` + ); + }); + + test('throws error when removing non-existent subnet', () => { + // GIVEN + const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + + const nonExistentSubnet = new subnet.SubnetV2(stack, 'NonExistentSubnet', { + vpc: myVpc, + availabilityZone: 'us-east-1c', + ipv4CidrBlock: new subnet.IpCidr('10.0.2.0/24'), + subnetType: SubnetType.PRIVATE_WITH_EGRESS, + }); + + // THEN + expect(() => attachment.removeSubnets([nonExistentSubnet])).toThrow( + `Subnet with ID ${nonExistentSubnet.subnetId} does not exist in the Attachment` + ); + }); +}); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 4e18f4dab0cde..4b2d4baddb84f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -116,7 +116,7 @@ describe('Transit Gateway with default settings', () => { tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ { Ref: 'TestSubnet2A4BE4CA', @@ -267,7 +267,7 @@ describe('Transit Gateway with default route table association and propagation d tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ { Ref: 'TestSubnet2A4BE4CA', @@ -418,7 +418,7 @@ describe('Transit Gateway with default route table association and propagation d tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ { Ref: 'TestSubnet2A4BE4CA', @@ -458,7 +458,7 @@ describe('Transit Gateway with default route table association and propagation d tgw.attachVpc('VpcAttachment', myVpc, [mySubnet], undefined, tgw.defaultRouteTable, [tgw.defaultRouteTable]); - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayVpcAttachment', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ { Ref: 'TestSubnet2A4BE4CA', From e1236388c1001deb932925761aa90d4099ba4488 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 22 Jan 2025 17:32:32 -0800 Subject: [PATCH 07/22] README draft --- packages/@aws-cdk/aws-ec2-alpha/README.md | 126 ++++++++++++++++++ .../lib/transit-gateway-vpc-attachment.ts | 2 +- .../aws-ec2-alpha/lib/transit-gateway.ts | 6 +- .../transit-gateway-vpc-attachment.test.ts | 28 ++-- 4 files changed, 144 insertions(+), 18 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index b387e02180ad4..b5932e19a487f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -664,3 +664,129 @@ const vpc = new VpcV2(this, 'VPC-integ-test-tag', { // Add custom tags if needed Tags.of(vpc).add('Environment', 'Production'); ``` + +## Transit Gateway + +The AWS Transit Gateway construct library allows you to create and configure Transit Gateway resources using AWS CDK. + +## Overview + +The Transit Gateway construct (`TransitGateway`) is the main entry point for creating and managing your Transit Gateway infrastructure. It provides methods to create route tables, attach VPCs, and configure cross-account access. + +The Transit Gateway construct library provides four main constructs: + +- `TransitGateway`: The central hub for your network connections +- `TransitGatewayRouteTable`: Manages routing between attached networks +- `TransitGatewayAttachment`: Connects VPCs and on-premises networks +- `TransitGatewayRoute`: Defines routing rules within your Transit Gateway + +### Basic Usage + +To create a minimal deployable `TransitGateway`: + +```ts +import * as ec2 from '@aws-cdk/aws-ec2-alpha'; + +const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway'); +``` + +Key properties available: + +- `transitGatewayId`: The ID of the Transit Gateway +- `transitGatewayArn`: The ARN of the Transit Gateway +- `defaultRouteTable`: The default route table created with the Transit Gateway +- `defaultRouteTableAssociation`: Controls automatic route table association +- `defaultRouteTablePropagation`: Controls automatic route propagation + +### Default Transit Gateway Route Table + +By default, `TransitGateway` is created with a default `TransitGatewayRouteTable`, for which automatic Associations and automatic Propagations are enabled. + +> Note: When you create a default Transit Gateway in AWS Console, EC2 creates the default `TransitGatewayRouteTable` for you. When using this construct, CDK will create the default `TransitGatewayRouteTable` for you instead with the automatic Association/Propagation features being mimicked by the CDK. +> +> **Default association route table** and **Default propagation route table** will show as disabled in your AWS console but can still be toggled within CDK using the `defaultRouteTableAssociation` and `defaultRouteTablePropagation` properties respectively. + +You can disable the automatic Association/Propagation on the default `TransitGatewayRouteTable` via the `TransitGateway` properties. This will still create a default route table for you: + +```ts +const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { + defaultRouteTableAssociation: false, + defaultRouteTablePropagation: false, +}); +``` + +You can also provide your own `TransitGatewayRouteTable` to be used as the default route table: + +```ts +const customRouteTable = new ec2.TransitGatewayRouteTable(this, 'TransitGatewayRouteTable'); + +const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { + customDefaultRouteTable: customRouteTable, +}); +``` + +## Transit Gateway Route Table Management + +Add additional Transit Gateway Route Tables using the `addRouteTable()` method: + +```ts +const tgw = new TransitGateway(this, 'TransitGateway'); +const routeTable = tgw.addRouteTable('CustomRouteTable'); +``` + +### Attaching VPCs to the Transit Gateway + +Create an attachment from a VPC to the Transit Gateway using the `attachVpc()` method: + +```ts +// Create a basic attachment +const attachment = transitGateway.attachVpc('VpcAttachment', vpc, [subnet1, subnet2]); +``` + +You can customize the VPC attachment by passing in optional parameters. These include options for fine-tuning the attachment behavior, such as support for DNS, IPv6, Appliance Mode and Security Group Referencing. +```ts +const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], { + dnsSupport: true, + applianceModeSupport: true, + ipv6Support: true, + securityGroupReferencingSupport: true, +}); +``` + +If you want to automatically associate and propagate routes with transit gateway route tables, you can pass the `associationRouteTable` and `propagationRouteTables` parameters. This will automatically create the necessary associations and propagations based on the provided route tables. + +```ts +const attachmentWithRoutes = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], undefined, associationRouteTable, [propagationRouteTable1, propagationRouteTable2]); +``` +In this example, the `associationRouteTable` is set to `associationRouteTable`, and `propagationRouteTables` is set to an array containing `propagationRouteTable1` and `propagationRouteTable2`. This triggers the automatic creation of route table associations and route propagations between the Transit Gateway and the specified route tables. + +### Adding static routes to the route table + +Add static routes using either the `addRoute()` method to add an active route or `addBlackholeRoute()` to add a blackhole route: + +```ts +// Add a static route to direct traffic +routeTable.addRoute('StaticRoute', { + transitGatewayAttachment: vpcAttachment, + destinationCidrBlock: '10.0.0.0/16', +}); + +// Block unwanted traffic with a blackhole route +routeTable.addBlackholeRoute('BlackholeRoute', '172.16.0.0/16'); +``` + +### Route Table Associations and Propagations + +Configure route table associations and enable route propagation: + +```ts +// Associate an attachment with a route table +routeTable.addAssociation('Association', attachment); + +// Enable route propagation for an attachment +routeTable.enablePropagation('Propagation', attachent); +``` + +**Associations** — The linking of a Transit Gateway attachment to a specific route table, which determines which routes that attachment will use for routing decisions. + +**Propagation** — The automatic advertisement of routes from an attachment to a route table, allowing the route table to learn about available network destinations. diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 3d206d42cc886..a426dfcf5750a 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -102,7 +102,7 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { }); } } - + addSubnets(subnets: ISubnet[]): void { for (const subnet of subnets) { if (this.subnets.some(existing => existing.subnetId === subnet.subnetId)) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 69bead5439525..ae4c43976ffc5 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -38,14 +38,14 @@ export interface TransitGatewayProps { /** * Enable or disable automatic association with the default association route table. * - * @default - enable + * @default - enable (true) */ readonly defaultRouteTableAssociation?: boolean; /** * Enable or disable automatic propagation of routes to the default propagation route table. * - * @default - enable + * @default - enable (true) */ readonly defaultRouteTablePropagation?: boolean; @@ -120,7 +120,7 @@ abstract class TransitGatewayBase extends Resource implements ITransitGateway, I // If `associationRouteTable` is provided, skip creating the Association only if `associationRouteTable` is the default route table and // automatic association (`defaultRouteTableAssociation`) is enabled, as the TransitGatewayRouteTableAttachment's constructor will handle it in that case. if (associationRouteTable && !(this.defaultRouteTable === associationRouteTable && this.defaultRouteTableAssociation)) { - new TransitGatewayRouteTableAssociation(this, `${id}-Assoc-${this.node.addr}`, { + new TransitGatewayRouteTableAssociation(this, `${id}-Association-${this.node.addr}`, { transitGatewayVpcAttachment: attachment, transitGatewayRouteTable: associationRouteTable, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index ad4286d17db75..821d31a7d8cf5 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -79,22 +79,22 @@ describe('TransitGatewayVpcAttachment', () => { test('can add subnets', () => { // GIVEN const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); - + const additionalSubnet = new subnet.SubnetV2(stack, 'AdditionalSubnet', { vpc: myVpc, availabilityZone: 'us-east-1b', ipv4CidrBlock: new subnet.IpCidr('10.0.1.0/24'), subnetType: SubnetType.PRIVATE_WITH_EGRESS, }); - + // WHEN attachment.addSubnets([additionalSubnet]); - + // THEN Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ { Ref: 'TestSubnet2A4BE4CA' }, - { Ref: 'AdditionalSubnetD5F4E6FA' } + { Ref: 'AdditionalSubnetD5F4E6FA' }, ], }); }); @@ -107,42 +107,42 @@ describe('TransitGatewayVpcAttachment', () => { ipv4CidrBlock: new subnet.IpCidr('10.0.1.0/24'), subnetType: SubnetType.PRIVATE_WITH_EGRESS, }); - + const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet, additionalSubnet]); - + // WHEN attachment.removeSubnets([additionalSubnet]); - + // THEN Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [{ Ref: 'TestSubnet2A4BE4CA' }], }); }); - + test('throws error when adding duplicate subnet', () => { // GIVEN const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); - + // THEN expect(() => attachment.addSubnets([mySubnet])).toThrow( - `Subnet with ID ${mySubnet.subnetId} is already added to the Attachment` + `Subnet with ID ${mySubnet.subnetId} is already added to the Attachment`, ); }); - + test('throws error when removing non-existent subnet', () => { // GIVEN const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); - + const nonExistentSubnet = new subnet.SubnetV2(stack, 'NonExistentSubnet', { vpc: myVpc, availabilityZone: 'us-east-1c', ipv4CidrBlock: new subnet.IpCidr('10.0.2.0/24'), subnetType: SubnetType.PRIVATE_WITH_EGRESS, }); - + // THEN expect(() => attachment.removeSubnets([nonExistentSubnet])).toThrow( - `Subnet with ID ${nonExistentSubnet.subnetId} does not exist in the Attachment` + `Subnet with ID ${nonExistentSubnet.subnetId} does not exist in the Attachment`, ); }); }); From faf600dcacec2e03ac055a280402e2baa16b5001 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Thu, 23 Jan 2025 14:45:30 -0800 Subject: [PATCH 08/22] integ snapshots + update attachment options --- packages/@aws-cdk/aws-ec2-alpha/README.md | 2 ++ .../lib/transit-gateway-vpc-attachment.ts | 9 +++--- ...way-disable-automatic-settings.assets.json | 4 +-- ...y-disable-automatic-settings.template.json | 22 +++++--------- .../manifest.json | 14 ++++----- .../tree.json | 30 +++++++++---------- .../test/integ.transit-gateway.ts | 24 ++++++++------- ...it-gateway-route-table-association.test.ts | 1 - 8 files changed, 51 insertions(+), 55 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index b5932e19a487f..0d657d2f993f5 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -744,6 +744,7 @@ const attachment = transitGateway.attachVpc('VpcAttachment', vpc, [subnet1, subn ``` You can customize the VPC attachment by passing in optional parameters. These include options for fine-tuning the attachment behavior, such as support for DNS, IPv6, Appliance Mode and Security Group Referencing. + ```ts const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], { dnsSupport: true, @@ -758,6 +759,7 @@ If you want to automatically associate and propagate routes with transit gateway ```ts const attachmentWithRoutes = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], undefined, associationRouteTable, [propagationRouteTable1, propagationRouteTable2]); ``` + In this example, the `associationRouteTable` is set to `associationRouteTable`, and `propagationRouteTables` is set to an array containing `propagationRouteTable1` and `propagationRouteTable2`. This triggers the automatic creation of route table associations and route propagations between the Transit Gateway and the specified route tables. ### Adding static routes to the route table diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index a426dfcf5750a..b563b5b2b091c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -4,6 +4,7 @@ import { Construct } from 'constructs'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; +// import { ValidationError } from 'aws-cdk-lib/core/lib/errors'; export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment {} @@ -73,13 +74,13 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, options: props.transitGatewayVpcAttachmentOptions ? { - applianceModeSupport: (props.transitGatewayVpcAttachmentOptions?.applianceModeSupport ?? false) + ApplianceModeSupport: (props.transitGatewayVpcAttachmentOptions?.applianceModeSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - dnsSupport: (props.transitGatewayVpcAttachmentOptions?.dnsSupport ?? false) + DnsSupport: (props.transitGatewayVpcAttachmentOptions?.dnsSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - ipv6Support: (props.transitGatewayVpcAttachmentOptions?.ipv6Support ?? false) + Ipv6Support: (props.transitGatewayVpcAttachmentOptions?.ipv6Support ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - securityGroupReferencingSupport: (props.transitGatewayVpcAttachmentOptions?.securityGroupReferencingSupport ?? false) + SecurityGroupReferencingSupport: (props.transitGatewayVpcAttachmentOptions?.securityGroupReferencingSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, } : undefined, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json index 151770ec5d5fd..18290e57f2195 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -1,7 +1,7 @@ { "version": "39.0.0", "files": { - "167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664": { + "b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829": { "source": { "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664.json", + "objectKey": "b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json index 7dd9b7d5cbb97..17eb898f4d90f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -106,18 +106,16 @@ "Blackhole": false, "DestinationCidrBlock": "0.0.0.0/0", "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "TransitGatewayRouteTableId": { "Ref": "TransitGatewayDefaultRouteTable608EC117" } } }, - "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709": { - "Type": "AWS::EC2::TransitGatewayVpcAttachment", + "TransitGatewayDefaultRtbAttachment6E19DB55": { + "Type": "AWS::EC2::TransitGatewayAttachment", "Properties": { - "AddSubnetIds": [], - "RemoveSubnetIds": [], "SubnetIds": [ { "Ref": "testSubnet1Subnet72087287" @@ -132,11 +130,7 @@ "VpcId" ] } - }, - "DependsOn": [ - "SubnetTest3296A161", - "SubnetTestSecondaryTest2AB12223" - ] + } }, "TransitGatewayRouteTable2047E2A04": { "Type": "AWS::EC2::TransitGatewayRouteTable", @@ -146,22 +140,22 @@ } } }, - "TransitGatewayRouteTable2customRtbAssociationTransitGatewayRouteTableAssociation9ADF3D3E": { + "TransitGatewayRouteTable2customRtbAssociation353F1A21": { "Type": "AWS::EC2::TransitGatewayRouteTableAssociation", "Properties": { "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "TransitGatewayRouteTableId": { "Ref": "TransitGatewayRouteTable2047E2A04" } } }, - "TransitGatewayRouteTable2customRtbPropagationTransitGatewayRouteTablePropagationFAE55BBD": { + "TransitGatewayRouteTable2customRtbPropagation45784C74": { "Type": "AWS::EC2::TransitGatewayRouteTablePropagation", "Properties": { "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "TransitGatewayRouteTableId": { "Ref": "TransitGatewayRouteTable2047E2A04" diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json index 45a6f02e329a9..00c76ebbbb0cb 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/167a5108084ceef3decb8bb7d4495162503fee0d91271b2a35cd9aade9293664.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -82,10 +82,10 @@ "data": "TransitGatewayDefaultRouteTabledefaultRTBRouteTransitGatewayRouteAB7CA8FF" } ], - "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/TransitGatewayAttachment": [ + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/DefaultRtbAttachment": [ { "type": "aws:cdk:logicalId", - "data": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "data": "TransitGatewayDefaultRtbAttachment6E19DB55" } ], "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/RouteTable2": [ @@ -94,16 +94,16 @@ "data": "TransitGatewayRouteTable2047E2A04" } ], - "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/TransitGatewayRouteTableAssociation": [ + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/customRtbAssociation": [ { "type": "aws:cdk:logicalId", - "data": "TransitGatewayRouteTable2customRtbAssociationTransitGatewayRouteTableAssociation9ADF3D3E" + "data": "TransitGatewayRouteTable2customRtbAssociation353F1A21" } ], - "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/TransitGatewayRouteTablePropagation": [ + "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/customRtbPropagation": [ { "type": "aws:cdk:logicalId", - "data": "TransitGatewayRouteTable2customRtbPropagationTransitGatewayRouteTablePropagationFAE55BBD" + "data": "TransitGatewayRouteTable2customRtbPropagation45784C74" } ], "/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/BootstrapVersion": [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json index 903c7983f53d4..7bb37e690242b 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -224,7 +224,7 @@ "blackhole": false, "destinationCidrBlock": "0.0.0.0/0", "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "transitGatewayRouteTableId": { "Ref": "TransitGatewayDefaultRouteTable608EC117" @@ -252,14 +252,12 @@ "id": "DefaultRtbAttachment", "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment", "children": { - "TransitGatewayAttachment": { - "id": "TransitGatewayAttachment", - "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/TransitGatewayAttachment", + "DefaultRtbAttachment": { + "id": "DefaultRtbAttachment", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/DefaultRtbAttachment/DefaultRtbAttachment", "attributes": { - "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayVpcAttachment", + "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayAttachment", "aws:cdk:cloudformation:props": { - "addSubnetIds": [], - "removeSubnetIds": [], "subnetIds": [ { "Ref": "testSubnet1Subnet72087287" @@ -277,7 +275,7 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayVpcAttachment", + "fqn": "aws-cdk-lib.aws_ec2.CfnTransitGatewayAttachment", "version": "0.0.0" } } @@ -311,14 +309,14 @@ "id": "customRtbAssociation", "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation", "children": { - "TransitGatewayRouteTableAssociation": { - "id": "TransitGatewayRouteTableAssociation", - "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/TransitGatewayRouteTableAssociation", + "customRtbAssociation": { + "id": "customRtbAssociation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbAssociation/customRtbAssociation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTableAssociation", "aws:cdk:cloudformation:props": { "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "transitGatewayRouteTableId": { "Ref": "TransitGatewayRouteTable2047E2A04" @@ -340,14 +338,14 @@ "id": "customRtbPropagation", "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation", "children": { - "TransitGatewayRouteTablePropagation": { - "id": "TransitGatewayRouteTablePropagation", - "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/TransitGatewayRouteTablePropagation", + "customRtbPropagation": { + "id": "customRtbPropagation", + "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings/TransitGateway/RouteTable2/customRtbPropagation/customRtbPropagation", "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTablePropagation", "aws:cdk:cloudformation:props": { "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachmentTransitGatewayAttachmentA377C709" + "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" }, "transitGatewayRouteTableId": { "Ref": "TransitGatewayRouteTable2047E2A04" diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts index 1de4e8c429c31..cca578777b83d 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts @@ -18,32 +18,34 @@ const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { enableDnsSupport: true, }); -/** - * Since source for IPAM IPv6 is set to amazonProvided, - * can assign IPv6 address only after the allocation - * uncomment ipv6CidrBlock and provide valid IPv6 range - */ -const subnet1 = new SubnetV2(stack, 'testSubnet1', { -// new SubnetV2(stack, 'testSubnet1', { +const subnet = new SubnetV2(stack, 'testSubnet1', { vpc, availabilityZone: 'us-east-1a', ipv4CidrBlock: new IpCidr('10.1.0.0/20'), - //defined on the basis of allocation done in IPAM console - //ipv6CidrBlock: new Ipv6Cidr('2a05:d02c:25:4000::/60'), subnetType: SubnetType.PRIVATE_ISOLATED, }); +// Create a Transit Gateway with const tgw = new TransitGateway(stack, 'TransitGateway', { defaultRouteTableAssociation: false, defaultRouteTablePropagation: false, }); -const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet1]); -attachment.node.addDependency(vpc); +// Can attach a VPC to the Transit Gateway +const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet]); + +// Can add additional route tables to the Transit Gateway const customRtb = tgw.addRouteTable('RouteTable2'); +// Can add a static route to the Transit Gateway Route Table tgw.defaultRouteTable.addRoute('defaultRTBRoute', attachment, '0.0.0.0/0'); + +// Add an Association and enable Propagation from the attachment to the custom Route Table customRtb.addAssociation('customRtbAssociation', attachment); + +// This will propagate the defaultRTBRoute to the custom route table. +// The propagation is done dynamically and is reflected in the AWS console but not in the generated CFN template. +// Run this test with --no-clean flag to confirm that the route is in both route tables. customRtb.enablePropagation('customRtbPropagation', attachment); new IntegTest(app, 'integtest-model', { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts index 0332aab98dd81..499dcbedbd51c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts @@ -42,7 +42,6 @@ describe('TransitGatewayRouteTableAssociation', () => { transitGateway: transitGateway, subnets: [mySubnet], }); - }); test('creates association with required properties', () => { From 3b473332de014eaeaed5e97e56b077f7f135c9cb Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Thu, 23 Jan 2025 15:00:34 -0800 Subject: [PATCH 09/22] fix unit test --- .../test/transit-gateway-vpc-attachment.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index 821d31a7d8cf5..440beb46a1e1e 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -68,10 +68,10 @@ describe('TransitGatewayVpcAttachment', () => { TransitGatewayId: stack.resolve(transitGateway.transitGatewayId), SubnetIds: [stack.resolve(mySubnet.subnetId)], Options: { - dnsSupport: 'enable', - ipv6Support: 'enable', - applianceModeSupport: 'enable', - securityGroupReferencingSupport: 'disable', + DnsSupport: 'enable', + Ipv6Support: 'enable', + ApplianceModeSupport: 'enable', + SecurityGroupReferencingSupport: 'disable', }, }); }); From c38c8b0c6090c83aa21dba2a56c19504fc28ff95 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Thu, 23 Jan 2025 15:03:15 -0800 Subject: [PATCH 10/22] remove unused import --- .../@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index b563b5b2b091c..ccd4c77c59e85 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -4,7 +4,6 @@ import { Construct } from 'constructs'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; -// import { ValidationError } from 'aws-cdk-lib/core/lib/errors'; export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment {} From a5db2e510812998a723543ffd148d1d4f940b126 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Fri, 24 Jan 2025 10:49:34 -0800 Subject: [PATCH 11/22] remove unused test --- .../test/integ.transit-gateway-route-table.ts | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts deleted file mode 100644 index 0fa2417abf694..0000000000000 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway-route-table.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as vpc_v2 from '../lib/vpc-v2'; -import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -import * as cdk from 'aws-cdk-lib'; -import { TransitGateway } from '../lib/transit-gateway'; -import { SubnetType } from 'aws-cdk-lib/aws-ec2'; -import { IpCidr, SubnetV2 } from '../lib'; - -const app = new cdk.App(); - -const stack = new cdk.Stack(app, 'aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings'); - -const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { - primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), - secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6( { - cidrBlockName: 'SecondaryTest', - })], - enableDnsHostnames: true, - enableDnsSupport: true, -}); - -/** - * Since source for IPAM IPv6 is set to amazonProvided, - * can assign IPv6 address only after the allocation - * uncomment ipv6CidrBlock and provide valid IPv6 range - */ -const subnet1 = new SubnetV2(stack, 'testSubnet1', { - vpc, - availabilityZone: 'us-east-1a', - ipv4CidrBlock: new IpCidr('10.1.0.0/20'), - //defined on the basis of allocation done in IPAM console - //ipv6CidrBlock: new Ipv6Cidr('2a05:d02c:25:4000::/60'), - subnetType: SubnetType.PRIVATE_ISOLATED, -}); - -const tgw = new TransitGateway(stack, 'TransitGateway', { - defaultRouteTableAssociation: false, - defaultRouteTablePropagation: false, -}); - -const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet1]); -attachment.node.addDependency(vpc); - -tgw.defaultRouteTable.addRoute('defaultRTBRoute', attachment, '0.0.0.0/0'); -tgw.defaultRouteTable.addBlackholeRoute('defaultRTBRoute2', '10.1.0.0/16'); -tgw.defaultRouteTable.addAssociation('customRtbAssociation', attachment); -tgw.defaultRouteTable.enablePropagation('customRtbPropagation', attachment); - -new IntegTest(app, 'integtest-model', { - testCases: [stack], -}); - From 4a53920f0be34d1381274eafb2373ab33505c1b6 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Fri, 24 Jan 2025 16:05:49 -0800 Subject: [PATCH 12/22] pr feedback --- packages/@aws-cdk/aws-ec2-alpha/README.md | 46 +++++------ ...transit-gateway-route-table-association.ts | 21 ++--- ...transit-gateway-route-table-propagation.ts | 22 +++--- .../lib/transit-gateway-route-table.ts | 6 +- .../lib/transit-gateway-route.ts | 40 +++++----- .../lib/transit-gateway-vpc-attachment.ts | 42 ++++++---- .../aws-ec2-alpha/lib/transit-gateway.ts | 78 +++++++++++++------ packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 9 +++ .../test/integ.transit-gateway.ts | 5 +- .../test/transit-gateway-route.test.ts | 4 +- .../transit-gateway-vpc-attachment.test.ts | 37 ++++++--- .../test/transit-gateway.test.ts | 22 +++++- 12 files changed, 204 insertions(+), 128 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index 5dfecdcdef20e..e3bcc020de337 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -701,7 +701,7 @@ Tags.of(vpc).add('Environment', 'Production'); The AWS Transit Gateway construct library allows you to create and configure Transit Gateway resources using AWS CDK. -## Overview +### Overview The Transit Gateway construct (`TransitGateway`) is the main entry point for creating and managing your Transit Gateway infrastructure. It provides methods to create route tables, attach VPCs, and configure cross-account access. @@ -722,21 +722,14 @@ import * as ec2 from '@aws-cdk/aws-ec2-alpha'; const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway'); ``` -Key properties available: - -- `transitGatewayId`: The ID of the Transit Gateway -- `transitGatewayArn`: The ARN of the Transit Gateway -- `defaultRouteTable`: The default route table created with the Transit Gateway -- `defaultRouteTableAssociation`: Controls automatic route table association -- `defaultRouteTablePropagation`: Controls automatic route propagation - ### Default Transit Gateway Route Table By default, `TransitGateway` is created with a default `TransitGatewayRouteTable`, for which automatic Associations and automatic Propagations are enabled. -> Note: When you create a default Transit Gateway in AWS Console, EC2 creates the default `TransitGatewayRouteTable` for you. When using this construct, CDK will create the default `TransitGatewayRouteTable` for you instead with the automatic Association/Propagation features being mimicked by the CDK. +> Note: When you create a default Transit Gateway in AWS Console, a default Transit Gateway Route Table is automatically created by AWS. However, when using the CDK Transit Gateway L2 construct, the underlying L1 construct is configured with `defaultRouteTableAssociation` and `defaultRouteTablePropagation` explicitly disabled. This ensures that AWS does not create the default route table, allowing the CDK to define a custom default route table instead. > -> **Default association route table** and **Default propagation route table** will show as disabled in your AWS console but can still be toggled within CDK using the `defaultRouteTableAssociation` and `defaultRouteTablePropagation` properties respectively. +> As a result, in the AWS Console, the **Default association route table** and **Default propagation route table** settings will appear as disabled. Despite this, the CDK still provides automatic association and propagation functionality through its internal implementation, which can be controlled using the `defaultRouteTableAssociation` and `defaultRouteTablePropagation` properties within the CDK. + You can disable the automatic Association/Propagation on the default `TransitGatewayRouteTable` via the `TransitGateway` properties. This will still create a default route table for you: @@ -747,17 +740,7 @@ const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { }); ``` -You can also provide your own `TransitGatewayRouteTable` to be used as the default route table: - -```ts -const customRouteTable = new ec2.TransitGatewayRouteTable(this, 'TransitGatewayRouteTable'); - -const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { - customDefaultRouteTable: customRouteTable, -}); -``` - -## Transit Gateway Route Table Management +### Transit Gateway Route Table Management Add additional Transit Gateway Route Tables using the `addRouteTable()` method: @@ -772,17 +755,24 @@ Create an attachment from a VPC to the Transit Gateway using the `attachVpc()` m ```ts // Create a basic attachment -const attachment = transitGateway.attachVpc('VpcAttachment', vpc, [subnet1, subnet2]); +const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: vpc, + subnets: [subnet1, subnet2] +}); ``` You can customize the VPC attachment by passing in optional parameters. These include options for fine-tuning the attachment behavior, such as support for DNS, IPv6, Appliance Mode and Security Group Referencing. ```ts -const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], { - dnsSupport: true, - applianceModeSupport: true, - ipv6Support: true, - securityGroupReferencingSupport: true, +const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', { + vpc: vpc, + subnets: [subnet], + vpcAttachmentOptions: { + dnsSupport: true, + applianceModeSupport: true, + ipv6Support: true, + securityGroupReferencingSupport: true, + } }); ``` diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index c3a2b404633e8..8b36c155cde3c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -6,34 +6,35 @@ import { Construct } from 'constructs'; export interface ITransitGatewayRouteTableAssociation extends IResource { /** - * The ID of the transit gateway route table association. - */ + * The ID of the transit gateway route table association. + * @attribute + */ readonly transitGatewayRouteTableAssociationId: string; } export interface TransitGatewayRouteTableAssociationProps { /** - * The ID of the transit gateway route table association. - */ + * The ID of the transit gateway route table association. + */ readonly transitGatewayVpcAttachment: ITransitGatewayAttachment; /** - * The ID of the transit gateway route table association. - */ + * The ID of the transit gateway route table association. + */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; } abstract class TransitGatewayRouteTableAssociationBase extends Resource implements ITransitGatewayRouteTableAssociation { /** - * The ID of the transit gateway route table association. - */ + * The ID of the transit gateway route table association. + */ public abstract readonly transitGatewayRouteTableAssociationId: string; } export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTableAssociationBase { /** - * The ID of the transit gateway route table association. - */ + * The ID of the transit gateway route table association. + */ public readonly transitGatewayRouteTableAssociationId: string; constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index bb29869f49104..8c540ed446c61 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -6,35 +6,35 @@ import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; export interface ITransitGatewayRouteTablePropagation extends IResource { /** - * The ID of the transit gateway route table propagation. - * @attribute - */ + * The ID of the transit gateway route table propagation. + * @attribute + */ readonly transitGatewayRouteTablePropagationId: string; } export interface TransitGatewayRouteTablePropagationProps { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ readonly transitGatewayVpcAttachment: ITransitGatewayAttachment; /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; } abstract class TransitGatewayRouteTablePropagationBase extends Resource implements ITransitGatewayRouteTablePropagation { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ public abstract readonly transitGatewayRouteTablePropagationId: string; } export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTablePropagationBase { /** - * The ID of the transit gateway route table propagation. - */ + * The ID of the transit gateway route table propagation. + */ public readonly transitGatewayRouteTablePropagationId: string; constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index 4652587e856af..e78eadebedf68 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -3,7 +3,7 @@ import { ITransitGateway } from './transit-gateway'; import { Construct } from 'constructs'; import { CfnTransitGatewayRouteTable, IRouteTable } from 'aws-cdk-lib/aws-ec2'; import { ITransitGatewayAttachment } from './transit-gateway-attachment'; -import { TransitGatewayActiveRoute, TransitGatewayBlackholeRoute } from './transit-gateway-route'; +import { TransitGatewayRoute, TransitGatewayBlackholeRoute } from './transit-gateway-route'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; @@ -26,8 +26,8 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit public abstract readonly routeTableId: string; public abstract readonly transitGateway: ITransitGateway; - addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayActiveRoute { - return new TransitGatewayActiveRoute(this, id, { + addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayRoute { + return new TransitGatewayRoute(this, id, { transitGatewayRouteTable: this, transitGatewayAttachment, destinationCidrBlock: destinationCidr, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index 850abdc7a1f7f..adb14955a5faa 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -6,45 +6,45 @@ import { ITransitGatewayAttachment } from './transit-gateway-attachment'; export interface ITransitGatewayRoute extends IResource { /** - * The destination CIDR block for this route. - * - * Destination Cidr cannot overlap for static routes but is allowed for propagated routes. - * When overlapping occurs, static routes take precedence over propagated routes. - */ + * The destination CIDR block for this route. + * + * Destination Cidr cannot overlap for static routes but is allowed for propagated routes. + * When overlapping occurs, static routes take precedence over propagated routes. + */ readonly destinationCidrBlock: string; /** - * The transit gateway route table this route belongs to. - */ + * The transit gateway route table this route belongs to. + */ readonly routeTable: ITransitGatewayRouteTable; } -export interface TransitGatewayActiveRouteProps { +export interface TransitGatewayRouteProps { /** - * The transit gateway attachment to route the traffic to. - */ + * The transit gateway attachment to route the traffic to. + */ readonly transitGatewayAttachment: ITransitGatewayAttachment; /** - * The CIDR block used for destination matches. - */ + * The CIDR block used for destination matches. + */ readonly destinationCidrBlock: string; /** - * The transit gateway route table you want to install this route into. - */ + * The transit gateway route table you want to install this route into. + */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; } export interface TransitGatewayBlackholeRouteProps { /** - * The CIDR block used for destination matches. - */ + * The CIDR block used for destination matches. + */ readonly destinationCidrBlock: string; /** - * The transit gateway route table you want to install this route into. - */ + * The transit gateway route table you want to install this route into. + */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; } @@ -53,11 +53,11 @@ abstract class TransitGatewayRouteBase extends Resource implements ITransitGatew public abstract destinationCidrBlock: string; } -export class TransitGatewayActiveRoute extends TransitGatewayRouteBase { +export class TransitGatewayRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; - constructor(scope: Construct, id: string, props: TransitGatewayActiveRouteProps) { + constructor(scope: Construct, id: string, props: TransitGatewayRouteProps) { super(scope, id); const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index ccd4c77c59e85..5cae34dc48df3 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -1,9 +1,11 @@ -import { ITransitGateway, TransitGatewayFeatureStatus } from './transit-gateway'; +import { ITransitGateway } from './transit-gateway'; import { CfnTransitGatewayAttachment, ISubnet, IVpc } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; +import { getFeatureStatusDefaultDisable } from './util'; +import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment {} @@ -37,27 +39,41 @@ export interface ITransitGatewayVpcAttachmentOptions { readonly securityGroupReferencingSupport?: boolean; } -export interface TransitGatewayVpcAttachmentProps { +interface BaseTransitGatewayVpcAttachmentProps { /** * A list of one or more subnets to place the attachment in. * It is recommended to specify more subnets for better availability. */ readonly subnets: ISubnet[]; + /** + * A VPC attachment(s) will get assigned to. + */ + readonly vpc: IVpc; + + /** + * The VPC attachment options. + */ + readonly vpcAttachmentOptions?: ITransitGatewayVpcAttachmentOptions; +} + +export interface TransitGatewayVpcAttachmentProps extends BaseTransitGatewayVpcAttachmentProps { /** * The transit gateway this attachment gets assigned to. */ readonly transitGateway: ITransitGateway; +} +export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { /** - * A VPC attachment(s) will get assigned to. + * An optional route table to associate with this VPC attachment. */ - readonly vpc: IVpc; + readonly associationRouteTable?: ITransitGatewayRouteTable; /** - * The VPC attachment options. + * A list of optional route tables to propagate routes to. */ - readonly transitGatewayVpcAttachmentOptions?: ITransitGatewayVpcAttachmentOptions; + readonly propagationRouteTables?: ITransitGatewayRouteTable[]; } export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { @@ -72,15 +88,11 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { subnetIds: props.subnets.map((subnet) => subnet.subnetId), transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, - options: props.transitGatewayVpcAttachmentOptions ? { - ApplianceModeSupport: (props.transitGatewayVpcAttachmentOptions?.applianceModeSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - DnsSupport: (props.transitGatewayVpcAttachmentOptions?.dnsSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - Ipv6Support: (props.transitGatewayVpcAttachmentOptions?.ipv6Support ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - SecurityGroupReferencingSupport: (props.transitGatewayVpcAttachmentOptions?.securityGroupReferencingSupport ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + options: props.vpcAttachmentOptions ? { + ApplianceModeSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.applianceModeSupport), + DnsSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.dnsSupport), + Ipv6Support: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.ipv6Support), + SecurityGroupReferencingSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.securityGroupReferencingSupport), } : undefined, }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index ae4c43976ffc5..5aed98b3b5068 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -1,11 +1,12 @@ -import { CfnTransitGateway, ISubnet, IVpc, RouterType } from 'aws-cdk-lib/aws-ec2'; +import { CfnTransitGateway, RouterType } from 'aws-cdk-lib/aws-ec2'; import { Resource } from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { ITransitGatewayRouteTable, TransitGatewayRouteTable } from './transit-gateway-route-table'; -import { TransitGatewayVpcAttachment, ITransitGatewayVpcAttachmentOptions } from './transit-gateway-vpc-attachment'; +import { TransitGatewayVpcAttachment, AttachVpcOptions } from './transit-gateway-vpc-attachment'; import { IRouteTarget } from './route'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; +import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable } from './util'; export enum TransitGatewayFeatureStatus { ENABLE = 'enable', @@ -13,10 +14,46 @@ export enum TransitGatewayFeatureStatus { } export interface ITransitGateway { + /** + * The unique identifier of the Transit Gateway. + * + * This ID is automatically assigned by AWS upon creation of the Transit Gateway + * and is used to reference it in various configurations and operations. + * @attribute + */ readonly transitGatewayId: string; + + /** + * The Amazon Resource Name (ARN) of the Transit Gateway. + * + * The ARN uniquely identifies the Transit Gateway across AWS and is commonly + * used for permissions and resource tracking. + * @attribute + */ readonly transitGatewayArn: string; + + /** + * The default route table associated with the Transit Gateway. + * + * This route table is created by the CDK and is used to manage the routes + * for attachments that do not have an explicitly defined route table association. + */ readonly defaultRouteTable: ITransitGatewayRouteTable; + + /** + * Indicates whether new attachments are automatically associated with the default route table. + * + * If set to `true`, any VPC or VPN attachment will be automatically associated with + * the default route table unless otherwise specified. + */ readonly defaultRouteTableAssociation: boolean; + + /** + * Indicates whether route propagation to the default route table is enabled. + * + * When set to `true`, routes from attachments will be automatically propagated + * to the default route table unless propagation is explicitly disabled. + */ readonly defaultRouteTablePropagation: boolean; } @@ -103,31 +140,25 @@ abstract class TransitGatewayBase extends Resource implements ITransitGateway, I }); } - attachVpc( - id: string, vpc: IVpc, - subnets: ISubnet[], - transitGatewayAttachmentOptions?: ITransitGatewayVpcAttachmentOptions, - associationRouteTable?: ITransitGatewayRouteTable, - propagationRouteTables?: ITransitGatewayRouteTable[], - ): TransitGatewayVpcAttachment { + attachVpc(id: string, options: AttachVpcOptions): TransitGatewayVpcAttachment { const attachment = new TransitGatewayVpcAttachment(this, id, { transitGateway: this, - vpc: vpc, - subnets: subnets, - transitGatewayVpcAttachmentOptions: transitGatewayAttachmentOptions ?? undefined, + vpc: options.vpc, + subnets: options.subnets, + vpcAttachmentOptions: options.vpcAttachmentOptions ?? undefined, }); // If `associationRouteTable` is provided, skip creating the Association only if `associationRouteTable` is the default route table and // automatic association (`defaultRouteTableAssociation`) is enabled, as the TransitGatewayRouteTableAttachment's constructor will handle it in that case. - if (associationRouteTable && !(this.defaultRouteTable === associationRouteTable && this.defaultRouteTableAssociation)) { + if (options.associationRouteTable && !(this.defaultRouteTable === options.associationRouteTable && this.defaultRouteTableAssociation)) { new TransitGatewayRouteTableAssociation(this, `${id}-Association-${this.node.addr}`, { transitGatewayVpcAttachment: attachment, - transitGatewayRouteTable: associationRouteTable, + transitGatewayRouteTable: options.associationRouteTable, }); } - if (propagationRouteTables) { - propagationRouteTables.forEach((propagationRouteTable, index) => { + if (options.propagationRouteTables) { + options.propagationRouteTables.forEach((propagationRouteTable, index) => { // If `propagationRouteTable` is provided, skip creating the Propagation only if `propagationRouteTable` is the default route table and // automatic propagation (`defaultRouteTablePropagation`) is enabled, as the TransitGatewayRouteTableAttachment's constructor will handle it in that case. if (!(this.defaultRouteTable === propagationRouteTable && this.defaultRouteTablePropagation)) { @@ -157,18 +188,15 @@ export class TransitGateway extends TransitGatewayBase { const resource = new CfnTransitGateway(this, id, { amazonSideAsn: props?.amazonSideAsn ?? undefined, - autoAcceptSharedAttachments: (props?.autoAcceptSharedAttachments ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + autoAcceptSharedAttachments: getFeatureStatusDefaultDisable(props?.autoAcceptSharedAttachments), // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. // Instead, CDK will create a custom default route table and use the properties to mimic the automatic assocation/propagation behaviour. - defaultRouteTableAssociation: (props?.defaultRouteTableAssociation ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - defaultRouteTablePropagation: (props?.defaultRouteTablePropagation ?? false) - ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + defaultRouteTableAssociation: getFeatureStatusDefaultDisable(props?.defaultRouteTableAssociation), + defaultRouteTablePropagation: getFeatureStatusDefaultDisable(props?.defaultRouteTablePropagation), description: props?.description, - dnsSupport: (props?.dnsSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - multicastSupport: (props?.multicastSupport ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, - vpnEcmpSupport: (props?.vpnEcmpSupport ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE, + dnsSupport: getFeatureStatusDefaultEnable(props?.dnsSupport), + multicastSupport: getFeatureStatusDefaultDisable(props?.multicastSupport), + vpnEcmpSupport: getFeatureStatusDefaultEnable(props?.vpnEcmpSupport), }); this.transitGatewayId = resource.ref; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index 56baeecc83e1e..afab959874703 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -1,6 +1,7 @@ /* eslint no-bitwise: ["error", { "allow": ["~", "|", "<<", "&"] }] */ import { ISubnet } from 'aws-cdk-lib/aws-ec2'; +import { TransitGatewayFeatureStatus } from './transit-gateway'; /** * Return a subnet name from its construct ID @@ -18,6 +19,14 @@ export function subnetId(name: string, i: number) { return `${name}Subnet${i + 1}`; } +export function getFeatureStatusDefaultEnable(status?: boolean): TransitGatewayFeatureStatus { + return (status ?? true)? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; +} + +export function getFeatureStatusDefaultDisable(status?: boolean): TransitGatewayFeatureStatus { + return (status ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; +} + /** * Return the union of table IDs from all selected subnets */ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts index cca578777b83d..99e38d2fa6d00 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.ts @@ -32,7 +32,10 @@ const tgw = new TransitGateway(stack, 'TransitGateway', { }); // Can attach a VPC to the Transit Gateway -const attachment = tgw.attachVpc('DefaultRtbAttachment', vpc, [subnet]); +const attachment = tgw.attachVpc('DefaultRtbAttachment', { + vpc: vpc, + subnets: [subnet], +}); // Can add additional route tables to the Transit Gateway const customRtb = tgw.addRouteTable('RouteTable2'); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts index 77e094fb618af..a318b38473908 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts @@ -6,7 +6,7 @@ import * as subnet from '../lib/subnet-v2'; import { SubnetType } from 'aws-cdk-lib/aws-ec2'; import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; -import { TransitGatewayActiveRoute, TransitGatewayBlackholeRoute } from '../lib/transit-gateway-route'; +import { TransitGatewayRoute, TransitGatewayBlackholeRoute } from '../lib/transit-gateway-route'; describe('Transit Gateway Route', () => { let stack: cdk.Stack; @@ -60,7 +60,7 @@ describe('Transit Gateway Route', () => { describe('TransitGatewayActiveRoute', () => { test('creates a route with the correct properties', () => { // WHEN - new TransitGatewayActiveRoute(stack, 'ActiveRoute', { + new TransitGatewayRoute(stack, 'ActiveRoute', { transitGatewayAttachment: attachment, destinationCidrBlock: '10.1.0.0/16', transitGatewayRouteTable: routeTable, diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index 440beb46a1e1e..bcb62682b57d3 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -33,7 +33,10 @@ describe('TransitGatewayVpcAttachment', () => { test('creates vpc attachment with required properties', () => { // WHEN - transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); // THEN Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { @@ -56,10 +59,14 @@ describe('TransitGatewayVpcAttachment', () => { test('creates vpc attachment with optional properties', () => { // WHEN - transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet], { - dnsSupport: true, - ipv6Support: true, - applianceModeSupport: true, + transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + vpcAttachmentOptions: { + dnsSupport: true, + ipv6Support: true, + applianceModeSupport: true, + }, }); // THEN @@ -78,7 +85,10 @@ describe('TransitGatewayVpcAttachment', () => { test('can add subnets', () => { // GIVEN - const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); const additionalSubnet = new subnet.SubnetV2(stack, 'AdditionalSubnet', { vpc: myVpc, @@ -108,7 +118,10 @@ describe('TransitGatewayVpcAttachment', () => { subnetType: SubnetType.PRIVATE_WITH_EGRESS, }); - const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet, additionalSubnet]); + const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet, additionalSubnet], + }); // WHEN attachment.removeSubnets([additionalSubnet]); @@ -121,7 +134,10 @@ describe('TransitGatewayVpcAttachment', () => { test('throws error when adding duplicate subnet', () => { // GIVEN - const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); // THEN expect(() => attachment.addSubnets([mySubnet])).toThrow( @@ -131,7 +147,10 @@ describe('TransitGatewayVpcAttachment', () => { test('throws error when removing non-existent subnet', () => { // GIVEN - const attachment = transitGateway.attachVpc('VpcAttachment', myVpc, [mySubnet]); + const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); const nonExistentSubnet = new subnet.SubnetV2(stack, 'NonExistentSubnet', { vpc: myVpc, diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 4b2d4baddb84f..9b8c217e73c3a 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -114,7 +114,10 @@ describe('Transit Gateway with default settings', () => { test('attach vpc method should create an attachment, association and propagation when default association/propagation are enabled', () => { - tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + tgw.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ @@ -265,7 +268,10 @@ describe('Transit Gateway with default route table association and propagation d test('attach vpc method should create an attachment and not create an association or propagation when default association/propagation are disabled', () => { - tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + tgw.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ @@ -416,7 +422,10 @@ describe('Transit Gateway with default route table association and propagation d test('attach vpc method should create an attachment and not create an association or propagation', () => { - tgw.attachVpc('VpcAttachment', myVpc, [mySubnet]); + tgw.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ @@ -456,7 +465,12 @@ describe('Transit Gateway with default route table association and propagation d test('attach vpc method should create an attachment, association and propagation when route tables are passed to the method', () => { - tgw.attachVpc('VpcAttachment', myVpc, [mySubnet], undefined, tgw.defaultRouteTable, [tgw.defaultRouteTable]); + tgw.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + associationRouteTable: tgw.defaultRouteTable, + propagationRouteTables: [tgw.defaultRouteTable], + }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { SubnetIds: [ From a00ecc7ecc408e643bbc232d212e200b61e4f174 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Mon, 27 Jan 2025 15:48:30 -0800 Subject: [PATCH 13/22] add docstrings, update readme, add fromxxx linter exemption --- packages/@aws-cdk/aws-ec2-alpha/README.md | 106 ++++++++++++++---- packages/@aws-cdk/aws-ec2-alpha/awslint.json | 5 +- packages/@aws-cdk/aws-ec2-alpha/lib/index.ts | 7 ++ .../lib/transit-gateway-attachment.ts | 8 +- ...transit-gateway-route-table-association.ts | 22 ++++ ...transit-gateway-route-table-propagation.ts | 22 ++++ .../lib/transit-gateway-route-table.ts | 52 ++++++++- .../lib/transit-gateway-route.ts | 49 ++++++-- .../lib/transit-gateway-vpc-attachment.ts | 53 ++++++++- .../aws-ec2-alpha/lib/transit-gateway.ts | 83 +++++++++----- packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 16 ++- .../aws-ec2-alpha/rosetta/default.ts-fixture | 2 +- ...it-gateway-route-table-association.test.ts | 4 +- ...it-gateway-route-table-propagation.test.ts | 4 +- 14 files changed, 363 insertions(+), 70 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index e3bcc020de337..5a30f9642fcff 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -717,9 +717,7 @@ The Transit Gateway construct library provides four main constructs: To create a minimal deployable `TransitGateway`: ```ts -import * as ec2 from '@aws-cdk/aws-ec2-alpha'; - -const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway'); +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); ``` ### Default Transit Gateway Route Table @@ -734,7 +732,7 @@ By default, `TransitGateway` is created with a default `TransitGatewayRouteTable You can disable the automatic Association/Propagation on the default `TransitGatewayRouteTable` via the `TransitGateway` properties. This will still create a default route table for you: ```ts -const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { +const transitGateway = new TransitGateway(this, 'MyTransitGateway', { defaultRouteTableAssociation: false, defaultRouteTablePropagation: false, }); @@ -745,8 +743,9 @@ const transitGateway = new ec2.TransitGateway(this, 'MyTransitGateway', { Add additional Transit Gateway Route Tables using the `addRouteTable()` method: ```ts -const tgw = new TransitGateway(this, 'TransitGateway'); -const routeTable = tgw.addRouteTable('CustomRouteTable'); +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); + +const routeTable = transitGateway.addRouteTable('CustomRouteTable'); ``` ### Attaching VPCs to the Transit Gateway @@ -754,19 +753,33 @@ const routeTable = tgw.addRouteTable('CustomRouteTable'); Create an attachment from a VPC to the Transit Gateway using the `attachVpc()` method: ```ts +const myVpc = new VpcV2(this, 'Vpc'); +const subnet1 = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PUBLIC +}); + +const subnet2 = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.1.0/24'), + subnetType: SubnetType.PUBLIC +}); + +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); + // Create a basic attachment const attachment = transitGateway.attachVpc('VpcAttachment', { - vpc: vpc, + vpc: myVpc, subnets: [subnet1, subnet2] }); -``` - -You can customize the VPC attachment by passing in optional parameters. These include options for fine-tuning the attachment behavior, such as support for DNS, IPv6, Appliance Mode and Security Group Referencing. -```ts -const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', { - vpc: vpc, - subnets: [subnet], +// Create an attachment with optional parameters +const attachmentWithOptions = transitGateway.attachVpc('VpcAttachmentWithOptions', { + vpc: myVpc, + subnets: [subnet1], vpcAttachmentOptions: { dnsSupport: true, applianceModeSupport: true, @@ -779,7 +792,33 @@ const attachmentWithOptions = transitGateway.attachVpc('VpcAttachment', { If you want to automatically associate and propagate routes with transit gateway route tables, you can pass the `associationRouteTable` and `propagationRouteTables` parameters. This will automatically create the necessary associations and propagations based on the provided route tables. ```ts -const attachmentWithRoutes = transitGateway.attachVpc('VpcAttachment', vpc, [subnet], undefined, associationRouteTable, [propagationRouteTable1, propagationRouteTable2]); +const myVpc = new VpcV2(this, 'Vpc'); +const subnet1 = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PUBLIC +}); + +const subnet2 = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.1.0/24'), + subnetType: SubnetType.PUBLIC +}); + +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); +const associationRouteTable = transitGateway.addRouteTable('AssociationRouteTable'); +const propagationRouteTable1 = transitGateway.addRouteTable('PropagationRouteTable1'); +const propagationRouteTable2 = transitGateway.addRouteTable('PropagationRouteTable2'); + +// Create an attachment with automatically created association + propagations +const attachmentWithRoutes = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [subnet1, subnet2], + associationRouteTable: associationRouteTable, + propagationRouteTables: [propagationRouteTable1, propagationRouteTable2], +}); ``` In this example, the `associationRouteTable` is set to `associationRouteTable`, and `propagationRouteTables` is set to an array containing `propagationRouteTable1` and `propagationRouteTable2`. This triggers the automatic creation of route table associations and route propagations between the Transit Gateway and the specified route tables. @@ -789,12 +828,25 @@ In this example, the `associationRouteTable` is set to `associationRouteTable`, Add static routes using either the `addRoute()` method to add an active route or `addBlackholeRoute()` to add a blackhole route: ```ts -// Add a static route to direct traffic -routeTable.addRoute('StaticRoute', { - transitGatewayAttachment: vpcAttachment, - destinationCidrBlock: '10.0.0.0/16', +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); +const routeTable = transitGateway.addRouteTable('CustomRouteTable'); + +const myVpc = new VpcV2(this, 'Vpc'); +const subnet = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PUBLIC +}); + +const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [subnet] }); +// Add a static route to direct traffic +routeTable.addRoute('StaticRoute', attachment, '10.0.0.0/16'); + // Block unwanted traffic with a blackhole route routeTable.addBlackholeRoute('BlackholeRoute', '172.16.0.0/16'); ``` @@ -804,11 +856,25 @@ routeTable.addBlackholeRoute('BlackholeRoute', '172.16.0.0/16'); Configure route table associations and enable route propagation: ```ts +const transitGateway = new TransitGateway(this, 'MyTransitGateway'); +const routeTable = transitGateway.addRouteTable('CustomRouteTable'); +const myVpc = new VpcV2(this, 'Vpc'); +const subnet = new SubnetV2(this, 'Subnet', { + vpc: myVpc, + availabilityZone: 'eu-west-2a', + ipv4CidrBlock: new IpCidr('10.0.0.0/24'), + subnetType: SubnetType.PUBLIC +}); +const attachment = transitGateway.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [subnet] +}); + // Associate an attachment with a route table routeTable.addAssociation('Association', attachment); // Enable route propagation for an attachment -routeTable.enablePropagation('Propagation', attachent); +routeTable.enablePropagation('Propagation', attachment); ``` **Associations** — The linking of a Transit Gateway attachment to a specific route table, which determines which routes that attachment will use for routing decisions. diff --git a/packages/@aws-cdk/aws-ec2-alpha/awslint.json b/packages/@aws-cdk/aws-ec2-alpha/awslint.json index ec8b3e125eeea..b05a4b36425bd 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/awslint.json +++ b/packages/@aws-cdk/aws-ec2-alpha/awslint.json @@ -1,6 +1,9 @@ { "exclude": [ "attribute-tag:@aws-cdk/aws-ec2-alpha.RouteTable.routeTableId", - "from-method:@aws-cdk/aws-ec2-alpha.Route" + "from-method:@aws-cdk/aws-ec2-alpha.Route", + "from-method:@aws-cdk/aws-ec2-alpha.TransitGateway", + "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTableAssociation", + "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTablePropagation" ] } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts index 26f148f30b2aa..17b3510f43740 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts @@ -8,3 +8,10 @@ export * from './ipam'; export * from './vpc-v2-base'; export * from './subnet-v2'; export * from './route'; +export * from './transit-gateway'; +export * from './transit-gateway-route'; +export * from './transit-gateway-route-table'; +export * from './transit-gateway-attachment'; +export * from './transit-gateway-vpc-attachment'; +export * from './transit-gateway-route-table-association'; +export * from './transit-gateway-route-table-propagation'; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index aa1084d27818d..fd31532f044fe 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -1,5 +1,7 @@ import { IResource, Resource } from 'aws-cdk-lib/core'; - +/** + * Represents a Transit Gateway Attachment. + */ export interface ITransitGatewayAttachment extends IResource { /** * The ID of the transit gateway attachment. @@ -8,6 +10,10 @@ export interface ITransitGatewayAttachment extends IResource { readonly transitGatewayVpcAttachmentId: string; } +/** + * A Transit Gateway Attachment. + * @internal + */ export abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { public abstract readonly transitGatewayVpcAttachmentId: string; } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index 8b36c155cde3c..a2c2eaafaf661 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -4,6 +4,9 @@ import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; import { CfnTransitGatewayRouteTableAssociation } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; +/** + * Represents a Transit Gateway Route Table Association + */ export interface ITransitGatewayRouteTableAssociation extends IResource { /** * The ID of the transit gateway route table association. @@ -12,6 +15,9 @@ export interface ITransitGatewayRouteTableAssociation extends IResource { readonly transitGatewayRouteTableAssociationId: string; } +/** + * Common properties for a Transit Gateway Route Table Association. + */ export interface TransitGatewayRouteTableAssociationProps { /** * The ID of the transit gateway route table association. @@ -22,8 +28,19 @@ export interface TransitGatewayRouteTableAssociationProps { * The ID of the transit gateway route table association. */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; + + /** + * Physical name of this association. + * + * @default - Assigned by CloudFormation. + */ + readonly transitGatewayRouteTableAssociationName?: string; } +/** + * A Transit Gateway Route Table Association. + * @internal + */ abstract class TransitGatewayRouteTableAssociationBase extends Resource implements ITransitGatewayRouteTableAssociation { /** * The ID of the transit gateway route table association. @@ -31,6 +48,11 @@ abstract class TransitGatewayRouteTableAssociationBase extends Resource implemen public abstract readonly transitGatewayRouteTableAssociationId: string; } +/** + * Create a Transit Gateway Route Table Association + * + * @resource AWS::EC2::TransitGatewayRouteTableAssociation + */ export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTableAssociationBase { /** * The ID of the transit gateway route table association. diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index 8c540ed446c61..5806c2bcace0c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -4,6 +4,9 @@ import { Construct } from 'constructs'; import { ITransitGatewayAttachment } from './transit-gateway-attachment'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; +/** + * Represents a Transit Gateway Route Table Propagation + */ export interface ITransitGatewayRouteTablePropagation extends IResource { /** * The ID of the transit gateway route table propagation. @@ -12,6 +15,9 @@ export interface ITransitGatewayRouteTablePropagation extends IResource { readonly transitGatewayRouteTablePropagationId: string; } +/** + * Common properties for a Transit Gateway Route Table Propagation. + */ export interface TransitGatewayRouteTablePropagationProps { /** * The ID of the transit gateway route table propagation. @@ -22,8 +28,19 @@ export interface TransitGatewayRouteTablePropagationProps { * The ID of the transit gateway route table propagation. */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; + + /** + * Physical name of this propagation. + * + * @default - Assigned by CloudFormation. + */ + readonly transitGatewayRouteTablePropagationName?: string; } +/** + * A Transit Gateway Route Table Propagation. + * @internal + */ abstract class TransitGatewayRouteTablePropagationBase extends Resource implements ITransitGatewayRouteTablePropagation { /** * The ID of the transit gateway route table propagation. @@ -31,6 +48,11 @@ abstract class TransitGatewayRouteTablePropagationBase extends Resource implemen public abstract readonly transitGatewayRouteTablePropagationId: string; } +/** + * Create a Transit Gateway Route Table Propagation + * + * @resource AWS::EC2::TransitGatewayRouteTablePropagation + */ export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTablePropagationBase { /** * The ID of the transit gateway route table propagation. diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index e78eadebedf68..b247cd6f0aabb 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -7,21 +7,66 @@ import { TransitGatewayRoute, TransitGatewayBlackholeRoute } from './transit-gat import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; +/** + * Represents a Transit Gateway Route Table + */ export interface ITransitGatewayRouteTable extends IResource { /** * The ID of the transit gateway route table * @attribute */ readonly routeTableId: string; + + /** + * Add an active route to this route table + * + * @returns TransitGatewayRoute + */ + addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayRoute; + + /** + * Add a blackhole route to this route table + * + * @returns TransitGatewayBlackholeRoute + */ + addBlackholeRoute(id: string, destinationCidr: string): TransitGatewayBlackholeRoute; + + /** + * Add an Association to this route table + * + * @returns TransitGatewayRouteTableAssociation + */ + addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTableAssociation; + + /** + * Enable propagation from an Attachment + * + * @returns TransitGatewayRouteTablePropagation + */ + enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTablePropagation; } +/** + * Common properties for creating a Transit Gateway Route Table resource. + */ export interface TransitGatewayRouteTableProps { /** - * The ID of the transit gateway + * The Transit Gateway that this route table belongs to. */ readonly transitGateway: ITransitGateway; + + /** + * Physical name of this Transit Gateway Route Table. + * + * @default - Assigned by CloudFormation. + */ + readonly transitGatewayRouteTableName?: string; } +/** + * A Transit Gateway Route Table. + * @internal + */ abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable, IRouteTable { public abstract readonly routeTableId: string; public abstract readonly transitGateway: ITransitGateway; @@ -57,12 +102,15 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit } /** - * An AWS Transit Gateway route table + * Creates a Transit Gateway route table. * * @resource AWS::EC2::TransitGatewayRouteTable */ export class TransitGatewayRouteTable extends TransitGatewayRouteTableBase { public readonly routeTableId: string; + /** + * The Transit Gateway. + */ public readonly transitGateway: ITransitGateway; constructor(scope: Construct, id: string, props: TransitGatewayRouteTableProps) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index adb14955a5faa..d194a81796b82 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -4,6 +4,9 @@ import { CfnTransitGatewayRoute } from 'aws-cdk-lib/aws-ec2'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; import { ITransitGatewayAttachment } from './transit-gateway-attachment'; +/** + * Represents a Transit Gateway Route. + */ export interface ITransitGatewayRoute extends IResource { /** * The destination CIDR block for this route. @@ -19,12 +22,10 @@ export interface ITransitGatewayRoute extends IResource { readonly routeTable: ITransitGatewayRouteTable; } -export interface TransitGatewayRouteProps { - /** - * The transit gateway attachment to route the traffic to. - */ - readonly transitGatewayAttachment: ITransitGatewayAttachment; - +/** + * Common properties for a Transit Gateway Route. + */ +export interface BaseTransitGatewayRouteProps { /** * The CIDR block used for destination matches. */ @@ -34,25 +35,44 @@ export interface TransitGatewayRouteProps { * The transit gateway route table you want to install this route into. */ readonly transitGatewayRouteTable: ITransitGatewayRouteTable; -} -export interface TransitGatewayBlackholeRouteProps { /** - * The CIDR block used for destination matches. + * Physical name of this Transit Gateway Route. + * + * @default - Assigned by CloudFormation. */ - readonly destinationCidrBlock: string; + readonly transitGatewayRouteName?: string; +} +/** + * Common properties for a Transit Gateway Route. + */ +export interface TransitGatewayRouteProps extends BaseTransitGatewayRouteProps { /** - * The transit gateway route table you want to install this route into. + * The transit gateway attachment to route the traffic to. */ - readonly transitGatewayRouteTable: ITransitGatewayRouteTable; + readonly transitGatewayAttachment: ITransitGatewayAttachment; } +/** + * Properties for a Transit Gateway Blackhole Route. + */ +export interface TransitGatewayBlackholeRouteProps extends BaseTransitGatewayRouteProps {} + +/** + * A Transit Gateway Route. + * @internal + */ abstract class TransitGatewayRouteBase extends Resource implements ITransitGatewayRoute { public abstract routeTable: ITransitGatewayRouteTable; public abstract destinationCidrBlock: string; } +/** + * Create a Transit Gateway Active Route + * + * @resource AWS::EC2::TransitGatewayRoute + */ export class TransitGatewayRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; @@ -72,6 +92,11 @@ export class TransitGatewayRoute extends TransitGatewayRouteBase { } } +/** + * Create a Transit Gateway Blackhole Route + * + * @resource AWS::EC2::TransitGatewayRoute + */ export class TransitGatewayBlackholeRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 5cae34dc48df3..4b88e9135ffda 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -7,8 +7,9 @@ import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './trans import { getFeatureStatusDefaultDisable } from './util'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; -export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment {} - +/** + * Options for Transit Gateway VPC Attachment + */ export interface ITransitGatewayVpcAttachmentOptions { /** * Enable or disable appliance mode support. @@ -39,6 +40,24 @@ export interface ITransitGatewayVpcAttachmentOptions { readonly securityGroupReferencingSupport?: boolean; } +/** + * Represents a Transit Gateway VPC Attachment + */ +export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment { + /** + * Add additional subnets to this attachment. + */ + addSubnets(subnets: ISubnet[]): void; + + /** + * Remove subnets from this attachment. + */ + removeSubnets(subnets: ISubnet[]): void; +} + +/** + * Base class for Transit Gateway VPC Attachment + */ interface BaseTransitGatewayVpcAttachmentProps { /** * A list of one or more subnets to place the attachment in. @@ -53,10 +72,22 @@ interface BaseTransitGatewayVpcAttachmentProps { /** * The VPC attachment options. + * + * @default - All options are disabled. */ readonly vpcAttachmentOptions?: ITransitGatewayVpcAttachmentOptions; + + /** + * Physical name of this Transit Gateway VPC Attachment. + * + * @default - Assigned by CloudFormation. + */ + readonly transitGatewayAttachmentName?: string; } +/** + * Common properties for creating a Transit Gateway VPC Attachment resource. + */ export interface TransitGatewayVpcAttachmentProps extends BaseTransitGatewayVpcAttachmentProps { /** * The transit gateway this attachment gets assigned to. @@ -64,18 +95,30 @@ export interface TransitGatewayVpcAttachmentProps extends BaseTransitGatewayVpcA readonly transitGateway: ITransitGateway; } +/** + * Options for creating an Attachment via the attachVpc() method + */ export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { /** * An optional route table to associate with this VPC attachment. + * + * @default - No associations will be created unless it is for the default route table and automatic association is enabled. */ readonly associationRouteTable?: ITransitGatewayRouteTable; /** * A list of optional route tables to propagate routes to. + * + * @default - No propagations will be created unless it is for the default route table and automatic propagation is enabled. */ readonly propagationRouteTables?: ITransitGatewayRouteTable[]; } +/** + * Creates a Transit Gateway VPC Attachment. + * + * @resource AWS::EC2::TransitGatewayAttachment + */ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { public readonly transitGatewayVpcAttachmentId: string; private readonly subnets: ISubnet[] = []; @@ -115,6 +158,9 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { } } + /** + * Add additional subnets to this attachment. + */ addSubnets(subnets: ISubnet[]): void { for (const subnet of subnets) { if (this.subnets.some(existing => existing.subnetId === subnet.subnetId)) { @@ -125,6 +171,9 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { this.transitGatewayVpcAttachment.subnetIds = this.subnets.map(subnet => subnet.subnetId); } + /** + * Remove additional subnets to this attachment. + */ removeSubnets(subnets: ISubnet[]): void { for (const subnet of subnets) { const index = this.subnets.findIndex(existing => existing.subnetId === subnet.subnetId); diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 5aed98b3b5068..eea275a3e1f46 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -1,19 +1,17 @@ import { CfnTransitGateway, RouterType } from 'aws-cdk-lib/aws-ec2'; -import { Resource } from 'aws-cdk-lib/core'; +import * as cdk from 'aws-cdk-lib/core'; import { Construct } from 'constructs'; import { ITransitGatewayRouteTable, TransitGatewayRouteTable } from './transit-gateway-route-table'; -import { TransitGatewayVpcAttachment, AttachVpcOptions } from './transit-gateway-vpc-attachment'; +import { TransitGatewayVpcAttachment, AttachVpcOptions, ITransitGatewayVpcAttachment } from './transit-gateway-vpc-attachment'; import { IRouteTarget } from './route'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable } from './util'; -export enum TransitGatewayFeatureStatus { - ENABLE = 'enable', - DISABLE = 'disable', -} - -export interface ITransitGateway { +/** + * Represents a Transit Gateway. + */ +export interface ITransitGateway extends cdk.IResource { /** * The unique identifier of the Transit Gateway. * @@ -21,7 +19,7 @@ export interface ITransitGateway { * and is used to reference it in various configurations and operations. * @attribute */ - readonly transitGatewayId: string; + readonly transitGatewayId: string; /** * The Amazon Resource Name (ARN) of the Transit Gateway. @@ -57,11 +55,21 @@ export interface ITransitGateway { readonly defaultRouteTablePropagation: boolean; } +/** + * Common properties for creating a Transit Gateway resource. + */ export interface TransitGatewayProps { + /** + * Physical name of this Transit Gateway. + * + * @default - Assigned by CloudFormation. + */ + readonly transitGatewayName?: string; + /** * A private Autonomous System Number (ASN) for the Amazon side of a BGP session. The range is 64512 to 65534 for 16-bit ASNs. * - * @default - undefined + * @default - 64512, assigned by CloudFormation. */ readonly amazonSideAsn?: number; @@ -88,6 +96,8 @@ export interface TransitGatewayProps { /** * The description of the transit gateway. + * + * @default - no description */ readonly description?: string; @@ -114,6 +124,8 @@ export interface TransitGatewayProps { /** * The transit gateway CIDR blocks. + * + * @default - none */ readonly transitGatewayCidrBlocks?: string[]; @@ -125,22 +137,36 @@ export interface TransitGatewayProps { readonly vpnEcmpSupport?: boolean; } -abstract class TransitGatewayBase extends Resource implements ITransitGateway, IRouteTarget { +/** + * A Transit Gateway. + * @internal + */ +abstract class TransitGatewayBase extends cdk.Resource implements ITransitGateway, IRouteTarget { public abstract readonly routerType: RouterType; public abstract readonly routerTargetId: string; public abstract readonly transitGatewayId: string; public abstract readonly transitGatewayArn: string; - public abstract readonly defaultRouteTable: TransitGatewayRouteTable; + public abstract readonly defaultRouteTable: ITransitGatewayRouteTable; public abstract readonly defaultRouteTableAssociation: boolean; public abstract readonly defaultRouteTablePropagation: boolean; - addRouteTable(id: string): TransitGatewayRouteTable { + /** + * Adds a new route table to the Transit Gateway. + * + * @returns The created Transit Gateway route table. + */ + public addRouteTable(id: string): ITransitGatewayRouteTable { return new TransitGatewayRouteTable(this, id, { transitGateway: this, }); } - attachVpc(id: string, options: AttachVpcOptions): TransitGatewayVpcAttachment { + /** + * Attaches a VPC to the Transit Gateway. + * + * @returns The created Transit Gateway VPC attachment. + */ + public attachVpc(id: string, options: AttachVpcOptions): ITransitGatewayVpcAttachment { const attachment = new TransitGatewayVpcAttachment(this, id, { transitGateway: this, vpc: options.vpc, @@ -174,29 +200,34 @@ abstract class TransitGatewayBase extends Resource implements ITransitGateway, I } } +/** + * Creates a Transit Gateway. + * + * @resource AWS::EC2::TransitGateway + */ export class TransitGateway extends TransitGatewayBase { public readonly routerType: RouterType; public readonly routerTargetId: string; public readonly transitGatewayId: string; public readonly transitGatewayArn: string; - public readonly defaultRouteTable: TransitGatewayRouteTable; + public readonly defaultRouteTable: ITransitGatewayRouteTable; public readonly defaultRouteTableAssociation: boolean; public readonly defaultRouteTablePropagation: boolean; - constructor(scope: Construct, id: string, props?: TransitGatewayProps) { + constructor(scope: Construct, id: string, props: TransitGatewayProps = {}) { super(scope, id); const resource = new CfnTransitGateway(this, id, { - amazonSideAsn: props?.amazonSideAsn ?? undefined, - autoAcceptSharedAttachments: getFeatureStatusDefaultDisable(props?.autoAcceptSharedAttachments), + amazonSideAsn: props.amazonSideAsn ?? undefined, + autoAcceptSharedAttachments: getFeatureStatusDefaultDisable(props.autoAcceptSharedAttachments), // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. // Instead, CDK will create a custom default route table and use the properties to mimic the automatic assocation/propagation behaviour. - defaultRouteTableAssociation: getFeatureStatusDefaultDisable(props?.defaultRouteTableAssociation), - defaultRouteTablePropagation: getFeatureStatusDefaultDisable(props?.defaultRouteTablePropagation), - description: props?.description, - dnsSupport: getFeatureStatusDefaultEnable(props?.dnsSupport), - multicastSupport: getFeatureStatusDefaultDisable(props?.multicastSupport), - vpnEcmpSupport: getFeatureStatusDefaultEnable(props?.vpnEcmpSupport), + defaultRouteTableAssociation: getFeatureStatusDefaultDisable(props.defaultRouteTableAssociation), + defaultRouteTablePropagation: getFeatureStatusDefaultDisable(props.defaultRouteTablePropagation), + description: props.description, + dnsSupport: getFeatureStatusDefaultEnable(props.dnsSupport), + multicastSupport: getFeatureStatusDefaultDisable(props.multicastSupport), + vpnEcmpSupport: getFeatureStatusDefaultEnable(props.vpnEcmpSupport), }); this.transitGatewayId = resource.ref; @@ -212,7 +243,7 @@ export class TransitGateway extends TransitGatewayBase { transitGateway: this, }); - this.defaultRouteTableAssociation = props?.defaultRouteTableAssociation ?? true; - this.defaultRouteTablePropagation = props?.defaultRouteTablePropagation ?? true; + this.defaultRouteTableAssociation = props.defaultRouteTableAssociation ?? true; + this.defaultRouteTablePropagation = props.defaultRouteTablePropagation ?? true; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index afab959874703..e267952bf4512 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -1,7 +1,6 @@ /* eslint no-bitwise: ["error", { "allow": ["~", "|", "<<", "&"] }] */ import { ISubnet } from 'aws-cdk-lib/aws-ec2'; -import { TransitGatewayFeatureStatus } from './transit-gateway'; /** * Return a subnet name from its construct ID @@ -19,6 +18,21 @@ export function subnetId(name: string, i: number) { return `${name}Subnet${i + 1}`; } +/** + * The status of a Transit Gateway feature. + */ +enum TransitGatewayFeatureStatus { + /** + * The feature is enabled. + */ + ENABLE = 'enable', + + /** + * The feature is disabled. + */ + DISABLE = 'disable', +} + export function getFeatureStatusDefaultEnable(status?: boolean): TransitGatewayFeatureStatus { return (status ?? true)? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; } diff --git a/packages/@aws-cdk/aws-ec2-alpha/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-ec2-alpha/rosetta/default.ts-fixture index 5704158e8073c..3e29ae294b046 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-ec2-alpha/rosetta/default.ts-fixture @@ -1,7 +1,7 @@ // Fixture with packages imported, but nothing else import { Construct } from 'constructs'; import { Stack, App, Fn, Tags } from 'aws-cdk-lib'; -import { VpcV2, SubnetV2, IpAddresses, IpamPoolPublicIpSource, RouteTable, InternetGateway, Route, NatGateway, EgressOnlyInternetGateway, VPCPeeringConnection } from '@aws-cdk/aws-ec2-alpha'; +import { VpcV2, SubnetV2, IpAddresses, IpamPoolPublicIpSource, RouteTable, InternetGateway, Route, NatGateway, EgressOnlyInternetGateway, VPCPeeringConnection, TransitGateway, TransitGatewayRoute, TransitGatewayRouteTable, TransitGatewayVpcAttachment } from '@aws-cdk/aws-ec2-alpha'; import { Ipam, AwsServiceName, IpCidr, AddressFamily } from '@aws-cdk/aws-ec2-alpha'; import { NatConnectivityType } from '@aws-cdk/aws-ec2-alpha'; import { SubnetType, VpnConnectionType } from 'aws-cdk-lib/aws-ec2'; diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts index 499dcbedbd51c..d89b9de0b541c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts @@ -2,7 +2,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import { Stack } from 'aws-cdk-lib/core'; import * as vpc from '../lib'; import { TransitGateway } from '../lib/transit-gateway'; -import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { ITransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; import { TransitGatewayRouteTableAssociation } from '../lib/transit-gateway-route-table-association'; import * as subnet from '../lib/subnet-v2'; @@ -12,7 +12,7 @@ describe('TransitGatewayRouteTableAssociation', () => { let stack: Stack; let myVpc: vpc.VpcV2; let transitGateway: TransitGateway; - let routeTable: TransitGatewayRouteTable; + let routeTable: ITransitGatewayRouteTable; let attachment: TransitGatewayVpcAttachment; let mySubnet: vpc.SubnetV2; diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts index 1b6a68332e454..97ec5e0ed0633 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts @@ -2,7 +2,7 @@ import { Template } from 'aws-cdk-lib/assertions'; import { Stack } from 'aws-cdk-lib/core'; import * as vpc from '../lib'; import { TransitGateway } from '../lib/transit-gateway'; -import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; +import { ITransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; import { TransitGatewayRouteTablePropagation } from '../lib/transit-gateway-route-table-propagation'; import * as subnet from '../lib/subnet-v2'; @@ -12,7 +12,7 @@ describe('TransitGatewayRouteTablePropagation', () => { let stack: Stack; let myVpc: vpc.VpcV2; let transitGateway: TransitGateway; - let routeTable: TransitGatewayRouteTable; + let routeTable: ITransitGatewayRouteTable; let attachment: TransitGatewayVpcAttachment; let mySubnet: vpc.SubnetV2; From 7c7fbb7b0db1b8490f9d74093eda685677c7b883 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Mon, 27 Jan 2025 23:18:56 -0800 Subject: [PATCH 14/22] fix unit tests --- packages/@aws-cdk/aws-ec2-alpha/README.md | 4 + packages/@aws-cdk/aws-ec2-alpha/awslint.json | 3 +- .../lib/transit-gateway-attachment.ts | 4 +- ...transit-gateway-route-table-association.ts | 12 +- ...transit-gateway-route-table-propagation.ts | 12 +- .../lib/transit-gateway-route-table.ts | 11 +- .../lib/transit-gateway-route.ts | 22 ++- .../lib/transit-gateway-vpc-attachment.ts | 22 +-- .../aws-ec2-alpha/lib/transit-gateway.ts | 22 +-- ...way-disable-automatic-settings.assets.json | 4 +- ...y-disable-automatic-settings.template.json | 45 ++++-- .../manifest.json | 2 +- .../tree.json | 59 +++++-- ...it-gateway-route-table-association.test.ts | 2 +- ...it-gateway-route-table-propagation.test.ts | 2 +- .../test/transit-gateway-route-table.test.ts | 50 ++++-- .../test/transit-gateway-route.test.ts | 19 ++- .../transit-gateway-vpc-attachment.test.ts | 5 +- .../test/transit-gateway.test.ts | 149 ++++++++++++++---- 19 files changed, 337 insertions(+), 112 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index 5a30f9642fcff..645f2be966c21 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -701,6 +701,8 @@ Tags.of(vpc).add('Environment', 'Production'); The AWS Transit Gateway construct library allows you to create and configure Transit Gateway resources using AWS CDK. +See [AWS Transit Gateway Docs](docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html) for more info. + ### Overview The Transit Gateway construct (`TransitGateway`) is the main entry point for creating and managing your Transit Gateway infrastructure. It provides methods to create route tables, attach VPCs, and configure cross-account access. @@ -750,6 +752,8 @@ const routeTable = transitGateway.addRouteTable('CustomRouteTable'); ### Attaching VPCs to the Transit Gateway +Currently only VPC to Transit Gateway attachments are supported. + Create an attachment from a VPC to the Transit Gateway using the `attachVpc()` method: ```ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/awslint.json b/packages/@aws-cdk/aws-ec2-alpha/awslint.json index b05a4b36425bd..23608305b3668 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/awslint.json +++ b/packages/@aws-cdk/aws-ec2-alpha/awslint.json @@ -4,6 +4,7 @@ "from-method:@aws-cdk/aws-ec2-alpha.Route", "from-method:@aws-cdk/aws-ec2-alpha.TransitGateway", "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTableAssociation", - "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTablePropagation" + "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTablePropagation", + "from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayVpcAttachment" ] } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts index fd31532f044fe..0f793f998333c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts @@ -7,7 +7,7 @@ export interface ITransitGatewayAttachment extends IResource { * The ID of the transit gateway attachment. * @attribute */ - readonly transitGatewayVpcAttachmentId: string; + readonly transitGatewayAttachmentId: string; } /** @@ -15,5 +15,5 @@ export interface ITransitGatewayAttachment extends IResource { * @internal */ export abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment { - public abstract readonly transitGatewayVpcAttachmentId: string; + public abstract readonly transitGatewayAttachmentId: string; } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index a2c2eaafaf661..623b35439e7f4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -59,14 +59,20 @@ export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTabl */ public readonly transitGatewayRouteTableAssociationId: string; + /** + * The AWS CloudFormation resource representing the Transit Gateway Route Table Association. + */ + public readonly resource: CfnTransitGatewayRouteTableAssociation; + constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) { super(scope, id); - const resource = new CfnTransitGatewayRouteTableAssociation(this, id, { - transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayVpcAttachmentId, + this.resource = new CfnTransitGatewayRouteTableAssociation(this, id, { + transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); + this.node.defaultChild = this.resource; - this.transitGatewayRouteTableAssociationId = resource.ref; + this.transitGatewayRouteTableAssociationId = this.resource.ref; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index 5806c2bcace0c..da96452935c1e 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -59,14 +59,20 @@ export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTabl */ public readonly transitGatewayRouteTablePropagationId: string; + /** + * The AWS CloudFormation resource representing the Transit Gateway Route Table Propagation. + */ + public readonly resource: CfnTransitGatewayRouteTablePropagation; + constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { super(scope, id); - const resource = new CfnTransitGatewayRouteTablePropagation(this, id, { - transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayVpcAttachmentId, + this.resource = new CfnTransitGatewayRouteTablePropagation(this, id, { + transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); + this.node.defaultChild = this.resource; - this.transitGatewayRouteTablePropagationId = resource.ref; + this.transitGatewayRouteTablePropagationId = this.resource.ref; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index b247cd6f0aabb..dc75cc0f85933 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -113,14 +113,21 @@ export class TransitGatewayRouteTable extends TransitGatewayRouteTableBase { */ public readonly transitGateway: ITransitGateway; + /** + * The AWS CloudFormation resource representing the Transit Gateway Route Table. + */ + public readonly resource: CfnTransitGatewayRouteTable; + constructor(scope: Construct, id: string, props: TransitGatewayRouteTableProps) { super(scope, id); - const resource = new CfnTransitGatewayRouteTable(this, id, { + this.resource = new CfnTransitGatewayRouteTable(this, id, { transitGatewayId: props.transitGateway.transitGatewayId, }); - this.routeTableId = resource.ref; + this.node.defaultChild = this.resource; + + this.routeTableId = this.resource.attrTransitGatewayRouteTableId; this.transitGateway = props.transitGateway; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index d194a81796b82..4c5be9f403483 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -77,17 +77,23 @@ export class TransitGatewayRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; + /** + * The AWS CloudFormation resource representing the Transit Gateway Route. + */ + public readonly resource: CfnTransitGatewayRoute; + constructor(scope: Construct, id: string, props: TransitGatewayRouteProps) { super(scope, id); - const resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { + this.resource = new CfnTransitGatewayRoute(this, 'TransitGatewayRoute', { blackhole: false, destinationCidrBlock: props.destinationCidrBlock, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, - transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayVpcAttachmentId, + transitGatewayAttachmentId: props.transitGatewayAttachment?.transitGatewayAttachmentId, }); - this.destinationCidrBlock = resource.destinationCidrBlock; + this.node.defaultChild = this.resource; + this.destinationCidrBlock = this.resource.destinationCidrBlock; this.routeTable = props.transitGatewayRouteTable; } } @@ -101,16 +107,22 @@ export class TransitGatewayBlackholeRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; + /** + * The AWS CloudFormation resource representing the Transit Gateway Route. + */ + public readonly resource: CfnTransitGatewayRoute; + constructor(scope: Construct, id: string, props: TransitGatewayBlackholeRouteProps) { super(scope, id); - const resource = new CfnTransitGatewayRoute(this, id, { + this.resource = new CfnTransitGatewayRoute(this, id, { blackhole: true, destinationCidrBlock: props.destinationCidrBlock, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); - this.destinationCidrBlock = resource.destinationCidrBlock; + this.node.defaultChild = this.resource; + this.destinationCidrBlock = this.resource.destinationCidrBlock; this.routeTable = props.transitGatewayRouteTable; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 4b88e9135ffda..aa1788280e2b5 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -120,14 +120,18 @@ export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { * @resource AWS::EC2::TransitGatewayAttachment */ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { - public readonly transitGatewayVpcAttachmentId: string; + public readonly transitGatewayAttachmentId: string; + + /** + * The AWS CloudFormation resource representing the Transit Gateway Attachment. + */ + public readonly resource: CfnTransitGatewayAttachment; private readonly subnets: ISubnet[] = []; - private transitGatewayVpcAttachment: CfnTransitGatewayAttachment; constructor(scope: Construct, id: string, props: TransitGatewayVpcAttachmentProps) { super(scope, id); - const resource = new CfnTransitGatewayAttachment(this, id, { + this.resource = new CfnTransitGatewayAttachment(this, id, { subnetIds: props.subnets.map((subnet) => subnet.subnetId), transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, @@ -138,9 +142,9 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { SecurityGroupReferencingSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.securityGroupReferencingSupport), } : undefined, }); + this.node.defaultChild = this.resource; - this.transitGatewayVpcAttachment = resource; - this.transitGatewayVpcAttachmentId = resource.ref; + this.transitGatewayAttachmentId = this.resource.attrId; this.subnets = props.subnets; if (props.transitGateway.defaultRouteTableAssociation) { @@ -164,11 +168,11 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { addSubnets(subnets: ISubnet[]): void { for (const subnet of subnets) { if (this.subnets.some(existing => existing.subnetId === subnet.subnetId)) { - throw new Error(`Subnet with ID ${subnet.subnetId} is already added to the Attachment ${this.transitGatewayVpcAttachmentId}.`); + throw new Error(`Subnet with ID ${subnet.subnetId} is already added to the Attachment ${this.transitGatewayAttachmentId}.`); } this.subnets.push(subnet); } - this.transitGatewayVpcAttachment.subnetIds = this.subnets.map(subnet => subnet.subnetId); + this.resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); } /** @@ -178,10 +182,10 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { for (const subnet of subnets) { const index = this.subnets.findIndex(existing => existing.subnetId === subnet.subnetId); if (index === -1) { - throw new Error(`Subnet with ID ${subnet.subnetId} does not exist in the Attachment ${this.transitGatewayVpcAttachmentId}.`); + throw new Error(`Subnet with ID ${subnet.subnetId} does not exist in the Attachment ${this.transitGatewayAttachmentId}.`); } this.subnets.splice(index, 1); } - this.transitGatewayVpcAttachment.subnetIds = this.subnets.map(subnet => subnet.subnetId); + this.resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index eea275a3e1f46..5f44ef6300525 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -11,7 +11,7 @@ import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable } from '. /** * Represents a Transit Gateway. */ -export interface ITransitGateway extends cdk.IResource { +export interface ITransitGateway extends cdk.IResource, IRouteTarget { /** * The unique identifier of the Transit Gateway. * @@ -19,7 +19,7 @@ export interface ITransitGateway extends cdk.IResource { * and is used to reference it in various configurations and operations. * @attribute */ - readonly transitGatewayId: string; + readonly transitGatewayId: string; /** * The Amazon Resource Name (ARN) of the Transit Gateway. @@ -213,11 +213,15 @@ export class TransitGateway extends TransitGatewayBase { public readonly defaultRouteTable: ITransitGatewayRouteTable; public readonly defaultRouteTableAssociation: boolean; public readonly defaultRouteTablePropagation: boolean; + /** + * The AWS CloudFormation resource representing the Transit Gateway. + */ + public readonly resource: CfnTransitGateway; constructor(scope: Construct, id: string, props: TransitGatewayProps = {}) { super(scope, id); - const resource = new CfnTransitGateway(this, id, { + this.resource = new CfnTransitGateway(this, id, { amazonSideAsn: props.amazonSideAsn ?? undefined, autoAcceptSharedAttachments: getFeatureStatusDefaultDisable(props.autoAcceptSharedAttachments), // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. @@ -230,14 +234,12 @@ export class TransitGateway extends TransitGatewayBase { vpnEcmpSupport: getFeatureStatusDefaultEnable(props.vpnEcmpSupport), }); - this.transitGatewayId = resource.ref; - this.routerTargetId = resource.ref; + this.node.defaultChild = this.resource; + + this.transitGatewayId = this.resource.attrId; + this.routerTargetId = this.resource.attrId; this.routerType = RouterType.TRANSIT_GATEWAY; - this.transitGatewayArn = this.getResourceArnAttribute(resource.ref, { - service: 'ec2', - resource: 'transit-gateway', - resourceName: this.physicalName, - }); + this.transitGatewayArn = this.resource.attrTransitGatewayArn; this.defaultRouteTable = new TransitGatewayRouteTable(this, 'DefaultRouteTable', { transitGateway: this, diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json index 18290e57f2195..56bb646999e08 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -1,7 +1,7 @@ { "version": "39.0.0", "files": { - "b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829": { + "11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441": { "source": { "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829.json", + "objectKey": "11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json index 17eb898f4d90f..e99b78f138500 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -96,7 +96,10 @@ "Type": "AWS::EC2::TransitGatewayRouteTable", "Properties": { "TransitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] } } }, @@ -106,10 +109,16 @@ "Blackhole": false, "DestinationCidrBlock": "0.0.0.0/0", "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "TransitGatewayRouteTableId": { - "Ref": "TransitGatewayDefaultRouteTable608EC117" + "Fn::GetAtt": [ + "TransitGatewayDefaultRouteTable608EC117", + "TransitGatewayRouteTableId" + ] } } }, @@ -122,7 +131,10 @@ } ], "TransitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] }, "VpcId": { "Fn::GetAtt": [ @@ -136,7 +148,10 @@ "Type": "AWS::EC2::TransitGatewayRouteTable", "Properties": { "TransitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] } } }, @@ -144,10 +159,16 @@ "Type": "AWS::EC2::TransitGatewayRouteTableAssociation", "Properties": { "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "TransitGatewayRouteTableId": { - "Ref": "TransitGatewayRouteTable2047E2A04" + "Fn::GetAtt": [ + "TransitGatewayRouteTable2047E2A04", + "TransitGatewayRouteTableId" + ] } } }, @@ -155,10 +176,16 @@ "Type": "AWS::EC2::TransitGatewayRouteTablePropagation", "Properties": { "TransitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "TransitGatewayRouteTableId": { - "Ref": "TransitGatewayRouteTable2047E2A04" + "Fn::GetAtt": [ + "TransitGatewayRouteTable2047E2A04", + "TransitGatewayRouteTableId" + ] } } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json index 00c76ebbbb0cb..0efb9205a03ef 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b0890f8ff89af38a878af643ffb12812be08ca48a35221152b73cc356314f829.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json index 7bb37e690242b..b5e607e14cf37 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -202,7 +202,10 @@ "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTable", "aws:cdk:cloudformation:props": { "transitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] } } }, @@ -224,10 +227,16 @@ "blackhole": false, "destinationCidrBlock": "0.0.0.0/0", "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "transitGatewayRouteTableId": { - "Ref": "TransitGatewayDefaultRouteTable608EC117" + "Fn::GetAtt": [ + "TransitGatewayDefaultRouteTable608EC117", + "TransitGatewayRouteTableId" + ] } } }, @@ -238,13 +247,13 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayRoute", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTable", "version": "0.0.0" } }, @@ -264,7 +273,10 @@ } ], "transitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] }, "vpcId": { "Fn::GetAtt": [ @@ -281,7 +293,7 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayVpcAttachment", "version": "0.0.0" } }, @@ -296,7 +308,10 @@ "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTable", "aws:cdk:cloudformation:props": { "transitGatewayId": { - "Ref": "TransitGateway11B93D57" + "Fn::GetAtt": [ + "TransitGateway11B93D57", + "Id" + ] } } }, @@ -316,10 +331,16 @@ "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTableAssociation", "aws:cdk:cloudformation:props": { "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "transitGatewayRouteTableId": { - "Ref": "TransitGatewayRouteTable2047E2A04" + "Fn::GetAtt": [ + "TransitGatewayRouteTable2047E2A04", + "TransitGatewayRouteTableId" + ] } } }, @@ -330,7 +351,7 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTableAssociation", "version": "0.0.0" } }, @@ -345,10 +366,16 @@ "aws:cdk:cloudformation:type": "AWS::EC2::TransitGatewayRouteTablePropagation", "aws:cdk:cloudformation:props": { "transitGatewayAttachmentId": { - "Ref": "TransitGatewayDefaultRtbAttachment6E19DB55" + "Fn::GetAtt": [ + "TransitGatewayDefaultRtbAttachment6E19DB55", + "Id" + ] }, "transitGatewayRouteTableId": { - "Ref": "TransitGatewayRouteTable2047E2A04" + "Fn::GetAtt": [ + "TransitGatewayRouteTable2047E2A04", + "TransitGatewayRouteTableId" + ] } } }, @@ -359,19 +386,19 @@ } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTablePropagation", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGatewayRouteTable", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "aws-cdk-lib.Resource", + "fqn": "@aws-cdk/aws-ec2-alpha.TransitGateway", "version": "0.0.0" } }, diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts index d89b9de0b541c..90ec35322f9d6 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-association.test.ts @@ -53,7 +53,7 @@ describe('TransitGatewayRouteTableAssociation', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { - TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayVpcAttachmentId), + TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayAttachmentId), TransitGatewayRouteTableId: stack.resolve(routeTable.routeTableId), }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts index 97ec5e0ed0633..aa79f821c6bdd 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts @@ -54,7 +54,7 @@ describe('TransitGatewayRouteTablePropagation', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { - TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayVpcAttachmentId), + TransitGatewayAttachmentId: stack.resolve(attachment.transitGatewayAttachmentId), TransitGatewayRouteTableId: stack.resolve(routeTable.routeTableId), }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts index 073b149721f48..701824a513b98 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -60,7 +60,10 @@ describe('Transit Gateway Route Table', () => { test('creates a transit gateway route table', () => { Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTable', { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, 2); @@ -81,7 +84,10 @@ describe('Transit Gateway Route Table', () => { Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -89,7 +95,10 @@ describe('Transit Gateway Route Table', () => { Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -104,10 +113,16 @@ describe('Transit Gateway Route Table', () => { Blackhole: false, DestinationCidrBlock: '10.0.0.0/16', TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment0B27B76B', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment0B27B76B', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); @@ -119,7 +134,10 @@ describe('Transit Gateway Route Table', () => { Blackhole: true, DestinationCidrBlock: '10.0.0.0/16', TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); @@ -129,10 +147,16 @@ describe('Transit Gateway Route Table', () => { Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment0B27B76B', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment0B27B76B', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); @@ -142,10 +166,16 @@ describe('Transit Gateway Route Table', () => { Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment0B27B76B', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment0B27B76B', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts index a318b38473908..57b5fffd14333 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route.test.ts @@ -70,11 +70,17 @@ describe('Transit Gateway Route', () => { Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRoute', { Blackhole: false, DestinationCidrBlock: '10.1.0.0/16', - TransitGatewayRouteTableId: { - Ref: 'TransitGatewayRouteTableD2EDBDC1', - }, TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment0B27B76B', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment0B27B76B', + 'Id', + ], + }, + TransitGatewayRouteTableId: { + 'Fn::GetAtt': [ + 'TransitGatewayRouteTableD2EDBDC1', + 'TransitGatewayRouteTableId', + ], }, }); }); @@ -93,7 +99,10 @@ describe('Transit Gateway Route', () => { Blackhole: true, DestinationCidrBlock: '10.2.0.0/16', TransitGatewayRouteTableId: { - Ref: 'TransitGatewayRouteTableD2EDBDC1', + 'Fn::GetAtt': [ + 'TransitGatewayRouteTableD2EDBDC1', + 'TransitGatewayRouteTableId', + ], }, }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index bcb62682b57d3..86f2acb4f81d7 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -46,7 +46,10 @@ describe('TransitGatewayVpcAttachment', () => { }, ], TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, VpcId: { 'Fn::GetAtt': [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 9b8c217e73c3a..6e26c5781ea16 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -68,7 +68,10 @@ describe('Transit Gateway with default settings', () => { Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -96,7 +99,10 @@ describe('Transit Gateway with default settings', () => { Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -104,7 +110,10 @@ describe('Transit Gateway with default settings', () => { Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -126,7 +135,10 @@ describe('Transit Gateway with default settings', () => { }, ], TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, VpcId: { 'Fn::GetAtt': [ @@ -138,19 +150,31 @@ describe('Transit Gateway with default settings', () => { Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment3EC29F61', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment3EC29F61', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment3EC29F61', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment3EC29F61', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); @@ -222,7 +246,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -250,7 +277,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -258,7 +288,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -280,7 +313,10 @@ describe('Transit Gateway with default route table association and propagation d }, ], TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, VpcId: { 'Fn::GetAtt': [ @@ -291,20 +327,32 @@ describe('Transit Gateway with default route table association and propagation d }); Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTableAssociation', { - TransitGatewayVpcAttachmentId: { - Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + TransitGatewayAttachmentId: { + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }, 0); Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTablePropagation', { - TransitGatewayVpcAttachmentId: { - Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + TransitGatewayAttachmentId: { + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }, 0); }); @@ -376,7 +424,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -404,7 +455,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -412,7 +466,10 @@ describe('Transit Gateway with default route table association and propagation d Type: 'AWS::EC2::TransitGatewayRouteTable', Properties: { TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, }, }, @@ -434,7 +491,10 @@ describe('Transit Gateway with default route table association and propagation d }, ], TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, VpcId: { 'Fn::GetAtt': [ @@ -446,19 +506,31 @@ describe('Transit Gateway with default route table association and propagation d Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTableAssociation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }, 0); Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTablePropagation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }, 0); }); @@ -479,7 +551,10 @@ describe('Transit Gateway with default route table association and propagation d }, ], TransitGatewayId: { - Ref: 'TransitGateway11B93D57', + 'Fn::GetAtt': [ + 'TransitGateway11B93D57', + 'Id', + ], }, VpcId: { 'Fn::GetAtt': [ @@ -491,19 +566,31 @@ describe('Transit Gateway with default route table association and propagation d Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment3EC29F61', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment3EC29F61', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { TransitGatewayAttachmentId: { - Ref: 'TransitGatewayVpcAttachment3EC29F61', + 'Fn::GetAtt': [ + 'TransitGatewayVpcAttachment3EC29F61', + 'Id', + ], }, TransitGatewayRouteTableId: { - Ref: 'TransitGatewayDefaultRouteTable608EC117', + 'Fn::GetAtt': [ + 'TransitGatewayDefaultRouteTable608EC117', + 'TransitGatewayRouteTableId', + ], }, }); }); From 596ea55fa9556219b54650a40b1bdfeaaea9867b Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Tue, 28 Jan 2025 16:06:14 -0800 Subject: [PATCH 15/22] add warnings when attaching VPC and update tests --- packages/@aws-cdk/aws-ec2-alpha/README.md | 2 +- ...transit-gateway-route-table-association.ts | 4 +- ...transit-gateway-route-table-propagation.ts | 4 +- .../lib/transit-gateway-route-table.ts | 42 ++++++------- .../lib/transit-gateway-route.ts | 9 ++- .../lib/transit-gateway-vpc-attachment.ts | 19 ++++-- .../aws-ec2-alpha/lib/transit-gateway.ts | 48 +++++++++------ packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 4 +- ...way-disable-automatic-settings.assets.json | 4 +- ...y-disable-automatic-settings.template.json | 2 +- .../manifest.json | 2 +- .../tree.json | 2 +- .../test/transit-gateway-route-table.test.ts | 2 +- .../transit-gateway-vpc-attachment.test.ts | 60 ++++++++++++++++++- .../test/transit-gateway.test.ts | 18 +++--- 15 files changed, 151 insertions(+), 71 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index 645f2be966c21..6130634646795 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -711,7 +711,7 @@ The Transit Gateway construct library provides four main constructs: - `TransitGateway`: The central hub for your network connections - `TransitGatewayRouteTable`: Manages routing between attached networks -- `TransitGatewayAttachment`: Connects VPCs and on-premises networks +- `TransitGatewayVpcAttachment`: Connects VPCs to the Transi Gateway - `TransitGatewayRoute`: Defines routing rules within your Transit Gateway ### Basic Usage diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index 623b35439e7f4..4838cceee2462 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -5,7 +5,7 @@ import { CfnTransitGatewayRouteTableAssociation } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; /** - * Represents a Transit Gateway Route Table Association + * Represents a Transit Gateway Route Table Association. */ export interface ITransitGatewayRouteTableAssociation extends IResource { /** @@ -49,7 +49,7 @@ abstract class TransitGatewayRouteTableAssociationBase extends Resource implemen } /** - * Create a Transit Gateway Route Table Association + * Create a Transit Gateway Route Table Association. * * @resource AWS::EC2::TransitGatewayRouteTableAssociation */ diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index da96452935c1e..79e9069ccce77 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -5,7 +5,7 @@ import { ITransitGatewayAttachment } from './transit-gateway-attachment'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; /** - * Represents a Transit Gateway Route Table Propagation + * Represents a Transit Gateway Route Table Propagation. */ export interface ITransitGatewayRouteTablePropagation extends IResource { /** @@ -49,7 +49,7 @@ abstract class TransitGatewayRouteTablePropagationBase extends Resource implemen } /** - * Create a Transit Gateway Route Table Propagation + * Create a Transit Gateway Route Table Propagation. * * @resource AWS::EC2::TransitGatewayRouteTablePropagation */ diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index dc75cc0f85933..6473445a69d3d 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -3,47 +3,47 @@ import { ITransitGateway } from './transit-gateway'; import { Construct } from 'constructs'; import { CfnTransitGatewayRouteTable, IRouteTable } from 'aws-cdk-lib/aws-ec2'; import { ITransitGatewayAttachment } from './transit-gateway-attachment'; -import { TransitGatewayRoute, TransitGatewayBlackholeRoute } from './transit-gateway-route'; -import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; -import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; +import { TransitGatewayRoute, TransitGatewayBlackholeRoute, ITransitGatewayRoute } from './transit-gateway-route'; +import { ITransitGatewayRouteTableAssociation, TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; +import { ITransitGatewayRouteTablePropagation, TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; /** - * Represents a Transit Gateway Route Table + * Represents a Transit Gateway Route Table. */ export interface ITransitGatewayRouteTable extends IResource { /** - * The ID of the transit gateway route table + * The ID of the transit gateway route table. * @attribute */ readonly routeTableId: string; /** - * Add an active route to this route table + * Add an active route to this route table. * - * @returns TransitGatewayRoute + * @returns ITransitGatewayRoute */ - addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayRoute; + addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): ITransitGatewayRoute; /** - * Add a blackhole route to this route table + * Add a blackhole route to this route table. * - * @returns TransitGatewayBlackholeRoute + * @returns ITransitGatewayRoute */ - addBlackholeRoute(id: string, destinationCidr: string): TransitGatewayBlackholeRoute; + addBlackholeRoute(id: string, destinationCidr: string): ITransitGatewayRoute; /** - * Add an Association to this route table + * Associate the provided Attachments with this route table. * - * @returns TransitGatewayRouteTableAssociation + * @returns ITransitGatewayRouteTableAssociation */ - addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTableAssociation; + addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): ITransitGatewayRouteTableAssociation; /** - * Enable propagation from an Attachment + * Enable propagation from the provided Attachments to this route table. * - * @returns TransitGatewayRouteTablePropagation + * @returns ITransitGatewayRouteTablePropagation */ - enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTablePropagation; + enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): ITransitGatewayRouteTablePropagation; } /** @@ -71,7 +71,7 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit public abstract readonly routeTableId: string; public abstract readonly transitGateway: ITransitGateway; - addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): TransitGatewayRoute { + public addRoute(id: string, transitGatewayAttachment: ITransitGatewayAttachment, destinationCidr: string): ITransitGatewayRoute { return new TransitGatewayRoute(this, id, { transitGatewayRouteTable: this, transitGatewayAttachment, @@ -79,21 +79,21 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit }); }; - addBlackholeRoute(id: string, destinationCidr: string): TransitGatewayBlackholeRoute { + public addBlackholeRoute(id: string, destinationCidr: string): ITransitGatewayRoute { return new TransitGatewayBlackholeRoute(this, id, { transitGatewayRouteTable: this, destinationCidrBlock: destinationCidr, }); } - addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTableAssociation { + public addAssociation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): ITransitGatewayRouteTableAssociation { return new TransitGatewayRouteTableAssociation(this, id, { transitGatewayVpcAttachment: transitGatewayAttachment, transitGatewayRouteTable: this, }); } - enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): TransitGatewayRouteTablePropagation { + public enablePropagation(id: string, transitGatewayAttachment: ITransitGatewayAttachment): ITransitGatewayRouteTablePropagation { return new TransitGatewayRouteTablePropagation(this, id, { transitGatewayVpcAttachment: transitGatewayAttachment, transitGatewayRouteTable: this, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index 4c5be9f403483..b2bb8f201741c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -27,7 +27,10 @@ export interface ITransitGatewayRoute extends IResource { */ export interface BaseTransitGatewayRouteProps { /** - * The CIDR block used for destination matches. + * The destination CIDR block for this route. + * + * Destination Cidr cannot overlap for static routes but is allowed for propagated routes. + * When overlapping occurs, static routes take precedence over propagated routes. */ readonly destinationCidrBlock: string; @@ -69,7 +72,7 @@ abstract class TransitGatewayRouteBase extends Resource implements ITransitGatew } /** - * Create a Transit Gateway Active Route + * Create a Transit Gateway Active Route. * * @resource AWS::EC2::TransitGatewayRoute */ @@ -99,7 +102,7 @@ export class TransitGatewayRoute extends TransitGatewayRouteBase { } /** - * Create a Transit Gateway Blackhole Route + * Create a Transit Gateway Blackhole Route. * * @resource AWS::EC2::TransitGatewayRoute */ diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index aa1788280e2b5..8c1ac8845018f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -6,9 +6,10 @@ import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-tab import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; import { getFeatureStatusDefaultDisable } from './util'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; +import { Annotations } from 'aws-cdk-lib'; /** - * Options for Transit Gateway VPC Attachment + * Options for Transit Gateway VPC Attachment. */ export interface ITransitGatewayVpcAttachmentOptions { /** @@ -41,7 +42,7 @@ export interface ITransitGatewayVpcAttachmentOptions { } /** - * Represents a Transit Gateway VPC Attachment + * Represents a Transit Gateway VPC Attachment. */ export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment { /** @@ -56,7 +57,7 @@ export interface ITransitGatewayVpcAttachment extends ITransitGatewayAttachment } /** - * Base class for Transit Gateway VPC Attachment + * Base class for Transit Gateway VPC Attachment. */ interface BaseTransitGatewayVpcAttachmentProps { /** @@ -96,7 +97,7 @@ export interface TransitGatewayVpcAttachmentProps extends BaseTransitGatewayVpcA } /** - * Options for creating an Attachment via the attachVpc() method + * Options for creating an Attachment via the attachVpc() method. */ export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { /** @@ -119,7 +120,7 @@ export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { * * @resource AWS::EC2::TransitGatewayAttachment */ -export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { +export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase implements ITransitGatewayVpcAttachment { public readonly transitGatewayAttachmentId: string; /** @@ -147,6 +148,14 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase { this.transitGatewayAttachmentId = this.resource.attrId; this.subnets = props.subnets; + if (props.vpcAttachmentOptions?.dnsSupport && !props.transitGateway.dnsSupport) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch', `\'DnsSupport\' is enabled for the VPC Attachment ${this.transitGatewayAttachmentId} but disabled on TransitGateway ${props.transitGateway.transitGatewayId}. The feature will not work unless DnsSupport is enabled on both.`); + } + + if (props.vpcAttachmentOptions?.securityGroupReferencingSupport && !props.transitGateway.securityGroupReferencingSupport) { + Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch', `\'SecurityGroupReferencingSupport\' is enabled for the VPC Attachment ${this.transitGatewayAttachmentId} but disabled on TransitGateway ${props.transitGateway.transitGatewayId}. The feature will not work unless SecurityGroupReferencingSupport is enabled on both.`); + } + if (props.transitGateway.defaultRouteTableAssociation) { new TransitGatewayRouteTableAssociation(this, id + 'Association', { transitGatewayVpcAttachment: this, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 5f44ef6300525..647f43adf3af4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -6,7 +6,7 @@ import { TransitGatewayVpcAttachment, AttachVpcOptions, ITransitGatewayVpcAttach import { IRouteTarget } from './route'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; -import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable } from './util'; +import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable, TransitGatewayFeatureStatus } from './util'; /** * Represents a Transit Gateway. @@ -53,6 +53,16 @@ export interface ITransitGateway extends cdk.IResource, IRouteTarget { * to the default route table unless propagation is explicitly disabled. */ readonly defaultRouteTablePropagation: boolean; + + /** + * Enable or disable DNS support. + */ + readonly dnsSupport: boolean; + + /** + * Enable or disablesecurity group referencing support. + */ + readonly securityGroupReferencingSupport: boolean; } /** @@ -69,7 +79,7 @@ export interface TransitGatewayProps { /** * A private Autonomous System Number (ASN) for the Amazon side of a BGP session. The range is 64512 to 65534 for 16-bit ASNs. * - * @default - 64512, assigned by CloudFormation. + * @default - undefined, 64512 is assigned by CloudFormation. */ readonly amazonSideAsn?: number; @@ -102,22 +112,21 @@ export interface TransitGatewayProps { readonly description?: string; /** - * Enable or disable DNS support + * Enable or disable DNS support. + * + * If dnsSupport is enabled on a VPC Attachment, this also needs to be enabled for the feature to work. + * Otherwise the resources will still deploy but the feature will not work. * * @default - enable (true) */ readonly dnsSupport?: boolean; - /** - * Indicates whether multicast is enabled on the transit gateway - * - * @default - disable (false) - */ - readonly multicastSupport?: boolean; - /** * Enable or disablesecurity group referencing support * + * If securityGroupReferencingSupport is enabled on a VPC Attachment, this also needs to be enabled for the feature to work. + * Otherwise the resources will still deploy but the feature will not work. + * * @default - disable (false) */ readonly securityGroupReferencingSupport?: boolean; @@ -128,13 +137,6 @@ export interface TransitGatewayProps { * @default - none */ readonly transitGatewayCidrBlocks?: string[]; - - /** - * Enable or disable Equal Cost Multipath Protocol support - * - * @default - enable (true) - */ - readonly vpnEcmpSupport?: boolean; } /** @@ -149,6 +151,8 @@ abstract class TransitGatewayBase extends cdk.Resource implements ITransitGatewa public abstract readonly defaultRouteTable: ITransitGatewayRouteTable; public abstract readonly defaultRouteTableAssociation: boolean; public abstract readonly defaultRouteTablePropagation: boolean; + public abstract readonly dnsSupport: boolean; + public abstract readonly securityGroupReferencingSupport: boolean; /** * Adds a new route table to the Transit Gateway. @@ -213,6 +217,9 @@ export class TransitGateway extends TransitGatewayBase { public readonly defaultRouteTable: ITransitGatewayRouteTable; public readonly defaultRouteTableAssociation: boolean; public readonly defaultRouteTablePropagation: boolean; + public readonly dnsSupport: boolean; + public readonly securityGroupReferencingSupport: boolean; + /** * The AWS CloudFormation resource representing the Transit Gateway. */ @@ -230,8 +237,9 @@ export class TransitGateway extends TransitGatewayBase { defaultRouteTablePropagation: getFeatureStatusDefaultDisable(props.defaultRouteTablePropagation), description: props.description, dnsSupport: getFeatureStatusDefaultEnable(props.dnsSupport), - multicastSupport: getFeatureStatusDefaultDisable(props.multicastSupport), - vpnEcmpSupport: getFeatureStatusDefaultEnable(props.vpnEcmpSupport), + // Currently only VPC to Transit Gateway attachments are supported so both of these are disabled. + multicastSupport: TransitGatewayFeatureStatus.DISABLE, + vpnEcmpSupport: TransitGatewayFeatureStatus.DISABLE, }); this.node.defaultChild = this.resource; @@ -240,6 +248,8 @@ export class TransitGateway extends TransitGatewayBase { this.routerTargetId = this.resource.attrId; this.routerType = RouterType.TRANSIT_GATEWAY; this.transitGatewayArn = this.resource.attrTransitGatewayArn; + this.dnsSupport = props.dnsSupport ?? true; + this.securityGroupReferencingSupport = props.securityGroupReferencingSupport ?? false; this.defaultRouteTable = new TransitGatewayRouteTable(this, 'DefaultRouteTable', { transitGateway: this, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index e267952bf4512..cc5b60eadba8c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -21,7 +21,7 @@ export function subnetId(name: string, i: number) { /** * The status of a Transit Gateway feature. */ -enum TransitGatewayFeatureStatus { +export enum TransitGatewayFeatureStatus { /** * The feature is enabled. */ @@ -34,7 +34,7 @@ enum TransitGatewayFeatureStatus { } export function getFeatureStatusDefaultEnable(status?: boolean): TransitGatewayFeatureStatus { - return (status ?? true)? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; + return (status ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; } export function getFeatureStatusDefaultDisable(status?: boolean): TransitGatewayFeatureStatus { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json index 56bb646999e08..4d5ed228fb9e8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -1,7 +1,7 @@ { "version": "39.0.0", "files": { - "11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441": { + "13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9": { "source": { "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441.json", + "objectKey": "13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json index e99b78f138500..2b41b73d7bd2c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -89,7 +89,7 @@ "DefaultRouteTablePropagation": "disable", "DnsSupport": "enable", "MulticastSupport": "disable", - "VpnEcmpSupport": "enable" + "VpnEcmpSupport": "disable" } }, "TransitGatewayDefaultRouteTable608EC117": { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json index 0efb9205a03ef..7aa596ffc1e18 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/11469bc5fb70b5c574647f74293ea591a38000f38ad07e29d61fe2110248d441.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json index b5e607e14cf37..e2b842a5315d1 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -183,7 +183,7 @@ "defaultRouteTablePropagation": "disable", "dnsSupport": "enable", "multicastSupport": "disable", - "vpnEcmpSupport": "enable" + "vpnEcmpSupport": "disable" } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts index 701824a513b98..009baefad27a4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -77,7 +77,7 @@ describe('Transit Gateway Route Table', () => { DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index 86f2acb4f81d7..83adf33d2d5c4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -1,4 +1,4 @@ -import { Template } from 'aws-cdk-lib/assertions'; +import { Annotations, Match, Template } from 'aws-cdk-lib/assertions'; import { Stack } from 'aws-cdk-lib/core'; import * as vpc from '../lib'; import { TransitGateway } from '../lib/transit-gateway'; @@ -167,4 +167,62 @@ describe('TransitGatewayVpcAttachment', () => { `Subnet with ID ${nonExistentSubnet.subnetId} does not exist in the Attachment`, ); }); + + test('throws warning when options are enabled on attachment but not on the transit gateway', () => { + // GIVEN + const transitGateway2 = new TransitGateway(stack, 'TransitGateway2', { + dnsSupport: false, + securityGroupReferencingSupport: false, + }) + + // WHEN + const attachment = transitGateway2.attachVpc('VpcAttachment', { + vpc: myVpc, + subnets: [mySubnet], + vpcAttachmentOptions: { + dnsSupport: true, + securityGroupReferencingSupport: true, + } + }); + + // THEN + const annotations = Annotations.fromStack(stack).findWarning('*', Match.anyValue()); + expect(annotations.length).toBe(2); + + Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', + { + 'Fn::Join': [ + '', + [ + "'DnsSupport' is enabled for the VPC Attachment ", + { + "Fn::GetAtt": [ "TransitGateway2VpcAttachmentE9A375F9", "Id" ] + }, + " but disabled on TransitGateway ", + { + "Fn::GetAtt": [ "TransitGateway2338EB7F2", "Id" ] + }, + ". The feature will not work unless DnsSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch]" + ] + ] + }); + + Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', + { + 'Fn::Join': [ + '', + [ + "'SecurityGroupReferencingSupport' is enabled for the VPC Attachment ", + { + "Fn::GetAtt": [ "TransitGateway2VpcAttachmentE9A375F9", "Id" ] + }, + " but disabled on TransitGateway ", + { + "Fn::GetAtt": [ "TransitGateway2338EB7F2", "Id" ] + }, + ". The feature will not work unless SecurityGroupReferencingSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch]" + ] + ] + }) + }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 6e26c5781ea16..731cf039f94ba 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -48,7 +48,7 @@ describe('Transit Gateway with default settings', () => { DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }); Template.fromStack(stack).templateMatches({ @@ -61,7 +61,7 @@ describe('Transit Gateway with default settings', () => { DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -92,7 +92,7 @@ describe('Transit Gateway with default settings', () => { DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -226,7 +226,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }); Template.fromStack(stack).templateMatches({ @@ -239,7 +239,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -270,7 +270,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -404,7 +404,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }); Template.fromStack(stack).templateMatches({ @@ -417,7 +417,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -448,7 +448,7 @@ describe('Transit Gateway with default route table association and propagation d DefaultRouteTablePropagation: 'disable', DnsSupport: 'enable', MulticastSupport: 'disable', - VpnEcmpSupport: 'enable', + VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { From 1e87d2080eea92be9ad8b543dec5d6896391c2a5 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Tue, 28 Jan 2025 16:44:05 -0800 Subject: [PATCH 16/22] update L1 values to pass undefined instead of CDK default + update tests --- .../lib/transit-gateway-vpc-attachment.ts | 10 ++-- .../aws-ec2-alpha/lib/transit-gateway.ts | 10 ++-- packages/@aws-cdk/aws-ec2-alpha/lib/util.ts | 12 ++--- ...way-disable-automatic-settings.assets.json | 4 +- ...y-disable-automatic-settings.template.json | 2 - .../manifest.json | 2 +- .../tree.json | 2 - .../test/transit-gateway-route-table.test.ts | 2 - .../transit-gateway-vpc-attachment.test.ts | 53 +++++++++---------- .../test/transit-gateway.test.ts | 18 ------- 10 files changed, 45 insertions(+), 70 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 8c1ac8845018f..9f079b3c6f577 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -4,7 +4,7 @@ import { Construct } from 'constructs'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; import { ITransitGatewayAttachment, TransitGatewayAttachmentBase } from './transit-gateway-attachment'; -import { getFeatureStatusDefaultDisable } from './util'; +import { getFeatureStatus } from './util'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; import { Annotations } from 'aws-cdk-lib'; @@ -137,10 +137,10 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase im transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, options: props.vpcAttachmentOptions ? { - ApplianceModeSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.applianceModeSupport), - DnsSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.dnsSupport), - Ipv6Support: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.ipv6Support), - SecurityGroupReferencingSupport: getFeatureStatusDefaultDisable(props.vpcAttachmentOptions?.securityGroupReferencingSupport), + ApplianceModeSupport: getFeatureStatus(props.vpcAttachmentOptions?.applianceModeSupport), + DnsSupport: getFeatureStatus(props.vpcAttachmentOptions?.dnsSupport), + Ipv6Support: getFeatureStatus(props.vpcAttachmentOptions?.ipv6Support), + SecurityGroupReferencingSupport: getFeatureStatus(props.vpcAttachmentOptions?.securityGroupReferencingSupport), } : undefined, }); this.node.defaultChild = this.resource; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 647f43adf3af4..0942b9c7ec2d2 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -6,7 +6,7 @@ import { TransitGatewayVpcAttachment, AttachVpcOptions, ITransitGatewayVpcAttach import { IRouteTarget } from './route'; import { TransitGatewayRouteTableAssociation } from './transit-gateway-route-table-association'; import { TransitGatewayRouteTablePropagation } from './transit-gateway-route-table-propagation'; -import { getFeatureStatusDefaultDisable, getFeatureStatusDefaultEnable, TransitGatewayFeatureStatus } from './util'; +import { getFeatureStatus, TransitGatewayFeatureStatus } from './util'; /** * Represents a Transit Gateway. @@ -230,13 +230,13 @@ export class TransitGateway extends TransitGatewayBase { this.resource = new CfnTransitGateway(this, id, { amazonSideAsn: props.amazonSideAsn ?? undefined, - autoAcceptSharedAttachments: getFeatureStatusDefaultDisable(props.autoAcceptSharedAttachments), + autoAcceptSharedAttachments: getFeatureStatus(props.autoAcceptSharedAttachments), // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. // Instead, CDK will create a custom default route table and use the properties to mimic the automatic assocation/propagation behaviour. - defaultRouteTableAssociation: getFeatureStatusDefaultDisable(props.defaultRouteTableAssociation), - defaultRouteTablePropagation: getFeatureStatusDefaultDisable(props.defaultRouteTablePropagation), + defaultRouteTableAssociation: TransitGatewayFeatureStatus.DISABLE, + defaultRouteTablePropagation: TransitGatewayFeatureStatus.DISABLE, description: props.description, - dnsSupport: getFeatureStatusDefaultEnable(props.dnsSupport), + dnsSupport: getFeatureStatus(props.dnsSupport), // Currently only VPC to Transit Gateway attachments are supported so both of these are disabled. multicastSupport: TransitGatewayFeatureStatus.DISABLE, vpnEcmpSupport: TransitGatewayFeatureStatus.DISABLE, diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts index cc5b60eadba8c..3da52b7d15a4d 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/util.ts @@ -33,12 +33,12 @@ export enum TransitGatewayFeatureStatus { DISABLE = 'disable', } -export function getFeatureStatusDefaultEnable(status?: boolean): TransitGatewayFeatureStatus { - return (status ?? true) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; -} - -export function getFeatureStatusDefaultDisable(status?: boolean): TransitGatewayFeatureStatus { - return (status ?? false) ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; +export function getFeatureStatus(status?: boolean): TransitGatewayFeatureStatus | undefined { + if (status === undefined) { + return undefined; + } else { + return status ? TransitGatewayFeatureStatus.ENABLE : TransitGatewayFeatureStatus.DISABLE; + } } /** diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json index 4d5ed228fb9e8..f588a3861ba75 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -1,7 +1,7 @@ { "version": "39.0.0", "files": { - "13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9": { + "9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b": { "source": { "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9.json", + "objectKey": "9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json index 2b41b73d7bd2c..3aff78b0d0ae4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -84,10 +84,8 @@ "TransitGateway11B93D57": { "Type": "AWS::EC2::TransitGateway", "Properties": { - "AutoAcceptSharedAttachments": "disable", "DefaultRouteTableAssociation": "disable", "DefaultRouteTablePropagation": "disable", - "DnsSupport": "enable", "MulticastSupport": "disable", "VpnEcmpSupport": "disable" } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json index 7aa596ffc1e18..7248da0f2fbc4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/13426a6f4e0d47cdb7cfd46f3f2d834b13a09c7a955adf7e5700eae492cb71c9.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json index e2b842a5315d1..a9a33099702c1 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -178,10 +178,8 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::EC2::TransitGateway", "aws:cdk:cloudformation:props": { - "autoAcceptSharedAttachments": "disable", "defaultRouteTableAssociation": "disable", "defaultRouteTablePropagation": "disable", - "dnsSupport": "enable", "multicastSupport": "disable", "vpnEcmpSupport": "disable" } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts index 009baefad27a4..405ff7561b2f9 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -72,10 +72,8 @@ describe('Transit Gateway Route Table', () => { TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index 83adf33d2d5c4..461d50dd518c4 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -81,7 +81,6 @@ describe('TransitGatewayVpcAttachment', () => { DnsSupport: 'enable', Ipv6Support: 'enable', ApplianceModeSupport: 'enable', - SecurityGroupReferencingSupport: 'disable', }, }); }); @@ -173,16 +172,16 @@ describe('TransitGatewayVpcAttachment', () => { const transitGateway2 = new TransitGateway(stack, 'TransitGateway2', { dnsSupport: false, securityGroupReferencingSupport: false, - }) + }); // WHEN - const attachment = transitGateway2.attachVpc('VpcAttachment', { + transitGateway2.attachVpc('VpcAttachment', { vpc: myVpc, subnets: [mySubnet], vpcAttachmentOptions: { dnsSupport: true, securityGroupReferencingSupport: true, - } + }, }); // THEN @@ -196,33 +195,33 @@ describe('TransitGatewayVpcAttachment', () => { [ "'DnsSupport' is enabled for the VPC Attachment ", { - "Fn::GetAtt": [ "TransitGateway2VpcAttachmentE9A375F9", "Id" ] + 'Fn::GetAtt': ['TransitGateway2VpcAttachmentE9A375F9', 'Id'], }, - " but disabled on TransitGateway ", + ' but disabled on TransitGateway ', { - "Fn::GetAtt": [ "TransitGateway2338EB7F2", "Id" ] + 'Fn::GetAtt': ['TransitGateway2338EB7F2', 'Id'], }, - ". The feature will not work unless DnsSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch]" - ] - ] + '. The feature will not work unless DnsSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch]', + ], + ], }); - Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', - { - 'Fn::Join': [ - '', - [ - "'SecurityGroupReferencingSupport' is enabled for the VPC Attachment ", - { - "Fn::GetAtt": [ "TransitGateway2VpcAttachmentE9A375F9", "Id" ] - }, - " but disabled on TransitGateway ", - { - "Fn::GetAtt": [ "TransitGateway2338EB7F2", "Id" ] - }, - ". The feature will not work unless SecurityGroupReferencingSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch]" - ] - ] - }) + Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', + { + 'Fn::Join': [ + '', + [ + "'SecurityGroupReferencingSupport' is enabled for the VPC Attachment ", + { + 'Fn::GetAtt': ['TransitGateway2VpcAttachmentE9A375F9', 'Id'], + }, + ' but disabled on TransitGateway ', + { + 'Fn::GetAtt': ['TransitGateway2338EB7F2', 'Id'], + }, + '. The feature will not work unless SecurityGroupReferencingSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch]', + ], + ], + }); }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 731cf039f94ba..b51f22118c23f 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -43,10 +43,8 @@ describe('Transit Gateway with default settings', () => { test('Creates a transit gateway with all default settings and default route table', () => { const template = Template.fromStack(stack); template.hasResourceProperties('AWS::EC2::TransitGateway', { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }); @@ -56,10 +54,8 @@ describe('Transit Gateway with default settings', () => { TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, @@ -87,10 +83,8 @@ describe('Transit Gateway with default settings', () => { TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, @@ -221,10 +215,8 @@ describe('Transit Gateway with default route table association and propagation d test('should create a transit gateway with all default settings and default route table', () => { const template = Template.fromStack(stack); template.hasResourceProperties('AWS::EC2::TransitGateway', { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }); @@ -234,10 +226,8 @@ describe('Transit Gateway with default route table association and propagation d TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, @@ -265,10 +255,8 @@ describe('Transit Gateway with default route table association and propagation d TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, @@ -399,10 +387,8 @@ describe('Transit Gateway with default route table association and propagation d test('should create a transit gateway with all default settings and default route table', () => { const template = Template.fromStack(stack); template.hasResourceProperties('AWS::EC2::TransitGateway', { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }); @@ -412,10 +398,8 @@ describe('Transit Gateway with default route table association and propagation d TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, @@ -443,10 +427,8 @@ describe('Transit Gateway with default route table association and propagation d TransitGateway11B93D57: { Type: 'AWS::EC2::TransitGateway', Properties: { - AutoAcceptSharedAttachments: 'disable', DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - DnsSupport: 'enable', MulticastSupport: 'disable', VpnEcmpSupport: 'disable', }, From 1db4acf2e7e96cca767ff554344b30d1e5fdfe69 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 29 Jan 2025 16:55:46 -0800 Subject: [PATCH 17/22] update route table interface + remove tgw L1 unused properties --- .../lib/transit-gateway-route-table.ts | 10 +- .../lib/transit-gateway-vpc-attachment.ts | 4 +- .../aws-ec2-alpha/lib/transit-gateway.ts | 9 +- ...way-disable-automatic-settings.assets.json | 4 +- ...y-disable-automatic-settings.template.json | 4 +- .../manifest.json | 2 +- .../tree.json | 4 +- .../test/transit-gateway-route-table.test.ts | 2 - .../transit-gateway-vpc-attachment.test.ts | 38 +-- .../test/transit-gateway.test.ts | 244 ------------------ 10 files changed, 15 insertions(+), 306 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index 6473445a69d3d..225fdea5c4b30 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -10,13 +10,7 @@ import { ITransitGatewayRouteTablePropagation, TransitGatewayRouteTablePropagati /** * Represents a Transit Gateway Route Table. */ -export interface ITransitGatewayRouteTable extends IResource { - /** - * The ID of the transit gateway route table. - * @attribute - */ - readonly routeTableId: string; - +export interface ITransitGatewayRouteTable extends IResource, IRouteTable { /** * Add an active route to this route table. * @@ -67,7 +61,7 @@ export interface TransitGatewayRouteTableProps { * A Transit Gateway Route Table. * @internal */ -abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable, IRouteTable { +abstract class TransitGatewayRouteTableBase extends Resource implements ITransitGatewayRouteTable { public abstract readonly routeTableId: string; public abstract readonly transitGateway: ITransitGateway; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 9f079b3c6f577..2c7aa5448a4ec 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -149,11 +149,11 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase im this.subnets = props.subnets; if (props.vpcAttachmentOptions?.dnsSupport && !props.transitGateway.dnsSupport) { - Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch', `\'DnsSupport\' is enabled for the VPC Attachment ${this.transitGatewayAttachmentId} but disabled on TransitGateway ${props.transitGateway.transitGatewayId}. The feature will not work unless DnsSupport is enabled on both.`); + Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch', '\'DnsSupport\' is enabled for the VPC Attachment but disabled on the TransitGateway. The feature will not work unless \'DnsSupport\' is enabled on both.'); } if (props.vpcAttachmentOptions?.securityGroupReferencingSupport && !props.transitGateway.securityGroupReferencingSupport) { - Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch', `\'SecurityGroupReferencingSupport\' is enabled for the VPC Attachment ${this.transitGatewayAttachmentId} but disabled on TransitGateway ${props.transitGateway.transitGatewayId}. The feature will not work unless SecurityGroupReferencingSupport is enabled on both.`); + Annotations.of(this).addWarningV2('@aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch', '\'SecurityGroupReferencingSupport\' is enabled for the VPC Attachment but disabled on the TransitGateway. The feature will not work unless \'SecurityGroupReferencingSupport\' is enabled on both.'); } if (props.transitGateway.defaultRouteTableAssociation) { diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 0942b9c7ec2d2..4afbeacef456e 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -55,12 +55,12 @@ export interface ITransitGateway extends cdk.IResource, IRouteTarget { readonly defaultRouteTablePropagation: boolean; /** - * Enable or disable DNS support. + * Whether or not DNS support is enabled on the Transit Gateway. */ readonly dnsSupport: boolean; /** - * Enable or disablesecurity group referencing support. + * Whether or not security group referencing support is enabled on the Transit Gateway. */ readonly securityGroupReferencingSupport: boolean; } @@ -122,7 +122,7 @@ export interface TransitGatewayProps { readonly dnsSupport?: boolean; /** - * Enable or disablesecurity group referencing support + * Enable or disable security group referencing support * * If securityGroupReferencingSupport is enabled on a VPC Attachment, this also needs to be enabled for the feature to work. * Otherwise the resources will still deploy but the feature will not work. @@ -237,9 +237,6 @@ export class TransitGateway extends TransitGatewayBase { defaultRouteTablePropagation: TransitGatewayFeatureStatus.DISABLE, description: props.description, dnsSupport: getFeatureStatus(props.dnsSupport), - // Currently only VPC to Transit Gateway attachments are supported so both of these are disabled. - multicastSupport: TransitGatewayFeatureStatus.DISABLE, - vpnEcmpSupport: TransitGatewayFeatureStatus.DISABLE, }); this.node.defaultChild = this.resource; diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json index f588a3861ba75..d3c16ab80f40b 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.assets.json @@ -1,7 +1,7 @@ { "version": "39.0.0", "files": { - "9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b": { + "abbff3a0484dd36d58296bffebd14d57a957f5202e481df8ef1ba150a399c149": { "source": { "path": "aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b.json", + "objectKey": "abbff3a0484dd36d58296bffebd14d57a957f5202e481df8ef1ba150a399c149.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json index 3aff78b0d0ae4..5d42c0f4971ba 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings.template.json @@ -85,9 +85,7 @@ "Type": "AWS::EC2::TransitGateway", "Properties": { "DefaultRouteTableAssociation": "disable", - "DefaultRouteTablePropagation": "disable", - "MulticastSupport": "disable", - "VpnEcmpSupport": "disable" + "DefaultRouteTablePropagation": "disable" } }, "TransitGatewayDefaultRouteTable608EC117": { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json index 7248da0f2fbc4..c6ed1632e2450 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9f0a002d82d045055d0a19b754cd70510300a96928581a9d16f055013ebd560b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/abbff3a0484dd36d58296bffebd14d57a957f5202e481df8ef1ba150a399c149.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json index a9a33099702c1..ba349ddb8e702 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.transit-gateway.js.snapshot/tree.json @@ -179,9 +179,7 @@ "aws:cdk:cloudformation:type": "AWS::EC2::TransitGateway", "aws:cdk:cloudformation:props": { "defaultRouteTableAssociation": "disable", - "defaultRouteTablePropagation": "disable", - "multicastSupport": "disable", - "vpnEcmpSupport": "disable" + "defaultRouteTablePropagation": "disable" } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts index 405ff7561b2f9..79c55e8e1f666 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -74,8 +74,6 @@ describe('Transit Gateway Route Table', () => { Properties: { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts index 461d50dd518c4..e1cd415b3fee8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-vpc-attachment.test.ts @@ -188,40 +188,8 @@ describe('TransitGatewayVpcAttachment', () => { const annotations = Annotations.fromStack(stack).findWarning('*', Match.anyValue()); expect(annotations.length).toBe(2); - Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', - { - 'Fn::Join': [ - '', - [ - "'DnsSupport' is enabled for the VPC Attachment ", - { - 'Fn::GetAtt': ['TransitGateway2VpcAttachmentE9A375F9', 'Id'], - }, - ' but disabled on TransitGateway ', - { - 'Fn::GetAtt': ['TransitGateway2338EB7F2', 'Id'], - }, - '. The feature will not work unless DnsSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch]', - ], - ], - }); - - Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', - { - 'Fn::Join': [ - '', - [ - "'SecurityGroupReferencingSupport' is enabled for the VPC Attachment ", - { - 'Fn::GetAtt': ['TransitGateway2VpcAttachmentE9A375F9', 'Id'], - }, - ' but disabled on TransitGateway ', - { - 'Fn::GetAtt': ['TransitGateway2338EB7F2', 'Id'], - }, - '. The feature will not work unless SecurityGroupReferencingSupport is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch]', - ], - ], - }); + Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', '\'DnsSupport\' is enabled for the VPC Attachment but disabled on the TransitGateway. The feature will not work unless \'DnsSupport\' is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewayDnsSupportMismatch]'); + + Annotations.fromStack(stack).hasWarning('/Default/TransitGateway2/VpcAttachment', '\'SecurityGroupReferencingSupport\' is enabled for the VPC Attachment but disabled on the TransitGateway. The feature will not work unless \'SecurityGroupReferencingSupport\' is enabled on both. [ack: @aws-cdk/aws-ec2:transitGatewaySecurityGroupReferencingSupportMismatch]'); }); }); diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index b51f22118c23f..8260da1371507 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -45,8 +45,6 @@ describe('Transit Gateway with default settings', () => { template.hasResourceProperties('AWS::EC2::TransitGateway', { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }); Template.fromStack(stack).templateMatches({ @@ -56,8 +54,6 @@ describe('Transit Gateway with default settings', () => { Properties: { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -85,8 +81,6 @@ describe('Transit Gateway with default settings', () => { Properties: { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -217,8 +211,6 @@ describe('Transit Gateway with default route table association and propagation d template.hasResourceProperties('AWS::EC2::TransitGateway', { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }); Template.fromStack(stack).templateMatches({ @@ -228,8 +220,6 @@ describe('Transit Gateway with default route table association and propagation d Properties: { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -257,8 +247,6 @@ describe('Transit Gateway with default route table association and propagation d Properties: { DefaultRouteTableAssociation: 'disable', DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', }, }, TransitGatewayDefaultRouteTable608EC117: { @@ -345,235 +333,3 @@ describe('Transit Gateway with default route table association and propagation d }, 0); }); }); - -describe('Transit Gateway with default route table association and propagation disabled', () => { - - let stack: cdk.Stack; - let tgw: TransitGateway; - let myVpc: vpc.VpcV2; - let mySubnet: subnet.SubnetV2; - - beforeEach(() => { - const app = new cdk.App({ - context: { - '@aws-cdk/core:newStyleStackSynthesis': false, - }, - }); - - stack = new cdk.Stack(app, 'TransitGatewayStack', { - env: { - region: 'us-east-1', - }, - }); - - myVpc = new vpc.VpcV2(stack, 'VpcA', { - primaryAddressBlock: vpc.IpAddresses.ipv4('10.0.0.0/16'), - secondaryAddressBlocks: [vpc.IpAddresses.ipv4('10.1.0.0/16', { cidrBlockName: 'TempSecondaryBlock' })], - }); - - mySubnet = new subnet.SubnetV2(stack, 'TestSubnet', { - vpc: myVpc, - availabilityZone: 'us-east-1a', - ipv4CidrBlock: new subnet.IpCidr('10.0.0.0/24'), - subnetType: SubnetType.PRIVATE_WITH_EGRESS, - }); - - tgw = new TransitGateway(stack, 'TransitGateway', { - defaultRouteTableAssociation: false, - defaultRouteTablePropagation: false, - }); - }); - - test('should create a transit gateway with all default settings and default route table', () => { - const template = Template.fromStack(stack); - template.hasResourceProperties('AWS::EC2::TransitGateway', { - DefaultRouteTableAssociation: 'disable', - DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', - }); - - Template.fromStack(stack).templateMatches({ - Resources: { - TransitGateway11B93D57: { - Type: 'AWS::EC2::TransitGateway', - Properties: { - DefaultRouteTableAssociation: 'disable', - DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', - }, - }, - TransitGatewayDefaultRouteTable608EC117: { - Type: 'AWS::EC2::TransitGatewayRouteTable', - Properties: { - TransitGatewayId: { - 'Fn::GetAtt': [ - 'TransitGateway11B93D57', - 'Id', - ], - }, - }, - }, - }, - }); - }); - - test('add route table method should create a second transit gateway route table tha references the transit gateway', () => { - tgw.addRouteTable('RouteTable2'); - - Template.fromStack(stack).templateMatches({ - Resources: { - TransitGateway11B93D57: { - Type: 'AWS::EC2::TransitGateway', - Properties: { - DefaultRouteTableAssociation: 'disable', - DefaultRouteTablePropagation: 'disable', - MulticastSupport: 'disable', - VpnEcmpSupport: 'disable', - }, - }, - TransitGatewayDefaultRouteTable608EC117: { - Type: 'AWS::EC2::TransitGatewayRouteTable', - Properties: { - TransitGatewayId: { - 'Fn::GetAtt': [ - 'TransitGateway11B93D57', - 'Id', - ], - }, - }, - }, - TransitGatewayRouteTable2047E2A04: { - Type: 'AWS::EC2::TransitGatewayRouteTable', - Properties: { - TransitGatewayId: { - 'Fn::GetAtt': [ - 'TransitGateway11B93D57', - 'Id', - ], - }, - }, - }, - }, - }); - }); - - test('attach vpc method should create an attachment and not create an association or propagation', () => { - - tgw.attachVpc('VpcAttachment', { - vpc: myVpc, - subnets: [mySubnet], - }); - - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { - SubnetIds: [ - { - Ref: 'TestSubnet2A4BE4CA', - }, - ], - TransitGatewayId: { - 'Fn::GetAtt': [ - 'TransitGateway11B93D57', - 'Id', - ], - }, - VpcId: { - 'Fn::GetAtt': [ - 'VpcAAD85CA4C', - 'VpcId', - ], - }, - }); - - Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTableAssociation', { - TransitGatewayAttachmentId: { - 'Fn::GetAtt': [ - 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', - 'Id', - ], - }, - TransitGatewayRouteTableId: { - 'Fn::GetAtt': [ - 'TransitGatewayDefaultRouteTable608EC117', - 'TransitGatewayRouteTableId', - ], - }, - }, 0); - - Template.fromStack(stack).resourcePropertiesCountIs('AWS::EC2::TransitGatewayRouteTablePropagation', { - TransitGatewayAttachmentId: { - 'Fn::GetAtt': [ - 'TransitGatewayVpcAttachmentTransitGatewayAttachment963F391D', - 'Id', - ], - }, - TransitGatewayRouteTableId: { - 'Fn::GetAtt': [ - 'TransitGatewayDefaultRouteTable608EC117', - 'TransitGatewayRouteTableId', - ], - }, - }, 0); - }); - - test('attach vpc method should create an attachment, association and propagation when route tables are passed to the method', () => { - - tgw.attachVpc('VpcAttachment', { - vpc: myVpc, - subnets: [mySubnet], - associationRouteTable: tgw.defaultRouteTable, - propagationRouteTables: [tgw.defaultRouteTable], - }); - - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayAttachment', { - SubnetIds: [ - { - Ref: 'TestSubnet2A4BE4CA', - }, - ], - TransitGatewayId: { - 'Fn::GetAtt': [ - 'TransitGateway11B93D57', - 'Id', - ], - }, - VpcId: { - 'Fn::GetAtt': [ - 'VpcAAD85CA4C', - 'VpcId', - ], - }, - }); - - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTableAssociation', { - TransitGatewayAttachmentId: { - 'Fn::GetAtt': [ - 'TransitGatewayVpcAttachment3EC29F61', - 'Id', - ], - }, - TransitGatewayRouteTableId: { - 'Fn::GetAtt': [ - 'TransitGatewayDefaultRouteTable608EC117', - 'TransitGatewayRouteTableId', - ], - }, - }); - - Template.fromStack(stack).hasResourceProperties('AWS::EC2::TransitGatewayRouteTablePropagation', { - TransitGatewayAttachmentId: { - 'Fn::GetAtt': [ - 'TransitGatewayVpcAttachment3EC29F61', - 'Id', - ], - }, - TransitGatewayRouteTableId: { - 'Fn::GetAtt': [ - 'TransitGatewayDefaultRouteTable608EC117', - 'TransitGatewayRouteTableId', - ], - }, - }); - }); -}); From 418c4360c72133c36443015fa8292c43da49d491 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 29 Jan 2025 17:01:58 -0800 Subject: [PATCH 18/22] add missing L1 prop --- packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 4afbeacef456e..691969acfbd16 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -237,6 +237,7 @@ export class TransitGateway extends TransitGatewayBase { defaultRouteTablePropagation: TransitGatewayFeatureStatus.DISABLE, description: props.description, dnsSupport: getFeatureStatus(props.dnsSupport), + securityGroupReferencingSupport: getFeatureStatus(props.securityGroupReferencingSupport), }); this.node.defaultChild = this.resource; From b0f24b75d9072b52a5eaa6ddff254278e1582261 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Wed, 29 Jan 2025 17:04:07 -0800 Subject: [PATCH 19/22] add missing l1 prop --- packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index 691969acfbd16..e56a7e44c776b 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -235,6 +235,7 @@ export class TransitGateway extends TransitGatewayBase { // Instead, CDK will create a custom default route table and use the properties to mimic the automatic assocation/propagation behaviour. defaultRouteTableAssociation: TransitGatewayFeatureStatus.DISABLE, defaultRouteTablePropagation: TransitGatewayFeatureStatus.DISABLE, + transitGatewayCidrBlocks: props.transitGatewayCidrBlocks, description: props.description, dnsSupport: getFeatureStatus(props.dnsSupport), securityGroupReferencingSupport: getFeatureStatus(props.securityGroupReferencingSupport), From 91a0a94e572b68f608f670ec73bb07cb0017cc2b Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Thu, 30 Jan 2025 23:43:44 -0800 Subject: [PATCH 20/22] create tgw association interface + remove private _resource prop --- packages/@aws-cdk/aws-ec2-alpha/README.md | 2 +- packages/@aws-cdk/aws-ec2-alpha/lib/index.ts | 1 + .../lib/transit-gateway-association.ts | 20 +++++++++++ ...transit-gateway-route-table-association.ts | 36 ++++--------------- ...transit-gateway-route-table-propagation.ts | 24 +++---------- .../lib/transit-gateway-route-table.ts | 11 ++---- .../lib/transit-gateway-route.ts | 11 ++---- .../lib/transit-gateway-vpc-attachment.ts | 14 ++++---- .../aws-ec2-alpha/lib/transit-gateway.ts | 16 +++------ 9 files changed, 51 insertions(+), 84 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-association.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/README.md b/packages/@aws-cdk/aws-ec2-alpha/README.md index 6130634646795..119915e001b8c 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/README.md +++ b/packages/@aws-cdk/aws-ec2-alpha/README.md @@ -711,7 +711,7 @@ The Transit Gateway construct library provides four main constructs: - `TransitGateway`: The central hub for your network connections - `TransitGatewayRouteTable`: Manages routing between attached networks -- `TransitGatewayVpcAttachment`: Connects VPCs to the Transi Gateway +- `TransitGatewayVpcAttachment`: Connects VPCs to the Transit Gateway - `TransitGatewayRoute`: Defines routing rules within your Transit Gateway ### Basic Usage diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts index 17b3510f43740..6f51175b8d6a8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/index.ts @@ -13,5 +13,6 @@ export * from './transit-gateway-route'; export * from './transit-gateway-route-table'; export * from './transit-gateway-attachment'; export * from './transit-gateway-vpc-attachment'; +export * from './transit-gateway-association'; export * from './transit-gateway-route-table-association'; export * from './transit-gateway-route-table-propagation'; diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-association.ts new file mode 100644 index 0000000000000..4c0f6a222aef3 --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-association.ts @@ -0,0 +1,20 @@ +import { IResource, Resource } from 'aws-cdk-lib/core'; + +/** + * Represents a Transit Gateway Route Table Association. + */ +export interface ITransitGatewayAssociation extends IResource { + /** + * The ID of the transit gateway route table association. + * @attribute + */ + readonly transitGatewayAssociationId: string; +} + +/** + * A Transit Gateway Association. + * @internal + */ +export abstract class TransitGatewayAssociationBase extends Resource implements ITransitGatewayAssociation { + public abstract readonly transitGatewayAssociationId: string; +} diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts index 4838cceee2462..6365907de4504 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-association.ts @@ -1,19 +1,13 @@ -import { IResource, Resource } from 'aws-cdk-lib/core'; import { ITransitGatewayAttachment } from './transit-gateway-attachment'; import { ITransitGatewayRouteTable } from './transit-gateway-route-table'; import { CfnTransitGatewayRouteTableAssociation } from 'aws-cdk-lib/aws-ec2'; import { Construct } from 'constructs'; +import { ITransitGatewayAssociation, TransitGatewayAssociationBase } from './transit-gateway-association'; /** * Represents a Transit Gateway Route Table Association. */ -export interface ITransitGatewayRouteTableAssociation extends IResource { - /** - * The ID of the transit gateway route table association. - * @attribute - */ - readonly transitGatewayRouteTableAssociationId: string; -} +export interface ITransitGatewayRouteTableAssociation extends ITransitGatewayAssociation {} /** * Common properties for a Transit Gateway Route Table Association. @@ -37,42 +31,26 @@ export interface TransitGatewayRouteTableAssociationProps { readonly transitGatewayRouteTableAssociationName?: string; } -/** - * A Transit Gateway Route Table Association. - * @internal - */ -abstract class TransitGatewayRouteTableAssociationBase extends Resource implements ITransitGatewayRouteTableAssociation { - /** - * The ID of the transit gateway route table association. - */ - public abstract readonly transitGatewayRouteTableAssociationId: string; -} - /** * Create a Transit Gateway Route Table Association. * * @resource AWS::EC2::TransitGatewayRouteTableAssociation */ -export class TransitGatewayRouteTableAssociation extends TransitGatewayRouteTableAssociationBase { +export class TransitGatewayRouteTableAssociation extends TransitGatewayAssociationBase { /** * The ID of the transit gateway route table association. */ - public readonly transitGatewayRouteTableAssociationId: string; - - /** - * The AWS CloudFormation resource representing the Transit Gateway Route Table Association. - */ - public readonly resource: CfnTransitGatewayRouteTableAssociation; + public readonly transitGatewayAssociationId: string; constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) { super(scope, id); - this.resource = new CfnTransitGatewayRouteTableAssociation(this, id, { + const resource = new CfnTransitGatewayRouteTableAssociation(this, id, { transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); - this.node.defaultChild = this.resource; + this.node.defaultChild = resource; - this.transitGatewayRouteTableAssociationId = this.resource.ref; + this.transitGatewayAssociationId = resource.ref; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts index 79e9069ccce77..1e795a408c81d 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table-propagation.ts @@ -37,42 +37,26 @@ export interface TransitGatewayRouteTablePropagationProps { readonly transitGatewayRouteTablePropagationName?: string; } -/** - * A Transit Gateway Route Table Propagation. - * @internal - */ -abstract class TransitGatewayRouteTablePropagationBase extends Resource implements ITransitGatewayRouteTablePropagation { - /** - * The ID of the transit gateway route table propagation. - */ - public abstract readonly transitGatewayRouteTablePropagationId: string; -} - /** * Create a Transit Gateway Route Table Propagation. * * @resource AWS::EC2::TransitGatewayRouteTablePropagation */ -export class TransitGatewayRouteTablePropagation extends TransitGatewayRouteTablePropagationBase { +export class TransitGatewayRouteTablePropagation extends Resource implements ITransitGatewayRouteTablePropagation { /** * The ID of the transit gateway route table propagation. */ public readonly transitGatewayRouteTablePropagationId: string; - /** - * The AWS CloudFormation resource representing the Transit Gateway Route Table Propagation. - */ - public readonly resource: CfnTransitGatewayRouteTablePropagation; - constructor(scope: Construct, id: string, props: TransitGatewayRouteTablePropagationProps) { super(scope, id); - this.resource = new CfnTransitGatewayRouteTablePropagation(this, id, { + const resource = new CfnTransitGatewayRouteTablePropagation(this, id, { transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); - this.node.defaultChild = this.resource; + this.node.defaultChild = resource; - this.transitGatewayRouteTablePropagationId = this.resource.ref; + this.transitGatewayRouteTablePropagationId = resource.ref; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index 225fdea5c4b30..f67b130026a80 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -107,21 +107,16 @@ export class TransitGatewayRouteTable extends TransitGatewayRouteTableBase { */ public readonly transitGateway: ITransitGateway; - /** - * The AWS CloudFormation resource representing the Transit Gateway Route Table. - */ - public readonly resource: CfnTransitGatewayRouteTable; - constructor(scope: Construct, id: string, props: TransitGatewayRouteTableProps) { super(scope, id); - this.resource = new CfnTransitGatewayRouteTable(this, id, { + const resource = new CfnTransitGatewayRouteTable(this, id, { transitGatewayId: props.transitGateway.transitGatewayId, }); - this.node.defaultChild = this.resource; + this.node.defaultChild = resource; - this.routeTableId = this.resource.attrTransitGatewayRouteTableId; + this.routeTableId = resource.attrTransitGatewayRouteTableId; this.transitGateway = props.transitGateway; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts index b2bb8f201741c..0178b99ac55e6 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route.ts @@ -110,22 +110,17 @@ export class TransitGatewayBlackholeRoute extends TransitGatewayRouteBase { public readonly routeTable: ITransitGatewayRouteTable; public readonly destinationCidrBlock: string; - /** - * The AWS CloudFormation resource representing the Transit Gateway Route. - */ - public readonly resource: CfnTransitGatewayRoute; - constructor(scope: Construct, id: string, props: TransitGatewayBlackholeRouteProps) { super(scope, id); - this.resource = new CfnTransitGatewayRoute(this, id, { + const resource = new CfnTransitGatewayRoute(this, id, { blackhole: true, destinationCidrBlock: props.destinationCidrBlock, transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId, }); - this.node.defaultChild = this.resource; - this.destinationCidrBlock = this.resource.destinationCidrBlock; + this.node.defaultChild = resource; + this.destinationCidrBlock = resource.destinationCidrBlock; this.routeTable = props.transitGatewayRouteTable; } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts index 2c7aa5448a4ec..95f4682a7efa1 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-vpc-attachment.ts @@ -122,17 +122,17 @@ export interface AttachVpcOptions extends BaseTransitGatewayVpcAttachmentProps { */ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase implements ITransitGatewayVpcAttachment { public readonly transitGatewayAttachmentId: string; + private readonly subnets: ISubnet[] = []; /** * The AWS CloudFormation resource representing the Transit Gateway Attachment. */ - public readonly resource: CfnTransitGatewayAttachment; - private readonly subnets: ISubnet[] = []; + private readonly _resource: CfnTransitGatewayAttachment; constructor(scope: Construct, id: string, props: TransitGatewayVpcAttachmentProps) { super(scope, id); - this.resource = new CfnTransitGatewayAttachment(this, id, { + this._resource = new CfnTransitGatewayAttachment(this, id, { subnetIds: props.subnets.map((subnet) => subnet.subnetId), transitGatewayId: props.transitGateway.transitGatewayId, vpcId: props.vpc.vpcId, @@ -143,9 +143,9 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase im SecurityGroupReferencingSupport: getFeatureStatus(props.vpcAttachmentOptions?.securityGroupReferencingSupport), } : undefined, }); - this.node.defaultChild = this.resource; + this.node.defaultChild = this._resource; - this.transitGatewayAttachmentId = this.resource.attrId; + this.transitGatewayAttachmentId = this._resource.attrId; this.subnets = props.subnets; if (props.vpcAttachmentOptions?.dnsSupport && !props.transitGateway.dnsSupport) { @@ -181,7 +181,7 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase im } this.subnets.push(subnet); } - this.resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); + this._resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); } /** @@ -195,6 +195,6 @@ export class TransitGatewayVpcAttachment extends TransitGatewayAttachmentBase im } this.subnets.splice(index, 1); } - this.resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); + this._resource.subnetIds = this.subnets.map(subnet => subnet.subnetId); } } diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts index e56a7e44c776b..b02c267681fa8 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway.ts @@ -220,15 +220,10 @@ export class TransitGateway extends TransitGatewayBase { public readonly dnsSupport: boolean; public readonly securityGroupReferencingSupport: boolean; - /** - * The AWS CloudFormation resource representing the Transit Gateway. - */ - public readonly resource: CfnTransitGateway; - constructor(scope: Construct, id: string, props: TransitGatewayProps = {}) { super(scope, id); - this.resource = new CfnTransitGateway(this, id, { + const resource = new CfnTransitGateway(this, id, { amazonSideAsn: props.amazonSideAsn ?? undefined, autoAcceptSharedAttachments: getFeatureStatus(props.autoAcceptSharedAttachments), // Default Association/Propagation will always be false when creating the L1 to prevent EC2 from creating the default route table. @@ -241,12 +236,11 @@ export class TransitGateway extends TransitGatewayBase { securityGroupReferencingSupport: getFeatureStatus(props.securityGroupReferencingSupport), }); - this.node.defaultChild = this.resource; - - this.transitGatewayId = this.resource.attrId; - this.routerTargetId = this.resource.attrId; + this.node.defaultChild = resource; + this.transitGatewayId = resource.attrId; + this.routerTargetId = resource.attrId; this.routerType = RouterType.TRANSIT_GATEWAY; - this.transitGatewayArn = this.resource.attrTransitGatewayArn; + this.transitGatewayArn = resource.attrTransitGatewayArn; this.dnsSupport = props.dnsSupport ?? true; this.securityGroupReferencingSupport = props.securityGroupReferencingSupport ?? false; From 7cf64c85093bd21e0c4b932a2ed3706d2af05fe5 Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Fri, 31 Jan 2025 14:47:18 -0800 Subject: [PATCH 21/22] linting --- .../lib/transit-gateway-route-table.ts | 2 +- .../aws-ec2-alpha/test/integ.cfntgw.ts | 46 +++++++++++++++++++ ...it-gateway-route-table-propagation.test.ts | 1 - .../test/transit-gateway-route-table.test.ts | 1 - .../test/transit-gateway.test.ts | 4 -- 5 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts index f67b130026a80..5b2df56c14a85 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-route-table.ts @@ -71,7 +71,7 @@ abstract class TransitGatewayRouteTableBase extends Resource implements ITransit transitGatewayAttachment, destinationCidrBlock: destinationCidr, }); - }; + } public addBlackholeRoute(id: string, destinationCidr: string): ITransitGatewayRoute { return new TransitGatewayBlackholeRoute(this, id, { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts new file mode 100644 index 0000000000000..9138820d758bf --- /dev/null +++ b/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts @@ -0,0 +1,46 @@ +import * as vpc_v2 from '../lib/vpc-v2'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { CfnTransitGateway, CfnTransitGatewayAttachment, CfnTransitGatewayRouteTableAssociation, SubnetType } from 'aws-cdk-lib/aws-ec2'; +import { IpCidr, SubnetV2 } from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings'); + +const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { + primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), + secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6( { + cidrBlockName: 'SecondaryTest', + })], + enableDnsHostnames: true, + enableDnsSupport: true, +}); + +const subnet = new SubnetV2(stack, 'testSubnet1', { + vpc, + availabilityZone: 'us-east-1a', + ipv4CidrBlock: new IpCidr('10.1.0.0/20'), + subnetType: SubnetType.PRIVATE_ISOLATED, +}); + +// Create a Transit Gateway with +const tgw = new CfnTransitGateway(stack, 'TestTgw'); + +const attachment = new CfnTransitGatewayAttachment(stack, 'TestTgwAttachment', { + transitGatewayId: tgw.ref, + vpcId: vpc.vpcId, + subnetIds: [subnet.subnetId], +}); + +const rtbId = tgw.propagationDefaultRouteTableId ?? 'invalid-id-string'; + +new CfnTransitGatewayRouteTableAssociation(stack, 'TestAssociation', { + transitGatewayAttachmentId: attachment.ref, + transitGatewayRouteTableId: rtbId, +}); + +new IntegTest(app, 'integtest-model', { + testCases: [stack], +}); + diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts index aa79f821c6bdd..4a71402416743 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table-propagation.test.ts @@ -42,7 +42,6 @@ describe('TransitGatewayRouteTablePropagation', () => { transitGateway: transitGateway, subnets: [mySubnet], }); - }); test('creates propagation with required properties', () => { diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts index 79c55e8e1f666..810fe8bc9fcf7 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway-route-table.test.ts @@ -8,7 +8,6 @@ import { TransitGatewayRouteTable } from '../lib/transit-gateway-route-table'; import { TransitGatewayVpcAttachment } from '../lib/transit-gateway-vpc-attachment'; describe('Transit Gateway Route Table', () => { - let stack: cdk.Stack; let tgw: TransitGateway; let myVpc: vpc.VpcV2; diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts index 8260da1371507..68d4afc28d5bc 100644 --- a/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts +++ b/packages/@aws-cdk/aws-ec2-alpha/test/transit-gateway.test.ts @@ -6,7 +6,6 @@ import * as subnet from '../lib/subnet-v2'; import { SubnetType } from 'aws-cdk-lib/aws-ec2'; describe('Transit Gateway with default settings', () => { - let stack: cdk.Stack; let tgw: TransitGateway; let myVpc: vpc.VpcV2; @@ -110,7 +109,6 @@ describe('Transit Gateway with default settings', () => { }); test('attach vpc method should create an attachment, association and propagation when default association/propagation are enabled', () => { - tgw.attachVpc('VpcAttachment', { vpc: myVpc, subnets: [mySubnet], @@ -169,7 +167,6 @@ describe('Transit Gateway with default settings', () => { }); describe('Transit Gateway with default route table association and propagation disabled', () => { - let stack: cdk.Stack; let tgw: TransitGateway; let myVpc: vpc.VpcV2; @@ -276,7 +273,6 @@ describe('Transit Gateway with default route table association and propagation d }); test('attach vpc method should create an attachment and not create an association or propagation when default association/propagation are disabled', () => { - tgw.attachVpc('VpcAttachment', { vpc: myVpc, subnets: [mySubnet], From e63d92a3d9c12671ba4869877495f0933c757fec Mon Sep 17 00:00:00 2001 From: Paul Sun Date: Sun, 2 Feb 2025 23:15:03 -0800 Subject: [PATCH 22/22] remove testing integ test --- .../aws-ec2-alpha/test/integ.cfntgw.ts | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts diff --git a/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts b/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts deleted file mode 100644 index 9138820d758bf..0000000000000 --- a/packages/@aws-cdk/aws-ec2-alpha/test/integ.cfntgw.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as vpc_v2 from '../lib/vpc-v2'; -import { IntegTest } from '@aws-cdk/integ-tests-alpha'; -import * as cdk from 'aws-cdk-lib'; -import { CfnTransitGateway, CfnTransitGatewayAttachment, CfnTransitGatewayRouteTableAssociation, SubnetType } from 'aws-cdk-lib/aws-ec2'; -import { IpCidr, SubnetV2 } from '../lib'; - -const app = new cdk.App(); - -const stack = new cdk.Stack(app, 'aws-cdk-ec2-alpha-transit-gateway-disable-automatic-settings'); - -const vpc = new vpc_v2.VpcV2(stack, 'SubnetTest', { - primaryAddressBlock: vpc_v2.IpAddresses.ipv4('10.1.0.0/16'), - secondaryAddressBlocks: [vpc_v2.IpAddresses.amazonProvidedIpv6( { - cidrBlockName: 'SecondaryTest', - })], - enableDnsHostnames: true, - enableDnsSupport: true, -}); - -const subnet = new SubnetV2(stack, 'testSubnet1', { - vpc, - availabilityZone: 'us-east-1a', - ipv4CidrBlock: new IpCidr('10.1.0.0/20'), - subnetType: SubnetType.PRIVATE_ISOLATED, -}); - -// Create a Transit Gateway with -const tgw = new CfnTransitGateway(stack, 'TestTgw'); - -const attachment = new CfnTransitGatewayAttachment(stack, 'TestTgwAttachment', { - transitGatewayId: tgw.ref, - vpcId: vpc.vpcId, - subnetIds: [subnet.subnetId], -}); - -const rtbId = tgw.propagationDefaultRouteTableId ?? 'invalid-id-string'; - -new CfnTransitGatewayRouteTableAssociation(stack, 'TestAssociation', { - transitGatewayAttachmentId: attachment.ref, - transitGatewayRouteTableId: rtbId, -}); - -new IntegTest(app, 'integtest-model', { - testCases: [stack], -}); -