Allow an Elastic IP to be re-associated in ec2_eip (#27389)
Trying to associate an already-associated ElasticIP was failing. This is however supported by the `boto` method that is used under the hood, `associate_address`: To quote `boto` documentation: ``` This option to allow an Elastic IP address that is already associated with another networkinterface or instance to be re-associated with the specified instance or interface. ``` This defaults to False, both per backwards-compatibility and to mirror the boto default value. Fixes #27385
This commit is contained in:
parent
a6e27a903a
commit
d332367018
1 changed files with 32 additions and 8 deletions
|
@ -72,6 +72,13 @@ options:
|
||||||
required: False
|
required: False
|
||||||
default: None
|
default: None
|
||||||
version_added: "2.3"
|
version_added: "2.3"
|
||||||
|
allow_reassociation:
|
||||||
|
description:
|
||||||
|
- Specify this option to allow an Elastic IP address that is already associated with another
|
||||||
|
network interface or instance to be re-associated with the specified instance or interface.
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
version_added: "2.5"
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- aws
|
- aws
|
||||||
- ec2
|
- ec2
|
||||||
|
@ -101,6 +108,12 @@ EXAMPLES = '''
|
||||||
device_id: eni-c8ad70f3
|
device_id: eni-c8ad70f3
|
||||||
ip: 93.184.216.119
|
ip: 93.184.216.119
|
||||||
|
|
||||||
|
- name: associate an elastic IP with a device and allow reassociation
|
||||||
|
ec2_eip:
|
||||||
|
device_id: eni-c8ad70f3
|
||||||
|
public_ip: 93.184.216.119
|
||||||
|
allow_reassociation: yes
|
||||||
|
|
||||||
- name: disassociate an elastic IP from an instance
|
- name: disassociate an elastic IP from an instance
|
||||||
ec2_eip:
|
ec2_eip:
|
||||||
device_id: i-1212f003
|
device_id: i-1212f003
|
||||||
|
@ -167,7 +180,7 @@ class EIPException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def associate_ip_and_device(ec2, address, private_ip_address, device_id, check_mode, isinstance=True):
|
def associate_ip_and_device(ec2, address, private_ip_address, device_id, allow_reassociation, check_mode, isinstance=True):
|
||||||
if address_is_associated_with_device(ec2, address, device_id, isinstance):
|
if address_is_associated_with_device(ec2, address, device_id, isinstance):
|
||||||
return {'changed': False}
|
return {'changed': False}
|
||||||
|
|
||||||
|
@ -175,11 +188,20 @@ def associate_ip_and_device(ec2, address, private_ip_address, device_id, check_m
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
if isinstance:
|
if isinstance:
|
||||||
if address.domain == "vpc":
|
if address.domain == "vpc":
|
||||||
res = ec2.associate_address(device_id, allocation_id=address.allocation_id, private_ip_address=private_ip_address)
|
res = ec2.associate_address(device_id,
|
||||||
|
allocation_id=address.allocation_id,
|
||||||
|
private_ip_address=private_ip_address,
|
||||||
|
allow_reassociation=allow_reassociation)
|
||||||
else:
|
else:
|
||||||
res = ec2.associate_address(device_id, public_ip=address.public_ip, private_ip_address=private_ip_address)
|
res = ec2.associate_address(device_id,
|
||||||
|
public_ip=address.public_ip,
|
||||||
|
private_ip_address=private_ip_address,
|
||||||
|
allow_reassociation=allow_reassociation)
|
||||||
else:
|
else:
|
||||||
res = ec2.associate_address(network_interface_id=device_id, allocation_id=address.allocation_id, private_ip_address=private_ip_address)
|
res = ec2.associate_address(network_interface_id=device_id,
|
||||||
|
allocation_id=address.allocation_id,
|
||||||
|
private_ip_address=private_ip_address,
|
||||||
|
allow_reassociation=allow_reassociation)
|
||||||
if not res:
|
if not res:
|
||||||
raise EIPException('association failed')
|
raise EIPException('association failed')
|
||||||
|
|
||||||
|
@ -297,7 +319,7 @@ def find_device(ec2, module, device_id, isinstance=True):
|
||||||
|
|
||||||
|
|
||||||
def ensure_present(ec2, module, domain, address, private_ip_address, device_id,
|
def ensure_present(ec2, module, domain, address, private_ip_address, device_id,
|
||||||
reuse_existing_ip_allowed, check_mode, isinstance=True):
|
reuse_existing_ip_allowed, allow_reassociation, check_mode, isinstance=True):
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
# Return the EIP object since we've been given a public IP
|
# Return the EIP object since we've been given a public IP
|
||||||
|
@ -315,12 +337,12 @@ def ensure_present(ec2, module, domain, address, private_ip_address, device_id,
|
||||||
if instance.vpc_id and len(instance.vpc_id) > 0 and domain is None:
|
if instance.vpc_id and len(instance.vpc_id) > 0 and domain is None:
|
||||||
raise EIPException("You must set 'in_vpc' to true to associate an instance with an existing ip in a vpc")
|
raise EIPException("You must set 'in_vpc' to true to associate an instance with an existing ip in a vpc")
|
||||||
# Associate address object (provided or allocated) with instance
|
# Associate address object (provided or allocated) with instance
|
||||||
assoc_result = associate_ip_and_device(ec2, address, private_ip_address, device_id,
|
assoc_result = associate_ip_and_device(ec2, address, private_ip_address, device_id, allow_reassociation,
|
||||||
check_mode)
|
check_mode)
|
||||||
else:
|
else:
|
||||||
instance = find_device(ec2, module, device_id, isinstance=False)
|
instance = find_device(ec2, module, device_id, isinstance=False)
|
||||||
# Associate address object (provided or allocated) with instance
|
# Associate address object (provided or allocated) with instance
|
||||||
assoc_result = associate_ip_and_device(ec2, address, private_ip_address, device_id,
|
assoc_result = associate_ip_and_device(ec2, address, private_ip_address, device_id, allow_reassociation,
|
||||||
check_mode, isinstance=False)
|
check_mode, isinstance=False)
|
||||||
|
|
||||||
if instance.vpc_id:
|
if instance.vpc_id:
|
||||||
|
@ -359,6 +381,7 @@ def main():
|
||||||
reuse_existing_ip_allowed=dict(required=False, type='bool',
|
reuse_existing_ip_allowed=dict(required=False, type='bool',
|
||||||
default=False),
|
default=False),
|
||||||
release_on_disassociation=dict(required=False, type='bool', default=False),
|
release_on_disassociation=dict(required=False, type='bool', default=False),
|
||||||
|
allow_reassociation=dict(type='bool', default=False),
|
||||||
wait_timeout=dict(default=300),
|
wait_timeout=dict(default=300),
|
||||||
private_ip_address=dict(required=False, default=None, type='str')
|
private_ip_address=dict(required=False, default=None, type='str')
|
||||||
))
|
))
|
||||||
|
@ -382,6 +405,7 @@ def main():
|
||||||
domain = 'vpc' if in_vpc else None
|
domain = 'vpc' if in_vpc else None
|
||||||
reuse_existing_ip_allowed = module.params.get('reuse_existing_ip_allowed')
|
reuse_existing_ip_allowed = module.params.get('reuse_existing_ip_allowed')
|
||||||
release_on_disassociation = module.params.get('release_on_disassociation')
|
release_on_disassociation = module.params.get('release_on_disassociation')
|
||||||
|
allow_reassociation = module.params.get('allow_reassociation')
|
||||||
|
|
||||||
# Parameter checks
|
# Parameter checks
|
||||||
if private_ip_address is not None and device_id is None:
|
if private_ip_address is not None and device_id is None:
|
||||||
|
@ -408,7 +432,7 @@ def main():
|
||||||
if state == 'present':
|
if state == 'present':
|
||||||
if device_id:
|
if device_id:
|
||||||
result = ensure_present(ec2, module, domain, address, private_ip_address, device_id,
|
result = ensure_present(ec2, module, domain, address, private_ip_address, device_id,
|
||||||
reuse_existing_ip_allowed, module.check_mode, isinstance=is_instance)
|
reuse_existing_ip_allowed, allow_reassociation, module.check_mode, isinstance=is_instance)
|
||||||
else:
|
else:
|
||||||
if address:
|
if address:
|
||||||
changed = False
|
changed = False
|
||||||
|
|
Loading…
Reference in a new issue