diff --git a/lib/ansible/modules/cloud/amazon/ec2_ami_facts.py b/lib/ansible/modules/cloud/amazon/ec2_ami_facts.py new file mode 100644 index 0000000000..5037337286 --- /dev/null +++ b/lib/ansible/modules/cloud/amazon/ec2_ami_facts.py @@ -0,0 +1,236 @@ +#!/usr/bin/python +# Copyright: Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = ''' +--- +module: ec2_ami_facts +version_added: '2.5' +short_description: Gather facts about ec2 AMIs +description: Gather facts about ec2 AMIs +author: + - Prasad Katti, @prasadkatti +requirements: [ boto3 ] +options: + image_ids: + description: One or more image IDs. + aliases: [image_id] + 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_DescribeImages.html) for possible filters. + - Filter names and values are case sensitive. + owners: + description: + - Filter the images by the owner. Valid options are an AWS account ID, self, + - or an AWS owner alias ( amazon | aws-marketplace | microsoft ). + aliases: [owner] + executable_users: + description: + - Filter images by users with explicit launch permissions. Valid options are an AWS account ID, self, or all (public AMIs). + aliases: [executable_user] + +extends_documentation_fragment: + - aws + - ec2 +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +- name: gather facts about an AMI using ami-id + ec2_ami_facts: + image_ids: ami-5b488823 + +- name: gather facts about all AMIs with tag key Name and value webapp + ec2_ami_facts: + filters: + "tag:Name": webapp + +- name: gather facts about an AMI with 'AMI Name' equal to foobar + ec2_ami_facts: + filters: + name: foobar + +- name: gather facts about Ubuntu 17.04 AMIs published by Canonical (099720109477) + ec2_ami_facts: + owners: 099720109477 + filters: + name: "ubuntu/images/ubuntu-zesty-17.04-*" +''' + +RETURN = ''' +images: + description: a list of images + returned: always + type: complex + contains: + architecture: + description: The architecture of the image + returned: always + type: string + sample: x86_64 + block_device_mappings: + description: Any block device mapping entries + returned: always + type: complex + contains: + device_name: + description: The device name exposed to the instance + returned: always + type: string + sample: /dev/sda1 + ebs: + description: EBS volumes + returned: always + type: complex + creation_date: + description: The date and time the image was created + returned: always + type: string + sample: '2017-10-16T19:22:13.000Z' + description: + description: The description of the AMI + returned: always + type: string + sample: '' + ena_support: + description: whether enhanced networking with ENA is enabled + returned: always + type: bool + sample: true + hypervisor: + description: The hypervisor type of the image + returned: always + type: string + sample: xen + image_id: + description: The ID of the AMI + returned: always + type: string + sample: ami-5b466623 + image_location: + description: The location of the AMI + returned: always + type: string + sample: 408466080000/Webapp + image_type: + description: The type of image + returned: always + type: string + sample: machine + launch_permissions: + description: launch permissions of the ami + returned: always + type: complex + sample: [{"group": "all"}, {"user_id": "408466080000"}] + name: + description: The name of the AMI that was provided during image creation + returned: always + type: string + sample: Webapp + owner_id: + description: The AWS account ID of the image owner + returned: always + type: string + sample: '408466080000' + public: + description: whether the image has public launch permissions + returned: always + type: bool + sample: true + root_device_name: + description: The device name of the root device + returned: always + type: string + sample: /dev/sda1 + root_device_type: + description: The type of root device used by the AMI + returned: always + type: string + sample: ebs + sriov_net_support: + description: whether enhanced networking is enabled + returned: always + type: string + sample: simple + state: + description: The current state of the AMI + returned: always + type: string + sample: available + tags: + description: Any tags assigned to the image + returned: always + type: complex + virtualization_type: + description: The type of virtualization of the AMI + returned: always + type: string + sample: hvm +''' + +try: + from botocore.exceptions import ClientError, BotoCoreError +except ImportError: + pass + +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.ec2 import (boto3_conn, ec2_argument_spec, get_aws_connection_info, ansible_dict_to_boto3_filter_list, + camel_dict_to_snake_dict, boto3_tag_list_to_ansible_dict) + + +def list_ec2_images(ec2_client, module): + + image_ids = module.params.get("image_ids") + filters = ansible_dict_to_boto3_filter_list(module.params.get("filters")) + owners = module.params.get("owners") + executable_users = module.params.get("executable_users") + + try: + images = ec2_client.describe_images(ImageIds=image_ids, Filters=filters, Owners=owners, ExecutableUsers=executable_users) + images = [camel_dict_to_snake_dict(image) for image in images["Images"]] + for image in images: + launch_permissions = ec2_client.describe_image_attribute(Attribute='launchPermission', ImageId=image['image_id'])['LaunchPermissions'] + image['launch_permissions'] = [camel_dict_to_snake_dict(perm) for perm in launch_permissions] + except (ClientError, BotoCoreError) as err: + module.fail_json_aws(err, msg="error describing images") + + for image in images: + image['tags'] = boto3_tag_list_to_ansible_dict(image.get('tags', []), 'key', 'value') + + module.exit_json(images=images) + + +def main(): + + argument_spec = ec2_argument_spec() + argument_spec.update( + dict( + image_ids=dict(default=[], type='list', aliases=['image_id']), + filters=dict(default={}, type='dict'), + owners=dict(default=[], type='list', aliases=['owner']), + executable_users=dict(default=[], type='list', aliases=['executable_user']) + ) + ) + + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) + + region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True) + + if region: + ec2_client = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params) + else: + module.fail_json(msg="region must be specified") + + list_ec2_images(ec2_client, module) + + +if __name__ == '__main__': + main() diff --git a/test/integration/targets/ec2_ami/aliases b/test/integration/targets/ec2_ami/aliases index ebdf4aa572..ed6bf47b3c 100644 --- a/test/integration/targets/ec2_ami/aliases +++ b/test/integration/targets/ec2_ami/aliases @@ -1,2 +1,3 @@ cloud/aws posix/ci/cloud/group1/aws +ec2_ami_facts diff --git a/test/integration/targets/ec2_ami/tasks/main.yml b/test/integration/targets/ec2_ami/tasks/main.yml index 8d96e10599..4172385d5b 100644 --- a/test/integration/targets/ec2_ami/tasks/main.yml +++ b/test/integration/targets/ec2_ami/tasks/main.yml @@ -118,6 +118,23 @@ # ============================================================ + - name: gather facts about the image created + ec2_ami_facts: + ec2_region: '{{ec2_region}}' + ec2_access_key: '{{ec2_access_key}}' + ec2_secret_key: '{{ec2_secret_key}}' + security_token: '{{security_token}}' + image_ids: '{{ ec2_ami_image_id }}' + register: ami_facts_result + ignore_errors: true + + - name: assert that the right image was found + assert: + that: + - "ami_facts_result.images[0].image_id == ec2_ami_image_id" + + # ============================================================ + - name: delete the image ec2_ami: ec2_region: '{{ec2_region}}'