Skip to content

Commit

Permalink
Add ec2_key_info module (#1715) (#1722)
Browse files Browse the repository at this point in the history
[PR #1715/937471be backport][stable-6] Add ec2_key_info module

This is a backport of PR #1715 as merged into main (937471b).
SUMMARY


Separated the info module from PR #1704
ISSUE TYPE


New Module Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Alina Buzachis
  • Loading branch information
patchback[bot] authored Sep 1, 2023
1 parent 7546cf6 commit b857c5d
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 0 deletions.
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ action_groups:
- ec2_instance
- ec2_instance_info
- ec2_key
- ec2_key_info
- ec2_security_group
- ec2_security_group_info
- ec2_snapshot
Expand Down
182 changes: 182 additions & 0 deletions plugins/modules/ec2_key_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

DOCUMENTATION = r"""
---
module: ec2_key_info
version_added: 6.4.0
short_description: Gather information about EC2 key pairs in AWS
description:
- Gather information about EC2 key pairs in AWS.
author:
- Aubin Bikouo (@abikouo)
options:
filters:
description:
- A dict of filters to apply. Each dict item consists of a filter key and a filter value. See
U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeKeyPairs.html) for possible filters. Filter
names and values are case sensitive.
required: false
default: {}
type: dict
names:
description:
- The key pair names.
required: false
type: list
elements: str
default: []
ids:
description:
- The IDs of the key pairs.
required: false
type: list
elements: str
default: []
include_public_key:
description:
- Whether or not to include the public key material in the response.
type: bool
default: false
extends_documentation_fragment:
- amazon.aws.common.modules
- amazon.aws.region.modules
- amazon.aws.boto3
"""

EXAMPLES = r"""
# Note: These examples do not set authentication details, see the AWS Guide for details.
- name: Gather information about all key pairs
amazon.aws.ec2_key_info:
- name: Gather information about a specific key pair
amazon.aws.ec2_key_info:
names:
- my-sample-key
- name: Retrieve EC2 key pair by fingerprint
amazon.aws.ec2_key_info:
filters:
fingerprint: "1bSd8jVye3In5oF4zZI4o8BcXfdbYN+daCt9O1fh3Qk="
"""

RETURN = r"""
keypairs:
description: A list of ec2 key pairs.
returned: always
type: complex
contains:
key_pair_id:
description: The ID of the key pair.
returned: always
type: str
sample: key-01238eb03f07d7268
key_fingerprint:
description: Fingerprint of the key.
returned: always
type: str
sample: '05:97:1a:2a:df:f6:06:a9:98:4b:ca:05:71:a1:81:e8:ff:6d:d2:a3'
key_name:
description: The name of the key pair.
returned: always
type: str
sample: my-sample-keypair
key_type:
description: The type of key pair.
returned: always
type: str
sample: rsa
public_key:
description: The public key material.
returned: always
type: str
create_time:
description: The time the key pair was created.
returned: always
type: str
sample: "2023-08-16T10:13:33.025000+00:00"
tags:
description: A dictionary representing the tags attached to the key pair.
returned: always
type: dict
sample: '{"my_key": "my value"}'
"""


try:
import botocore
except ImportError:
pass # caught by AnsibleAWSModule

from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict

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.tagging import boto3_tag_list_to_ansible_dict
from ansible_collections.amazon.aws.plugins.module_utils.botocore import is_boto3_error_code


def list_ec2_key_pairs(connection, module):
ids = module.params.get("ids")
names = module.params.get("names")
include_public_key = module.params.get("include_public_key")
filters = module.params.get("filters")
if filters:
filters = ansible_dict_to_boto3_filter_list(filters)

params = {}
if filters:
params["Filters"] = filters
if ids:
params["KeyPairIds"] = ids
if names:
params["KeyNames"] = names
if include_public_key:
params["IncludePublicKey"] = True

try:
result = connection.describe_key_pairs(**params)
except is_boto3_error_code("InvalidKeyPair.NotFound"):
result = {}
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg="Failed to list EC2 key pairs")

# Turn the boto3 result in to ansible_friendly_snaked_names
snaked_keys = [camel_dict_to_snake_dict(key) for key in result.get("KeyPairs", [])]

# Turn the boto3 result in to ansible friendly tag dictionary
for key in snaked_keys:
key["tags"] = boto3_tag_list_to_ansible_dict(key.get("tags", []), "key", "value")

module.exit_json(keypairs=snaked_keys)


def main():
argument_spec = dict(
filters=dict(type="dict", default={}),
names=dict(type="list", elements="str", default=[]),
ids=dict(type="list", elements="str", default=[]),
include_public_key=dict(type="bool", default=False),
)

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

try:
connection = module.client("ec2", retry_decorator=AWSRetry.jittered_backoff())
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
module.fail_json_aws(e, msg="Failed to connect to AWS")

list_ec2_key_pairs(connection, module)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions tests/integration/targets/ec2_key/aliases
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
# Zuul nodes
# https://github.com/ansible-collections/amazon.aws/issues/428
cloud/aws
ec2_key_info
51 changes: 51 additions & 0 deletions tests/integration/targets/ec2_key/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@
- '"spaced key" in result.key.tags'
- result.key.tags['spaced key'] == 'Spaced value'

- name: Gather info about the key pair
ec2_key_info:
names: '{{ ec2_key_name }}'
register: key_info

- name: assert the gathered key info
assert:
that:
- key_info.keypairs[0].key_name == ec2_key_name
- key_info.keypairs[0].key_pair_id.startswith('key-')
- '"snake_case" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['snake_case'] == 'a_snake_case_value'
- '"CamelCase" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['CamelCase'] == 'CamelCaseValue'
- '"spaced key" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['spaced key'] == 'Spaced value'

- set_fact:
key_id_1: '{{ result.key.id }}'

Expand Down Expand Up @@ -167,6 +184,25 @@
- '"newKey" in result.key.tags'
- result.key.tags['newKey'] == 'Another value'

- name: Gather info about the updated tags
ec2_key_info:
names: '{{ ec2_key_name }}'
register: key_info

- name: assert the gathered key info
assert:
that:
- key_info.keypairs[0].key_name == ec2_key_name
- key_info.keypairs[0].key_pair_id == key_id_1
- '"snake_case" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['snake_case'] == 'a_snake_case_value'
- '"CamelCase" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['CamelCase'] == 'CamelCaseValue'
- '"spaced key" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['spaced key'] == 'Spaced value'
- '"newKey" in key_info.keypairs[0].tags'
- key_info.keypairs[0].tags['newKey'] == 'Another value'

- name: test updating tags without purge - idempotency (check mode)
ec2_key:
name: '{{ ec2_key_name }}'
Expand Down Expand Up @@ -344,6 +380,21 @@
- 'result.key.name == "{{ec2_key_name}}"'
- 'result.key.fingerprint == "{{fingerprint}}"'

- name: Gather key info with fingerprint
ec2_key_info:
filters:
fingerprint: "{{ fingerprint }}"
register: key_info

- name: assert gathered key info
assert:
that:
- '"key_fingerprint" in key_info.keypairs[0]'
- '"private_key" not in key_info.keypairs[0]'
- '"key_pair_id" in key_info.keypairs[0]'
- '"tags" in key_info.keypairs[0]'
- 'key_info.keypairs[0].key_name == "{{ec2_key_name}}"'
- 'key_info.keypairs[0].key_fingerprint == "{{fingerprint}}"'
# ============================================================
- name: test state=present with key_material (idempotency)
ec2_key:
Expand Down

0 comments on commit b857c5d

Please sign in to comment.