From 5f1dd479540f4b5cc86ce0aeefca2dc73da7b142 Mon Sep 17 00:00:00 2001 From: Thomas van Noort Date: Fri, 15 Nov 2013 10:14:13 +0100 Subject: [PATCH 1/2] Allow for reuse of allocated but unassociated Elastic IPs. --- library/cloud/ec2_eip | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/library/cloud/ec2_eip b/library/cloud/ec2_eip index 1c5db8cf4c1..420f2cc9f97 100644 --- a/library/cloud/ec2_eip +++ b/library/cloud/ec2_eip @@ -53,6 +53,11 @@ options: required: false default: false version_added: "1.4" + reuse: + description: + - Reuse an EIP that is not associated to an instance (when available), instead of allocating a new one. + required: false + default: false requirements: [ "boto" ] author: Lorin Hochstein notes: @@ -198,13 +203,27 @@ def ip_is_associated_with_instance(ec2, public_ip, instance_id, module): return False -def allocate_address(ec2, domain, module): - """ Allocate a new elastic IP address and return it """ +def allocate_address(ec2, domain, module, reuse): + """ Allocate a new elastic IP address (when needed) and return it """ # If we're in check mode, nothing else to do if module.check_mode: module.exit_json(change=True) - address = ec2.allocate_address(domain=domain) + if reuse: + if domain: + domain_filter = { 'domain' : domain } + else: + domain_filter = { 'domain' : 'standard' } + all_addresses = ec2.get_all_addresses(filters=domain_filter) + + unassociated_addresses = filter(lambda a: a.instance_id is None, all_addresses) + if unassociated_addresses: + address = unassociated_addresses[0]; + else: + address = ec2.allocate_address(domain=domain) + else: + address = ec2.allocate_address(domain=domain) + return address @@ -252,6 +271,7 @@ def main(): ec2_access_key = dict(required=False, aliases=['EC2_ACCESS_KEY']), region = dict(required=False, aliases=['ec2_region']), in_vpc = dict(required=False, choices=BOOLEANS, default=False), + reuse = dict(required=False, choices=BOOLEANS, default=False), ), supports_check_mode=True ) @@ -272,18 +292,19 @@ def main(): state = module.params.get('state') in_vpc = module.params.get('in_vpc') domain = "vpc" if in_vpc else None + reuse = module.params.get('reuse'); if state == 'present': if public_ip is None: if instance_id is None: - address = allocate_address(ec2, domain, module) + address = allocate_address(ec2, domain, module, reuse) module.exit_json(changed=True, public_ip=address.public_ip) else: # Determine if the instance is inside a VPC or not instance = find_instance(ec2, instance_id, module) if instance.vpc_id != None: domain = "vpc" - address = allocate_address(ec2, domain, module) + address = allocate_address(ec2, domain, module, reuse) else: address = find_address(ec2, public_ip, module) associate_ip_and_instance(ec2, address, instance_id, module) From 2b84a40d8ef63977a307e5b2bec8206a05b9794e Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Tue, 11 Mar 2014 11:12:23 -0500 Subject: [PATCH 2/2] Renaming reuse parameter in ec2_eip and adding a version_added string --- library/cloud/ec2_eip | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/cloud/ec2_eip b/library/cloud/ec2_eip index 6d8f2e0d3ad..e6ecf091a48 100644 --- a/library/cloud/ec2_eip +++ b/library/cloud/ec2_eip @@ -75,11 +75,12 @@ options: default: null aliases: [] version_added: "1.6" - reuse: + reuse_existing_ip_allowed: description: - Reuse an EIP that is not associated to an instance (when available), instead of allocating a new one. required: false default: false + version_added: "1.6" requirements: [ "boto" ] author: Lorin Hochstein @@ -194,13 +195,13 @@ def ip_is_associated_with_instance(ec2, public_ip, instance_id, module): return False -def allocate_address(ec2, domain, module, reuse): +def allocate_address(ec2, domain, module, reuse_existing_ip_allowed): """ Allocate a new elastic IP address (when needed) and return it """ # If we're in check mode, nothing else to do if module.check_mode: module.exit_json(change=True) - if reuse: + if reuse_existing_ip_allowed: if domain: domain_filter = { 'domain' : domain } else: @@ -258,7 +259,7 @@ def main(): state = dict(required=False, default='present', choices=['present', 'absent']), in_vpc = dict(required=False, choices=BOOLEANS, default=False), - reuse = dict(required=False, choices=BOOLEANS, default=False), + reuse_existing_ip_allowed = dict(required=False, type='bool', default=False), ) ) @@ -277,19 +278,19 @@ def main(): state = module.params.get('state') in_vpc = module.params.get('in_vpc') domain = "vpc" if in_vpc else None - reuse = module.params.get('reuse'); + reuse_existing_ip_allowed = module.params.get('reuse_existing_ip_allowed'); if state == 'present': if public_ip is None: if instance_id is None: - address = allocate_address(ec2, domain, module, reuse) + address = allocate_address(ec2, domain, module, reuse_existing_ip_allowed) module.exit_json(changed=True, public_ip=address.public_ip) else: # Determine if the instance is inside a VPC or not instance = find_instance(ec2, instance_id, module) if instance.vpc_id != None: domain = "vpc" - address = allocate_address(ec2, domain, module, reuse) + address = allocate_address(ec2, domain, module, reuse_existing_ip_allowed) else: address = find_address(ec2, public_ip, module) associate_ip_and_instance(ec2, address, instance_id, module)