Commit 0e459f65 by Peter Sankauskas

First round of changes to the EIP module to get it to be able to work well…

First round of changes to the EIP module to get it to be able to work well inside a VPC, and to be able to delete EIPs as well
parent 1d090b5b
......@@ -47,6 +47,11 @@ options:
required: false
default: null
aliases: [ ec2_region ]
in_vpc:
description:
- allocate an EIP inside a VPC or not
required: false
default: false
requirements: [ "boto" ]
author: Lorin Hochstein <lorin@nimbisservices.com>
notes:
......@@ -81,6 +86,11 @@ EXAMPLES = '''
ec2_eip: "instance_id={{ item }}"
with_items: ec2.instance_ids
- name: allocate a new elastic IP inside a VPC in us-west-2
ec2_eip: region=us-west-2 in_vpc=yes
register: eip
- name: output the IP
debug: msg="Allocated IP inside a VPC is {{ eip.public_ip }}"
'''
try:
......@@ -122,23 +132,30 @@ def connect(ec2_url, ec2_secret_key, ec2_access_key, region):
return ec2
def associate_ip_and_instance(ec2, public_ip, instance_id, module):
if ip_is_associated_with_instance(ec2, public_ip, instance_id):
module.exit_json(changed=False, public_ip=public_ip)
def associate_ip_and_instance(ec2, address, instance_id, module):
if ip_is_associated_with_instance(ec2, address.public_ip, instance_id, module):
module.exit_json(changed=False, public_ip=address.public_ip)
# If we're in check mode, nothing else to do
if module.check_mode:
module.exit_json(changed=True)
res = ec2.associate_address(instance_id, public_ip)
try:
if address.domain == "vpc":
res = ec2.associate_address(instance_id, allocation_id=address.allocation_id)
else:
res = ec2.associate_address(instance_id, public_ip=address.public_ip)
except boto.exception.EC2ResponseError, e:
module.fail_json(msg=str(e))
if res:
module.exit_json(changed=True, public_ip=public_ip)
module.exit_json(changed=True, public_ip=address.public_ip)
else:
module.fail_json(msg="association failed")
def disassociate_ip_and_instance(ec2, public_ip, instance_id, module):
if not ip_is_associated_with_instance(ec2, public_ip, instance_id):
if not ip_is_associated_with_instance(ec2, public_ip, instance_id, module):
module.exit_json(changed=False, public_ip=public_ip)
# If we're in check mode, nothing else to do
......@@ -152,23 +169,66 @@ def disassociate_ip_and_instance(ec2, public_ip, instance_id, module):
module.fail_json(msg="disassociation failed")
def ip_is_associated_with_instance(ec2, public_ip, instance_id):
""" Check if the elastic IP is currently associated with the instance """
def find_address(ec2, public_ip, module):
""" Find an existing Elastic IP address """
try:
addresses = ec2.get_all_addresses([public_ip])
if addresses:
return addresses[0].instance_id == instance_id
except boto.exception.EC2ResponseError, e:
module.fail_json(msg=str(e.message))
return addresses[0]
def ip_is_associated_with_instance(ec2, public_ip, instance_id, module):
""" Check if the elastic IP is currently associated with the instance """
address = find_address(ec2, public_ip, module)
if address:
return address.instance_id == instance_id
else:
return False
def allocate_new_ip(ec2, module):
""" Allocate a new elastic IP and return the IP address"""
def allocate_address(ec2, domain, module):
""" Allocate a new elastic IP address 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)
return address
def release_address(ec2, public_ip, module):
""" Release a previously allocated elastic IP address """
address = find_address(ec2, public_ip, module)
# If we're in check mode, nothing else to do
if module.check_mode:
module.exit_json(change=True)
ec2_address = ec2.allocate_address()
return ec2_address.public_ip
res = address.release()
if res:
module.exit_json(changed=True)
else:
module.fail_json(msg="release failed")
def find_instance(ec2, instance_id, module):
""" Attempt to find the EC2 instance and return it """
try:
reservations = ec2.get_all_reservations(instance_ids=[instance_id])
except boto.exception.EC2ResponseError, e:
module.fail_json(msg=str(e))
if len(reservations) == 1:
instances = reservations[0].instances
if len(instances) == 1:
return instances[0]
module.fail_json(msg="could not find instance" + instance_id)
def main():
......@@ -181,7 +241,8 @@ def main():
ec2_url = dict(required=False, aliases=['EC2_URL']),
ec2_secret_key = dict(required=False, aliases=['EC2_SECRET_KEY'], no_log=True),
ec2_access_key = dict(required=False, aliases=['EC2_ACCESS_KEY']),
region = dict(required=False, aliases=['ec2_region'])
region = dict(required=False, aliases=['ec2_region']),
in_vpc = dict(required=False, choices=BOOLEANS, default=False),
),
supports_check_mode=True
)
......@@ -197,13 +258,26 @@ def main():
instance_id = module.params.get('instance_id')
public_ip = module.params.get('public_ip')
state = module.params.get('state')
in_vpc = module.params.get('in_vpc')
domain = "vpc" if in_vpc else None
if state == 'present':
if public_ip is None:
public_ip = allocate_new_ip(ec2, module)
if instance_id is None:
module.exit_json(changed=True, public_ip=public_ip)
associate_ip_and_instance(ec2, public_ip, instance_id, module)
address = allocate_address(ec2, domain, module)
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)
else:
address = find_address(ec2, public_ip, module)
associate_ip_and_instance(ec2, address, instance_id, module)
else:
if instance_id is None:
release_address(ec2, public_ip, module)
else:
disassociate_ip_and_instance(ec2, public_ip, instance_id, module)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment