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: ...@@ -47,6 +47,11 @@ options:
required: false required: false
default: null default: null
aliases: [ ec2_region ] aliases: [ ec2_region ]
in_vpc:
description:
- allocate an EIP inside a VPC or not
required: false
default: false
requirements: [ "boto" ] requirements: [ "boto" ]
author: Lorin Hochstein <lorin@nimbisservices.com> author: Lorin Hochstein <lorin@nimbisservices.com>
notes: notes:
...@@ -81,6 +86,11 @@ EXAMPLES = ''' ...@@ -81,6 +86,11 @@ EXAMPLES = '''
ec2_eip: "instance_id={{ item }}" ec2_eip: "instance_id={{ item }}"
with_items: ec2.instance_ids 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: try:
...@@ -122,23 +132,30 @@ def connect(ec2_url, ec2_secret_key, ec2_access_key, region): ...@@ -122,23 +132,30 @@ def connect(ec2_url, ec2_secret_key, ec2_access_key, region):
return ec2 return ec2
def associate_ip_and_instance(ec2, public_ip, instance_id, module): def associate_ip_and_instance(ec2, address, instance_id, module):
if ip_is_associated_with_instance(ec2, public_ip, instance_id): if ip_is_associated_with_instance(ec2, address.public_ip, instance_id, module):
module.exit_json(changed=False, public_ip=public_ip) module.exit_json(changed=False, public_ip=address.public_ip)
# If we're in check mode, nothing else to do # If we're in check mode, nothing else to do
if module.check_mode: if module.check_mode:
module.exit_json(changed=True) 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: if res:
module.exit_json(changed=True, public_ip=public_ip) module.exit_json(changed=True, public_ip=address.public_ip)
else: else:
module.fail_json(msg="association failed") module.fail_json(msg="association failed")
def disassociate_ip_and_instance(ec2, public_ip, instance_id, module): 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) module.exit_json(changed=False, public_ip=public_ip)
# If we're in check mode, nothing else to do # If we're in check mode, nothing else to do
...@@ -152,25 +169,68 @@ def disassociate_ip_and_instance(ec2, public_ip, instance_id, module): ...@@ -152,25 +169,68 @@ def disassociate_ip_and_instance(ec2, public_ip, instance_id, module):
module.fail_json(msg="disassociation failed") module.fail_json(msg="disassociation failed")
def ip_is_associated_with_instance(ec2, public_ip, instance_id): def find_address(ec2, public_ip, module):
""" Find an existing Elastic IP address """
try:
addresses = ec2.get_all_addresses([public_ip])
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 """ """ Check if the elastic IP is currently associated with the instance """
addresses = ec2.get_all_addresses([public_ip]) address = find_address(ec2, public_ip, module)
if addresses: if address:
return addresses[0].instance_id == instance_id return address.instance_id == instance_id
else: else:
return False return False
def allocate_new_ip(ec2, module): def allocate_address(ec2, domain, module):
""" Allocate a new elastic IP and return the IP address""" """ Allocate a new elastic IP address and return it """
# If we're in check mode, nothing else to do # If we're in check mode, nothing else to do
if module.check_mode: if module.check_mode:
module.exit_json(change=True) module.exit_json(change=True)
ec2_address = ec2.allocate_address() address = ec2.allocate_address(domain=domain)
return ec2_address.public_ip 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)
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(): def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec = dict( argument_spec = dict(
...@@ -181,7 +241,8 @@ def main(): ...@@ -181,7 +241,8 @@ def main():
ec2_url = dict(required=False, aliases=['EC2_URL']), ec2_url = dict(required=False, aliases=['EC2_URL']),
ec2_secret_key = dict(required=False, aliases=['EC2_SECRET_KEY'], no_log=True), ec2_secret_key = dict(required=False, aliases=['EC2_SECRET_KEY'], no_log=True),
ec2_access_key = dict(required=False, aliases=['EC2_ACCESS_KEY']), 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 supports_check_mode=True
) )
...@@ -197,15 +258,28 @@ def main(): ...@@ -197,15 +258,28 @@ def main():
instance_id = module.params.get('instance_id') instance_id = module.params.get('instance_id')
public_ip = module.params.get('public_ip') public_ip = module.params.get('public_ip')
state = module.params.get('state') state = module.params.get('state')
in_vpc = module.params.get('in_vpc')
domain = "vpc" if in_vpc else None
if state == 'present': if state == 'present':
if public_ip is None: if public_ip is None:
public_ip = allocate_new_ip(ec2, module)
if instance_id is None: if instance_id is None:
module.exit_json(changed=True, public_ip=public_ip) address = allocate_address(ec2, domain, module)
associate_ip_and_instance(ec2, public_ip, instance_id, 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: else:
disassociate_ip_and_instance(ec2, public_ip, instance_id, module) 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