-
Notifications
You must be signed in to change notification settings - Fork 342
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit was initially merged in https://github.com/ansible-collections/community.aws See: ansible-collections/community.aws@eb75681
- Loading branch information
1 parent
e104e40
commit fff14a3
Showing
3 changed files
with
339 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
#!/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) | ||
|
||
from __future__ import absolute_import, division, print_function | ||
__metaclass__ = type | ||
|
||
ANSIBLE_METADATA = {'metadata_version': '1.1', | ||
'status': ['preview'], | ||
'supported_by': 'community'} | ||
|
||
|
||
DOCUMENTATION = ''' | ||
--- | ||
module: ec2_placement_group | ||
short_description: Create or delete an EC2 Placement Group | ||
description: | ||
- Create an EC2 Placement Group; if the placement group already exists, | ||
nothing is done. Or, delete an existing placement group. If the placement | ||
group is absent, do nothing. See also | ||
U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/placement-groups.html) | ||
author: "Brad Macpherson (@iiibrad)" | ||
options: | ||
name: | ||
description: | ||
- The name for the placement group. | ||
required: true | ||
type: str | ||
state: | ||
description: | ||
- Create or delete placement group. | ||
default: present | ||
choices: [ 'present', 'absent' ] | ||
type: str | ||
strategy: | ||
description: | ||
- Placement group strategy. Cluster will cluster instances into a | ||
low-latency group in a single Availability Zone, while Spread spreads | ||
instances across underlying hardware. | ||
default: cluster | ||
choices: [ 'cluster', 'spread' ] | ||
type: str | ||
extends_documentation_fragment: | ||
- ansible.amazon.aws | ||
- ansible.amazon.ec2 | ||
''' | ||
|
||
EXAMPLES = ''' | ||
# Note: These examples do not set authentication details, see the AWS Guide | ||
# for details. | ||
# Create a placement group. | ||
- ec2_placement_group: | ||
name: my-cluster | ||
state: present | ||
# Create a Spread placement group. | ||
- ec2_placement_group: | ||
name: my-cluster | ||
state: present | ||
strategy: spread | ||
# Delete a placement group. | ||
- ec2_placement_group: | ||
name: my-cluster | ||
state: absent | ||
''' | ||
|
||
|
||
RETURN = ''' | ||
placement_group: | ||
description: Placement group attributes | ||
returned: when state != absent | ||
type: complex | ||
contains: | ||
name: | ||
description: PG name | ||
type: str | ||
sample: my-cluster | ||
state: | ||
description: PG state | ||
type: str | ||
sample: "available" | ||
strategy: | ||
description: PG strategy | ||
type: str | ||
sample: "cluster" | ||
''' | ||
|
||
from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule | ||
from ansible_collections.ansible.amazon.plugins.module_utils.ec2 import AWSRetry | ||
try: | ||
from botocore.exceptions import (BotoCoreError, ClientError) | ||
except ImportError: | ||
pass # caught by AnsibleAWSModule | ||
|
||
|
||
@AWSRetry.exponential_backoff() | ||
def get_placement_group_details(connection, module): | ||
name = module.params.get("name") | ||
try: | ||
response = connection.describe_placement_groups( | ||
Filters=[{ | ||
"Name": "group-name", | ||
"Values": [name] | ||
}]) | ||
except (BotoCoreError, ClientError) as e: | ||
module.fail_json_aws( | ||
e, | ||
msg="Couldn't find placement group named [%s]" % name) | ||
|
||
if len(response['PlacementGroups']) != 1: | ||
return None | ||
else: | ||
placement_group = response['PlacementGroups'][0] | ||
return { | ||
"name": placement_group['GroupName'], | ||
"state": placement_group['State'], | ||
"strategy": placement_group['Strategy'], | ||
} | ||
|
||
|
||
@AWSRetry.exponential_backoff() | ||
def create_placement_group(connection, module): | ||
name = module.params.get("name") | ||
strategy = module.params.get("strategy") | ||
|
||
try: | ||
connection.create_placement_group( | ||
GroupName=name, Strategy=strategy, DryRun=module.check_mode) | ||
except (BotoCoreError, ClientError) as e: | ||
if e.response['Error']['Code'] == "DryRunOperation": | ||
module.exit_json(changed=True, placement_group={ | ||
"name": name, | ||
"state": 'DryRun', | ||
"strategy": strategy, | ||
}) | ||
module.fail_json_aws( | ||
e, | ||
msg="Couldn't create placement group [%s]" % name) | ||
|
||
module.exit_json(changed=True, | ||
placement_group=get_placement_group_details( | ||
connection, module | ||
)) | ||
|
||
|
||
@AWSRetry.exponential_backoff() | ||
def delete_placement_group(connection, module): | ||
name = module.params.get("name") | ||
|
||
try: | ||
connection.delete_placement_group( | ||
GroupName=name, DryRun=module.check_mode) | ||
except (BotoCoreError, ClientError) as e: | ||
module.fail_json_aws( | ||
e, | ||
msg="Couldn't delete placement group [%s]" % name) | ||
|
||
module.exit_json(changed=True) | ||
|
||
|
||
def main(): | ||
argument_spec = dict( | ||
name=dict(required=True, type='str'), | ||
state=dict(default='present', choices=['present', 'absent']), | ||
strategy=dict(default='cluster', choices=['cluster', 'spread']) | ||
) | ||
|
||
module = AnsibleAWSModule( | ||
argument_spec=argument_spec, | ||
supports_check_mode=True | ||
) | ||
|
||
connection = module.client('ec2') | ||
|
||
state = module.params.get("state") | ||
|
||
if state == 'present': | ||
placement_group = get_placement_group_details(connection, module) | ||
if placement_group is None: | ||
create_placement_group(connection, module) | ||
else: | ||
strategy = module.params.get("strategy") | ||
if placement_group['strategy'] == strategy: | ||
module.exit_json( | ||
changed=False, placement_group=placement_group) | ||
else: | ||
name = module.params.get("name") | ||
module.fail_json( | ||
msg=("Placement group '{}' exists, can't change strategy" + | ||
" from '{}' to '{}'").format( | ||
name, | ||
placement_group['strategy'], | ||
strategy)) | ||
|
||
elif state == 'absent': | ||
placement_group = get_placement_group_details(connection, module) | ||
if placement_group is None: | ||
module.exit_json(changed=False) | ||
else: | ||
delete_placement_group(connection, module) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ec2_placement_group_info.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#!/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) | ||
|
||
from __future__ import absolute_import, division, print_function | ||
__metaclass__ = type | ||
|
||
ANSIBLE_METADATA = {'metadata_version': '1.1', | ||
'status': ['preview'], | ||
'supported_by': 'community'} | ||
|
||
|
||
DOCUMENTATION = ''' | ||
--- | ||
module: ec2_placement_group_info | ||
short_description: List EC2 Placement Group(s) details | ||
description: | ||
- List details of EC2 Placement Group(s). | ||
- This module was called C(ec2_placement_group_facts) before Ansible 2.9. The usage did not change. | ||
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. | ||
type: list | ||
elements: str | ||
required: false | ||
default: [] | ||
extends_documentation_fragment: | ||
- ansible.amazon.aws | ||
- ansible.amazon.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_info: | ||
register: all_ec2_placement_groups | ||
# List two placement groups. | ||
- ec2_placement_group_info: | ||
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: str | ||
sample: my-cluster | ||
state: | ||
description: PG state | ||
type: str | ||
sample: "available" | ||
strategy: | ||
description: PG strategy | ||
type: str | ||
sample: "cluster" | ||
''' | ||
|
||
from ansible_collections.ansible.amazon.plugins.module_utils.aws.core import AnsibleAWSModule | ||
try: | ||
from botocore.exceptions import (BotoCoreError, ClientError) | ||
except ImportError: | ||
pass # caught by AnsibleAWSModule | ||
|
||
|
||
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 = dict( | ||
names=dict(type='list', default=[]) | ||
) | ||
|
||
module = AnsibleAWSModule( | ||
argument_spec=argument_spec, | ||
supports_check_mode=True | ||
) | ||
if module._module._name == 'ec2_placement_group_facts': | ||
module._module.deprecate("The 'ec2_placement_group_facts' module has been renamed to 'ec2_placement_group_info'", version='2.13') | ||
|
||
connection = module.client('ec2') | ||
|
||
placement_groups = get_placement_groups_details(connection, module) | ||
module.exit_json(changed=False, placement_groups=placement_groups) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |