Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ec2-alpha): add Transit Gateway L2 #32956

Merged
merged 28 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
50b9d34
WIP feat(ec2-alpha): transit gateway L2
paulhcsun Dec 3, 2024
d2af8a5
skeleton
paulhcsun Jan 9, 2025
a76835c
updated classes
paulhcsun Jan 15, 2025
9c0bf44
remove add/removeSubnetIds property + implement methods
paulhcsun Jan 15, 2025
353ca25
some unit tests + class updates
paulhcsun Jan 22, 2025
5f0c30b
update vpc attachment resource + unit tests
paulhcsun Jan 22, 2025
e123638
README draft
paulhcsun Jan 23, 2025
faf600d
integ snapshots + update attachment options
paulhcsun Jan 23, 2025
3b47333
fix unit test
paulhcsun Jan 23, 2025
c38c8b0
remove unused import
paulhcsun Jan 23, 2025
6bdd545
Merge branch 'main' into vpcv2-transit-gateway
paulhcsun Jan 23, 2025
55f16a3
Merge branch 'main' into vpcv2-transit-gateway
paulhcsun Jan 24, 2025
a5db2e5
remove unused test
paulhcsun Jan 24, 2025
4a53920
pr feedback
paulhcsun Jan 25, 2025
39e8ae9
Merge branch 'main' into vpcv2-transit-gateway
paulhcsun Jan 25, 2025
a00ecc7
add docstrings, update readme, add fromxxx linter exemption
paulhcsun Jan 27, 2025
7c7fbb7
fix unit tests
paulhcsun Jan 28, 2025
596ea55
add warnings when attaching VPC and update tests
paulhcsun Jan 29, 2025
1e87d20
update L1 values to pass undefined instead of CDK default + update tests
paulhcsun Jan 29, 2025
1db4acf
update route table interface + remove tgw L1 unused properties
paulhcsun Jan 30, 2025
418c436
add missing L1 prop
paulhcsun Jan 30, 2025
b0f24b7
add missing l1 prop
paulhcsun Jan 30, 2025
91a0a94
create tgw association interface + remove private _resource prop
paulhcsun Jan 31, 2025
c4d2815
Merge branch 'main' into vpcv2-transit-gateway
paulhcsun Jan 31, 2025
7cf64c8
linting
paulhcsun Jan 31, 2025
4b63235
Merge branch 'main' into vpcv2-transit-gateway
mergify[bot] Jan 31, 2025
f515acc
Merge branch 'main' into vpcv2-transit-gateway
mergify[bot] Feb 1, 2025
e63d92a
remove testing integ test
paulhcsun Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions packages/@aws-cdk/aws-ec2-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -717,3 +717,191 @@ 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.
paulhcsun marked this conversation as resolved.
Show resolved Hide resolved

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.

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 Transit Gateway
- `TransitGatewayRoute`: Defines routing rules within your Transit Gateway

### Basic Usage

To create a minimal deployable `TransitGateway`:

```ts
const transitGateway = new TransitGateway(this, 'MyTransitGateway');
```

### 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, 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.
>
> 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:
paulhcsun marked this conversation as resolved.
Show resolved Hide resolved

```ts
const transitGateway = new TransitGateway(this, 'MyTransitGateway', {
defaultRouteTableAssociation: false,
defaultRouteTablePropagation: false,
});
```

### Transit Gateway Route Table Management

Add additional Transit Gateway Route Tables using the `addRouteTable()` method:

```ts
const transitGateway = new TransitGateway(this, 'MyTransitGateway');

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
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: myVpc,
subnets: [subnet1, subnet2]
});

// Create an attachment with optional parameters
const attachmentWithOptions = transitGateway.attachVpc('VpcAttachmentWithOptions', {
vpc: myVpc,
subnets: [subnet1],
vpcAttachmentOptions: {
dnsSupport: true,
applianceModeSupport: true,
ipv6Support: true,
securityGroupReferencingSupport: true,
}
});
paulhcsun marked this conversation as resolved.
Show resolved Hide resolved
```

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 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.

