211 lines
6.8 KiB
Python
211 lines
6.8 KiB
Python
#!/usr/bin/python
|
|
# Copyright: 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
|
|
|
|
|
|
DOCUMENTATION = '''
|
|
---
|
|
module: elasticache_snapshot
|
|
version_added: 1.0.0
|
|
short_description: Manage cache snapshots in Amazon ElastiCache
|
|
description:
|
|
- Manage cache snapshots in Amazon ElastiCache.
|
|
- Returns information about the specified snapshot.
|
|
author: "Sloane Hertel (@s-hertel)"
|
|
extends_documentation_fragment:
|
|
- amazon.aws.aws
|
|
- amazon.aws.ec2
|
|
options:
|
|
name:
|
|
description:
|
|
- The name of the snapshot we want to create, copy, delete.
|
|
required: true
|
|
type: str
|
|
state:
|
|
description:
|
|
- Actions that will create, destroy, or copy a snapshot.
|
|
required: true
|
|
choices: ['present', 'absent', 'copy']
|
|
type: str
|
|
replication_id:
|
|
description:
|
|
- The name of the existing replication group to make the snapshot.
|
|
type: str
|
|
cluster_id:
|
|
description:
|
|
- The name of an existing cache cluster in the replication group to make the snapshot.
|
|
type: str
|
|
target:
|
|
description:
|
|
- The name of a snapshot copy.
|
|
type: str
|
|
bucket:
|
|
description:
|
|
- The s3 bucket to which the snapshot is exported.
|
|
type: str
|
|
'''
|
|
|
|
EXAMPLES = """
|
|
# Note: None of these examples set aws_access_key, aws_secret_key, or region.
|
|
# It is assumed that their matching environment variables are set.
|
|
|
|
- name: 'Create a snapshot'
|
|
community.aws.elasticache_snapshot:
|
|
name: 'test-snapshot'
|
|
state: 'present'
|
|
cluster_id: '{{ cluster }}'
|
|
replication_id: '{{ replication }}'
|
|
"""
|
|
|
|
RETURN = """
|
|
response_metadata:
|
|
description: response metadata about the snapshot
|
|
returned: always
|
|
type: dict
|
|
sample:
|
|
http_headers:
|
|
content-length: 1490
|
|
content-type: text/xml
|
|
date: 'Tue, 07 Feb 2017 16:43:04 GMT'
|
|
x-amzn-requestid: 7f436dea-ed54-11e6-a04c-ab2372a1f14d
|
|
http_status_code: 200
|
|
request_id: 7f436dea-ed54-11e6-a04c-ab2372a1f14d
|
|
retry_attempts: 0
|
|
snapshot:
|
|
description: snapshot data
|
|
returned: always
|
|
type: dict
|
|
sample:
|
|
auto_minor_version_upgrade: true
|
|
cache_cluster_create_time: '2017-02-01T17:43:58.261000+00:00'
|
|
cache_cluster_id: test-please-delete
|
|
cache_node_type: cache.m1.small
|
|
cache_parameter_group_name: default.redis3.2
|
|
cache_subnet_group_name: default
|
|
engine: redis
|
|
engine_version: 3.2.4
|
|
node_snapshots:
|
|
cache_node_create_time: '2017-02-01T17:43:58.261000+00:00'
|
|
cache_node_id: 0001
|
|
cache_size:
|
|
num_cache_nodes: 1
|
|
port: 11211
|
|
preferred_availability_zone: us-east-1d
|
|
preferred_maintenance_window: wed:03:00-wed:04:00
|
|
snapshot_name: deletesnapshot
|
|
snapshot_retention_limit: 0
|
|
snapshot_source: manual
|
|
snapshot_status: creating
|
|
snapshot_window: 10:00-11:00
|
|
vpc_id: vpc-c248fda4
|
|
changed:
|
|
description: if a snapshot has been created, deleted, or copied
|
|
returned: always
|
|
type: bool
|
|
sample:
|
|
changed: true
|
|
"""
|
|
|
|
try:
|
|
import botocore
|
|
except ImportError:
|
|
pass # Handled by AnsibleAWSModule
|
|
|
|
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict
|
|
|
|
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule
|
|
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code
|
|
|
|
|
|
def create(module, connection, replication_id, cluster_id, name):
|
|
""" Create an ElastiCache backup. """
|
|
try:
|
|
response = connection.create_snapshot(ReplicationGroupId=replication_id,
|
|
CacheClusterId=cluster_id,
|
|
SnapshotName=name)
|
|
changed = True
|
|
except is_boto3_error_code('SnapshotAlreadyExistsFault'):
|
|
response = {}
|
|
changed = False
|
|
except botocore.exceptions.ClientError as e: # pylint: disable=duplicate-except
|
|
module.fail_json_aws(e, msg="Unable to create the snapshot.")
|
|
return response, changed
|
|
|
|
|
|
def copy(module, connection, name, target, bucket):
|
|
""" Copy an ElastiCache backup. """
|
|
try:
|
|
response = connection.copy_snapshot(SourceSnapshotName=name,
|
|
TargetSnapshotName=target,
|
|
TargetBucket=bucket)
|
|
changed = True
|
|
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
|
|
module.fail_json_aws(e, msg="Unable to copy the snapshot.")
|
|
return response, changed
|
|
|
|
|
|
def delete(module, connection, name):
|
|
""" Delete an ElastiCache backup. """
|
|
try:
|
|
response = connection.delete_snapshot(SnapshotName=name)
|
|
changed = True
|
|
except is_boto3_error_code('SnapshotNotFoundFault'):
|
|
response = {}
|
|
changed = False
|
|
except is_boto3_error_code('InvalidSnapshotState'): # pylint: disable=duplicate-except
|
|
module.fail_json(msg="Error: InvalidSnapshotState. The snapshot is not in an available state or failed state to allow deletion."
|
|
"You may need to wait a few minutes.")
|
|
except botocore.exceptions.ClientError as e: # pylint: disable=duplicate-except
|
|
module.fail_json_aws(e, msg="Unable to delete the snapshot.")
|
|
return response, changed
|
|
|
|
|
|
def main():
|
|
argument_spec = dict(
|
|
name=dict(required=True, type='str'),
|
|
state=dict(required=True, type='str', choices=['present', 'absent', 'copy']),
|
|
replication_id=dict(type='str'),
|
|
cluster_id=dict(type='str'),
|
|
target=dict(type='str'),
|
|
bucket=dict(type='str'),
|
|
)
|
|
|
|
module = AnsibleAWSModule(argument_spec=argument_spec)
|
|
|
|
name = module.params.get('name')
|
|
state = module.params.get('state')
|
|
replication_id = module.params.get('replication_id')
|
|
cluster_id = module.params.get('cluster_id')
|
|
target = module.params.get('target')
|
|
bucket = module.params.get('bucket')
|
|
|
|
try:
|
|
connection = module.client('elasticache')
|
|
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
|
|
module.fail_json_aws(e, msg='Failed to connect to AWS')
|
|
|
|
changed = False
|
|
response = {}
|
|
|
|
if state == 'present':
|
|
if not all((replication_id, cluster_id)):
|
|
module.fail_json(msg="The state 'present' requires options: 'replication_id' and 'cluster_id'")
|
|
response, changed = create(module, connection, replication_id, cluster_id, name)
|
|
elif state == 'absent':
|
|
response, changed = delete(module, connection, name)
|
|
elif state == 'copy':
|
|
if not all((target, bucket)):
|
|
module.fail_json(msg="The state 'copy' requires options: 'target' and 'bucket'.")
|
|
response, changed = copy(module, connection, name, target, bucket)
|
|
|
|
facts_result = dict(changed=changed, **camel_dict_to_snake_dict(response))
|
|
|
|
module.exit_json(**facts_result)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|