dms_replication_subnet_group (#56980
* dms_replication_subnet_group implementation
This commit is contained in:
parent
bc3c90f2f1
commit
edcb5b6775
5 changed files with 438 additions and 0 deletions
247
lib/ansible/modules/cloud/amazon/dms_replication_subnet_group.py
Normal file
247
lib/ansible/modules/cloud/amazon/dms_replication_subnet_group.py
Normal file
|
@ -0,0 +1,247 @@
|
|||
#!/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: dms_replication_subnet_group
|
||||
short_description: creates or destroys a data migration services subnet group
|
||||
description:
|
||||
- Creates or destroys a data migration services subnet group
|
||||
version_added: "2.9"
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- State of the subnet group
|
||||
default: present
|
||||
choices: ['present', 'absent']
|
||||
type: str
|
||||
identifier:
|
||||
description:
|
||||
- The name for the replication subnet group.
|
||||
This value is stored as a lowercase string.
|
||||
Must contain no more than 255 alphanumeric characters,
|
||||
periods, spaces, underscores, or hyphens. Must not be "default".
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- The description for the subnet group.
|
||||
type: str
|
||||
subnet_ids:
|
||||
description:
|
||||
- A list containing the subnet ids for the replication subnet group,
|
||||
needs to be at least 2 items in the list
|
||||
type: list
|
||||
author:
|
||||
- "Rui Moreira (@ruimoreira)"
|
||||
extends_documentation_fragment:
|
||||
- aws
|
||||
- ec2
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- dms_replication_subnet_group:
|
||||
state: present
|
||||
identifier: "dev-sngroup"
|
||||
description: "Development Subnet Group asdasdas"
|
||||
subnet_ids: ['subnet-id1','subnet-id2']
|
||||
'''
|
||||
|
||||
RETURN = ''' # '''
|
||||
__metaclass__ = type
|
||||
import traceback
|
||||
from ansible.module_utils.aws.core import AnsibleAWSModule
|
||||
from ansible.module_utils.ec2 import boto3_conn, HAS_BOTO3, \
|
||||
camel_dict_to_snake_dict, get_aws_connection_info, AWSRetry
|
||||
try:
|
||||
import botocore
|
||||
except ImportError:
|
||||
pass # caught by AnsibleAWSModule
|
||||
|
||||
backoff_params = dict(tries=5, delay=1, backoff=1.5)
|
||||
|
||||
|
||||
@AWSRetry.backoff(**backoff_params)
|
||||
def describe_subnet_group(connection, subnet_group):
|
||||
"""checks if instance exists"""
|
||||
try:
|
||||
subnet_group_filter = dict(Name='replication-subnet-group-id',
|
||||
Values=[subnet_group])
|
||||
return connection.describe_replication_subnet_groups(Filters=[subnet_group_filter])
|
||||
except botocore.exceptions.ClientError:
|
||||
return {'ReplicationSubnetGroups': []}
|
||||
|
||||
|
||||
@AWSRetry.backoff(**backoff_params)
|
||||
def replication_subnet_group_create(connection, **params):
|
||||
""" creates the replication subnet group """
|
||||
return connection.create_replication_subnet_group(**params)
|
||||
|
||||
|
||||
@AWSRetry.backoff(**backoff_params)
|
||||
def replication_subnet_group_modify(connection, **modify_params):
|
||||
return connection.modify_replication_subnet_group(**modify_params)
|
||||
|
||||
|
||||
@AWSRetry.backoff(**backoff_params)
|
||||
def replication_subnet_group_delete(module, connection):
|
||||
subnetid = module.params.get('identifier')
|
||||
delete_parameters = dict(ReplicationSubnetGroupIdentifier=subnetid)
|
||||
return connection.delete_replication_subnet_group(**delete_parameters)
|
||||
|
||||
|
||||
def get_dms_client(module, aws_connect_params, client_region, ec2_url):
|
||||
client_params = dict(
|
||||
module=module,
|
||||
conn_type='client',
|
||||
resource='dms',
|
||||
region=client_region,
|
||||
endpoint=ec2_url,
|
||||
**aws_connect_params
|
||||
)
|
||||
return boto3_conn(**client_params)
|
||||
|
||||
|
||||
def replication_subnet_exists(subnet):
|
||||
""" Returns boolean based on the existance of the endpoint
|
||||
:param endpoint: dict containing the described endpoint
|
||||
:return: bool
|
||||
"""
|
||||
return bool(len(subnet['ReplicationSubnetGroups']))
|
||||
|
||||
|
||||
def create_module_params(module):
|
||||
"""
|
||||
Reads the module parameters and returns a dict
|
||||
:return: dict
|
||||
"""
|
||||
instance_parameters = dict(
|
||||
# ReplicationSubnetGroupIdentifier gets translated to lower case anyway by the API
|
||||
ReplicationSubnetGroupIdentifier=module.params.get('identifier').lower(),
|
||||
ReplicationSubnetGroupDescription=module.params.get('description'),
|
||||
SubnetIds=module.params.get('subnet_ids'),
|
||||
)
|
||||
|
||||
return instance_parameters
|
||||
|
||||
|
||||
def compare_params(module, param_described):
|
||||
"""
|
||||
Compares the dict obtained from the describe function and
|
||||
what we are reading from the values in the template We can
|
||||
never compare passwords as boto3's method for describing
|
||||
a DMS endpoint does not return the value for
|
||||
the password for security reasons ( I assume )
|
||||
"""
|
||||
modparams = create_module_params(module)
|
||||
changed = False
|
||||
# need to sanitize values that get retured from the API
|
||||
if 'VpcId' in param_described.keys():
|
||||
param_described.pop('VpcId')
|
||||
if 'SubnetGroupStatus' in param_described.keys():
|
||||
param_described.pop('SubnetGroupStatus')
|
||||
for paramname in modparams.keys():
|
||||
if paramname in param_described.keys() and \
|
||||
param_described.get(paramname) == modparams[paramname]:
|
||||
pass
|
||||
elif paramname == 'SubnetIds':
|
||||
subnets = []
|
||||
for subnet in param_described.get('Subnets'):
|
||||
subnets.append(subnet.get('SubnetIdentifier'))
|
||||
for modulesubnet in modparams['SubnetIds']:
|
||||
if modulesubnet in subnets:
|
||||
pass
|
||||
else:
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
|
||||
def create_replication_subnet_group(module, connection):
|
||||
try:
|
||||
params = create_module_params(module)
|
||||
return replication_subnet_group_create(connection, **params)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
module.fail_json(msg="Failed to create DMS replication subnet group.",
|
||||
exception=traceback.format_exc(),
|
||||
**camel_dict_to_snake_dict(e.response))
|
||||
except botocore.exceptions.BotoCoreError as e:
|
||||
module.fail_json(msg="Failed to create DMS replication subnet group.",
|
||||
exception=traceback.format_exc())
|
||||
|
||||
|
||||
def modify_replication_subnet_group(module, connection):
|
||||
try:
|
||||
modify_params = create_module_params(module)
|
||||
return replication_subnet_group_modify(connection, **modify_params)
|
||||
except botocore.exceptions.ClientError as e:
|
||||
module.fail_json(msg="Failed to Modify the DMS replication subnet group.",
|
||||
exception=traceback.format_exc(),
|
||||
**camel_dict_to_snake_dict(e.response))
|
||||
except botocore.exceptions.BotoCoreError as e:
|
||||
module.fail_json(msg="Failed to Modify the DMS replication subnet group.",
|
||||
exception=traceback.format_exc())
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
state=dict(type='str', choices=['present', 'absent'], default='present'),
|
||||
identifier=dict(type='str', required=True),
|
||||
description=dict(type='str', required=True),
|
||||
subnet_ids=dict(type='list', elements='str', required=True),
|
||||
)
|
||||
module = AnsibleAWSModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True
|
||||
)
|
||||
exit_message = None
|
||||
changed = False
|
||||
if not HAS_BOTO3:
|
||||
module.fail_json(msg='boto3 required for this module')
|
||||
|
||||
state = module.params.get('state')
|
||||
aws_config_region, ec2_url, aws_connect_params = \
|
||||
get_aws_connection_info(module, boto3=True)
|
||||
dmsclient = get_dms_client(module, aws_connect_params, aws_config_region, ec2_url)
|
||||
subnet_group = describe_subnet_group(dmsclient,
|
||||
module.params.get('identifier'))
|
||||
if state == 'present':
|
||||
if replication_subnet_exists(subnet_group):
|
||||
if compare_params(module, subnet_group["ReplicationSubnetGroups"][0]):
|
||||
if not module.check_mode:
|
||||
exit_message = modify_replication_subnet_group(module, dmsclient)
|
||||
else:
|
||||
exit_message = dmsclient
|
||||
changed = True
|
||||
else:
|
||||
exit_message = "No changes to Subnet group"
|
||||
else:
|
||||
if not module.check_mode:
|
||||
exit_message = create_replication_subnet_group(module, dmsclient)
|
||||
changed = True
|
||||
else:
|
||||
exit_message = "Check mode enabled"
|
||||
|
||||
elif state == 'absent':
|
||||
if replication_subnet_exists(subnet_group):
|
||||
if not module.check_mode:
|
||||
replication_subnet_group_delete(module, dmsclient)
|
||||
changed = True
|
||||
exit_message = "Replication subnet group Deleted"
|
||||
else:
|
||||
exit_message = dmsclient
|
||||
changed = True
|
||||
|
||||
else:
|
||||
changed = False
|
||||
exit_message = "Replication subnet group does not exist"
|
||||
|
||||
module.exit_json(changed=changed, msg=exit_message)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,2 @@
|
|||
cloud/aws
|
||||
unsupported
|
|
@ -0,0 +1,2 @@
|
|||
resource_prefix: "test_dms_sg"
|
||||
dms_role_role_name: dms-vpc-role
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "dms.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
---
|
||||
|
||||
- name: set connection information for all tasks
|
||||
set_fact:
|
||||
aws_connection_info: &aws_connection_info
|
||||
aws_access_key: "{{ aws_access_key }}"
|
||||
aws_secret_key: "{{ aws_secret_key }}"
|
||||
region: "{{ aws_region }}"
|
||||
dms_sg_identifier: "{{ resource_prefix }}-dms"
|
||||
no_log: yes
|
||||
|
||||
- block:
|
||||
|
||||
- name: ensure IAM role exists
|
||||
iam_role:
|
||||
<<: *aws_connection_info
|
||||
name: "{{ dms_role_role_name }}"
|
||||
assume_role_policy_document: "{{ lookup('file','dmsAssumeRolePolicyDocument.json') }}"
|
||||
state: present
|
||||
create_instance_profile: no
|
||||
managed_policy:
|
||||
- 'arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole'
|
||||
register: iam_role_output
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Create VPC for use in testing
|
||||
ec2_vpc_net:
|
||||
name: "{{ resource_prefix }}-vpc"
|
||||
cidr_block: 10.22.32.0/23
|
||||
tags:
|
||||
Name: Ansible ec2_instance Testing VPC
|
||||
tenancy: default
|
||||
<<: *aws_connection_info
|
||||
register: testing_vpc
|
||||
|
||||
- name: create subnet1
|
||||
ec2_vpc_subnet:
|
||||
state: present
|
||||
vpc_id: "{{ testing_vpc.vpc.id }}"
|
||||
cidr: 10.22.32.16/28
|
||||
az: eu-west-1a
|
||||
<<: *aws_connection_info
|
||||
register: subnet1
|
||||
|
||||
- name: create subnet2
|
||||
ec2_vpc_subnet:
|
||||
state: present
|
||||
vpc_id: "{{ testing_vpc.vpc.id }}"
|
||||
cidr: 10.22.32.32/28
|
||||
az: eu-west-1c
|
||||
<<: *aws_connection_info
|
||||
register: subnet2
|
||||
|
||||
- name: create replication subnet group
|
||||
dms_replication_subnet_group:
|
||||
state: present
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result is not failed
|
||||
|
||||
- name: create subnet group no change
|
||||
dms_replication_subnet_group:
|
||||
state: present
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result is not failed
|
||||
|
||||
- name: update subnet group
|
||||
dms_replication_subnet_group:
|
||||
state: present
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group updated"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result is not failed
|
||||
|
||||
- name: update subnet group no change
|
||||
dms_replication_subnet_group:
|
||||
state: present
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group updated"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result is not failed
|
||||
|
||||
always:
|
||||
- name: delete subnet group no change
|
||||
dms_replication_subnet_group:
|
||||
state: absent
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group updated"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
- result is not failed
|
||||
|
||||
- name: delete subnet group no change
|
||||
dms_replication_subnet_group:
|
||||
state: absent
|
||||
identifier: "{{ dms_sg_identifier }}"
|
||||
description: "Development Subnet Group updated"
|
||||
subnet_ids: [ "{{ subnet1.subnet.id }}", "{{ subnet2.subnet.id }}"]
|
||||
<<: *aws_connection_info
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is not changed
|
||||
- result is not failed
|
||||
|
||||
- name: delete subnet1
|
||||
ec2_vpc_subnet:
|
||||
state: absent
|
||||
vpc_id: "{{ testing_vpc.vpc.id }}"
|
||||
cidr: 10.22.32.16/28
|
||||
az: eu-west-1a
|
||||
<<: *aws_connection_info
|
||||
|
||||
- name: delete subnet2
|
||||
ec2_vpc_subnet:
|
||||
state: absent
|
||||
vpc_id: "{{ testing_vpc.vpc.id }}"
|
||||
cidr: 10.22.32.32/28
|
||||
az: eu-west-1c
|
||||
<<: *aws_connection_info
|
||||
|
||||
- name: delete VPC for use in testing
|
||||
ec2_vpc_net:
|
||||
name: "{{ resource_prefix }}-vpc"
|
||||
cidr_block: 10.22.32.0/23
|
||||
tags:
|
||||
Name: Ansible ec2_instance Testing VPC
|
||||
tenancy: default
|
||||
state: absent
|
||||
<<: *aws_connection_info
|
||||
|
||||
- name: delete dms-vpc role
|
||||
iam_role:
|
||||
<<: *aws_connection_info
|
||||
name: "{{ dms_role_role_name }}"
|
||||
assume_role_policy_document: "{{ lookup('file','dmsAssumeRolePolicyDocument.json') }}"
|
||||
state: absent
|
||||
create_instance_profile: no
|
||||
managed_policy:
|
||||
- 'arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole'
|
||||
register: iam_role_output
|
||||
ignore_errors: yes
|
Loading…
Reference in a new issue