Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
ELB Automatic resource naming
Browse files Browse the repository at this point in the history
This change removes settings LoadBalancerName manually and
uses the AWS auto naming instead. ELB names are now not
mandatory. (Closes #136)

- Add elb dns names as outputs
- Arbitrary elb logical ids
- Remove default security group for ELBs
- Pass troposphere template to elb function so that resources
and outputs can be set up internal to the function
- Check we have AutoScalingGroups before attaching to them
- Update tests for elb method requiring template
- Merge test:test_elb security group checks into overall cfg check
- PEP8 fixes
  • Loading branch information
Niall Creech committed Jul 23, 2015
1 parent 330cac6 commit 8c23f75
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 126 deletions.
85 changes: 46 additions & 39 deletions bootstrap_cfn/config.py
Expand Up @@ -68,10 +68,7 @@ def process(self):
map(template.add_resource, ec2)

if 'elb' in self.data:
elbs, sgs = self.elb()
map(template.add_resource, elbs)
map(template.add_resource, sgs)
template = self._attach_elbs(template)
self.elb(template)

if 'rds' in self.data:
rds = self.rds()
Expand Down Expand Up @@ -375,32 +372,43 @@ def rds(self):

return resources

def elb(self):
def elb(self, template):
# REQUIRED FIELDS AND MAPPING
required_fields = {
'listeners': 'Listeners',
'scheme': 'Scheme',
'name': 'LoadBalancerName',
'hosted_zone': 'HostedZoneName'
}

elb_list = []
elb_sgs = []
# COULD HAVE MULTIPLE ELB'S (PUBLIC / PRIVATE etc)
elb_count = 0
for elb in self.data['elb']:
safe_name = elb['name'].replace('-', '').replace('.', '').replace('_', '')
# Create a base logical id for our elb related resources.
# If an elb name has been specified, then use that,
# maintaining the previous behaviour
raw_name = ("%s-%s" % (self.stack_name, elb_count))
if 'name' in elb:
raw_name = elb['name']

base_name = raw_name.replace(".", "")
# Create a 'safe' version of the base_name for AWS use
safe_name = base_name.replace('-', '').replace('.', '').replace('_', '')

# TEST FOR REQUIRED FIELDS AND EXIT IF MISSING ANY
for i in required_fields.keys():
if i not in elb.keys():
print "\n\n[ERROR] Missing ELB fields [%s]" % i
sys.exit(1)

logging.debug("config:elb: Creating ELB resource with logical id '%s'"
% ("ELB" + safe_name))
load_balancer = LoadBalancer(
"ELB" + safe_name,
Subnets=[Ref("SubnetA"), Ref("SubnetB"), Ref("SubnetC")],
Listeners=elb['listeners'],
Scheme=elb['scheme'],
LoadBalancerName=self._get_elb_canonical_name(elb['name']),
ConnectionDrainingPolicy=ConnectionDrainingPolicy(
Enabled=True,
Timeout=120,
Expand All @@ -413,6 +421,7 @@ def elb(self):
)
]
)

if "health_check" in elb:
load_balancer.HealthCheck = HealthCheck(**elb['health_check'])

Expand Down Expand Up @@ -445,14 +454,16 @@ def elb(self):

elb_list.append(load_balancer)

logging.debug("config:elb: Creating DNS resource with logical id '%s'"
% ("DNS" + safe_name))
dns_record = RecordSetGroup(
"DNS" + safe_name,
HostedZoneName=elb['hosted_zone'],
Comment="Zone apex alias targeted to ElasticLoadBalancer.",
RecordSets=[
RecordSet(
"TitleIsIgnoredForThisResource",
Name="%s.%s" % (elb['name'], elb['hosted_zone']),
Name="%s.%s" % (raw_name, elb['hosted_zone']),
Type="A",
AliasTarget=AliasTarget(
GetAtt(load_balancer, "CanonicalHostedZoneNameID"),
Expand All @@ -463,9 +474,11 @@ def elb(self):
)
elb_list.append(dns_record)

logging.debug("config:elb: Creating Policy resource with logical id '%s'"
% ("Policy" + safe_name))
elb_role_policies = PolicyType(
"Policy" + safe_name,
PolicyName=safe_name+"BaseHost",
PolicyName=safe_name + 'BaseHost',
PolicyDocument={"Statement": [{
"Action": [
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
Expand All @@ -477,7 +490,8 @@ def elb(self):
Ref("AWS::Region"),
":",
Ref("AWS::AccountId"),
':loadbalancer/%s' % load_balancer.LoadBalancerName
':loadbalancer/',
Ref(load_balancer)
])
],
"Effect": "Allow"}
Expand All @@ -489,6 +503,8 @@ def elb(self):
if "security_groups" in elb:
load_balancer.SecurityGroups = []
for sg_name, sg_rules in elb['security_groups'].items():
logging.debug("config:elb: Creating Security Group resource with logical id '%s'"
% (sg_name))
sg = SecurityGroup(
sg_name,
GroupDescription=sg_name,
Expand All @@ -497,29 +513,20 @@ def elb(self):
)
load_balancer.SecurityGroups.append(Ref(sg))
elb_sgs.append(sg)
else:
sg = SecurityGroup(
"DefaultSG" + safe_name,
GroupDescription="DefaultELBSecurityGroup",
SecurityGroupIngress=[
{
"IpProtocol": "tcp",
"FromPort": 443,
"ToPort": 443,
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"CidrIp": "0.0.0.0/0"
}
],
VpcId=Ref("VPC")
)
load_balancer.SecurityGroups = [Ref(sg)]
elb_sgs.append(sg)
return elb_list, elb_sgs

# Add outputs
logging.debug("config:elb:Adding output to ELB '%s'"
% ("ELB" + safe_name))
template.add_output(Output(
"ELB" + safe_name,
Description="ELB DNSName",
Value=GetAtt(load_balancer, "DNSName")
))
# Update elb count
elb_count += 1
map(template.add_resource, elb_list)
map(template.add_resource, elb_sgs)
template = self._attach_elbs(template)

def _convert_ref_dict_to_objects(self, o):
"""
Expand Down Expand Up @@ -698,10 +705,10 @@ def _attach_elbs(self, template):
return template
asgs = self._find_resources(template,
'AWS::AutoScaling::AutoScalingGroup')
elbs = self._find_resources(template,
'AWS::ElasticLoadBalancing::LoadBalancer')

asgs[0].LoadBalancerNames = [x.LoadBalancerName for x in elbs]
template.resources[asgs[0].title] = asgs[0]
if len(asgs) > 0:
elbs = self._find_resources(template,
'AWS::ElasticLoadBalancing::LoadBalancer')
asgs[0].LoadBalancerNames = [Ref(x) for x in elbs]
template.resources[asgs[0].title] = asgs[0]

return template
10 changes: 10 additions & 0 deletions tests/sample-project.yaml
Expand Up @@ -43,6 +43,16 @@ dev:
- LoadBalancerPort: 443
InstancePort: 443
Protocol: TCP
security_groups:
TestSG:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- name: test-dev-internal
hosted_zone: kyrtest.pf.dsd.io.
scheme: internal
Expand Down

0 comments on commit 8c23f75

Please sign in to comment.