diff --git a/lib/ansible/modules/cloud/amazon/GUIDELINES.md b/lib/ansible/modules/cloud/amazon/GUIDELINES.md index 8e725d23fe..a3845bd457 100644 --- a/lib/ansible/modules/cloud/amazon/GUIDELINES.md +++ b/lib/ansible/modules/cloud/amazon/GUIDELINES.md @@ -1,8 +1,8 @@ # Guidelines for AWS modules The Ansible AWS modules and these guidelines are maintained by the Ansible AWS Working Group. For -further information see -[the AWS working group community page](https://github.com/ansible/community/tree/master/group-aws). +further information see +[the AWS working group community page](https://github.com/ansible/community/tree/master/group-aws). If you are planning to contribute AWS modules to Ansible then getting in touch with the the working group will be a good way to start, especially because a similar module may already be under development. @@ -63,7 +63,8 @@ as the module does that check. If you want to import the modules anyway (for example `from botocore.exception import ClientError`) Wrap import statements in a try block and fail the module later using `HAS_BOTO3` if -the import fails. +the import fails. See below as well (`Exception Handling for boto3 and botocore`) for more detail +on how to safely import botocore exceptions. #### boto @@ -336,7 +337,7 @@ If the underlying `describe_some_resources` API call throws a `ResourceNotFound` exception, `AWSRetry` takes this as a cue to retry until it's not thrown (this is so that when creating a resource, we can just retry until it exists). -To handle authorization failures or parameter validation errors in +To handle authorization failures or parameter validation errors in `describe_some_resource_with_backoff`, where we just want to return `None` if the resource doesn't exist and not retry, we need: @@ -373,7 +374,7 @@ snake_case. There is a helper function in module_utils/ec2.py called `camel_dict that allows you to easily convert the boto3 response to snake_case. You should use this helper function and avoid changing the names of values returned by Boto3. -E.g. if boto3 returns a value called 'SecretAccessKey' do not change it to 'AccessKey'. +E.g. if boto3 returns a value called 'SecretAccessKey' do not change it to 'AccessKey'. ```python # Make a call to AWS diff --git a/lib/ansible/modules/cloud/amazon/ec2_placement_group_facts.py b/lib/ansible/modules/cloud/amazon/ec2_placement_group_facts.py new file mode 100644 index 0000000000..b492e23d6c --- /dev/null +++ b/lib/ansible/modules/cloud/amazon/ec2_placement_group_facts.py @@ -0,0 +1,137 @@ +#!/usr/bin/python +# Copyright (c) 2017 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_placement_group_facts +short_description: List EC2 Placement Group(s) details +description: + - List details of EC2 Placement Group(s). +version_added: "2.5" +author: "Brad Macpherson (@iiibrad)" +options: + names: + description: + - A list of names to filter on. If a listed group does not exist, there + will be no corresponding entry in the result; no error will be raised. + required: false + default: [] +extends_documentation_fragment: + - aws + - ec2 +''' + +EXAMPLES = ''' +# Note: These examples do not set authentication details or the AWS region, +# see the AWS Guide for details. + +# List all placement groups. +- ec2_placement_group_facts: + register: all_ec2_placement_groups + +# List two placement groups. +- ec2_placement_group_facts: + names: + - my-cluster + - my-other-cluster + register: specific_ec2_placement_groups + +- debug: msg="{{ specific_ec2_placement_groups | json_query(\"[?name=='my-cluster']\") }}" + +''' + + +RETURN = ''' +placement_groups: + description: Placement group attributes + returned: always + type: complex + contains: + name: + description: PG name + type: string + sample: my-cluster + state: + description: PG state + type: string + sample: "available" + strategy: + description: PG strategy + type: string + sample: "cluster" + +''' + +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.ec2 import (connect_to_aws, + boto3_conn, + ec2_argument_spec, + get_aws_connection_info, + HAS_BOTO3) +try: + from botocore.exceptions import (BotoCoreError, ClientError) +except ImportError: + pass # caught by imported HAS_BOTO3 + + +def get_placement_groups_details(connection, module): + names = module.params.get("names") + try: + if len(names) > 0: + response = connection.describe_placement_groups( + Filters=[{ + "Name": "group-name", + "Values": names + }]) + else: + response = connection.describe_placement_groups() + except (BotoCoreError, ClientError) as e: + module.fail_json_aws( + e, + msg="Couldn't find placement groups named [%s]" % names) + + results = [] + for placement_group in response['PlacementGroups']: + results.append({ + "name": placement_group['GroupName'], + "state": placement_group['State'], + "strategy": placement_group['Strategy'], + }) + return results + + +def main(): + argument_spec = ec2_argument_spec() + argument_spec.update( + dict( + names=dict(type='list', default=[]) + ) + ) + + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True + ) + + if not HAS_BOTO3: + module.fail_json(msg='boto3 and botocore are required for this module') + + region, ec2_url, aws_connect_params = get_aws_connection_info( + module, boto3=True) + + connection = boto3_conn(module, + resource='ec2', conn_type='client', + region=region, **aws_connect_params) + + placement_groups = get_placement_groups_details(connection, module) + module.exit_json(changed=False, placement_groups=placement_groups) + + +if __name__ == '__main__': + main()