Skip to content

Commit

Permalink
Refactor aws_az_region_info* modules (#2163)
Browse files Browse the repository at this point in the history
SUMMARY
Refactor aws_az_info,aws_region_info modules
ISSUE TYPE


Feature Pull Request

COMPONENT NAME


aws_az_info
aws_region_info

Reviewed-by: Alina Buzachis
  • Loading branch information
abikouo authored Jul 4, 2024
1 parent cf97514 commit 42675e2
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- aws_az_info - refactored code to use ``AnsibleEC2Error`` as well as moving shared code into module_utils.ec2 (https://github.com/ansible-collections/amazon.aws/pull/2163). - aws_region_info - refactored code to use ``AnsibleEC2Error`` as well as moving shared code into module_utils.ec2 (https://github.com/ansible-collections/amazon.aws/pull/2163).
22 changes: 22 additions & 0 deletions plugins/module_utils/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
from copy import deepcopy
from typing import Any
from typing import Callable
from typing import Dict
from typing import List
from typing import Mapping
from typing import Optional
from typing import Sequence
Expand Down Expand Up @@ -229,3 +231,23 @@ def boto3_resource_list_to_ansible_dict(
boto3_resource_to_ansible_dict(resource, transform_tags, force_tags, normalize, ignore_list, nested_transforms)
for resource in resource_list
]


def sanitize_filters_to_boto3_filter_list(
filters: Dict[str, Any], ignore_keys: Optional[List[str]] = None
) -> Dict[str, Any]:
"""
Replace filter key underscores with dashes, for compatibility and tranform ansible dict
into boto3 filter list.
:param filters: Ansible module params filters
:return: Sanitized filters
"""
sanitized_filters = deepcopy(filters)
for k, v in filters.items():
if ignore_keys and any((k.startswith(x) for x in ignore_keys)):
continue
if "_" in k:
sanitized_filters[k.replace("_", "-")] = v
del sanitized_filters[k]
return ansible_dict_to_boto3_filter_list(sanitized_filters)
21 changes: 7 additions & 14 deletions plugins/modules/aws_az_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,34 +155,27 @@

from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict

from ansible_collections.amazon.aws.plugins.module_utils.ec2 import describe_availability_zones
from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry
from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list
from ansible_collections.amazon.aws.plugins.module_utils.transformation import sanitize_filters_to_boto3_filter_list


def main():
argument_spec = dict(filters=dict(default={}, type="dict"))

module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True)

connection = module.client("ec2", retry_decorator=AWSRetry.jittered_backoff())

# Replace filter key underscores with dashes, for compatibility
sanitized_filters = dict(module.params.get("filters"))
for k in module.params.get("filters").keys():
if "_" in k:
sanitized_filters[k.replace("_", "-")] = sanitized_filters[k]
del sanitized_filters[k]
connection = module.client("ec2")

# Sanitize filters
sanitized_filters = sanitize_filters_to_boto3_filter_list(module.params.get("filters"))
try:
availability_zones = connection.describe_availability_zones(
aws_retry=True, Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)
)
availability_zones = describe_availability_zones(connection, Filters=sanitized_filters)
except (BotoCoreError, ClientError) as e:
module.fail_json_aws(e, msg="Unable to describe availability zones.")

# Turn the boto3 result into ansible_friendly_snaked_names
snaked_availability_zones = [camel_dict_to_snake_dict(az) for az in availability_zones["AvailabilityZones"]]
snaked_availability_zones = [camel_dict_to_snake_dict(az) for az in availability_zones]

module.exit_json(availability_zones=snaked_availability_zones)

Expand Down
21 changes: 7 additions & 14 deletions plugins/modules/aws_region_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@

from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict

from ansible_collections.amazon.aws.plugins.module_utils.ec2 import describe_regions
from ansible_collections.amazon.aws.plugins.module_utils.modules import AnsibleAWSModule
from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry
from ansible_collections.amazon.aws.plugins.module_utils.transformation import ansible_dict_to_boto3_filter_list
from ansible_collections.amazon.aws.plugins.module_utils.transformation import sanitize_filters_to_boto3_filter_list


def main():
Expand All @@ -89,23 +89,16 @@ def main():

module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True)

connection = module.client("ec2", retry_decorator=AWSRetry.jittered_backoff())

# Replace filter key underscores with dashes, for compatibility
sanitized_filters = dict(module.params.get("filters"))
for k in module.params.get("filters").keys():
if "_" in k:
sanitized_filters[k.replace("_", "-")] = sanitized_filters[k]
del sanitized_filters[k]
connection = module.client("ec2")

# Sanitize filters
sanitized_filters = sanitize_filters_to_boto3_filter_list(module.params.get("filters"))
try:
regions = connection.describe_regions(
aws_retry=True, Filters=ansible_dict_to_boto3_filter_list(sanitized_filters)
)
regions = describe_regions(connection, Filters=sanitized_filters)
except (BotoCoreError, ClientError) as e:
module.fail_json_aws(e, msg="Unable to describe regions.")

module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions["Regions"]])
module.exit_json(regions=[camel_dict_to_snake_dict(r) for r in regions])


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
instance_type: "{{ ec2_instance_type }}"
wait: true
ignore_errors: true
register: instance_creation
register: instance_creation_group_name

- name: Gather ec2 facts to check placement group options
amazon.aws.ec2_instance_info:
Expand All @@ -41,11 +41,11 @@
- name: Validate instance with placement group name
ansible.builtin.assert:
that:
- instance_creation is success
- instance_creation is changed
- instance_creation_group_name is success
- instance_creation_group_name is changed
- instance_facts.instances[0].placement.group_name == ec2_placement_group_name
# - instance_creation is failed
# - '"You are not authorized to perform this operation." in instance_creation.msg'

- ansible.builtin.include_tasks: select_availability_zone.yml

- name: New instance with dedicated tenancy
amazon.aws.ec2_instance:
Expand All @@ -58,10 +58,10 @@
TestId: "{{ ec2_instance_tag_TestId }}"
security_group: default
instance_type: "{{ ec2_instance_type }}"
availability_zone: us-east-1c
availability_zone: "{{ ec2_availability_zone }}"
wait: true
ignore_errors: true
register: instance_creation
register: instance_creation_tenancy

- name: Gather ec2 facts to check placement tenancy
amazon.aws.ec2_instance_info:
Expand All @@ -75,8 +75,25 @@
- name: Validate instance with dedicated tenancy
ansible.builtin.assert:
that:
- instance_creation is success
- instance_creation is changed
- instance_creation_tenancy is success
- instance_creation_tenancy is changed
- instance_facts.instances[0].placement.tenancy == ec2_tenancy
# - instance_creation is failed
# - '"You are not authorized to perform this operation." in instance_creation.msg'

always:
- name: Delete instances created with placement group name
amazon.aws.ec2_instance:
state: absent
instance_ids: "{{ instance_creation_group_name.instance_ids }}"
wait: false
ignore_errors: true
when: instance_creation_group_name is defined

- name: Delete instances created with placement tenancy
amazon.aws.ec2_instance:
state: absent
instance_ids: "{{ instance_creation_tenancy.instance_ids }}"
wait: false
ignore_errors: true
when: instance_creation_tenancy is defined
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# aws regions supporting 't3.micro' instance type
- ansible.builtin.set_fact:
av_zones:
- us-east-1a
- us-east-1b
- us-east-1c
- us-east-1d
- us-east-1f

- name: List t3.micro instances
amazon.aws.ec2_instance_info:
filters:
instance-type: t3.micro
instance-state-name:
- pending
- running
register: _instances

- ansible.builtin.set_fact:
instances_zones: "{{ _instances.instances | map(attribute='placement.availability_zone') | list | ansible.builtin.unique }}"

- ansible.builtin.set_fact:
ec2_availability_zone: "{{ av_zones | ansible.builtin.difference(instances_zones) | list | ansible.builtin.random }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# (c) 2024 Red Hat Inc.
#
# This file is part of Ansible
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from unittest.mock import patch

from ansible_collections.amazon.aws.plugins.module_utils import transformation

filters = {
"tag:Test_Name": "ansible-test-units",
"ansible_test_version": "milestone",
}

expected_no_ignore_keys = {
"tag:Test-Name": "ansible-test-units",
"ansible-test-version": "milestone",
}

expected_ignore_keys = {
"tag:Test_Name": "ansible-test-units",
"ansible-test-version": "milestone",
}


@patch("ansible_collections.amazon.aws.plugins.module_utils.transformation.ansible_dict_to_boto3_filter_list")
def test_sanitize_filters_to_boto3_filter_list_no_ignore_keys(m_ansible_dict_to_boto3_filter_list):
m_ansible_dict_to_boto3_filter_list.side_effect = lambda x: x
assert expected_no_ignore_keys == transformation.sanitize_filters_to_boto3_filter_list(filters)


@patch("ansible_collections.amazon.aws.plugins.module_utils.transformation.ansible_dict_to_boto3_filter_list")
def test_sanitize_filters_to_boto3_filter_list_ignore_keys(m_ansible_dict_to_boto3_filter_list):
m_ansible_dict_to_boto3_filter_list.side_effect = lambda x: x
assert expected_ignore_keys == transformation.sanitize_filters_to_boto3_filter_list(filters, ignore_keys=["tag:"])

0 comments on commit 42675e2

Please sign in to comment.