Last active
May 1, 2023 21:57
-
-
Save it-am/3185d3f0c6e8afcd3664f9b195e7c70a to your computer and use it in GitHub Desktop.
Python script with troposphere library which creates CloudFormation template for you (VPC, Subnets, IGW, NAT etc.)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import troposphere.ec2 as ec2 | |
from troposphere import Ref, Template, Tags, GetAtt | |
from troposphere.ec2 import Route, VPCGatewayAttachment, SubnetRouteTableAssociation, \ | |
Subnet, RouteTable, VPC, SubnetNetworkAclAssociation, EIP, InternetGateway | |
#user input requests | |
input_tag = input('Tag (name tag of each aws resource will include it)(ex.: projectx): ').lower() | |
input_aws_region = input('AWS region (ex.: us-east-1): ') | |
input_vpc_cidr = input('VPC CIDR (ex.: 10.0.0.0/16): ') | |
input_pub_az_amount = int(input('In how many different AZs you want to create PUBLIC subnets? (max. 3): ')) | |
input_pri_az_amount = int(input('In how many different AZs you want to create PRIVATE subnets? (max. 3): ')) | |
t = Template() | |
t.set_version('2010-09-09') | |
t.set_description('AWS CloudFormation VPC Custom Template') | |
ref_stack_id = Ref('AWS::StackId') | |
ref_region = Ref('AWS::Region') | |
ref_stack_name = Ref('AWS::StackName') | |
#Create VPC | |
VPC = t.add_resource( | |
VPC( | |
'VPC', | |
CidrBlock=input_vpc_cidr, | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag+'-vpc' | |
))) | |
#Create Internet Gateway | |
internetGateway = t.add_resource( | |
InternetGateway( | |
'InternetGateway', | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag+'-ig' | |
))) | |
#Attach Internet Gateway to the VPC | |
gatewayAttachment = t.add_resource( | |
VPCGatewayAttachment( | |
'AttachGateway', | |
VpcId=Ref(VPC), | |
InternetGatewayId=Ref(internetGateway))) | |
#Create default Main Public RouteTable | |
mainRouteTable = t.add_resource( | |
RouteTable( | |
'MainRouteTable', | |
VpcId=Ref(VPC), | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag+'-PublicRouteTable-Main' | |
))) | |
#Create default route 0.0.0.0/0 in the Public RouteTable | |
route = t.add_resource( | |
Route( | |
'Route', | |
DependsOn='AttachGateway', | |
GatewayId=Ref('InternetGateway'), | |
DestinationCidrBlock='0.0.0.0/0', | |
RouteTableId=Ref(mainRouteTable), | |
)) | |
#Create Public Subnets and associate them with MainRouteTable | |
for i in range(input_pub_az_amount): | |
if i == 0: AZ = input_aws_region+'a' | |
elif i == 1: AZ = input_aws_region+'b' | |
elif i == 2: AZ = input_aws_region+'c' | |
input_number_of_public_subnets = int(input('How many PUBLIC subnets in ' + AZ + ' AZ you need?: ')) #user input request | |
while input_number_of_public_subnets > 0: | |
subnet_logical_id = 'PubSubnet' + str(input_number_of_public_subnets) + AZ.replace("-", "") | |
input_number_of_public_subnets -= 1 | |
input_pub_subnet_cidr = input('Public Subnet ' + subnet_logical_id + ' desired CIDR (ex. 10.0.1.0/24): ') #user input request | |
#Create Public Subnet | |
subnet = t.add_resource( | |
Subnet( | |
subnet_logical_id, | |
CidrBlock=input_pub_subnet_cidr, | |
VpcId=Ref(VPC), | |
AvailabilityZone=AZ, | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + subnet_logical_id | |
))) | |
#Create RouteTable Association (MAIN) | |
UniqueSubnetRouteTableAssociation = 'SubnetRouteTableAssociation' + subnet_logical_id | |
subnetRouteTableAssociation = t.add_resource( | |
SubnetRouteTableAssociation( | |
UniqueSubnetRouteTableAssociation, | |
SubnetId=Ref(subnet), | |
RouteTableId=Ref(mainRouteTable), | |
)) | |
#user input request | |
input_nat_gateway_option = int(input('''Please choose option "1" or "2". | |
- Option#1: create only one NAT Gateway per each AZ | |
- Option#2: create a separate NAT Gateway for each private subnet: ''')) | |
#Create Private Subnets | |
for i in range(input_pri_az_amount): | |
if i == 0: AZ = input_aws_region+'a' | |
elif i == 1: AZ = input_aws_region+'b' | |
elif i == 2: AZ = input_aws_region+'c' | |
#Create Public Subnet for NATGateway | |
subnet_logical_id = 'PubSubnetNAT' + AZ.replace("-", "") | |
input_pub_subnet_cidr = input('Public Subnet ' + subnet_logical_id + ' desired CIDR (ex. 10.0.100.0/28): ') #user input request | |
public_nat_net = t.add_resource( | |
Subnet( | |
subnet_logical_id, | |
CidrBlock=input_pub_subnet_cidr, | |
VpcId=Ref(VPC), | |
AvailabilityZone=AZ, | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + subnet_logical_id | |
))) | |
#Create RouteTable Association (MAIN) | |
UniqueSubnetRouteTableAssociation = 'SubnetRouteTableAssociation' + subnet_logical_id | |
subnetRouteTableAssociation = t.add_resource( | |
SubnetRouteTableAssociation( | |
UniqueSubnetRouteTableAssociation, | |
SubnetId=Ref(public_nat_net), | |
RouteTableId=Ref(mainRouteTable), | |
)) | |
#Create NAT Gateway - one per each AZ | |
if input_nat_gateway_option == 1: | |
#Allocate EIP | |
UniqueNatEipName = 'NatEip' + AZ.replace("-", "") | |
nat_eip = t.add_resource(ec2.EIP( | |
UniqueNatEipName, | |
Domain="vpc", | |
)) | |
#Create NAT Gateway | |
UniqueNatGatewayName = 'NAT' + AZ.replace("-", "") | |
nat = t.add_resource(ec2.NatGateway( | |
UniqueNatGatewayName, | |
AllocationId=GetAtt(nat_eip, 'AllocationId'), | |
SubnetId=Ref(public_nat_net), | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + UniqueNatGatewayName | |
))) | |
input_number_of_private_subnets = int(input('How many PRIVATE subnets in ' + AZ + ' AZ you need?: ')) #user input request | |
while input_number_of_private_subnets > 0: | |
subnet_logical_id = 'PriSubnet' + str(input_number_of_private_subnets) + AZ.replace("-", "") | |
input_number_of_private_subnets -= 1 | |
input_pri_subnet_cidr = input('Private Subnet ' + subnet_logical_id + ' desired CIDR (ex. 10.0.10.0/24): ') | |
#Create Private Subnet | |
subnet = t.add_resource( | |
Subnet( | |
subnet_logical_id, | |
CidrBlock=input_pri_subnet_cidr, | |
VpcId=Ref(VPC), | |
AvailabilityZone=AZ, | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + subnet_logical_id | |
))) | |
#Create RouteTable for each private subnet | |
UniqueRouteTableName = 'PrivateRouteTable' + subnet_logical_id | |
privateRouteTable = t.add_resource( | |
RouteTable( | |
UniqueRouteTableName, | |
VpcId=Ref(VPC), | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + UniqueRouteTableName | |
))) | |
#Create RouteTable Association for each private subnet | |
UniqueSubnetRouteTableAssociation = 'SubnetRouteTableAssociation' + subnet_logical_id | |
subnetRouteTableAssociation = t.add_resource( | |
SubnetRouteTableAssociation( | |
UniqueSubnetRouteTableAssociation, | |
SubnetId=Ref(subnet), | |
RouteTableId=Ref(privateRouteTable), | |
)) | |
if input_nat_gateway_option == 1: | |
#Add default route NAT | |
UniqueNatRouteName = 'NATRoute' + subnet_logical_id | |
route = t.add_resource( | |
Route( | |
UniqueNatRouteName, | |
DependsOn=UniqueNatGatewayName, | |
NatGatewayId=Ref(UniqueNatGatewayName), | |
DestinationCidrBlock='0.0.0.0/0', | |
RouteTableId=Ref(UniqueRouteTableName), | |
)) | |
elif input_nat_gateway_option == 2: | |
#Allocate EIP for new NAT Gateway | |
UniqueNatEipName = 'NatEip' + subnet_logical_id | |
nat_eip = t.add_resource(ec2.EIP( | |
UniqueNatEipName, | |
Domain="vpc", | |
)) | |
#Create NAT Gateway for each private subnet | |
UniqueNatGatewayName = 'NATGateway' + subnet_logical_id | |
nat = t.add_resource(ec2.NatGateway( | |
UniqueNatGatewayName, | |
AllocationId=GetAtt(nat_eip, 'AllocationId'), | |
SubnetId=Ref(public_nat_net), | |
Tags=Tags( | |
Application=ref_stack_id, | |
Name=input_tag + '-' + UniqueNatGatewayName | |
))) | |
#Add default route NAT | |
UniqueNatRouteName = 'NATRoute' + subnet_logical_id | |
route = t.add_resource( | |
Route( | |
UniqueNatRouteName, | |
DependsOn=UniqueNatGatewayName, | |
NatGatewayId=Ref(UniqueNatGatewayName), | |
DestinationCidrBlock='0.0.0.0/0', | |
RouteTableId=Ref(UniqueRouteTableName), | |
)) | |
input_json_or_yaml = input('Get CF template in JSON or YAML format? (ex.: yaml, json, both): ') | |
if input_json_or_yaml.lower() == 'yaml': | |
print('---YAML-CF-TEMPLATE-START----\n') | |
print(t.to_yaml()) | |
print('---YAML-CF-TEMPLATE-END----') | |
elif input_json_or_yaml.lower() == 'json': | |
print('---JSON-CF-TEMPLATE-START----\n') | |
print(t.to_json()) | |
print('---JSON-CF-TEMPLATE-START----') | |
elif input_json_or_yaml.lower() == 'both': | |
print('---YAML-CF-TEMPLATE-START----\n') | |
print(t.to_yaml()) | |
print('---YAML-CF-TEMPLATE-END----\n') | |
print('---JSON-CF-TEMPLATE-START----\n') | |
print(t.to_json()) | |
print('---JSON-CF-TEMPLATE-START----') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment