From 88b1efa7be9718047afbbd7ec45b0a2b576705f5 Mon Sep 17 00:00:00 2001 From: Mike Buzzetti Date: Fri, 18 Apr 2014 09:59:35 -0400 Subject: [PATCH 1/3] Adds support for VPC subnets to ELB --- cloud/ec2_elb_lb | 112 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/cloud/ec2_elb_lb b/cloud/ec2_elb_lb index 5de76cb5df0..8603c7a5b76 100644 --- a/cloud/ec2_elb_lb +++ b/cloud/ec2_elb_lb @@ -66,6 +66,22 @@ options: - The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used. required: false aliases: ['aws_region', 'ec2_region'] + subnets: + description: + - A list of VPC subnets to use when creating ELB. Zones should be empty if using this. + required: false + default: None + aliases: [] + version_added: "1.6" + validate_certs: + description: + - When set to "no", SSL certificates will not be validated for boto versions >= 2.6.0. + required: false + default: "yes" + choices: ["yes", "no"] + aliases: [] + version_added: "1.5" + extends_documentation_fragment: aws """ @@ -92,6 +108,21 @@ EXAMPLES = """ # ssl certificate required for https or ssl ssl_certificate_id: "arn:aws:iam::123456789012:server-certificate/company/servercerts/ProdServerCert" + +# Basic VPC provisioning example +- local_action: + module: ec2_elb_lb + name: "test-vpc" + state: present + subnets: + zones: + - subnet-abcd1234 + - subnet-1a2b3c4d + listeners: + - protocol: http # options are http, https, ssl, tcp + load_balancer_port: 80 + instance_port: 80 + # Configure a health check - local_action: module: ec2_elb_lb @@ -149,6 +180,19 @@ EXAMPLES = """ load_balancer_port: 80 instance_port: 80 purge_zones: yes + +# Creates a ELB and assigns a list of subnets to it. +- local_action: + module: ec2_elb_lb + state: present + name: 'New ELB' + security_group_ids: 'sg-123456, sg-67890' + region: us-west-2 + subnets: 'subnet-123456, subnet-67890' + listeners: + - protocol: http + load_balancer_port: 80 + instance_port: 80 """ import sys @@ -168,8 +212,10 @@ class ElbManager(object): """Handles ELB creation and destruction""" def __init__(self, module, name, listeners=None, purge_listeners=None, - zones=None, purge_zones=None, security_group_ids=None, health_check=None, + zones=None, purge_zones=None, security_group_ids=None, + health_check=None, subnets=None, region=None, **aws_connect_params): + self.module = module self.name = name self.listeners = listeners @@ -178,6 +224,7 @@ class ElbManager(object): self.purge_zones = purge_zones self.security_group_ids = security_group_ids self.health_check = health_check + self.subnets = subnets self.aws_connect_params = aws_connect_params self.region = region @@ -196,6 +243,7 @@ class ElbManager(object): self._set_zones() self._set_security_groups() self._set_elb_listeners() + self._set_subnets() self._set_health_check() def ensure_gone(self): @@ -215,7 +263,8 @@ class ElbManager(object): 'dns_name': self.elb.dns_name, 'zones': self.elb.availability_zones, 'security_group_ids': self.elb.security_groups, - 'status': self.status + 'status': self.status, + 'subnets': self.subnets } if self.elb.health_check: @@ -266,7 +315,8 @@ class ElbManager(object): self.elb = self.elb_conn.create_load_balancer(name=self.name, zones=self.zones, security_groups=self.security_group_ids, - complex_listeners=listeners) + complex_listeners=listeners, + subnets=self.subnets) if self.elb: self.changed = True self.status = 'created' @@ -373,22 +423,42 @@ class ElbManager(object): self.elb_conn.disable_availability_zones(self.name, zones) self.changed = True + def _attach_subnets(self, subnets): + self.elb_conn.attach_lb_to_subnets(self.name, subnets) + self.changed = True + + def _detach_subnets(self, subnets): + self.elb_conn.detach_lb_from_subnets(self.name, subnets) + self.changed = True + + def _set_subnets(self): + """Determine which subnets need to be attached or detached on the ELB""" + if self.subnets: + subnets_to_detach = list(set(self.elb.subnets) - set(self.subnets)) + subnets_to_attach = list(set(self.subnets) - set(self.elb.subnets)) + + if subnets_to_attach: + self._attach_subnets(subnets_to_attach) + if subnets_to_detach: + self._detach_subnets(subnets_to_detach) + def _set_zones(self): """Determine which zones need to be enabled or disabled on the ELB""" - if self.purge_zones: - zones_to_disable = list(set(self.elb.availability_zones) - + if self.zones: + if self.purge_zones: + zones_to_disable = list(set(self.elb.availability_zones) - set(self.zones)) - zones_to_enable = list(set(self.zones) - - set(self.elb.availability_zones)) - else: - zones_to_disable = None - zones_to_enable = list(set(self.zones) - - set(self.elb.availability_zones)) - if zones_to_enable: - self._enable_zones(zones_to_enable) - # N.B. This must come second, in case it would have removed all zones - if zones_to_disable: - self._disable_zones(zones_to_disable) + zones_to_enable = list(set(self.zones) - + set(self.elb.availability_zones)) + else: + zones_to_disable = None + zones_to_enable = list(set(self.zones) - + set(self.elb.availability_zones)) + if zones_to_enable: + self._enable_zones(zones_to_enable) + # N.B. This must come second, in case it would have removed all zones + if zones_to_disable: + self._disable_zones(zones_to_disable) def _set_security_groups(self): if self.security_group_ids != None and set(self.elb.security_groups) != set(self.security_group_ids): @@ -447,6 +517,7 @@ def main(): purge_zones={'default': False, 'required': False, 'type': 'bool'}, security_group_ids={'default': None, 'required': False, 'type': 'list'}, health_check={'default': None, 'required': False, 'type': 'dict'}, + subnets={'default': None, 'required': False, 'type': 'list'} ) ) @@ -466,15 +537,16 @@ def main(): purge_zones = module.params['purge_zones'] security_group_ids = module.params['security_group_ids'] health_check = module.params['health_check'] + subnets = module.params['subnets'] if state == 'present' and not listeners: module.fail_json(msg="At least one port is required for ELB creation") - if state == 'present' and not zones: - module.fail_json(msg="At least one availability zone is required for ELB creation") + if state == 'present' and not (zones or subnets): + module.fail_json(msg="At least one availability zone or subnet is required for ELB creation") - elb_man = ElbManager(module, name, listeners, purge_listeners, zones, - purge_zones, security_group_ids, health_check, + elb_man = ElbManager(module, name, listeners, purge_listeners, zones, + purge_zones, security_group_ids, health_check, subnets, region=region, **aws_connect_params) if state == 'present': From 83507a90bcd0f78c8a7aed73855a06ff069706fb Mon Sep 17 00:00:00 2001 From: Mike Buzzetti Date: Mon, 21 Apr 2014 21:42:05 -0400 Subject: [PATCH 2/3] Adding support for purging subnets --- cloud/ec2_elb_lb | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/cloud/ec2_elb_lb b/cloud/ec2_elb_lb index 8603c7a5b76..d08db5f7571 100644 --- a/cloud/ec2_elb_lb +++ b/cloud/ec2_elb_lb @@ -72,7 +72,12 @@ options: required: false default: None aliases: [] - version_added: "1.6" + version_added: "1.6" + purge_subnets: + description: + - Purge existing subnet on ELB that are not found in subnets + required: false + default: false validate_certs: description: - When set to "no", SSL certificates will not be validated for boto versions >= 2.6.0. @@ -189,6 +194,7 @@ EXAMPLES = """ security_group_ids: 'sg-123456, sg-67890' region: us-west-2 subnets: 'subnet-123456, subnet-67890' + purge_subnets: yes listeners: - protocol: http load_balancer_port: 80 @@ -213,7 +219,7 @@ class ElbManager(object): def __init__(self, module, name, listeners=None, purge_listeners=None, zones=None, purge_zones=None, security_group_ids=None, - health_check=None, subnets=None, + health_check=None, subnets=None, purge_subnets=None, region=None, **aws_connect_params): self.module = module @@ -225,6 +231,7 @@ class ElbManager(object): self.security_group_ids = security_group_ids self.health_check = health_check self.subnets = subnets + self.purge_subnets = purge_subnets self.aws_connect_params = aws_connect_params self.region = region @@ -434,8 +441,12 @@ class ElbManager(object): def _set_subnets(self): """Determine which subnets need to be attached or detached on the ELB""" if self.subnets: - subnets_to_detach = list(set(self.elb.subnets) - set(self.subnets)) - subnets_to_attach = list(set(self.subnets) - set(self.elb.subnets)) + if self.purge_subnets: + subnets_to_detach = list(set(self.elb.subnets) - set(self.subnets)) + subnets_to_attach = list(set(self.subnets) - set(self.elb.subnets)) + else: + subnets_to_detach = None + subnets_to_attach = list(set(self.subnets) - set(self.elb.subnets)) if subnets_to_attach: self._attach_subnets(subnets_to_attach) @@ -517,7 +528,8 @@ def main(): purge_zones={'default': False, 'required': False, 'type': 'bool'}, security_group_ids={'default': None, 'required': False, 'type': 'list'}, health_check={'default': None, 'required': False, 'type': 'dict'}, - subnets={'default': None, 'required': False, 'type': 'list'} + subnets={'default': None, 'required': False, 'type': 'list'}, + purge_subnets={'default': False, 'required': False, 'type': 'bool'} ) ) @@ -538,6 +550,7 @@ def main(): security_group_ids = module.params['security_group_ids'] health_check = module.params['health_check'] subnets = module.params['subnets'] + purge_subnets = module.params['purge_subnets'] if state == 'present' and not listeners: module.fail_json(msg="At least one port is required for ELB creation") @@ -546,7 +559,8 @@ def main(): module.fail_json(msg="At least one availability zone or subnet is required for ELB creation") elb_man = ElbManager(module, name, listeners, purge_listeners, zones, - purge_zones, security_group_ids, health_check, subnets, + purge_zones, security_group_ids, health_check, + subnets, purge_subnets, region=region, **aws_connect_params) if state == 'present': From 657edc2116c3ee154218ab50ea8e2627c6f65eb5 Mon Sep 17 00:00:00 2001 From: Mike Buzzetti Date: Tue, 22 Apr 2014 09:27:26 -0400 Subject: [PATCH 3/3] Updated and corrected example section --- cloud/ec2_elb_lb | 1 - 1 file changed, 1 deletion(-) diff --git a/cloud/ec2_elb_lb b/cloud/ec2_elb_lb index d08db5f7571..eef5fb0dc01 100644 --- a/cloud/ec2_elb_lb +++ b/cloud/ec2_elb_lb @@ -120,7 +120,6 @@ EXAMPLES = """ name: "test-vpc" state: present subnets: - zones: - subnet-abcd1234 - subnet-1a2b3c4d listeners: