Skip to content

Commit

Permalink
ec2_eip: add support of updating reverse dns record for eip (#2292)
Browse files Browse the repository at this point in the history
SUMMARY

Add support of updating reverse dns record for eip
Fixes #1296

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

ec2_eip
ADDITIONAL INFORMATION


https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2/client/modify_address_attribute.html

Reviewed-by: Bikouo Aubin
Reviewed-by: Mandar Kulkarni <[email protected]>
Reviewed-by: Alina Buzachis
Reviewed-by: GomathiselviS
  • Loading branch information
mandar242 committed Sep 27, 2024
1 parent 8592624 commit efcaf86
Show file tree
Hide file tree
Showing 6 changed files with 426 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- ec2_eip - Add support to update reverse DNS record of an EIP (https://github.com/ansible-collections/amazon.aws/pull/2292).
113 changes: 113 additions & 0 deletions plugins/modules/ec2_eip.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
- Allocates the new Elastic IP from the provided public IPv4 pool (BYOIP)
only applies to newly allocated Elastic IPs, isn't validated when O(reuse_existing_ip_allowed=true).
type: str
domain_name:
description: The domain name to attach to the IP address.
required: false
type: str
version_added: 8.3.0
extends_documentation_fragment:
- amazon.aws.common.modules
- amazon.aws.region.modules
Expand Down Expand Up @@ -201,6 +206,23 @@
tag_name: reserved_for
tag_value: "{{ inventory_hostname }}"
public_ipv4_pool: ipv4pool-ec2-0588c9b75a25d1a02
- name: create new IP and modify it's reverse DNS record
amazon.aws.ec2_eip:
state: present
domain_name: test-domain.xyz
- name: Modify reverse DNS record of an existing EIP
amazon.aws.ec2_eip:
public_ip: 44.224.84.105
domain_name: test-domain.xyz
state: present
- name: Remove reverse DNS record of an existing EIP
amazon.aws.ec2_eip:
public_ip: 44.224.84.105
domain_name: ""
state: present
"""

RETURN = r"""
Expand All @@ -214,6 +236,46 @@
returned: on success
type: str
sample: 52.88.159.209
update_reverse_dns_record_result:
description: Information about result of update reverse dns record operation.
returned: When O(domain_name) is specified.
type: dict
contains:
address:
description: Information about the Elastic IP address.
returned: always
type: dict
contains:
allocation_id:
description: The allocation ID.
returned: always
type: str
sample: "eipalloc-00a11aa111aaa1a11"
ptr_record:
description: The pointer (PTR) record for the IP address.
returned: always
type: str
sample: "ec2-11-22-33-44.us-east-2.compute.amazonaws.com."
ptr_record_update:
description: The updated PTR record for the IP address.
returned: always
type: dict
contains:
status:
description: The status of the PTR record update.
returned: always
type: str
sample: "PENDING"
value:
description: The value for the PTR record update.
returned: always
type: str
sample: "example.com"
public_ip:
description: The public IP address.
returned: always
type: str
sample: "11.22.33.44"
"""

from typing import Any
Expand All @@ -223,6 +285,8 @@
from typing import Tuple
from typing import Union

from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict

from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AnsibleEC2Error
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import allocate_address as allocate_ip_address
from ansible_collections.amazon.aws.plugins.module_utils.ec2 import associate_address
Expand Down Expand Up @@ -410,6 +474,7 @@ def ensure_present(
public_ipv4_pool = module.params.get("public_ipv4_pool")
tags = module.params.get("tags")
purge_tags = module.params.get("purge_tags")
domain_name = module.params.get("domain_name")

# Tags for *searching* for an EIP.
search_tags = generate_tag_dict(module)
Expand All @@ -422,6 +487,12 @@ def ensure_present(
client, module.check_mode, search_tags, domain, reuse_existing_ip_allowed, tags, public_ipv4_pool
)

if domain_name is not None:
changed, update_reverse_dns_record_result = update_reverse_dns_record_of_eip(
client, module, address, domain_name
)
result.update({"update_reverse_dns_record_result": update_reverse_dns_record_result})

# Associate address to instance
if device_id:
# Find instance
Expand Down Expand Up @@ -462,13 +533,55 @@ def ensure_present(
client, module, address["AllocationId"], resource_type="elastic-ip", tags=tags, purge_tags=purge_tags
)
result.update({"public_ip": address["PublicIp"], "allocation_id": address["AllocationId"]})

result["changed"] = changed
return result


def update_reverse_dns_record_of_eip(client, module: AnsibleAWSModule, address, domain_name):
if module.check_mode:
return True, {}

current_ptr_record_domain = client.describe_addresses_attribute(
AllocationIds=[address["AllocationId"]], Attribute="domain-name"
)

if (
current_ptr_record_domain["Addresses"]
and current_ptr_record_domain["Addresses"][0]["PtrRecord"] == domain_name + "."
):
return False, {"ptr_record": domain_name + "."}

if len(domain_name) == 0:
try:
update_reverse_dns_record_result = client.reset_address_attribute(
AllocationId=address["AllocationId"], Attribute="domain-name"
)
changed = True
except AnsibleEC2Error as e:
module.fail_json_aws_error(e)

if "ResponseMetadata" in update_reverse_dns_record_result:
del update_reverse_dns_record_result["ResponseMetadata"]
else:
try:
update_reverse_dns_record_result = client.modify_address_attribute(
AllocationId=address["AllocationId"], DomainName=domain_name
)
changed = True
except AnsibleEC2Error as e:
module.fail_json_aws_error(e)

if "ResponseMetadata" in update_reverse_dns_record_result:
del update_reverse_dns_record_result["ResponseMetadata"]

return changed, camel_dict_to_snake_dict(update_reverse_dns_record_result)


def main():
argument_spec = dict(
device_id=dict(required=False),
domain_name=dict(required=False, type="str"),
public_ip=dict(required=False, aliases=["ip"]),
state=dict(required=False, default="present", choices=["present", "absent"]),
in_vpc=dict(required=False, type="bool", default=False),
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/targets/ec2_eip/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ eip_test_tags:
AnsibleEIPTestPrefix: "{{ resource_prefix }}"
eip_info_filters:
tag:AnsibleEIPTestPrefix: "{{ resource_prefix }}"
test_domain: "{{ resource_prefix }}.example.xyz"
test_hosted_zone: "{{ resource_prefix }}.example.xyz"
3 changes: 3 additions & 0 deletions tests/integration/targets/ec2_eip/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
- ansible.builtin.include_tasks: tasks/attach_detach_to_eni.yml
- ansible.builtin.include_tasks: tasks/attach_detach_to_instance.yml

# Disabled as it requires a registered domain, and corresponding hosted zone
# - ansible.builtin.include_tasks: tasks/update_reverse_dns_record.yml

always:
- ansible.builtin.include_tasks: tasks/teardown.yml
117 changes: 117 additions & 0 deletions tests/integration/targets/ec2_eip/tasks/update_reverse_dns_record.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
- name: Test EIP allocation and reverse DNS record operations
block:
# ------------------------------------------------------------------------------------------
# Allocate EIP with reverse DNS record - check mode
# ------------------------------------------------------------------------------------------
- name: Allocate a new EIP and modify it's reverse DNS record - check_mode
amazon.aws.ec2_eip:
state: present
domain_name: "{{ test_domain }}"
tags: "{{ eip_test_tags }}"
register: eip
check_mode: true

- name: Assert that task result was as expected
ansible.builtin.assert:
that:
- eip is changed

- name: Ensure no new EIP was created
ansible.builtin.include_tasks: tasks/common.yml
vars:
has_no_new_eip: true

# ------------------------------------------------------------------------------------------
# Allocate EIP with reverse DNS record
# ------------------------------------------------------------------------------------------
- name: Allocate a new EIP and modify it's reverse DNS record
amazon.aws.ec2_eip:
state: present
domain_name: "{{ test_domain }}"
tags: "{{ eip_test_tags }}"
register: eip

- name: Add EIP IP address an A record
amazon.aws.route53:
state: present
zone: "{{ test_hosted_zone }}"
record: "{{ test_domain }}"
type: A
ttl: 7200
value: "{{ eip.public_ip}}"
identifier: "{{ resource_prefix }}"
wait: true

- name: Wait for reverse DNS record update to complete
pause:
minutes: 3

- name: Assert that task result was as expected
ansible.builtin.assert:
that:
- eip is changed
- eip.public_ip is defined and ( eip.public_ip | ansible.utils.ipaddr )
- eip.allocation_id is defined and eip.allocation_id.startswith("eipalloc-")
- eip.update_reverse_dns_record_result is defined
- eip.update_reverse_dns_record_result.address.ptr_record_update is defined
- eip.update_reverse_dns_record_result.address.ptr_record_update.value == "{{ test_domain }}."

# ------------------------------------------------------------------------------------------
# Allocate EIP with reverse DNS record - idempotence
# ------------------------------------------------------------------------------------------
- name: Try modifying reverse DNS record of EIP to same domain as current - Idempotent
amazon.aws.ec2_eip:
state: present
public_ip: "{{ eip.public_ip }}"
domain_name: "{{ test_domain }}"
tags: "{{ eip_test_tags }}"
register: eip

- name: Assert that task result was as expected
ansible.builtin.assert:
that:
- eip is not changed
- eip.public_ip is defined and ( eip.public_ip | ansible.utils.ipaddr )
- eip.allocation_id is defined and eip.allocation_id.startswith("eipalloc-")
- eip.update_reverse_dns_record_result is defined
- eip.update_reverse_dns_record_result.ptr_record == "{{ test_domain }}."

# ------------------------------------------------------------------------------------------
# Update reverse DNS record of existing EIP - remove reverse DNS record
# ------------------------------------------------------------------------------------------
- name: Try modifying reverse DNS record of EIP to different domain than current
amazon.aws.ec2_eip:
state: present
public_ip: "{{ eip.public_ip }}"
domain_name: ""
tags: "{{ eip_test_tags }}"
register: eip

- name: Assert that changes were applied
ansible.builtin.assert:
that:
- eip is changed
- eip.public_ip is defined and ( eip.public_ip | ansible.utils.ipaddr )
- eip.allocation_id is defined and eip.allocation_id.startswith("eipalloc-")

- name: Wait for reverse DNS record update to complete
pause:
minutes: 3

always:

- name: Delete EIP IP address an A record
amazon.aws.route53:
state: present
zone: "{{ test_hosted_zone }}"
record: "{{ test_domain }}"
type: A
ttl: 7200
value: "{{ eip.public_ip}}"
identifier: "{{ resource_prefix }}"
wait: true

- name: Delete EIP
ansible.builtin.include_tasks: tasks/common.yml
vars:
delete_eips: true
Loading

0 comments on commit efcaf86

Please sign in to comment.