@ttoss/cloud-vpc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +34 -0
- package/dist/esm/index.js +227 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +259 -0
- package/package.json +48 -0
- package/src/index.ts +258 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { CloudFormationTemplate } from '@ttoss/cloudformation';
|
|
2
|
+
|
|
3
|
+
const NUMBER_OF_AVAILABILITY_ZONES = 3;
|
|
4
|
+
|
|
5
|
+
const PUBLIC_ROUTER_TABLE_LOGICAL_ID = 'PublicRouteTable';
|
|
6
|
+
|
|
7
|
+
const PRIVATE_ROUTER_TABLE_LOGICAL_ID = 'PrivateRouteTable';
|
|
8
|
+
|
|
9
|
+
export const createVpcTemplate = ({
|
|
10
|
+
cidrBlock,
|
|
11
|
+
createPublicSubnets = true,
|
|
12
|
+
}: {
|
|
13
|
+
cidrBlock: string;
|
|
14
|
+
createPublicSubnets?: boolean;
|
|
15
|
+
}) => {
|
|
16
|
+
const totalOfSubnetsOnEachType = 2;
|
|
17
|
+
|
|
18
|
+
const getSubnetResource = ({
|
|
19
|
+
number,
|
|
20
|
+
isPublic,
|
|
21
|
+
}: {
|
|
22
|
+
number: number;
|
|
23
|
+
isPublic: boolean;
|
|
24
|
+
}) => {
|
|
25
|
+
const subnetType = isPublic ? 'Public' : 'Private';
|
|
26
|
+
|
|
27
|
+
const key = `${subnetType}Subnet${number}`;
|
|
28
|
+
|
|
29
|
+
const routerTableAssociationKey = `${subnetType}Subnet${number}RouteTableAssociation`;
|
|
30
|
+
|
|
31
|
+
const index = (isPublic ? 0 : 1) * totalOfSubnetsOnEachType + number - 1;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* It's because AWS infrastructure has a minimum of 3 availability zones
|
|
35
|
+
* in each region. So, we need to calculate the index of the availability
|
|
36
|
+
* zone based on the number of subnets and the type of subnet.
|
|
37
|
+
*
|
|
38
|
+
* https://aws.amazon.com/about-aws/global-infrastructure/regions_az/
|
|
39
|
+
*/
|
|
40
|
+
const azIndex = index % NUMBER_OF_AVAILABILITY_ZONES;
|
|
41
|
+
|
|
42
|
+
const cidrSubBlockCount = 2 * totalOfSubnetsOnEachType;
|
|
43
|
+
|
|
44
|
+
const cidrPrefixLength = parseInt(cidrBlock.split('/')[1], 10);
|
|
45
|
+
|
|
46
|
+
const cidrSubBlockBits =
|
|
47
|
+
32 - cidrPrefixLength - Math.ceil(Math.log2(cidrSubBlockCount));
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
let resources: any = {
|
|
51
|
+
[key]: {
|
|
52
|
+
Type: 'AWS::EC2::Subnet',
|
|
53
|
+
Properties: {
|
|
54
|
+
AvailabilityZone: {
|
|
55
|
+
'Fn::Select': [azIndex, { 'Fn::GetAZs': '' }],
|
|
56
|
+
},
|
|
57
|
+
CidrBlock: {
|
|
58
|
+
'Fn::Select': [
|
|
59
|
+
index,
|
|
60
|
+
{ 'Fn::Cidr': [cidrBlock, cidrSubBlockCount, cidrSubBlockBits] },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
MapPublicIpOnLaunch: isPublic,
|
|
64
|
+
VpcId: {
|
|
65
|
+
Ref: 'Vpc',
|
|
66
|
+
},
|
|
67
|
+
Tags: [
|
|
68
|
+
{
|
|
69
|
+
Key: 'Name',
|
|
70
|
+
Value: {
|
|
71
|
+
'Fn::Sub': `\${Project}-${subnetType.toLowerCase()}-subnet-${number}-\${AWS::Region}`,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
[routerTableAssociationKey]: {
|
|
78
|
+
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
79
|
+
Properties: {
|
|
80
|
+
RouteTableId: {
|
|
81
|
+
Ref: isPublic
|
|
82
|
+
? PUBLIC_ROUTER_TABLE_LOGICAL_ID
|
|
83
|
+
: PRIVATE_ROUTER_TABLE_LOGICAL_ID,
|
|
84
|
+
},
|
|
85
|
+
SubnetId: {
|
|
86
|
+
Ref: key,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (isPublic) {
|
|
93
|
+
resources = {
|
|
94
|
+
...resources,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!isPublic) {
|
|
99
|
+
resources = {
|
|
100
|
+
...resources,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return resources;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const template: CloudFormationTemplate = {
|
|
108
|
+
AWSTemplateFormatVersion: '2010-09-09',
|
|
109
|
+
Description: 'VPC, Subnets, and Route Tables for the project.',
|
|
110
|
+
Parameters: {
|
|
111
|
+
Project: {
|
|
112
|
+
Type: 'String',
|
|
113
|
+
Description: 'The name of the project',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
Resources: {
|
|
117
|
+
Vpc: {
|
|
118
|
+
Type: 'AWS::EC2::VPC',
|
|
119
|
+
Properties: {
|
|
120
|
+
CidrBlock: cidrBlock,
|
|
121
|
+
EnableDnsHostnames: true,
|
|
122
|
+
EnableDnsSupport: true,
|
|
123
|
+
Tags: [
|
|
124
|
+
{
|
|
125
|
+
Key: 'Name',
|
|
126
|
+
Value: {
|
|
127
|
+
'Fn::Sub': '${Project}-vpc',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
...getSubnetResource({ number: 1, isPublic: false }),
|
|
134
|
+
...getSubnetResource({ number: 2, isPublic: false }),
|
|
135
|
+
[PRIVATE_ROUTER_TABLE_LOGICAL_ID]: {
|
|
136
|
+
Type: 'AWS::EC2::RouteTable',
|
|
137
|
+
Properties: {
|
|
138
|
+
VpcId: {
|
|
139
|
+
Ref: 'Vpc',
|
|
140
|
+
},
|
|
141
|
+
Tags: [
|
|
142
|
+
{
|
|
143
|
+
Key: 'Name',
|
|
144
|
+
Value: {
|
|
145
|
+
'Fn::Sub': '${Project}-private-rtb',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
Outputs: {
|
|
153
|
+
DefaultSecurityGroup: {
|
|
154
|
+
Description: 'The default security group ID',
|
|
155
|
+
Value: {
|
|
156
|
+
'Fn::GetAtt': ['Vpc', 'DefaultSecurityGroup'],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
VpcId: {
|
|
160
|
+
Description: 'The VPC ID',
|
|
161
|
+
Value: {
|
|
162
|
+
Ref: 'Vpc',
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
PrivateSubnet1: {
|
|
166
|
+
Description: 'The private subnet 1 ID',
|
|
167
|
+
Value: {
|
|
168
|
+
Ref: 'PrivateSubnet1',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
PrivateSubnet2: {
|
|
172
|
+
Description: 'The private subnet 2 ID',
|
|
173
|
+
Value: {
|
|
174
|
+
Ref: 'PrivateSubnet2',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
if (createPublicSubnets) {
|
|
181
|
+
template.Resources = {
|
|
182
|
+
...template.Resources,
|
|
183
|
+
...getSubnetResource({ number: 1, isPublic: true }),
|
|
184
|
+
...getSubnetResource({ number: 2, isPublic: true }),
|
|
185
|
+
InternetGateway: {
|
|
186
|
+
Type: 'AWS::EC2::InternetGateway',
|
|
187
|
+
Properties: {
|
|
188
|
+
Tags: [
|
|
189
|
+
{
|
|
190
|
+
Key: 'Name',
|
|
191
|
+
Value: {
|
|
192
|
+
'Fn::Sub': '${Project}-igw',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
[PUBLIC_ROUTER_TABLE_LOGICAL_ID]: {
|
|
199
|
+
Type: 'AWS::EC2::RouteTable',
|
|
200
|
+
Properties: {
|
|
201
|
+
VpcId: {
|
|
202
|
+
Ref: 'Vpc',
|
|
203
|
+
},
|
|
204
|
+
Tags: [
|
|
205
|
+
{
|
|
206
|
+
Key: 'Name',
|
|
207
|
+
Value: {
|
|
208
|
+
'Fn::Sub': '${Project}-public-rtb',
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
InternetGatewayAttachment: {
|
|
215
|
+
Type: 'AWS::EC2::VPCGatewayAttachment',
|
|
216
|
+
Properties: {
|
|
217
|
+
InternetGatewayId: {
|
|
218
|
+
Ref: 'InternetGateway',
|
|
219
|
+
},
|
|
220
|
+
VpcId: {
|
|
221
|
+
Ref: 'Vpc',
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
PublicRoute: {
|
|
226
|
+
Type: 'AWS::EC2::Route',
|
|
227
|
+
DependsOn: 'InternetGatewayAttachment',
|
|
228
|
+
Properties: {
|
|
229
|
+
DestinationCidrBlock: '0.0.0.0/0',
|
|
230
|
+
GatewayId: {
|
|
231
|
+
Ref: 'InternetGateway',
|
|
232
|
+
},
|
|
233
|
+
RouteTableId: {
|
|
234
|
+
Ref: PUBLIC_ROUTER_TABLE_LOGICAL_ID,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
template.Outputs = {
|
|
241
|
+
...template.Outputs,
|
|
242
|
+
PublicSubnet1: {
|
|
243
|
+
Description: 'The public subnet 1 ID',
|
|
244
|
+
Value: {
|
|
245
|
+
Ref: 'PublicSubnet1',
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
PublicSubnet2: {
|
|
249
|
+
Description: 'The public subnet 2 ID',
|
|
250
|
+
Value: {
|
|
251
|
+
Ref: 'PublicSubnet2',
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return template;
|
|
258
|
+
};
|