### 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
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');
```

### Route Table Associations and Propagations

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', 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.

**Propagation** — The automatic advertisement of routes from an attachment to a route table, allowing the route table to learn about available network destinations.
6 changes: 5 additions & 1 deletion packages/@aws-cdk/aws-ec2-alpha/awslint.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"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",
"from-method:@aws-cdk/aws-ec2-alpha.TransitGatewayVpcAttachment"
]
}
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-ec2-alpha/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,11 @@ 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-association';
export * from './transit-gateway-route-table-association';
export * from './transit-gateway-route-table-propagation';
20 changes: 20 additions & 0 deletions packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-association.ts
Original file line number Diff line number Diff line change
@@ -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;
}
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-ec2-alpha/lib/transit-gateway-attachment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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.
* @attribute
*/
readonly transitGatewayAttachmentId: string;
}

/**
* A Transit Gateway Attachment.
* @internal
*/
export abstract class TransitGatewayAttachmentBase extends Resource implements ITransitGatewayAttachment {
paulhcsun marked this conversation as resolved.
Show resolved Hide resolved
public abstract readonly transitGatewayAttachmentId: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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 ITransitGatewayAssociation {}

/**
* Common properties for a Transit Gateway Route Table Association.
*/
export interface TransitGatewayRouteTableAssociationProps {
/**
* The ID of the transit gateway route table association.
*/
readonly transitGatewayVpcAttachment: ITransitGatewayAttachment;

/**
* The ID of the transit gateway route table association.
*/
readonly transitGatewayRouteTable: ITransitGatewayRouteTable;

/**
* Physical name of this association.
*
* @default - Assigned by CloudFormation.
*/
readonly transitGatewayRouteTableAssociationName?: string;
}

/**
* Create a Transit Gateway Route Table Association.
*
* @resource AWS::EC2::TransitGatewayRouteTableAssociation
*/
export class TransitGatewayRouteTableAssociation extends TransitGatewayAssociationBase {
/**
* The ID of the transit gateway route table association.
*/
public readonly transitGatewayAssociationId: string;

constructor(scope: Construct, id: string, props: TransitGatewayRouteTableAssociationProps) {
super(scope, id);

const resource = new CfnTransitGatewayRouteTableAssociation(this, id, {
transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId,
transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId,
});
this.node.defaultChild = resource;

this.transitGatewayAssociationId = resource.ref;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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';

/**
* Represents a Transit Gateway Route Table Propagation.
*/
export interface ITransitGatewayRouteTablePropagation extends IResource {
/**
* The ID of the transit gateway route table propagation.
* @attribute
*/
readonly transitGatewayRouteTablePropagationId: string;
}

/**
* Common properties for a Transit Gateway Route Table Propagation.
*/
export interface TransitGatewayRouteTablePropagationProps {
/**
* The ID of the transit gateway route table propagation.
*/
readonly transitGatewayVpcAttachment: ITransitGatewayAttachment;

/**
* The ID of the transit gateway route table propagation.
*/
readonly transitGatewayRouteTable: ITransitGatewayRouteTable;

/**
* Physical name of this propagation.
*
* @default - Assigned by CloudFormation.
*/
readonly transitGatewayRouteTablePropagationName?: string;
}

/**
* Create a Transit Gateway Route Table Propagation.
*
* @resource AWS::EC2::TransitGatewayRouteTablePropagation
*/
export class TransitGatewayRouteTablePropagation extends Resource implements ITransitGatewayRouteTablePropagation {
/**
* 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, id, {
transitGatewayAttachmentId: props.transitGatewayVpcAttachment.transitGatewayAttachmentId,
transitGatewayRouteTableId: props.transitGatewayRouteTable.routeTableId,
});
this.node.defaultChild = resource;

this.transitGatewayRouteTablePropagationId = resource.ref;
}
}
Loading
Loading