forked from AWSFrederick/Spires-Infra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
aws_frederick_ec2.py
156 lines (139 loc) · 5.79 KB
/
aws_frederick_ec2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from aws_frederick_common import AWSFrederickCommonTemplate
from troposphere import Ref, GetAtt, Base64, Join, Output, Template
from troposphere.policies import UpdatePolicy, AutoScalingRollingUpdate
import troposphere.elasticloadbalancingv2 as alb
import troposphere.constants as tpc
import troposphere.autoscaling as autoscaling
import troposphere.cloudwatch as cloudwatch
import troposphere.route53 as r53
class AWSFrederickEC2Template(AWSFrederickCommonTemplate):
"""
Enhances basic template by providing AWS Frederick EC2 resources
"""
# Collect all the values we need to assemble our SuperBowlOnARoll stack
def __init__(self, env_name, region, cidr_range, aws_frederick_config):
super(AWSFrederickEC2Template, self).__init__('AWSFrederickEC2')
self.env_name = env_name
self.region = region
self.cidr_range = cidr_range
self.config = aws_frederick_config
def build_hook(self):
print "Building Template for AWS Frederick EC2"
hosted_zone_name = self.config.get('hosted_zone')
ec2_config = self.config.get('ec2')
if ec2_config is not None:
self.add_ec2(
ec2_config.get('ami_id'),
ec2_config.get('instance_size'),
ec2_config.get('asg_size'),
self.cidr_range,
hosted_zone_name
)
def add_ec2(self, ami_name, instance_type, asg_size, cidr, hosted_zone):
"""
Helper method creates ingress given a source cidr range and a set of
ports
@param ami_name [string] Name of the AMI for launching the app
@param instance_type [string] Instance for the application
@param asg_size [int] Sets the size of the asg
@param cidr [string] Range of addresses for this vpc
@param hosted_zone [string] Name of the hosted zone the elb will be
mapped to
"""
print "Creating EC2"
self.internal_security_group = self.add_sg_with_cidr_port_list(
"ASGSG",
"Security Group for EC2",
'vpcId',
cidr,
[{"443": "443"}, {"80": "80"}]
)
self.public_lb_security_group = self.add_sg_with_cidr_port_list(
"ELBSG",
"Security Group for accessing EC2 publicly",
'vpcId',
'0.0.0.0/0',
[{"443": "443"}]
)
name = self.env_name.replace('-', '')
public_subnet_count = len(self._subnets.get('public').get('public'))
public_subnets = [{'Ref': x} for x in ["publicAZ%d" % n for n in range(0, public_subnet_count)]]
public_alb = self.add_resource(alb.LoadBalancer(
"PublicALB",
Scheme='internet-facing',
Subnets=public_subnets,
SecurityGroups=[Ref(sg) for sg in [self.public_lb_security_group]]
))
target_group = self.add_resource(alb.TargetGroup(
"AppTargetGroup80",
Port=80,
Protocol="HTTP",
VpcId=self.vpc_id
))
certificate = 'arn:aws:acm:us-east-1:422548007577:certificate/d9b8fbd2-13bb-4d6e-aba4-53061b1580f9'
alb_ssl_listener = self.add_resource(alb.Listener(
"ALBListner",
Port=443,
Certificates=[alb.Certificate(CertificateArn=certificate)],
Protocol="HTTPS",
DefaultActions=[alb.Action(
Type="forward",
TargetGroupArn=Ref(target_group))],
LoadBalancerArn=Ref(public_alb)
))
self.add_elb_dns_alias(public_alb, '', hosted_zone)
policies = ['cloudwatchlogs']
policies_for_profile = [self.get_policy(policy, 'EC2') for policy in policies]
asg = self.add_asg(
"EC2",
min_size=asg_size,
max_size=6,
ami_name=ami_name,
# load_balancer=public_elb,
instance_profile=self.add_instance_profile(name, policies_for_profile, name),
instance_type=instance_type,
security_groups=['commonSecurityGroup', Ref(self.internal_security_group)],
subnet_layer='private',
update_policy=UpdatePolicy(
AutoScalingRollingUpdate=AutoScalingRollingUpdate(
PauseTime='PT5M',
MinInstancesInService=1,
# The maximum number of instances that are terminated at a given time, left at 1 to ease into updates.
# Can be increased at a later time
MaxBatchSize='1'
)
),
user_data=Base64(Join('', [
'#!/bin/bash\n',
'echo Good to go'
])))
asg.resource['Properties']['TargetGroupARNs'] = [Ref(target_group)]
# Cluster Memory Scaling policies
asg_scale_up_policy = self.add_resource(
autoscaling.ScalingPolicy(
name + 'ScaleUpPolicy',
AdjustmentType='ChangeInCapacity',
AutoScalingGroupName=Ref(asg),
Cooldown=300,
ScalingAdjustment=1
)
)
# ELB latency above a threshold
self.add_resource(
cloudwatch.Alarm(
name + 'LatencyHigh',
MetricName='Latency',
ComparisonOperator='GreaterThanThreshold',
Period=300,
EvaluationPeriods=1,
Statistic='Average',
Namespace='AWS/ELB',
AlarmDescription=name + 'LatencyHigh',
Dimensions=[cloudwatch.MetricDimension(Name='LoadBalancerName', Value=Ref(public_alb))],
Threshold='6',
AlarmActions=[
Ref(asg_scale_up_policy),
'arn:aws:sns:us-east-1:422548007577:notify-pat'
]
)
)